$! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990 $! On 26-JUN-1991 16:48:08.60 By user FRISBIE $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 8 PARTS, TO KEEP EACH PART $! BELOW 30 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. README.;2 $! 2. TPC.CMD;4 $! 3. TPC.DOC;2 $! 4. TPC.HLP;1 $! 5. TPC.MAC;3 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:= CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b)); LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1); IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE; MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1; ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")= 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF"; POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r); ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1; COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE, "output_file"));ENDPROCEDURE;Unpacker;QUIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create 'f' X`09TPC -- Fast Tape Copy X X26-Jun-91 X X This is version 1.75 of TPC, the fast tape copy program. There Xare several enhancements over previous versions. These include: X X1.`09Some unknown enhancer added magtape devices MU: and MA: to X`09the device list. X X2.`09Someone also added the /MI (Magtape In) and /MO (Magtape Out) X`09switches to force a device to be treated as a tape (useful X`09if new tape devices are ever defined). X X3.`09I fixed a serious bug in the AST routines: none of them ever X`09saved R0-R5!!! Since only one AST routine could ever execute at X`09a time (and the mainline code was suspended), this bug has gone X`09undetected for 14 years. It finally bit me when I tried to go X`09disk-to-tape from a high-speed caching disk controller. The X`09first QIO completed (and triggered the AST) before the second QIO X`09was issued. The registers were then clobbered, causing the X`09remainder of the setup code to execute incorrectly.`20 X X There is still at least one more problem to be fixed when someone Xfinds some time. On RSX-11M-Plus, if the tape is not mounted foreign, Xthe program will simply hang. This condition needs to be checked for Xand reported. X X`09Alan E. Frisbie X`09Flying Disk Systems X`094759 Round Top Drive X`09Los Angeles, CA 90065 X X`09(213) 256-2575 $ CALL UNPACK README.;2 593683676 $ create 'f' X;`09T P C . C m d X; X; Indirect command file to assemble and taskbuild TPC X.; X.Enable Substitution X.; X.SetS OldCLI X.If ne "MCR" Set /MCR=TI: X.; X.IfNINS ...MAC INS $MAC X.IFNINS ...TKB INS $TKB X.; XMAC TPC,TPC/-SP=TPC X.; X.Open TPCTKB.Bld X.Enable Data XTPC,TPC/-sp=TPC X/ XTask=...TPC X// X.Disable Data X.Close X.; XTKB @TPCTKB.Bld X.; XPip TPC.LST,TPC.OBJ,TPC.Tsk/PU,TPC.Map,TPCTKB.Bld X.; X.; Done X.; X.Done: X;`09`07Done X.If OldCLI ne "MCR" Set /'OldCLI'=TI: X.Exit $ CALL UNPACK TPC.CMD;4 1628701098 $ create 'f' X`09`09 TPC - Fast Tape Copy X`09`09 ==================== X X`09`09`09Users' Guide X`09`09`09============ X X (Version 1.75, June 1991) X X This program will copy a complete magtape to a Files-11 disk X and store it there in a special image mode, from which it can create X one or more copies of the tape (must faster than FLX ever could). X X BIGTPC is not only able to do this, but also will handle any block X size on tape up to 4200. bytes (big enough for BRU tapes). X X If it is desired to support larger BIGTPC block sizes, it is possible X to reduce the number of BIGTPC buffers (and the buffer headers) and to X reduce the disk buffer count of blocks. This works well with the number X of disk blocks reduced to 8., the number of BIGTPC buffers reduced from X 4 to 3, and the size increased to 11000. bytes, supporting image copies X of such formats as VMS BACKUP or UNIX TAR tapes. Note however that where X these counts are changed, BIGTPC may not terminate correctly when writing X a container file from another version. You may have to abort and write X EOFs with another utility. If you have a tape and recreate container files, X there will be no trouble. X X The command format is:- X X`09TPC Output-filespec=Input-filespec X X where one of the 'filespecs' must be a magtape device (e.g. MT:) and X the other the name of an image file on disk. X X Legal switches are:- X X /BL:nnnn - Specifies an initial allocation specification for X the image file if a disk is the output device. X`09`09 Defaults to 200. X X /SA:nnnn - Specifies a secondary allocation specification for X the image file if a disk is the output device. X`09`09 Defaults to 50. X X /CO - Specifies that the disk file is to be contiguous X X /HD - Indicates High Density (1600 BPI) tape is to be X`09`09 written. (For TE16, tape is read at the proper density X`09`09 automagically.) This permits a container file from one X`09`09 density to be written out in another. X X /NR`09- Specifies NO positioning of the tape prior to the X`09`09 start of copying. This will allow TPC to merge X`09`09 several backup collections on a single output tape X`09`09 if used with care. X X`09`09 After the end of a copy, TPC will write 4 EOF records and X`09`09 backspace so that it will be positioned after the first X`09`09 EOF on tape. This will ensure that a second backup X`09`09 done with the /NR switch will correctly copy onto a FLX X`09`09 tape in readable fashion. X X /VE`09- Verify the transfer. After the copy (in either direction) X`09`09 is made, the tape is rewound and both the tape and file X`09`09 are read and compared. X X /CM`09- Compare the tape with an existing TPC file. Note that X`09`09 the "transfer" can be in either direction. That is, the X`09`09 tape specification can be on either side of the equal sign. X X`09`09 *** NOTE *** The /VE & /CM options are only implemented X`09`09 for "vanilla" tape/disk/tape transfers. Use of these X`09`09 switches with any of the "exotic" copy modes is not X`09`09 supported and may cause undesired effects. This restriction X`09`09 may be removed at a future date. X X /SC:nnnn - Sets tape characteristics to nnnn (octal), to allow read V or write X`09`09 of tapes with even parity, 556BPI, etc. If the /HD switch is X`09`09 used, the high density bit is ORed in with the nnnn value X`09`09 specified in the /SC switch. X X /AN`09- Specifies possible ANSI format tape. If TPC sees this switch X`09`09 it will look for ANSI label records and permit copies X`09`09 even where the tape has null files and hence double EOF X`09`09 before the real end of tape. Only 80 byte records are X`09`09 examined and EOFs are treated specially only between X`09`09 HDR2 and EOF2 (or EOV). The headers are assumed to be in X`09`09 ASCII unless the switch /EB is given, in which case they X`09`09 are assumed to be in EBCDIC. If the tape is not really X`09`09 an ANSI format tape, the TPC copy operation is not X`09`09 changed. Thus the /ANsi switch may be used on a tape of X`09`09 unknown format. X`09`09 The default is /AN, and to force BIGTPC NOT to X`09`09 look for ANSI labels (looking normally only at 80 byte X`09`09 records unless the /RT subswitch is used), use the /-AN X`09`09 switch. X X /EB`09- This subswitch of the /AN switch forces on ANSI label X`09`09 checks but causes TPC to look for EBCDIC header labels X`09`09 rather than ASCII. Note that TPC looks for either ASCII X`09`09 or EBCDIC, not both. The default is not to look for X`09`09 ANSI labels and end copy at double EOF; the /AN or /EB switch X`09`09 settings allow some modifications to this. X X /RT`09- Use RT11 type "ANSI" labels. RT11 may not make label X`09`09 records 80. bytes long, and if you have RT11 tapes, the X`09`09 ANSI checks will normally ignore the RT11 ANSI labels X`09`09 unless you use this switch. It causes BIGTPC to ignore X`09`09 length of records and checks everything to see if it is X`09`09 an ANSI label record. It is not a very good default because X`09`09 it probably can be fooled easily but may be needed for X`09`09 RT11 tapes. X X /ER`09- Specifies that TPC will ignore errors on tape. This X`09`09 specifically means that all errors except EOT/EOV/EOF X`09`09 will be ignored. This is quite useful for recovering X`09`09 data from tapes which are old and full of errors, or for X`09`09 writing an output to a tape with bad spots (though X`09`09 it won't cure bad spots and this method of writing X`09`09 anyway is not necessarily a good idea...). X X /EV`09- Ignore End-of-Volume or /End-of-Tape errors. This allows X`09`09 copying past the EOT marker to the actual end of data on X`09`09 a tape that is completely full. Note that this makes it X`09`09 possible to run completely off the end of reel. You have X`09`09 been warned. X X /FR`09- Rewind the tape after copying to it. Note the /NR switch X`09`09 applies to BEFORE the tape is used and inhibits positioning X`09`09 at that time. The /FR switch will rewind the tape AFTER X`09`09 writing to it. X X /TR`09- This switch allows BIGTPC to read a disk to a container X`09`09 file as though it were a tape. It implies BIGTPC should X`09`09 act as though the input device were a tape even if it X`09`09 is not. BIGTPC will need to know the size to copy (defaults X`09`09 to 494. blocks, the size of an RX01) and the start block X`09`09 number (defaults to 0,0) as octal numnbers in the form X`09`09 low:high (see /SZ and /LO switches). The input device is X`09`09 copied 1 block at a time. The normal "control" features X`09`09 like density, rewind, etc., are suppressed UNLESS the X`09`09 /CT switch is used. Their effect is not likely to be X`09`09 meaningful. X X /TW`09- This switch allows BIGTPC to write a container file to X`09`09 a disk as though the disk were a tape (on the output side X`09`09 of the command line). It is the inverse of the /TR switch X`09`09 and needs the /SZ and /LO information too. X X /SZ:low:high - This switch sets the device size for /TR, /TW, and X`09`09 /IM copies, in 2 words of block counts. Note the number X`09`09 of blocks is given, not the last block number, so a disk X`09`09 with 494 blocks is specified as /SZ:494., the high size X`09`09 defaulting to 0. Default value is /SZ:494.:0. X X /LO:low:high - This switch specifies the starting physical block X`09`09 of the disk to begin transfer from in /TR and /IM, or X`09`09 transfer to in /TW cases. This allows you to move blocks X`09`09 around or to copy only parts of a disk. The default is X`09`09 0:0, so you won't need to use /LO often unless you intend X`09`09 to copy partial volumes. X X /CT`09- This switch allows control-type QIO's to occur even if X`09`09 /IM, /TR, or /TW are specified. These QIO's do things X`09`09 like rewind, write endfile, space forward or back, X`09`09 and set density as well as attach the LUNs. It is not X`09`09 very meaningful for /TR or /TW unless you have a strange X`09`09 device that nevertheless is really a tape (and it's not X`09`09 certain you can emulate it properly this way anyhow). For X`09`09 /IM copies, it allows a tape to be the output device X`09`09 and to receive a blocked copy of a device in format X`09`09 independent ways while still setting density, rewinding, X`09`09 etc. Note the control QIOs are not error checked so if X`09`09 you try to rewind a disk, it'll not hurt you. X X`09/MI`09- Treat the input device as a Magtape without checking X`09`09 to see if it matches one of the valid devices. This X`09`09 allows new devices to be supported without rebuilding X`09`09 TPC. X X`09/MO`09- Treat the output device as a Magtape without checking X`09`09 to see if it matches one of the valid devices. This X`09`09 allows new devices to be supported without rebuilding X`09`09 TPC. X X /IM:low:high:blkfactor - This switch allows BIGTPC to copy data X`09`09 in image mode directly from one device to another. It X`09`09 does not operate AST driven in this mode as it does in X`09`09 all others, but uses all buffers as one large I/O buffer X`09`09 permitting I/O transfers of up to about 72. blocks at X`09`09 a time. The low:high arguments are the block number X`09`09 to begin the output transfer to on the output device X`09`09 (/SZ specifies the length in blocks to move), and the X`09`09 "blkfactor" argument is the number of blocks to X`09`09 be transferred at each QIO$ to the output device. X`09`09 This defaults to 8. so that if the output device is X`09`09 tape, the buffers will be 4096. bytes long. If you X`09`09 specify a bigger blocking factor than BIGTPC can X`09`09 handle, it will just use its maximum. Normal operation X`09`09 will not issue any "write-EOF" operations, but if tape X`09`09 is the output device, the /CT switch will permit X`09`09 these controls to be done so the resulting tape will X`09`09 work (and the /FR switch, the /HD switch, and the X`09`09 /SC switch will work). X X /FL:filnam`09-This switch works only with the /IM and /CT X`09`09 switches and will have no effect unless BOTH of these X`09`09 are specified. It causes BIGTPC to write a standard X`09`09 DOS format (FLX format) label record before it writes X`09`09 an image file on tape, using "filnam" (up to 6 characters) X`09`09 as the filename. The full file specification is X`09`09 `5B1,1`5Dfilnam.OLB with standard DOS protection and a creation X`09`09 date of 00-JAN-70. This permits the image file to co-exist X`09`09 on a FLX tape (.OLB is the extension chosen since FLX will X`09`09 copy it in image mode). FLX can skip the nonstandard X`09`09 file and make directories, read, or write on the tape, X`09`09 allowing it to contain other interesting programs (perhaps X`09`09 a copy of BIGTPC to read the images with, for instance). X`09`09 Also, multiple files may be more easily kept on the tape. X`09`09 On input, you must skip this record on tape prior to X`09`09 inputting the file. X`09`09 If /ER is specified, zero byte reads will NOT terminate X`09`09 copies (so sizes better be right!) and lengths copied will X`09`09 be calculated from given block factors, not from returned X`09`09 actual byte counts. X X /NI`09- This switch ("Nibble In") allows /IM copies to read a X`09`09 disk 1 block at a time instead of using big QIOs of "blkfct" X`09`09 blocks at a time. Thus, if there is a bad disk block, data X`09`09 on following blocks will not be lost. See the /IM switch doc. X`09`09 for interaction with /ER. X X /NO`09- This switch ("Nibble Out") allows /IM copies to write a X`09`09 disk 1 block at a time. It is supplied also to aid in writing X`09`09 to a disk with bad blocks, guaranteeing that not more than 1 X`09`09 block's data will be lost. Its interaction with /ER is as that X`09`09 of /IM. The /NI and /NO switches apply only to the /IMage X`09`09 mode copies of BIGTPC. X X /HE`09- This switch causes BIGTPC to print a help message X`09`09 summarizing the action of all of its switches and X`09`09 giving the defaults for the more important ones. X X X So that, for instance, X X`09`09TPC BACKUP=MT: X X will create the file BACKUP (.TPC by default) from the magtape on MT:, and X X`09`09TPC MT:=BACKUP X X would then create an exact copy of the original magtape onto the tape X now mounted on MT:. X X Note that TPC will only handle one tape at a time and cannot handle X block sizes of greater than 4200 bytes without edit and rebuild. If X the tapes are FLX format tapes, however, the TPCDIR program (`5B312,315`5D) X may be used to list directories or extract copies of files in the X container file, though in a fairly cumbersone way. Otherwise, BIGTPC X acts as a format-independent tape copy to EOT (signalled by 2 consecutive X EOFs). X X CAVEAT: X It is possible for a FILES-11 tape to have 2 EOFs in a row where a zero X length file is copied, yet not be at EOT. X X If the tape you are copying may be of this sort, use the /ANSI X switch while copying (or the /EBCDIC switch if it came from an IBM site usi Vng X EBCDIC labels). This will allow TPC to correctly handle double EOFs in the X middle of a file. If your tape does not have this pathology, TPC will funct Vion X correctly also, so the /ANsi switch is a good one to set most all X the time unless you have some sort of pseudo-ANSI tape that may have X records starting with HDR2, EOV, or EOF. X X If your tape was produced by RT11 PIP (possibly also under RSTS), you may X need the /RT switch to successfully handle null files. The /ANsi switch is X now on by default; use /-AN to turn it off if you must. X`0C X TPC can report the following errors:- X X 1. TPC -- Disk I/O error. Code = n X X TPC encountered an error while reading from/writing to the disk. X X 2. TPC -- Magtape I/O error. Code = n X X TPC encountered an error while reading from/writing to the magtape. X X 3. TPC -- Command line input error X X TPC encountered an error in reading the command line. X X 4. TPC -- Command line syntax error X X TPC encountered an error when trying to parse the command line. X X 5. TPC -- Invalid switch X X The command line contained a switch that TPC could not recognise, X or a file specification that it could not parse. X X 6. TPC -- Open error on output file X X A file was specified as output, but TPC encountered an error when X it tried to open it. X X 7. TPC -- Open error on input file X X A file was specified as input, but TPC encountered an error when X it tried to open it. X X *** NOTE *** When using the /VE or /CM switches, TPC may be X forced to reverse the input and output LUNs in order to do the X compare operation. During the compare phase, the disk file X will always be the "output" device, even though it is being X read. X X 8. TPC -- Specify 1 file & 1 magtape device X X The command line either specified magtape as both input and output X device, or a disk file as both input and output device. X X 9. TPC -- Starting Verify pass. X X The /VE switch was specified and the compare operation has started. X X 10. TPC -- Compare OK. X X The compare operation specified by the /VE or /CM switches has X found the disk file and tape to be identical. X X 11. TPC -- Compare error. Files are different. X X During the compare operation specified by either the /VE or /CM X switches, the disk file and tape were not identical. X X 12. TPC -- /VE and /CM Not valid at same time. X X The Verify and Compare options may not be specified at the same X time. Use /VE to make a copy and verify it. Use /CM to verify X an existing copy. X X TPC tends to crash when it has an allocation failure while reading X tape to disk. This will be fixed in the next release, to be on the X Fall 1983 RSX/IAS tape. X X Any bugs, errors, or suggestions should be reported to the default X TPC maintainer. No guarantee is made that they will acted on, etc. X X`09Alan E. Frisbie X`09Flying Disk Systems X`093786 E. Mountain View Ave. X`09Pasadena, CA 91107 X X`09(213) 577-2579`09(Note: A forthcoming area code shuffle and an X`09`09`09 impending move will make this number obsolete X`09`09`09 by 31-Dec-83, at the latest.) $ CALL UNPACK TPC.DOC;2 826364069 $ create 'f' X1 TPCOPY X `1B`5B1mTPCOPY - Tape Copy Program X ==========================`1B`5B0m X X The TPCOPY program is a very flexible program which copies X between a mag-tape and a disk file. The disk file is a specially X formatted "container file" which contains the entire image of the X tape. The main use of TPCOPY is to duplicate tapes or to convert X a tape from one density to another. X X To use TPCOPY for duplicating tapes, you copy the "master" tape X to a container file on disk, then for each duplicate tape, copy X the container file out to the tape. X X To use TPCOPY for changing the density of a tape, read the tape X into a temporary container file, change the density setting on X the tape drive and then write the container file back out to X tape. Then `1B`5B1mdelete the temporary file`1B`5B0m. X X2 TAPE_TO_DISK X X `1B`5B1mTPCOPY - Tape to Disk Command Format X ====================================`1B`5B0m X X To copy a tape into a "container" file on disk, the command is: X X $ TPCOPY file=MSA0: X X where 'file' is the name you want to give to the container file. X If you are using TPCOPY to reformat a tape to another density, X you can name the file something like TEMP.TPC, so you'll know X it's a scratch file if you happen to see it a few days later and X you forgot to delete it. If you making a "master", such as a X CT*OS Demo Tape image, name the file CTOSDEMO.TPC, or something X that will jog your memory as to it's contents. There is no easy X way to look at the contents of a container file and determine X what is there. X X2 DISK_TO_TAPE X X `1B`5B1mTPCOPY - Disk to Tape Command Format X ====================================`1B`5B0m X X To recreate a tape from a TPCOPY "container" file, the command X looks like this: X X $ TPCOPY MSA0:=file X X where 'file' is the name of the container file. X X2 CHANGE_DENSITY X X `1B`5B1mTPCOPY - Changing Tape Density X ==============================`1B`5B0m X X To use TPCOPY to change the density of a tape, do the following X steps: X X $ ALLOCATE MSA0: X $ MOUNT/FOREIGN MSA0: X $ TPCOPY TEMP.TPC=MSA0: X $ X < At this point, go in and change the density on the tape > X $ TPCOPY MSA0:=TEMP.TPC X `1B`5B1m$ DELETE TEMP.TPC;*`1B`5B0m X $ DISMOUNT MSA0: X $ DEALLOCATE MSA0: X X That's all there is to it. Try to figure out what each step X does. $ CALL UNPACK TPC.HLP;1 292650598 $ create 'f' X`09.Enable`09lc X; X`09.TITLE`09TPC - TAPE/DISK COPY UTILITY X$VAX=1`09`09; Define version for very large tape records (11000 bytes) X; X`09.SBTTL`09Introduction X; X .IDENT /V01.75/ X; X`09.MCALL`09GCMLB$,GCML$,CSI$,CSI$1,CSI$2,CSI$SW,CSI$ND,DIR$,PUT$ X .MCALL FDBDF$,FDAT$R,NMBLK$,WTSE$S,GET$,EXIT$S,FINIT$`09;JKN02 X`09.MCALL`09QIOW$,OFNB$,CSI$SV,FSRSZ$ X`09.MCALL`09ALUN$S,CLOSE$ X`09.MCALL`09QIOW$S,ASTX$S,FDOP$R,QIO$S,CLEF$S,SETF$S X`09.NLIST`09BEX X;+ X; X; TPC -- Fast Tape/Disk/Tape Copy Utility X; X; Version 01.75 X; X; This routine will preserve any arbitrary format magtape in an image form X; on disk, or restore an image format file from disk to magtape. X; X; Its utility is its ability to drive the magtape at full speed. This X; feature is useful when making many copies of DOS-11 magtapes. The RSX-11 X; Files-11 file is compatible with FCS variable length, block spanned X; record mode. X; X; X; Reid L Brown`0927-Oct-77 X; X; Modified by: X; X;`09G H Cohen, 21-Aug-78 X;`091) Insert a default value for file allocation size. X;`092) Use .TRNCL in place of .CLOSE. X;`093) Provide a means for file extension. X;`094) Attach to magtape unit and set density to 800BPI. X; X;+AF1`09Alan E. Frisbie, 31-Jan-80 X;`09When moving error codes to MTERR or DSKERR, use MOVB instead of MOV, X;`09followed by a MOVB #-1 if the result is negative. This corrects the X;`09problem of error numbers being printed as a positive value. X; X;+AF2`09Alan E. Frisbie, 12-Mar-80 X;`09Enlarge buffer size to handle larrrrrrrge records (4200. bytes). X;`09This allows TPC to copy DSC and BRU tapes. X; X; gce02 Glenn C. Everhart, 15-Dec-81 X;`09Add /ANsi switch to check for EOV as 1st 3 bytes in 80 byte X;`09records seen. This should allow BIGTPC to copy ANSI tapes without X;`09errors due to null files. X; `09Add /SC:nnnnnn switch to allow one to set tape characteristics X;`09to nnnnnn (in RSX format) to handle really strange tape formats X;`09Add processing to write 4 extra EOFs on tape at EOV and back-space X;`09over all but 1 EOF to permit easy appending to FLX format tapes. X;`09(The 4 EOFs will allow TPC input to stop fully when reading X;`09the tapes in.) X;`09Add /EB switch as subset of /ANsi switch, specifying EBCDIC X;`09labels. Note that /AN will check for EITHER set X;`09depending on this but not both. X; X; gce03 Glen C. Everhart, 3-Jan-83 X;`09Add /RT11 switch to handle RT11 variant ANSI format (512 byte labels). X;`09Add /TR and /TW and associated logic for disk-disk copies in both X;`09directions. Improve help message to give defaults. Change default X;`09to /ANsi and make switches negatable. X; X; gce04 Glenn C. Everhart, (V01.40) X;`09Add /FLX:NAME switch to allow creation of pseudo-FLX-type label X;`09record in `5B1,1`5D on output tape. X; X; JKN01 Jim Neeland, (V01.44) X;`09Add tape device "MF" to list to support TU78's. X; X; GCE04 Glenn Everhart X;`09Conditional $VAX will define a "BIGGERTPC" to handle records up X;`09to 11000. bytes long (works fine on VAX). X; X;+AF3 Alan E. Frisbie, 11-May-83 (V01.50) X;`09Add /VE (Verify) and /CM (Compare) switches. X;`09Make TPC serially re-usable when switching Tape/Disk directions. X;`09Also do general cleanup of local symbols (using KED). X; X;JKN02 Jim Neeland, 3-Jun-83 (V01.51) X; Add call to FINIT$ so files don't go to/from `5B0,0`5D! X; X;GCE05 Glenn Everhart, 23-Jun-83 (V01.70) X;`09Add support for passing beyond the eov/eot to the double EOF X;`09beyond it (if any...) X; X;???00 Unknown X. Unknown, ??-???-?? (V01.71-V01.74) X;`09Various miscellaneous changes, including: X;`09`091) Add MU: and MA: to list of tape devices X;`09`092) Add /MI (Magtape In) and /MO (Magtape Out) switches X;`09`09 to force a device to be treated as a tape (useful X;`09`09 if new tape devices are ever defined). X; X;+AF4 Alan E. Frisbie, 26-Jun-91 (V01.75) X;`09Fix serious bug in AST routines: none of them ever saved X;`09R0-R5!!! Since only one AST routine could ever execute X;`09at a time (and the mainline code was suspended), this X;`09bug has gone undetected for 14 years. X;`09It finally bit me when I tried to go disk-to-tape from X;`09a high-speed caching disk controller. The first QIO X;`09completed (and triggered the AST) before the second QIO X;`09was issued. The registers were then clobbered, causing X;`09the remainder of the setup code to execute incorrectly. X; X;- X; X; Local MACROS X; X X`09.MACRO`09ERRMSG`09MESSAG,WHERE,?A,?B,?C X`09BR`09C XA:`09.ASCII`09`5EMESSAG`5E XB:`09.EVEN XC:`09MOV`09#A,QIO+Q.IOPL X`09MOV`09#B-A,QIO+Q.IOPL+2 X`09DIR$`09#QIO X`09.IIF`09DF,WHERE`09JMP`09WHERE X`09.ENDM`09ERRMSG X X`09.MACRO`09PAUSE X`09CLEF$S`09#16. X`09WTSE$S`09#16. X`09.ENDM`09PAUSE X X`09.MACRO`09RESUME X`09SETF$S`09#16. X`09.ENDM`09RESUME X X; X; Allocate FSR area X; X X`09FSRSZ$`093`09`09`09; Allocate 3 buffers X`09.page X`09.SBTTL`09CSI & FCS data & buffers X; X; File descriptor blocks & related information X; X XFDBST:`09`09`09`09; Start of FDB'S XFDBINP::FDBDF$`09`09`09; Define input FDB XFDBOUT::FDBDF$`09`09`09; Define output FDB XFDBEND:`09`09`09`09; End address of FDB'S X XGCMBLK:`09GCMLB$`093,TPC,,TILUN`09; Command line control block X XINDFN:`09NMBLK$`09TAPECOPY,TPC,,SY,0`09`09; Default input filename XOUTDFN:`09NMBLK$`09TAPECOPY,TPC,,SY,0`09`09; Default output filename X X; X; LUNS X; X XINLUN=`091`09`09`09; Input file on 1 XOUTLUN=`092`09`09`09; Output file on 2 XTILUN=`095`09`09`09; GCML & QIO'S to #5 (Default from TKB) X X; X; Command string interpreter X; X XCSIFLG:`09.WORD`090`09`09; Flag word for command switches X XHLPMSK=`091`09`09`09; /HE - Print help message XBLKMSK= 2`09`09`09; /BL - Allocate blocks XSALMSK= 4`09`09`09; /SA - Secondary allocation (blocks) XCONMSK= 10`09`09`09; /CO - Contiguous file XHDMSK=20`09`09`09; /HD - 1600 BPI tape I/O XNRMSK=40`09`09`09; /NR - No rewind before start XERMSK=100`09`09`09; /ER - Ignore errors (except end-tape, EOV) XSCMSK=200`09`09`09; /SC:NNNNNN set characteristics to NNNNNN (Octal) XEVMSK=400`09`09`09; /EV = Copy to EOV1/2, ignore IE.EOT/IE.EOV XANSFLG:`09.WORD`090`09; Flag nonzero for ANSI tapes XANSCNT:`09.WORD`090`09; Count of EOV1 or EOV2 records seen XHDRLVL:`09.WORD`090`09; Count bumped up by HDR2 and down by EOF2 or EOV2 X XCSISW:`09CSI$SW`09HE,HLPMSK,CSIFLG X`09CSI$SW`09BL,BLKMSK,CSIFLG,SET,NEG,ALCTAB X`09CSI$SW`09SC,SCMSK,CSIFLG,SET,NEG,SCTAB X`09CSI$SW`09SA,SALMSK,CSIFLG,SET,NEG,SALTAB X`09CSI$SW`09CO,CONMSK,CSIFLG,SET,NEG X`09CSI$SW`09EV,EVMSK,CSIFLG,SET,NEG`09;GCE05 X`09CSI$SW`09HD,HDMSK,CSIFLG,SET,NEG X`09CSI$SW`09NR,NRMSK,CSIFLG,SET,NEG X`09CSI$SW`09ER,ERMSK,CSIFLG,SET,NEG X`09CSI$SW`09AN,1,ANSFLG,SET,NEG X`09CSI$SW`09EB,2,ANSFLG,SET,NEG`09; /EBCDIC label flag X`09CSI$SW`09RT,4,ANSFLG,SET,NEG`09; /RT11 version of ANSI format X; X; New switches for counts X; allows copy of disk to disk X; /TR = Tape in reading to file X; /TW = Tape out writing tape from file X; either ==> disk-disk X; /SZ:NNNNN:MMMMM = Length (low:high) of copy if disk-disk X; /LO:NNNNN:MMMMM = Start blk (octal, lo:hi) of copy on nonfile disk X; /CT - Enable control accesses (density, etc.) X; X;gce04 new switches for image mode copy X; /IM:lo:hi:blkfct X;`09Where lo and hi are octal output blk # and blkfct is number of X; 512 byte blocks to buffer onto the output device (default 8.) X; X`09CSI$SW`09TR,1,D2DMSK,SET,NEG X`09CSI$SW`09TW,2,D2DMSK,SET,NEG X`09CSI$SW`09SZ,4,D2DMSK,SET,NEG,SZTAB X`09CSI$SW`09LO,10,D2DMSK,SET,NEG,LOTAB X`09CSI$SW`09FR,20,D2DMSK,SET,NEG`09; /FR = Rewind after end X`09CSI$SW`09CT,40,D2DMSK,SET,NEG X`09CSI$SW`09IM,100,D2DMSK,SET,NEG,IMTAB X`09CSI$SW`09FL,200,D2DMSK,SET,NEG,FLXNMB X`09CSI$SW`09NI,400,D2DMSK,SET,NEG`09; /NI = Input file read 512 bytes at X`09`09`09`09`09; a time (nibble in) X`09CSI$SW`09NO,1000,D2DMSK,SET,NEG`09; /NO = Output file write 512 bytes at X`09`09`09`09`09; a time (nibble out). X`09`09`09`09`09; /NI and /NO work only on /IM copies. X`09CSI$SW`09MI,1,TFAKMK,SET,NEG`09; /MI for Magtape In (override dev parse) X`09CSI$SW`09MO,1,TFAKMK,SET,NEG`09; /MO for Magtape Out (override dev parse) X`09CSI$SW`09CM,1,VFYMSK,SET,NEG`09;+AF3 /CM = Compare tape with existing fil Ve X`09CSI$SW`09VE,2,VFYMSK,SET,NEG`09;+AF3 /VE = Verify Tape/Disk transfers X; X; X`09CSI$ND X X X .GLOBL LOLO,LOHI,SZLO,SZHI,START,D2DMSK,FDBINP,FDBOUT,INVEC X .GLOBL OUTVEC,HELP,TPLHD,DSKLHD,DSKTTP,TPTDSK,MAGTST,WAIT X .GLOBL ERROR,TAPEIN,DSKOUT,TPDKDQ,DSKIN,TAPOUT,DKTPDQ,NODADD,NODDEL X; XALCTAB:`09CSI$SV`09DECIMAL,ALLOC,2 XSALTAB:`09CSI$SV`09DECIMAL,SALOC,2 XSCTAB:`09CSI$SV`09OCTAL,SCVAL,2 XSZTAB:`09CSI$SV`09OCTAL,SZLO,2 X`09CSI$SV`09OCTAL,SZHI,2 XLOTAB:`09CSI$SV`09OCTAL,LOLO,2 X`09CSI$SV`09OCTAL,LOHI,2 XIMTAB:`09CSI$SV`09OCTAL,IMLO,2 X`09CSI$SV`09OCTAL,IMHI,2 X`09CSI$SV`09DECIMAL,IMBF,2 XFLXNMB:`09CSI$SV`09ASCII,FLXNAM,6 X`09CSI$ND XFLXNAM:`09.ASCII`09/IMGFIL/ X; X; FLX type label block (To write if image mode copy to tape) X; XLBLBK:`09.RAD50`09/IMG/ X`09.RAD50`09/FIL/ X`09.RAD50`09/OLB/`09; Pick a file type FLX treats in image mode X`09.BYTE`091,1`09; UIC `5B1,1`5D X`09.WORD`09233`09; Standard DOS protection X`09.WORD`091`09; Forget the date of creation ... dunno how to do easily X`09.WORD`090`09; Spare in DOS, last 3 name chars in RSX FLX X; X; End of DOS label block X; XSCVAL:`09.WORD`090`09; charac. value. XALLOC:`09.WORD`09-100.`09; Allocation value `5B+/-`5D XSALOC:`09.WORD`09-50.`09; Secondary allocation value `5B+/-`5D XTFAKMK:`09.WORD`090`09; Tape fake mask XD2DMSK:`09.WORD`090 XSZHI:`09.WORD`090 XSZLO:`09.WORD`090`09; Length HI,LO words XLOHI:`09.WORD`090`09; Low blk # HI part XLOLO:`09.WORD`090`09; and low part XENDBK:`09.WORD`090,0`09; End logical block to use (sum of LO, size) XENDIO:`09.WORD`090,0`09; Count of I/O dones seen at AST entry XIMHI:`09.WORD`090 XIMLO:`09.WORD`090 XIMBF:`09.WORD`098.`09; Blocking factor XVFYMSK:`09.WORD`090`09;+AF3 Verify and Compare switches XCMPPAS:`09.WORD`090`09;+AF3 0 = Normal copy pass, -1 = Compare pass in pro Vgress XSWTDEV:`09.WORD`090`09;+AF3 0 = Nothing, -1 = Switch devices for compare p Vass X`09CSI$ XCSI:`09.BLKB`09C.SIZE`09`09; Define the CSI work area X`09.EVEN X`09.page X`09.SBTTL`09Help message & text X; X; Error message processing & help X; X XQIO::`09QIOW$`09IO.WVB,TILUN,1,,IOSTAT,,<.-.,.-.,40,.-.,.-.,.-.> XIOSTAT::.WORD`090,0 X XERRBUF:`09.BLKB`0980. X XHLPMSG: X.ASCIZ`09'TPC -`09Tape / Disk utility program' X.ASCIZ`09'`09This program will copy magtapes to RSX-11 disk' X.ASCIZ`09'`09files and record them in a special image mode.' X.ASCIZ`09'`09This allows very fast multiple copies of tapes to be made' X.ASCIZ`09'`09from the disk image (much faster than FLX).' X`09.IF`09NDF,$VAX X.ASCIZ`09'`09Maximum block size is 4200. bytes. per tape block.' X`09.IFF X.ASCIZ`09'`09Maximum block size is 11000. bytes. per tape block.' X`09.ENDC X.ASCIZ`09' ' X.ASCIZ`09'`09The command format is standard RSX-11:' X.ASCIZ`09' ' X.ASCIZ`09'`09`09TPC>outfile=infile`5B/BL:nnnn`5D`5B/SA:mmmm`5D`5B/CO`5D`5B/H VE`5D' X.ASCIZ`09'`09Where:' X.ASCIZ`09'`09`09-One "file" must be a magtape device' X.ASCIZ`09'`09`09/BL:nnnn = An optional allocation specification' X.ASCIZ`09'`09`09 if disk is the output device.' X.ASCIZ`09'`09`09/SA:mmmm = An optional secondary allocation amount' X.ASCIZ`09'`09`09 if disk is the output device.' X.ASCIZ`09'`09`09/CO = Disk file to be contiguous' X.ASCIZ`09'`09`09/HE = This help text' X.ASCIZ`09'`09`09/NR = Do not rewind tape before use' X.ASCIZ`09'`09`09/HD = Use high density (1600 BPI) on tape' X.ASCIZ`09'`09`09/ER = Ignore input tape errors except EOT/EOV/EOF' X.ASCIZ`09'`09`09/EV = Ignore End-Volume or End-Tape errors' X.ASCIZ`09'`09`09/AN = ANSI format tape, use EOV1 and EOV2 for endtape' X.ASCIZ`09'`09`09/EB = EBCDIC labels (requires /AN switch)' X.ASCIZ`09'`09`09/SC:nnnn Sets tape characteristics to nnnn (octal)' X.ASCIZ`09'`09`09/TR = Read disk as if tape, to file on output' X.ASCIZ`09'`09`09/TW = Write file to disk as if tape output' X.ASCIZ`09'`09`09/SZ:low:high = Size in blks of disk to read on /TR' X.ASCIZ`09'`09`09/LO:low:high = Low blk number to start with on' X.ASCIZ`09'`09`09`09nonfile disk' X.ASCIZ`09'`09`09/FR = Rewind tape after writing' X.ASCIZ`09'`09`09/RT = RT11 version of ANSI format (Not 80 byte lbls)' X.ASCIZ`09'`09`09/VE = Verify tape/disk transfer after copy' X.ASCIZ`09'`09`09/CM = Compare tape and existing disk file' X.ASCIZ`09'`09`09/MI = Magtape In (overrides device name recog.)' X.ASCIZ`09'`09`09/MO = Magtape Out (overrides device name recog.)' X.ASCIZ`09'`09`09/IM:lo:hi:blkfct = Image copy, output blk no (lo:hi)' X.ASCIZ`09'`09`09`09and block factor args (blkfct=8 default)' X.ASCIZ`09'`09Image mode subswitches:' X.ASCIZ`09'`09`09/FL:filnam = Create FLX label first on tape of' X.ASCIZ`09'`09`09`09filnam.OLB`5B1,1`5D<233>' X.ASCIZ`09'`09`09/CT = Include control QIOS even if dsk-dsk' X.ASCIZ`09'`09`09/NI = "Nibble copy" In (read input in 1 blk a time)' X.ASCIZ`09'`09`09/NO = "Nibble copy" Out (wrt output 1 blk at a time)' X.ASCIZ`09'`09Defaults: /AN/-HD/-EB/BL:100/SA:50/-CO/SZ:494.:0/LO:0:0/-CT' XHLPEND=`09. X`09.EVEN X XDSKERM:`09.ASCIZ`09'TPC -- Disk I/O error. Code=%D' XMTERM:`09.ASCIZ`09'TPC -- Magtape I/O error. Code=%D' XCMPERM:`09.ASCIZ`09'TPC -- Compare error. Files are different.' X X`09.EVEN X`09.page X`09.SBTTL`09Tape / disk data & tables X; X; Disk & tape operations are entirely AST driven, using linked lists to X; control the sequence of events to be followed. All buffers for both X; input & output operations are kept in linked lists by types (input or X; output) and are scanned at each AST to see what work needs to be done. X; X; The general format for a list node is: X; XN.FWD`09= 0`09; WD: 0`09`09`5B Link to next node`09`5D XN.BWD`09= 2`09; WD: 1`09`09`5B Link to prior node`09`5D XN.IOST`09= 4`09; WD: 2`09`09`5B I/O status word #0`09`5D X`09`09; WD: 3`09`09`5B I/O status word #1`09`5D XN.WRK`09= 10`09; WD: 4`09`09`5B Temporary work var.`09`5D XN.BUF`09= 12`09; WD: 5`09`09`5B Buffer address`09`5D XN.LEN`09= 14`09; WD: 6`09`09`5B Buffer length`09`09`5D XN.PTR`09= 16`09; WD: 7`09`09`5B Current buffer pointer`5D XN.BKH`09= 20`09; WD: 10`09`5B High order block no.`09`5D XN.BKL`09= 22`09; WD: 11`09`5B Low order block no.`09`5D XN.SIZE`09= 24`09; Size of node X; X X`09.IF`09NDF,$VAX XDSKBKS`09=`0920.`09`09;+AF2 No. of blocks in disk buffer X`09.IFF XDSKBKS`09=`098.`09`09; Use small disk buffer to allow big tape buffer X`09.ENDC XDSKBFS`09= DSKBKS*512.`09`09; Disk buffer size = 16 blocks XDSKBF0:`09.BLKB`09DSKBFS`09`09; Allocate 1st buffer XDSKBF1:`09.BLKB`09DSKBFS`09`09; & 2nd buffer X X`09.IF`09NDF,$VAX XTPBFS`09= 4200.+2`09`09;+AF2 Tape buffer size = 1 block + 1 word X`09.IFF XTPBFS=11000.+2. X`09.ENDC XTPBF0:`09.BLKB`09TPBFS`09`09; Tape buffer 1 XTPBF1:`09.BLKB`09TPBFS`09`09; Tape buffer 2 XTPBF2:`09.BLKB`09TPBFS`09`09; Tape buffer 3 X`09.IF`09NDF,$VAX XTPBF3:`09.BLKB`09TPBFS`09`09; Tape buffer 4 (Except for big tape buffers) XIMBFMX=<2*DSKBKS>+<4*> X`09.IFF XIMBFMX=<2*DSKBKS>+<3*> X`09.ENDC X .PRINT IMBFMX ;max buffer for /IM mode X; X; Control variables X; X XDSKFCT:`09.WORD`09DSKBKS`09`09; Disk blocking factor XINVEC:`09.WORD`090`09`09; Current input vector XOUTVEC:`09.WORD`090`09`09; Current output vector XOUTDVF:`09.WORD`090`09`09; Output device flag(-1 for magtape, 0 for disk) XINDVF:`09.WORD`090`09`09; Input device flag XMAGDEV:`09.WORD`09"MM,"MS,"MT,"MF,"MU,"MA,0 ; Magtape device list`09`09;JKN0 V1 XIOST:`09.WORD`090,0`09`09; I/O status block for simple QIO'S XFLAGS:`09.WORD`090`09`09; Disk & magtape flags XMTERR:`09.WORD`090`09`09; Magtape error value XDSKERR:`09.WORD`090`09`09; Disk error variable X; X; Literals for label string searches for /ANSI switch (modified to X; EBCDIC values if /EB switch seen) X; XLITEO:`09.ASCII`09/EO/ XLITF2:`09.ASCII`09/F2/ XLITVV:`09.ASCII`09/VV/ XLITHD:`09.ASCII`09/HD/ XLITR2:`09.ASCII`09/R2/ X; X; Flag values for disk & magtape flags X; XEOV`09= 1`09; End of volume seen XEOF`09= 2`09; End of file seen XERR`09= 4`09; Error encountered XDONE`09= 10`09; Transfer done XCMPERR`09= 20`09; Compare error X; X; VFYMSK flags X; XCMPFLG`09= 1`09; Do a compare XVFYFLG`09= 2`09; Do a verify after this copy X; X`09.page X; X; Disk node list X; X XDSKLHD:`09.WORD`09DSKLHD`09`09; Disk node listhead, forward pointer X`09.WORD`09DSKLHD`09`09; & backward pointer X`09`09`09`09; NOTE: listhead & lists must remain together X XDSKLST:`09.WORD`090,0,0,0,0,DSKBF0,DSKBFS,DSKBF0,0,0`09; Disk node #0 X`09.WORD`090,0,0,0,0,DSKBF1,DSKBFS,DSKBF0,0,0`09; Disk node #1 XDSKLND=`09. X X; X; Tape node list X; X XTPLHD:`09.WORD`09TPLHD`09`09; Tape node listhead address, forward pointer X`09.WORD`09TPLHD`09`09; & backward pointer X XTPLST:`09.WORD`090,0,0,0,0,TPBF0,TPBFS,0,0,0`09`09; Tape buffer #0 X`09.WORD`090,0,0,0,0,TPBF1,TPBFS,0,0,0`09`09; Tape buffer #1 X`09.WORD`090,0,0,0,0,TPBF2,TPBFS,0,0,0`09`09; Tape buffer #2 X`09.IF`09NDF,$VAX X`09.WORD`090,0,0,0,0,TPBF3,TPBFS,0,0,0`09`09; Tape buffer #3 X`09.ENDC XTPLND=`09. X`09.page X`09.SBTTL`09Parse input specification & choose action X X; X; Get command line, parse it & start all files X; X XBEGIN: FINIT$ ;JKN02 Once-only call to init FCS use XSTART: X`09CLR`09VFYMSK`09`09;+AF3 Clear VErify and CoMpare switches X`09CLR`09CMPPAS`09`09;+AF3 Set normal copy pass operation XSTART2: X`09CLR`09SWTDEV`09`09;+AF3 Clear switch-device flag X`09BIT`09#VFYFLG,VFYMSK`09;+AF3 Second time thru, do a verify? X`09BEQ`0910$`09`09;+AF3 No, skip X`09MOV`09#-1,CMPPAS`09;+AF3 Yes, set compare-pass flag X`09CLR`09VFYMSK`09`09;+AF3 Make sure we only do it once X`09ERRMSG`09`09;Not really an error... X10$: X`09ALUN$S`09#TILUN,#"TI,#0`09; Ensure terminal assigned on TILUN X`09CALL`09CLOSE`09`09; Insure all files are closed (ignore errors) XSTART3: X`09MOV`09#DSKLHD,DSKLHD X`09MOV`09#DSKLHD,DSKLHD+2`09; set up queues X`09MOV`09#TPLHD,TPLHD X`09MOV`09#TPLHD,TPLHD+2`09`09; anew in case screwed up before X`09MOV`09#FDBST,R0`09; Point to the first FDB X10$:`09CLR`09(R0)+`09`09; Clear out the file descriptor blocks X`09CMP`09R0,#FDBEND`09; At end yet? X`09BLO`0910$`09`09; No - continue X`09MOV`09#"EO,LITEO`09; Set up ANSI search literals X`09MOV`09#"F2,LITF2 X`09MOV`09#"VV,LITVV X`09MOV`09#"HD,LITHD X`09MOV`09#"R2,LITR2 X`09MOV`09#1,ANSFLG`09; Say ANSI mode`09;GCE02 X`09CLR`09ANSCNT`09`09; and zero ANSI EOVs seen ;GCE02 X`09CLR`09HDRLVL`09`09; Zero header level counter X`09CLR`09CSIFLG`09`09; Reset the command string flags X`09CLR`09INDVF`09`09; Reset input device type X`09CLR`09OUTDVF`09`09; Reset output device type X`09MOV`09#-100.,ALLOC`09; Reset the allocation amount X`09MOV`09#-50.,SALOC`09; Reset the secondary allocation X`09CLR`09D2DMSK X`09CLR`09TFAKMK`09`09; Zero aux flag words X`09.IF`09NDF,$$$PRO X`09MOV`09#494.,SZLO`09; Default RX01 size for /SZ X`09.IFF X`09MOV`09#800.,SZLO`09; Default RX50 size for /SZ (PRO 350) X`09.ENDC X`09CLR`09SZHI X`09CLR`09LOLO X`09CLR`09LOHI`09`09; Start with blk 0 X`09CLR`09IMHI X`09CLR`09IMLO X.IF GE, IMBFMX-8. XIMMM=8. X.IFF XIMMM=IMBFMX X.ENDC X.PRINT IMMM ; Default /IM blk factor X`09MOV`09#IMMM,IMBF`09; Set block factor default for /IM copy X`09TST`09CMPPAS`09`09;+AF3 Is this a compare pass? X`09BNE`0930$`09`09;+AF3 Yes, don't read a command line - use old one X`09GCML$`09#GCMBLK`09`09; Read a command line X`09BCC`0930$`09`09; Continue if no errors X`09CMPB`09#GE.EOF,G.ERR(R0) ; End of command input? X`09BNE`0920$`09`09; No - command input error X`09EXIT$S X X20$:`09ERRMSG`09 X`09JMP`09START X X30$:`09CSI$1`09#CSI,GCMBLK+G.CMLD+2,GCMBLK+G.CMLD ; Parse command line X`09BCC`0950$`09`09; Continue if no errors X40$:`09ERRMSG`09 X`09JMP`09START X; X; Now that we have a valid command line, parse it to get any combination X; of switches on both input and output sides. X; X50$: X`09Tst`09CMPPAS`09`09;+AF3 Are we already in a compare pass? X`09BNE`0958$`09`09;+AF3 Yes -- skip this stuff X; X`09CSI$2`09R0,INPUT,#CSISW`09;+AF3 Parse just for /CM & /VE switches X`09CSI$2`09R0,OUTPUT,#CSISW ;+AF3 Parse just for /CM & /VE switches X`09CMP`09#CMPFLG!VFYFLG,VFYMSK`09;+AF3 Both compare and verify specified? X`09BNE`0952$`09`09;+AF3 No, OK X`09ERRMSG`09,START X52$: X`09BIT`09#CMPFLG,VFYMSK`09;+AF3 Does the user want to compare tape/file?? X`09BEQ`0954$`09`09;+AF3 NO, Skip X`09MOV`09#-1,CMPPAS`09;+AF3 YES, Set compare pass flag X`09CLR`09VFYMSK`09`09;+AF3 and remove switches X54$: X`09CSI$1`09#CSI,GCMBLK+G.CMLD+2,GCMBLK+G.CMLD ;+AF3 Re-parse command line X; X58$: X; X`09TST`09SWTDEV`09`09;+AF3 Do we need to switch input & output for compare? X`09BEQ`0960$`09`09;+AF3 NO, thank god X`09CSI$2`09R0,INPUT,#CSISW`09;+AF3 For compare, magtape must be the input de Vvice X`09BR`0988$`09`09;+AF3 Continue X60$: X`09CSI$2`09R0,OUTPUT,#CSISW ; Parse output filespec & switches X88$: X`09BCC`0995$`09`09; No errors - continue X90$: X`09ERRMSG`09 X`09JMP`09START X X95$:`09BITB`09#,C.STAT(R0) X`09BEQ`0998$`09`09;+AF3 OK, skip X`09Jmp`0940$`09`09;+AF3 Report error X98$: X; X; Set up /EBCDIC subliterals if /EB switch was seen X; X`09BIT`09#2,ANSFLG`09; Did he set the /EBCDIC switch? X`09BEQ`09100$`09`09; If EQ no X`09BIS`09#1,ANSFLG`09; If so force ON /ANSI switch X`09MOV`09#153305,LITEO`09; Set up EBCDIC literals for label text X`09MOV`09#171306,LITF2 X`09MOV`09#162745,LITVV X`09MOV`09#142310,LITHD X`09MOV`09#171331,LITR2 X100$: X`09BIT`09#4,ANSFLG`09; /RT11 switch set? X`09BEQ`09110$`09`09; If EQ no X`09MOV`09#"F1,LITF2 X`09MOV`09#"R1,LITR2`09; Look for HDR1, EOF1 if so X110$: X`09BIT`09#HLPMSK,CSIFLG`09; Did the user want help? X`09BEQ`09120$`09`09; No - continue X`09JMP`09HELP`09`09; Give him help X X120$: X`09BIT`09#CONMSK,CSIFLG`09; Is file to be contiguous? X`09BNE`09150$`09`09; If NE, yes X`09TST`09ALLOC`09`09; Is ALLOC negative? X`09BMI`09160$`09`09; If yes, skip X`09NEG`09ALLOC`09`09; Negate it X`09BR`09160$ X150$:`09TST`09ALLOC`09`09; Is ALLOC positive? X`09BPL`09160$`09`09; If yes skip X`09NEG`09ALLOC`09`09; Negate it X160$:`09BNE`09170$`09`09; (Always allocate something!) X`09MOV`09#200.,ALLOC`09; Start at 200 at least X170$:`09TST`09SALOC`09`09; But never let SALOC remain negative X`09BPL`09180$`09`09; If positive, skip X`09NEG`09SALOC`09`09; Negate it X180$:`09BNE`09190$`09`09; Also always have a secondary alloc. X`09MOV`09#50.,SALOC X190$:`09FDAT$R`09#FDBOUT,#R.VAR,#FD.CR,,ALLOC,SALOC ; Init the FDB X`09FDOP$R`09R0,#OUTLUN X`09MOV`09R0,R1`09`09; R1 = Filename block address X`09ADD`09#F.FNB,R1`09; ... X`09MOV`09#CSI+C.DSDS,R2`09; R2 = Dataset descriptor X`09MOV`09#OUTDFN,R3`09; R3 = Default filename address X`09BIT`09#102,D2DMSK X`09BEQ`09200$`09`09; Normal if not dsk-dsk X`09CALL`09.PRSDV`09`09; Parse device info X`09BR`09210$ X200$:`09CALL`09.GTDID`09`09; Get default directory ;GCE03 X`09CALL`09.PARSE`09`09; Parse the filename block info X210$:`09BCS`09250$`09`09; Error on parse X`09BIT`09#102,D2DMSK`09; Is this writing a "tape" (really disk?) X`09BNE`09220$`09`09; If so forget device name check X`09BIT`09#2,TFAKMK`09; Is output tape via /MO switch? X`09BNE`09220$`09`09; If NE yes, go flag it so. X`09CALL`09MAGTST`09`09; Test for magtape device X`09BCC`09230$`09`09; Output file is disk - open it X220$:`09DEC`09OUTDVF`09`09; Output is magtape - so indicate X; X; X;+AF3 Here we do something really crazy. Rather than write the compare X;+AF3 code for both tape-to-disk and disk-to-tape, I wrote it only for X;+AF3 tape-to-disk. When a compare (verify) is called for when the X;+AF3 user specifies disk-to-tape, we simply switch the output and input X;+AF3 devices. X;+AF3 X;+AF3 This is done by testing to see if the output device is a disk. X;+AF3 If not, a flag is set and the command line is re-parsed with CSI$2 X;+AF3 called with "OUTPUT" and "INPUT" reversed. Clever, huh? X;+AF3 I was afraid you would say that. Oh well, at least it seems to wor Vk. X; X`09TST`09CMPPAS`09`09;+AF3 Doing compare operation now? X`09BEQ`09260$`09`09;+AF3 No, skip X`09MOV`09#-1,SWTDEV`09;+AF3 Set Switch Device flag X`09JMP`09START3`09`09;+AF3 and go parse the command line again X`09`09`09`09;+AF3 with input and output devices switched X; X230$: X`09TST`09CMPPAS`09`09;+AF3 Doing compare pass? X`09BEQ`09240$`09`09;+AF3 NO, normal copy X`09OFNB$`09R0,#FO.RD,#OUTLUN,,,#FD.RWM`09;+AF3 Open for read during compare X`09BCC`09270$`09`09;+AF3 Skip if OK X`09BR`09250$`09`09;+AF3 else error X240$: X`09OFNB$`09R0,#FO.WRT,#OUTLUN,,,#FD.RWM X`09BCC`09260$`09`09; Continue if no errors X250$:`09ERRMSG`09 X`09JMP START X X260$:`09MOV`09#1002,F.RSIZ(R0) ; Init the record size in FDB X`09CLR`09F.FFBY(R0)`09; Indicate next block empty X270$: X`09TST`09SWTDEV`09`09;+AF3 Do we need to switch input & output? X`09BEQ`09280$`09`09;+AF3 No, thank god X`09CSI$2`09#CSI,OUTPUT,#CSISW`09;+AF3 For compare, disk must be output devic Ve X`09BR`09290$`09`09;+AF3 Continue X280$: X`09CSI$2`09#CSI,INPUT,#CSISW ; Parse input file & switches X290$: X`09BCC`09300$`09`09; No error if carry clear X`09JMP`0990$`09`09; Report switch error X300$:`09BITB`09#,C.STAT(R0) ; No wildcards, etc allowed X`09BEQ`09310$`09`09; OK - continue X`09JMP`0940$`09`09; Report it as error X310$:`09BIT`09#HLPMSK,CSIFLG`09; Did he want help? X`09BEQ`09320$`09`09; No - continue X`09JMP`09HELP`09`09; Yes - give him help X X320$:`09FDOP$R`09#FDBINP,#INLUN,,#INDFN`09; Declare LUN to input FDB X`09MOV`09R0,R1`09`09; R1 = FNB address X`09ADD`09#F.FNB,R1`09; ... X`09MOV`09#CSI+C.DSDS,R2`09; R2 = Dataset descriptor X`09MOV`09#INDFN,R3`09; R3 = Default filename X`09BIT`09#101,D2DMSK X`09BEQ`09330$ X`09CALL`09.PRSDV X`09BR`09340$ X330$:`09CALL`09.GTDID`09`09; Get default directory X`09CALL`09.PARSE`09`09; Parse the filename block data X340$:`09BCS`09360$`09`09; Error on parse X`09BIT`09#101,D2DMSK`09; Is the input a disk looking like a tape? X`09BNE`09350$`09`09; If so, flag for later X`09BIT`09#1,TFAKMK`09; /MI switch force us to treat IN as tape? X`09BNE`09350$`09`09; If NE yes, go treat IN as tape. Skip test. X`09CALL`09MAGTST`09`09; See if this is magtape X`09BCC`09370$`09`09; No - try to open the file X350$:`09DEC`09INDVF`09`09; Indicate input device is magtape X`09BR`09380$`09`09; Continue X360$:`09ERRMSG`09 X`09JMP`09START X X370$:`09OFNB$`09R0,#FO.RD,,#INLUN,,,#FD.RWM`09; (If not magtape) X`09BCS`09360$`09`09; Error on open X X; X; Determine whether we have correct combination of disk & magtape devices: X; i.e. 1 disk & 1 magtape X; X X380$:`09MOV`09OUTDVF,R0`09; R0 = Output device flag X`09MOV`09INDVF,R1`09; R1 = Input device flag X`09BIT`09#100,D2DMSK X`09BNE`09390$`09`09; /IM copy is both devices. X`09XOR`09R0,R1`09`09; If not -1, then we have 2 of a kind! X`09BMI`09390$`09`09; Good! - continue X`09ERRMSG`09,START X X390$: X; X; Set up ENDBK block X; X`09MOV`09LOLO,ENDBK+2 X`09MOV`09LOHI,ENDBK X`09ADD`09SZLO,ENDBK+2 X`09ADC`09ENDBK X`09ADD`09SZHI,ENDBK`09; Now have ENDBK as (HI,LO) as QIO$ needs. X`09MOV`09LOLO,ENDIO+2`09; Copy start blk # for count of done I/O'S X`09MOV`09LOHI,ENDIO X`09BIT`09#100,D2DMSK`09; /IMage mode? X`09BNE`09410$`09`09; If so handle specially X`09TST`09CMPPAS`09`09;+AF3 Compare pass? X`09BNE`09400$`09`09;+AF3 Handled as special case of tape-to-disk X`09TST`09R0`09`09; Which was it? X`09BPL`09400$`09`09; Output is disk X`09JMP`09DSKTTP`09`09; Output is magtape X400$:`09JMP`09TPTDSK`09`09; Tape-to-disk X410$:`09JMP`09IMGMOD`09`09; Image mode copy X`09.page X; X; MAGTST - Subroutine to test for magtape as the redirected device which X;`09 was assigned in the filename block. X; X XMAGTST:`09MOV`09#MAGDEV,R5`09; Point R5 to device list X X10$:`09CMP`09(R5)+,N.DVNM(R1); Test device name field of filename block X`09BEQ`0920$`09`09; Got it! - It's magtape (set carry) X`09TST`09(R5)`09`09; Any more entries? X`09BNE`0910$`09`09; Yes - continue X`09RETURN X20$:`09SEC`09`09`09; Indicate magtape X`09RETURN X; X; CLOSE - Close files at end of run X; XCLOSE: X`09TST`09INDVF`09`09; Input device a file? X`09BNE`0910$`09`09; If NE, no - don't close it X`09CLOSE$`09#FDBINP`09`09; Close input file X`09BR`0920$`09`09; Check output file X10$: X`09QIOW$S`09#IO.KIL,#INLUN,#1`09; Else kill I/O just in case X`09QIOW$S`09#IO.DET,#INLUN,#1`09;+AF3 and Detach from the tape X20$: X`09TST`09OUTDVF`09`09; Is output device a file? X`09BNE`0930$`09`09; If NE no, don't close it X`09MOV`09#FDBOUT,R0`09; Point to output FDB X`09CALL`09.TRNCL`09`09; Truncate and close it X`09BR`0940$`09`09; Exit X30$: X`09QIOW$S`09#IO.KIL,#OUTLUN,#1`09; Else kill I/O just in case X`09QIOW$S`09#IO.DET,#OUTLUN,#1`09;+AF3 and Detach from the tape X40$: X`09RETURN X; X; X; X; HELP - List out the help text on TI: X; X XHELP:`09MOV`09#HLPMSG,R0`09; R0 = Help message text address X`09MOV`09#40,QIO+Q.IOPL+4; Set the CC-Type to CR-LF X; X10$:`09MOV`09R0,QIO+Q.IOPL`09; Put the address in the DPB X`09MOV`09R0,R1`09`09; Save the beginning address in R1 X; X20$:`09TSTB`09(R0)+`09`09; Scan to null at end X`09BNE`0920$`09`09; Continue till NULL character X`09MOV`09R0,R2`09`09; R2 = Ending line address + 1 X`09DEC`09R2`09`09; Backup to end of line X`09SUB`09R1,R2`09`09; R2 = Length of line X`09MOV`09R2,QIO+Q.IOPL+2`09; Put length in QIO DPB X`09DIR$`09#QIO`09`09; Output the line X`09CMP`09R0,#HLPEND`09; Any more text to go? X`09BLO`0910$`09`09; Yes - continue X`09JMP`09START X`09.page X`09.SBTTL`09Wait code & error processing X; X; WAIT-`09Processing of normal code suspends itself here after initiating X;`09the tape copy operation. All work is done via AST routines, and X;`09is completely 'interrupt' driven. When an error occurs, or the X;`09transfer is finished, the main program is 'resumed'. It must then X;`09check for any errors encountered in the AST routines. X; X; XWAIT:`09PAUSE`09`09`09; Wait for processing to complete X`09BIT`09#ERR,FLAGS`09; Any errors ? X`09BNE`0920$`09`09; Yes - process it X`09TST`09CMPPAS`09`09;+AF3 In compare pass? X`09BEQ`0910$`09`09;+AF3 No - do restart X`09ERRMSG`09`09;+AF3 Not really an error message X`09JMP`09START`09`09;+AF3 Just finished compare pass - do original start X10$: X`09JMP`09START2`09`09;+AF3 Restart X X20$:`09MOV`09#DSKERM,R1`09; Assume a disk error X`09MOV`09DSKERR,-(SP)`09; Put error code on stack X`09BEQ`0930$`09`09; No code - not disk error X`09JMP`09ERROR`09`09; Go process error X X30$:`09MOV`09#MTERM,R1`09; Setup magtape error message X`09MOV`09MTERR,(SP)`09; & error code X`09BEQ`0940$`09`09;+AF3 No code - not magtape error X`09JMP`09ERROR`09`09; Process the error X; X; X40$: X`09MOV`09#CMPERM,R1`09;+AF3 Point to compare error message X`09MOV`09#0,(SP)`09`09;+AF3 Null parameter X`09JMP`09ERROR`09`09;+AF3 Process error message X X X; X; ERROR-Process error messages. This routine outputs error messages to X;`09the users terminal using $EDMSG. The pattern string is assumed X;`09to be pointed to by R1, and the error code on the stack. This X;`09routine should be passed control via`09'JMP`09ERROR'. X; X XERROR:`09MOV`09#ERRBUF,R0`09; R0 = Output buffer pointer X`09MOV`09SP,R2`09`09; R2 = Parameter pointer X`09CALL`09$EDMSG`09`09; Edit the message X`09MOV`09#ERRBUF,QIO+Q.IOPL`09; Setup the QIO DPB X`09MOV`09R1,QIO+Q.IOPL+2`09`09; ... X`09TST`09(SP)+`09`09; Pop the parameter from the stack X`09DIR$`09#QIO`09`09; Output it X`09JMP`09START`09`09; Restart X`09.page X`09.SBTTL`09Tape to disk operations X; X; Tape to disk X; X;`09This function initiates a transfer sequence from the tape drive X;`09to the disk file. The tape is rewound prior to the start of X;`09the copy, and all operations are multi-buffered. X; X XTPTDSK:`09CLR`09FLAGS`09`09; RESET ALL FLAGS X`09CLR`09DSKERR`09`09; RESET DISK ERROR VALUE X`09CLR`09MTERR`09`09; & MAGTAPE ERROR VALUE X`09MOV`09#TAPEIN,INVEC`09; SETUP AST VECTORS X`09MOV`09#DSKOUT,OUTVEC`09; ... X`09BIT`09#3,D2DMSK`09;SEE IF CONTROL QIOS ARE CORRECT X`09BEQ`0910$`09`09;IF SO LEAVE IN X`09BIT`09#40,D2DMSK`09;SEE IF WANTED EVEN THO' DISK-DISK X`09BEQ`0950$`09`09;IF NOT,SKIP 'EM X10$: X`09QIOW$S`09#IO.ATT,#INLUN,#1`09; ATTACH TO TAPE UNIT X`09BIT`09#NRMSK,CSIFLG`09;DID HE WANT TO SKIP THE REWIND? X`09BNE`0920$`09`09;IF SO, SKIP REWIND X`09QIOW$S`09#IO.RWD,#INLUN,#1`09; REWIND THE MAGTAPE X20$:`09CLR`09R0`09`09;SET 800 BPI DENSITY INITIALLY X`09BIT`09#HDMSK,CSIFLG`09;DID HE SAY HIGH DENSITY? X`09BEQ`0930$`09`09;IF NOT LEAVE AT 800 BPI X`09MOV`09#4000,R0`09;IF SO, SET 1600 BPI X30$:`09BIT`09#SCMSK,CSIFLG`09;WAS THE /SC:NNNNNN SWITCH USED? X`09BEQ`0940$`09`09;IF NOT JUST SET CHARACTS. X`09BIS`09SCVAL,R0`09;ELSE OR IN CHARACTERISTICS WANTED X40$: X`09QIOW$S`09#IO.STC,#INLUN,#1,,,, ; SET TO 800BPI OR 1600 BPI X50$: X; X; INITIALIZE & PLACE ALL DISK BUFFERS IN THE QUEUE X; X X`09MOV`09#DSKLHD,R0`09; R0 = DISK BUFFER LISTHEAD X`09MOV`09R0,R4`09`09; R4 = SAVED LISTHEAD ADDRESS X`09MOV`09R4,(R0)+`09; SETUP A NULL LISTHEAD X`09MOV`09R4,(R0)+`09; ... X`09`09`09`09; NOTE: THE LISTHEAD & LISTS MUST BE TOGETHER! X X60$:`09MOV`09R0,R5`09`09; R5 = BUFFER NODE ADDRESS X`09CALL`09NODADD`09`09; ADD IT TO DISK QUEUE X`09MOV`09N.BUF(R5),N.PTR(R5)`09; UPDATE POINTER TO BUFFER START X`09ADD`09#N.SIZE,R0`09; R0 = NEXT POINTER X`09CMP`09R0,#DSKLND`09; AT END OF LIST YET? X`09BLO`0960$`09`09; NO - CONTINUE X X; X; INITIALIZE TAPE BUFFER LISTHEAD TO NULL, AND INITIATE I/O TO THE TAPE X; DRIVE FOR EVERY AVAILABLE BUFFER NODE IN ORDER TO START THE PROCESS GOING. X; X X`09MOV`09#TPLHD,R0`09; R0 = TAPE LISTHEAD ADDRESS X`09MOV`09R0,R1`09`09; R1 = SAVED LISTHEAD ADDRESS X`09MOV`09R1,(R0)+`09; INITIALIZE THE LISTHEAD TO NULL X`09MOV`09R1,(R0)+`09; ... X X80$:`09MOV`09R0,R1`09`09; R1 = COPY OF NODE ADDRESS X`09CLR`09N.PTR(R0)`09; RESET THE POINTER VALUE X`09ADD`09#N.IOST,R1`09; R1 = IO STATUS ADDRESS X`09MOV`09R1,R2`09`09; R2 = " "`09 " X`09ADD`09#N.BUF-N.IOST,R1; POINT R1 TO BUFFER ADDRESS CELL X`09MOV`09(R1)+,R3`09; R3 = BUFFER ADDRESS X`09TST`09(R3)+`09`09; ADVANCE BEYOND 1ST WORD X`09MOV`09(R1),R4`09`09; & GET BUFFER SIZE X`09SUB`09#2,R4`09`09; DECREASE BY TWO TO ACCOUNT FOR R3 OFFSET X`09BIT`09#1,D2DMSK`09;READING DISK, NOT REAL TAPE? X`09BEQ`0985$`09`09;IF EQ NO, NORMAL X`09MOV`09#512.,R4`09;ELSE SET 1BLOCK SIZE OF BUFFER X85$: X`09QIO$S`09#IO.RLB,#INLUN,,,R2,INVEC,;READ THE BLOCK X`09BIT`09#3,D2DMSK X`09BEQ`0995$`09`09;IF NOT DSK-DSK OMIT COUNT HERE X`09ADD`09#1,LOLO X`09ADC`09LOHI`09`09;THEN COUNT UP THE BLOCK NUMBER X95$:`09ADD`09#N.SIZE,R0`09; R0 = ADDRESS OF NEXT BUFFER NODE X`09CMP`09R0,#TPLND`09; ANY MORE TAPE BUFFERS? X`09BLO`0980$`09`09; YES - CONTINUE X`09TST`09CMPPAS`09`09;+AF3 Doing compare pass? X`09BNE`09100$`09`09;+AF3 Yes, skip to startup disk stuff X`09JMP`09WAIT`09`09;+AF3 No - go wait for I/O Done X100$: X; X; X; HERE IS WHERE WE START UP THE DISK READS WHEN DOING A COMPARE OPERATION X; X; X`09MOV`09#DSKIN,OUTVEC`09;+AF3 Setup AST vector X X; X; INITATE DISK I/O OPERATIONS FOR ALL AVAILABLE DISK BUFFERS X; X X`09MOV`09#DSKLHD,R0`09; R0 = DISK LISTHEAD POINTER X`09MOV`09R0,R1`09`09; R1 = SAVE LISTHEAD ADDR X`09MOV`09R1,(R0)+`09; INITIATE THE LISTHEAD TO NULL X`09MOV`09R1,(R0)+`09; ... X X110$:`09MOV`09N.BUF(R0),R2`09; R2 = BUFFER ADDRESS X`09MOV`09R2,N.PTR(R0)`09; INIT THE BUFFER POINTER X`09MOV`09N.LEN(R0),R3`09; R3 = LENGTH OF READ X`09MOV`09R0,R1`09`09; R1 = IO STATUS BLOCK ADDR X`09ADD`09#N.IOST,R1`09; ... X`09MOV`09#FDBOUT,R5`09; R5 = INPUT FDB ADDRESS X`09QIO$S`09#IO.RVB,#OUTLUN,,,R1,OUTVEC, X`09ADD`09DSKFCT,F.BKVB+2(R5) ; UPDATE THE NEXT BLOCK NO. X`09ADC`09F.BKVB(R5)`09; ... X`09ADD`09#N.SIZE,R0`09; ADVANCE TO NEXT BUFFER NODE X`09CMP`09R0,#DSKLND`09;+AF3 Past end? X;????`09CMP`09R0,#DSKLND`09;+AF3 Past end? X`09BLO`09110$`09`09; CONTINUE IF IN RANGE X`09JMP`09WAIT`09`09; ELSE GO WAIT FOR XFER TO COMPLETE X`09.page X`09.SBTTL`09TAPEIN`09- Tape input AST X; X; TAPEIN - Handle tape input AST X; X X`09.GLOBL`09TAPEIN,FLAGS XTAPEIN: X`09JSR`09R5, ASTQIO`09;+AF4 Save registers & call us back with X`09`09`09`09;+AF4 AST parameter in R3 X`09MOV`09R3, R5`09`09;+AF4 R5 = I/O STATUS ADDRESS X`09BIT`09#,FLAGS`09; ERROR OR END FLAGGED? X`09BEQ`0910$ X`09JMP`09180$`09`09; YES - GET OUT X10$: X`09ADD`09#1,ENDIO+2`09;COUNT BLKS FINISHED X`09ADC`09ENDIO X`09BIT`09#1,D2DMSK`09;SKIP UNLESS DSK-DSK X`09BEQ`0920$ X`09CMP`09ENDIO,ENDBK`09;HI PAST END? X`09BHI`0995$`09`09;IF SO TREAT AS EOF X`09BLO`0920$`09`09;IF LO ALLS WELL X`09CMP`09ENDIO+2,ENDBK+2`09;LO BLK # PAST OR AT END? X`09BHI`0995$`09`09;IF SO TREAT AS EOF X20$: X`09MOV`09N.BUF-N.IOST(R5),R4 ; R4 = BUFFER ADDRESS X`09BIT`09#ERMSK,CSIFLG`09;IGNORING ERRORS? X`09BEQ`0930$`09`09;IF NOT, LOOK AT ALL. X`09CMPB`09#IE.EOF,@R5`09;WAS IT ENDFILE??? X`09BEQ`0930$`09`09;YES, LEAVE THAT 'ERROR' X; X;gce05 - If ignoring EOV,EOT errors just treat as OK... X; X`09BIT`09#EVMSK,CSIFLG`09;IGNORING IE.EOT,IE.EOV? X`09BNE`0924$`09`09;IF NE YES, SKIP TEST... X`09CMPB`09#IE.EOT,@R5 X`09BEQ`0930$`09`09; Skip if End-Of-Tape X`09CMPB`09#IE.EOV,@R5 X`09BEQ`0930$`09`09; or End-Of-Volume X24$: X`09CMPB`09#IE.PRI,@R5 X`09BEQ`0930$`09`09; or if tape dismounted X; X; Make all other errors be ignored... X; X`09MOVB`09#IS.SUC,@R5`09; YES, SAY ALL WAS OK X30$: XANST00==. X`09TSTB`09(R5)`09`09; ERROR ON I/O? X`09BMI`0985$`09`09; IF MI YES, GO HANDLE IT X; X; HERE WE CHECK FOR SPECIAL ANSI LABEL RECORDS. X; RECORD LENGTH MUST BE 80. BYTES ON INPUT AND TEXT OF FIRST X; 3 OR 4 CHARACTERS IN THE RECORD IS CHECKED.`09;GCE02 X; XANST01==. X`09BIT`09#1,ANSFLG`09; /ANSI SWITCH SEEN `09;GCE02 X`09BEQ`09130$`09`09; IF EQ NO, JUST PROCESS DATA X; X; SEE IF THIS WAS AN "EOV" RECORD. R4 POINTS TO DATA AREA. X; BE SURE RECORD LENGTH IS 80 BYTES FIRST. X; X`09BIT`09#4,ANSFLG`09;/RT11 ANSI? (512 BYTE HEADERS) X`09BNE`0940$`09`09; IF SO IGNORE LENGTH FOR CHECKS X`09CMP`092(R5),#80.`09; WAS THE RECORD AN 80 BYTE ONE? X`09BNE`09130$`09`09; IF NOT CAN'T BE AN ANSI EOV LABEL X40$:`09CMP`092(R4),LITEO`09; CHECK FOR FIRST 2 CHARS X`09BNE`0950$`09`09;IF NOT "EO", RESET ANSCNT X`09CMPB`094(R4),LITVV`09;SEE IF IT'S "EOV" X`09BNE`0950$`09`09;IF NE, RESET ANSCNT X`09INC`09ANSCNT`09`09;ELSE COUNT UP ANSCNT X`09BR`09130$ X50$:`09CLR`09ANSCNT`09`09;REQUIRE EOV1 AND EOV2 IN IMMEDIATE SUCCESSION XANST02==. X; TEST FOR HDR2 OR EOF2 AND INCREMENT OR DECREMENT HDRLVL THEN X; THIS ALLOWS ONE TO HANDLE PARTIALLY FILLED ANSI TAPES. X`09CMP`092(R4),LITHD`09;HDR2 X`09BNE`0960$`09`09;IF NE NO, TRY EOF2 X`09CMP`094(R4),LITR2`09;SEE IF STILL HDR2 X`09BNE`0960$`09`09;IF NOT CHECK EOF2 X`09MOV`09#1,HDRLVL`09;IF IT IS HDR2 SET LEVEL COUNTER UP TO 1 X;`09`09`09`09;(THIS PROTECTS AGAINST ACCIDENTAL SETS) X`09BR`09130$`09`09;THEN SCRAM XANST03==. X60$:`09CMP`092(R4),LITEO`09;SEE IF IT'S EOF2 X`09BNE`09130$`09`09;IF NOT WE'RE THRU WITH IT X`09CMP`094(R4),LITF2`09;IF NOT THEN DONE X`09BNE`09130$ X`09DEC`09HDRLVL`09`09;COUNT DOWN FILE LEVEL X`09BGE`09130$`09`09;IF 0 OR +, ALL'S WELL X`09CLR`09HDRLVL`09`09;BUT CLAMP IT TO 0 IF WE MANAGE TO SCREW UP. X80$:`09BR`09130$ X85$: X; ALLOW IE.EOT AND IE.EOV ERRORS TO PROPAGATE IN AN ATTEMPT TO HANDLE CASES X; WHERE THOSE ERRORS OCCUR ON READING THE TAPE. IF ANSI TAPE, THEY REALLY X; ARE NOT THE END OF DATA AND SHOULD BE BYPASSED. XANST04==. X`09BIT`09#EVMSK,CSIFLG`09;IGNORING EOV/EOT ETC... X`09BEQ`0987$`09`09;IF EQ NO X`09CMPB`09#IE.EOT,(R5) X`09BEQ`0986$ X`09CMPB`09#IE.EOV,(R5) X`09BNE`0987$ X86$:`09MOVB`09#IS.SUC,(R5)`09;FLAG ALL WELL X`09BR`0930$ X87$: X`09CMPB`09#IE.EOT,(R5)`09;EOT? IF SO ALWAYS MAKE EOV X`09BEQ`09110$ X`09CMPB`09#IE.EOV,(R5) X`09BEQ`09110$ X`09CMPB`09#IE.EOF,(R5)`09; EOF? X`09BNE`09160$`09`09; NO - ERROR X88$: X; X; GCE02 START X; ****** HERE ADD CODE TO SUPPORT /ANSI SWITCH IF SET X`09BIT`09#1,ANSFLG`09; ANSI SWITCH SET? X`09BEQ`0995$`09`09; IF EQ NO, JUST DO THE USUAL THINGS X; PROCESS ANSI MODE EOF RETURNS... X; X; ACTUALLY, NEED TO DUPLICATE EOF, BUT NEED EOV IF 2 ANSI EOVS THERE. X; IF ANSCNT IS 2 ALREADY, ALLOW NORMAL PROCESSING. X`09.GLOBL`09ANSCNT,HDRLVL,ANSFLG X`09CMP`09ANSCNT,#2`09;SEEN AT LEAST 2 EOV RECORDS? X`09BHIS`0995$`09`09;IF SO GO TEST FOR 2ND EOF AND WRITE THEM X`09TST`09HDRLVL`09`09;ARE WE BETWEEN HDR2 AND EOF2? X`09BNE`09100$`09`09;IF WE ARE (I.E. IF NE), JUST WRITE EOFS X;`09`09`09`09;OTHERWISE JUST TREAT EOF MARKS AS END OF TAPE X95$: X; GCE02 END X`09BIT`09#EOF,FLAGS`09; IS THIS 2ND EOF IN ROW? (EOV?) X`09BNE`09120$`09`09; YES - END-OF-VOLUME X100$:`09BIS`09#EOF,FLAGS`09; NO - SO SET IT TO INDICATE 1ST EOF X`09MOV`09#2,2(R5)`09; YES - SET LENGTH FOR OUTPUT = 2 BYTES X`09CLR`09(R4)`09`09; DATA VALUE = 0 (COUNT = 0) X`09BR`09140$`09`09; CONTINUE X;GCE02 START XANST05==. X110$:`09BIT`09#1,ANSFLG`09;THIS AN ANSI TAPE? IF SO IGNORE THESE ERRS X`09BEQ`09120$`09`09;IF NOT ANSI TAPE (EQ) JUST SET EOV X`09TST`092(R5)`09`09;ANY DATA THERE? X`09BNE`09130$`09`09;IF ANSI TAPE (NE), THEN ACCEPT RECORD X`09BR`09150$`09`09;IF NO DATA JUST CONTINUE X;GCE02 END XANST06==. X120$:`09BIS`09#EOV,FLAGS`09; INDICATE EOV SEEN X`09MOV`09#4,2(R5)`09; YES - DATA LENGTH = 4 BYTES (2 NULLS) X`09CLR`09(R4)+`09`09; RESET THE TWO 'NULL' RECORDS X`09CLR`09(R4)`09`09; ... X`09BR`09140$`09`09; CONTINUE X X130$:`09MOV`092(R5),(R4)`09; SETUP 1ST BUFFER WORD WITH DATA LENGTH X`09ADD`09#2,2(R5)`09; TOTAL LENGTH INCLUDES THE LENGTH WORD X`09BIC`09#EOF,FLAGS`09; RESET THE EOF SEEN FLAG X X140$:`09SUB`09#4,R5`09`09; ADJUST R5 TO POINT TO START OF NODE X`09MOV`09N.BUF(R5),N.PTR(R5) ; SETUP THE POINTER TO START OF DATA X`09MOV`09TPLHD+2,R4`09; R4 = PRIOR NODE ADDRESS FOR ADD OPERATION X`09CALL`09NODADD`09`09; ADD NODE TO TAPE BUFFER LIST X150$:`09JMP`09TPDKDQ`09`09; GO TRY TO DEQUEUE SOME WORK. X X160$:`09QIOW$S`09#IO.KIL,#INLUN,#1,,IOST`09; CANCEL ALL TAPE I/O'S IN PROG. X`09BIS`09#ERR,FLAGS`09; FLAG THE ERROR X`09MOVB`09(R5),MTERR`09;+AF1 COPY ERROR CODE FOR MAGTAPE X`09BPL`09170$`09`09;+AF1 SKIP IF POSITIVE (NOT LIKELY) X`09MOVB`09#-1,MTERR+1`09;+AF1 ELSE MAKE HI BYTE NEGATIVE ALSO X170$: X`09RESUME`09`09`09; RESUME THE MAIN TASK X X180$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X`09.SBTTL`09IMGMOD - Do image mode copies X; X; This section is primarily for copying disk to disk with no format dependen Vce X; but if the /CT switch is set will try to do set-characteristics and X; rewinds, etc., as needed for tape. also will try to write a couple eofs X; after the writes. X; Note the /FL:name switch allows one to write pseudo-flx tapes which can X; then contain other (real) FLX programs. FLX can't handle big block X; sizes, but can skip files like this since labels are ok. Creation dates X; will be fouled up but otherwise ok. The /IM and /CT switches must be X; used to permit /FL to have any effect. X; XIMGCT:`09.WORD`090,0`09;COUNT OF BLOCKS TO DO LEFT XIMGNM:`09.WORD`090,0`09;BLOCK NUMBERS TO USE XIMGIOS:`09.WORD`090,0`09;I/O STATUS BLK XIMGMOD: X`09MOV`09IMHI,IMGNM X`09MOV`09IMLO,IMGNM+2`09;SET UP BLK #S TO USE X`09MOV`09SZLO,IMGCT+2 X`09MOV`09SZHI,IMGCT`09;SET UP COUNT TO DO X`09CLR`09FLAGS`09`09; RESET ALL FLAGS X`09CLR`09DSKERR`09`09; RESET DISK ERROR VALUE X`09CLR`09MTERR`09`09; & MAGTAPE ERROR VALUE X`09BIT`09#40,D2DMSK`09;SEE IF WANTED EVEN THO' DISK-DISK X`09BNE`0910$`09`09;IF OK DO THE TAPE STUFF X`09JMP`0985$`09`09;IF NOT, SKIP 'EM X10$: X`09QIOW$S`09#IO.ATT,#INLUN,#1`09; ATTACH TO TAPE UNIT X`09QIOW$S`09#IO.ATT,#OUTLUN,#1`09; ATTACH TO TAPE UNIT X`09BIT`09#NRMSK,CSIFLG`09;DID HE WANT TO SKIP THE REWIND? X`09BNE`0920$`09`09;IF SO, SKIP REWIND X`09QIOW$S`09#IO.RWD,#INLUN,#1`09; REWIND THE MAGTAPE X`09QIOW$S`09#IO.RWD,#OUTLUN,#1`09; REWIND TAPE X20$:`09CLR`09R0`09`09;SET 800 BPI DENSITY INITIALLY X`09BIT`09#HDMSK,CSIFLG`09;DID HE SAY HIGH DENSITY? X`09BEQ`0930$`09`09;IF NOT LEAVE AT 800 BPI X`09MOV`09#4000,R0`09;IF SO, SET 1600 BPI X30$:`09BIT`09#SCMSK,CSIFLG`09;WAS THE /SC:NNNNNN SWITCH USED? X`09BEQ`0940$`09`09;IF NOT JUST SET CHARACTS. X`09BIS`09SCVAL,R0`09;ELSE OR IN CHARACTERISTICS WANTED X40$: X`09QIOW$S`09#IO.STC,#OUTLUN,#1,,,, ; SET TO 800BPI OR 1600BPI X`09QIOW$S`09#IO.STC,#OUTLUN,#1,,,, ; SET TO 800BPI OR 1600BPI X`09BIT`09#200,D2DMSK`09;/FLX SWITCH SET UP A NAME? X`09BEQ`0985$`09`09;IF NOT, SKIP WRITE OF LABEL. X`09CMPB`09FLXNAM,#'A`09;LEGAL NAMES ARE THIS BIG OR MORE X`09BLO`0980$`09`09;IF NOT, USE DEFAULT X`09MOV`09R0,-(SP) X`09MOV`09R1,-(SP) X`09MOV`09R2,-(SP) X;RADIX-50 PACK THE FILE NAME X`09MOV`09#FLXNAM,R0`09;NAME IN X`09CLR`09R1`09`09;NO PERIODS PLEASE X`09JSR`09PC,$CAT5`09;CONVERT THE RAD50 X`09BCS`0950$ X`09MOV`09R1,LBLBK`09;STORE OFF 1ST 3 CHARS X`09CLR`09R1 X`09JSR`09PC,$CAT5`09;CONVERT 2ND HALF X`09MOV`09R1,LBLBK+2`09;STORE WHATEVER WE HAVE X`09BR`0960$ X50$:`09MOV`09R1,LBLBK`09;STORE 3 OR LESS CHAR NAME X`09CLR`09LBLBK+2`09`09;ZERO 2ND HALF NAME X60$: X`09MOV`09(SP)+,R2 X`09MOV`09(SP)+,R1 X`09MOV`09(SP)+,R0 X80$:`09QIOW$S`09#IO.WLB,#OUTLUN,#1,,,,<#LBLBK,#14.> ;WRITE THE FLX LABEL X85$: X; X;MAIN LOOP. USE ALL SPACE AVAILABLE AS A BIG BUFFER AND JUST SHUFFLE BACK X;AND FORTH TILL DONE. X.MCALL QIOW$S XIMGS: X`09CMP`09IMBF,#IMBFMX`09;IS BLOCK FACTOR LEGAL? X`09BLOS`0910$`09`09;IF LOS ALL'S WELL X`09MOV`09#IMBFMX,IMBF`09;ELSE SET MAX AS BLOCK FACTOR X10$: X`09MOV`09IMBF,R3`09`09;GET MAX BLK # X`09ASH`09#9.,R3`09`09;SHIFT OVER 9 BITS FOR BUFFER SIZE X;DSKBF0 IS BUFFER ADDRESS XIMGLOP: X`09BIT`09#400,D2DMSK`09;/NI SWITCH SET? (IF SO READ 512 AT A TIME) X`09BNE`0910$`09`09;IF NE YES X`09QIOW$S`09#IO.RLB,#INLUN,#1,,#IMGIOS,,<#DSKBF0,R3,,LOHI,LOLO> X;THE ABOVE READS INPUT AT BLKS GIVEN. X`09BR`0950$`09`09;SKIP 1 BLK AT A TIME READIN X10$: X;NIBBLE READIN (USE TO AVOID LOSS OF DATA DUE TO BAD BLOCKS) X`09MOV`09R0,-(SP) X`09MOV`09IMBF,R0 X`09MOV`09R1,-(SP) X`09MOV`09#DSKBF0,R1`09;DATA AREA X`09MOV`09R4,-(SP) X`09MOV`09R5,-(SP) X`09MOV`09LOHI,R4 X`09MOV`09LOLO,R5 X20$:`09QIOW$S`09#IO.RLB,#INLUN,#1,,#IMGIOS,, X`09ADD`09#1,R5 X`09ADC`09R4`09`09;COUNT BLOCKS... X`09ADD`09#1000,R1`09;BUMP ADDRESS POINTER X`09TSTB`09IMGIOS X`09BPL`0930$`09`09;IF NO ERR, +; SKIP ERR MSG X`09ERRMSG`09 X`09TST`09IMGIOS+2`09;SEE IF 0 WORDS READ (==> DONE) X`09BNE`0930$`09`09;IF NONZERO GO ON X`09BIT`09#ERMSK,CSIFLG`09;IF /ER SPEC'D, USE BLK FACTOR ALWAYS X`09BNE`0930$ X`09MOV`09R1,IMGIOS+2`09;ELSE SAY HOW MANY WE GOT X`09SUB`09#DSKBF0+1000,IMGIOS+2`09;MAKE IT A BYTE COUNT X`09BR`0940$ X30$:`09DEC`09R0`09`09;COUNT DOWN BLKS TO DO X`09BGT`0920$ X`09MOV`09R3,IMGIOS+2`09;COPY WC WE WOULD HAVE USED... X40$:`09MOV`09#1,IMGIOS X`09MOV`09(SP)+,R5 X`09MOV`09(SP)+,R4 X`09MOV`09(SP)+,R1 X`09MOV`09(SP)+,R0 X50$: X`09TSTB`09IMGIOS`09`09;SEE IF ALL WENT OK X`09BPL`0960$ X`09ERRMSG`09 X60$:`09MOV`09IMGIOS+2,R4`09;GET BYTES READ X`09BNE`0980$`09`09;IF NONZERO WE KEEP GOING X`09BIT`09#ERMSK,CSIFLG`09;IF /ER SPECIFIED DON'T TEST THIS X`09BNE`0980$ X`09JMP`09IMGDUN`09`09;ZERO READ MEANS ALL DONE. X80$:`09BIT`09#1000,D2DMSK`09;/NO NUBBLE WRITE SPECIFIED? X`09BNE`0985$`09`09;IF NE YES, DO IT 1 BLK AT A TIME X`09QIOW$S`09#IO.WLB,#OUTLUN,#1,,#IMGIOS,,<#DSKBF0,R4,,IMGNM,IMGNM+2> X;WRITE THE DATA OUT X`09BR`09110$`09`09;SKIP NIBBLE WRITE X85$: X;NIBBLE WRITE (1 BLK AT A TIME TO AVOID LOSS OF DATA ON ERRORS) X`09MOV`09R0,-(SP) X`09MOV`09R1,-(SP) X`09MOV`09R2,-(SP) X`09MOV`09R3,-(SP) X`09MOV`09R4,R0 X`09ASH`09#-9.,R0`09`09;CONVERT TO A NUMBER OF BLOCKS TO DO X`09MOV`09#DSKBF0,R1`09;BUFFER ADDRESS X`09MOV`09IMGNM,R2`09;HI BLK NO X`09MOV`09IMGNM+2,R3`09;LO BLK NO X95$:`09QIOW$S`09#IO.WLB,#OUTLUN,#1,,#IMGIOS,, X`09ADD`09#1,R3 X`09ADC`09R2`09`09;BUMB BLK NO X`09ADD`09#1000,R1`09;AND BUFF ADDR X`09TSTB`09IMGIOS`09`09;CHECK ERRS X`09BPL`09100$`09`09;IF PL ALL WELL X`09ERRMSG`09 X100$: X`09DEC`09R0`09`09;COUNT DOWN BLKS TO DO X`09BGT`0995$`09`09;AND LOOP TILL DONE X`09MOV`09R4,IMGIOS+2`09;SAY WE WROTE ALL X`09MOV`09#1,IMGIOS`09;WITH SUCCESS!!!! X`09MOV`09(SP)+,R3 X`09MOV`09(SP)+,R2 X`09MOV`09(SP)+,R1 X`09MOV`09(SP)+,R0 X110$:`09TSTB`09IMGIOS X`09BPL`09120$ X`09ERRMSG`09 X120$:`09ASH`09#-9.,R4`09`09;GET NO. BLOCKS HANDLED LAST TIME X`09BEQ`09IMGDUN`09`09;IF 0, EXIT X`09SUB`09R4,IMGCT+2`09;COUNT DOWN BLOCKS TO DO X`09SBC`09IMGCT X`09BMI`09IMGDUN`09`09;COUNT NEGATIVE MEANS DONE X`09BNE`09130$ X`09TST`09IMGCT+2 X`09BEQ`09IMGDUN`09`09;END WHEN WE COUNT DOWN TO 0 LEFT X130$:`09ADD`09R4,LOLO X`09ADC`09LOHI`09`09;ELSE BUMP BLOCK NUMBERS LEFT X`09ADD`09R4,IMGNM+2 X`09ADC`09IMGNM`09`09;IN BOTH INPUT AND OUTPUT X`09;SEE HERE IF IMGCT+2 IS LESS THAN IMBF AND RESET THE X`09;BUFFER SIZE IF SO TO DO MORE REASONABLE THINGS. X`09TST`09IMGCT`09`09;IF H.O. COUNT IS NONZERO DONT DO THIS X`09BNE`09140$ X`09CMP`09IMGCT+2,IMBF`09;ENOUGH BLKS LEFT FOR FULL BUFFER? X`09BHIS`09140$`09`09;IF HIS YES X`09MOV`09IMGCT+2,R3`09;ELSE SET UP COUNT OF WHAT'S LEFT TO DO X`09ASH`09#9.,R3`09`09;AND MAKE A VALID BYTE COUNT OF IT. X`09BEQ`09IMGDUN X140$: X`09JMP`09IMGLOP`09`09;THEN GO TRY ANOTHER CHUNK XIMGDUN: X;ALL DONE... FINISH UP X`09BIT`09#40,D2DMSK`09;/CT SPEC'D? X`09BEQ`0910$`09`09;IF EQ NO X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3 X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3 X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3 X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3 X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3 X;NOW HAVE 5 EOF'S OUT TO DO. THUS WE NEED TO BACKSPACE OVER 4 RECORDS X;TO LEAVE TAPE IN POSITION AFTER THE FIRST EOF. DO IT THUS: X`09.MCALL`09QIOW$S X`09QIOW$S`09#IO.SPF,#OUTLUN,#20.,,R3,,#-4`09;BACKSPACE OVER 4 EOFS X`09BIT`09#20,D2DMSK`09;/FR FINAL REWIND WANTED? X`09BEQ`0910$`09`09;IF NOT SKIP IT X`09QIOW$S`09#IO.RWD,#OUTLUN,#20.,,R3`09;DO THE REWIND X10$: X`09JMP`09START`09`09;DONE! X`09.page X`09.SBTTL`09DSKOUT`09- Disk output AST X; X; DSKOUT - Process disk output AST X; X XDSKOUT: X`09JSR`09R5, ASTQIO`09;+AF4 Save registers & call us back with X`09`09`09`09;+AF4 AST parameter in R3 X`09MOV`09R3, R5`09`09;+AF4 R5 = I/O STATUS ADDRESS X`09BIT`09#,FLAGS`09; ANY ERRORS OR OPERATION COMPLETE? X`09BEQ`0910$ X`09JMP`0940$`09`09; YES - JUST EXIT AST X10$: X`09TSTB`09(R5)`09`09; ANY ERRORS ON OPERATION? X`09BMI`0920$`09`09; YES - ERROR X X`09SUB`09#4,R5`09`09; R5 = NODE ADDRESS (ADJUSTED) X`09MOV`09N.BUF(R5),N.PTR(R5)`09; RESET THE BUFFER POINTER X`09MOV`09DSKLHD+2,R4`09; R4 = PRIOR NODE ADDRESS FOR ADD X`09CALL`09NODADD`09`09; ADD THIS TO DISK BUFFER QUEUE X`09JMP`09TPDKDQ`09`09; TRY TO DEQUEUE SOME WORK X X20$:`09QIOW$S`09#IO.KIL,#OUTLUN,#1,,#IOST`09; CANCEL ALL OUTPUT I/O X`09BIS`09#ERR,FLAGS`09; FLAG THE ERROR X`09MOVB`09(R5),DSKERR`09;+AF1 SAVE THE ERROR CODE X`09BPL`0930$`09`09;+AF1 SKIP IF POSITIVE (NOT LIKELY) X`09MOVB`09#-1,DSKERR+1`09;+AF1 ELSE MAKE HI BYTE NEGATIVE ALSO X30$: X`09RESUME`09`09`09; CONTINUE THE MAIN TASK X X40$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X`09.SBTTL`09TPDKDQ`09- Tape to disk dequeue routine X; X; TPDKDQ- X; X;`09This routine performs the majority of work in the transfer operation. X;`09Entries in the tape input queue represent data input from the mag- X;`09tape drive, which needs to be output to the disk. The entries in the X;`09disk queue are empty buffers. This routine copies magtape buffer X;`09information starting with the 1st buffer in the queue to the disk X;`09buffers, only exiting the AST when there are no more buffers available X;`09at any time to continue the operation. X; X XTPDKDQ:`09MOV`09#DSKLHD,R0`09; R0 = DISK LISTHEAD ADDRESS X`09CMP`09R0,(R0)`09`09; ANY OUTPUT BUFFERS AVAILABLE? X`09BEQ`0910$`09`09; NO - JUST EXIT AST X`09MOV`09(R0),R0`09`09; R0 = BUFFER NODE ADDRESS X X`09MOV`09#TPLHD,R2`09; R2 = TAPE LISTHEAD ADDRESS X`09CMP`09R2,(R2)`09`09; ANY TAPE BUFFERS READY? X`09BEQ`0910$`09`09; NO - WAIT FOR SOME TO COME X`09MOV`09(R2),R2`09`09; R2 = BUFFER ADDRESS X`09BR`0920$`09`09; CONTINUE X X10$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X X; X; THERE IS AT LEAST ONE INPUT BUFFER READY & ONE OUTPUT BUFFER AVAILABLE. X; SETUP ALL POINTERS, CALCULATE THE NUMBER OF BYTES TO COPY & THE AMOUNT X; OF SPACE LEFT IN THE DISK BUFFER. TRANSFER AS MUCH AS WILL FIT INTO X; THE DISK BUFFER. X; X X20$:`09MOV`09N.PTR(R0),R1`09; R1 = REMAINING LENGTH IN DISK BUFFER X`09SUB`09N.BUF(R0),R1`09; ... X`09NEG`09R1`09`09; (R1 = -AMOUNT USED) X`09ADD`09N.LEN(R0),R1`09; ... X`09BLE`09DSKWRT`09`09; NONE LEFT! X`09MOV`09N.IOST+2(R2),R3`09; R3 = LENGTH OF TAPE BUFFER DATA X`09BNE`0930$ X`09JMP`09QUEMTR`09`09; NO TAPE DATA! X30$: X X`09CMP`09R1,R3`09`09; COMPARE REMAINING DISK TO TAPE BUFFER X`09BHIS`0940$`09`09; DISK BUFFER WILL HOLD IT ALL - CONTINUE X`09SUB`09R1,R3`09`09; R3 = AMOUNT WHICH WILL NOT FIT X`09MOV`09R3,N.IOST+2(R2)`09; UPDATE THE AMOUNT WHICH REMAINS FOR TAPE X`09MOV`09R1,R3`09`09; R3 = TRANSFER COUNT X`09BR`0950$`09`09; CONTINUE X X40$:`09CLR`09N.IOST+2(R2)`09; XFER WILL FIT - NO DATA WILL BE LEFT X X50$:`09MOV`09N.PTR(R2),R4`09; R4 = FROM POINTER X`09MOV`09N.PTR(R0),R5`09; R5 = TO POINTER X`09ASR`09R3`09`09; R3 = XFER COUNT IN WORDS X`09TST`09CMPPAS`09`09;+AF3 Is this a compare pass?? X`09BEQ`0960$`09`09;+AF3 No, go move data X`09JMP`09CMPBUF`09`09;+AF3 If compare, go do compare operation X X60$:`09MOV`09(R4)+,(R5)+`09; COPY THE BUFFER X`09SOB`09R3,60$`09`09; ... X X`09MOV`09R5,N.PTR(R0)`09; RESTORE NEW BUFFER POINTER VALUES X`09MOV`09R4,N.PTR(R2)`09; ... X X; X; WRITE OUT DISK BUFFER IF REQUIRED X; X X`09SUB`09N.BUF(R0),R5`09; R5 = AMOUNT OF BUFFER USED X`09CMP`09R5,N.LEN(R0)`09; COMPARE TO BUFFER SIZE X`09BLO`09QUEMTR`09`09; CONTINUE IF MORE ROOM LEFT X XDSKWRT: X`09TST`09CMPPAS`09`09;+AF3 In compare pass? X`09BEQ`0920$`09`09;+AF3 No, skip to normal write X`09BIT`09#EOF,FLAGS`09;+AF3 This should be END-OF-FILE time X`09BNE`0910$`09`09;+AF3 It is, exit gracefully X`09BIS`09#CMPERR,FLAGS`09;+AF3 Not EOF on disk file. Flag error X10$: X`09JMP`09TDDONE`09`09;+AF3 EXIT X20$: X`09MOV`09R0,R5`09`09; R5 = NODE ADDRESS X`09CALL`09NODDEL`09`09; DELETE THE NODE X`09MOV`09R2,-(SP)`09; SAVE R2 X`09MOV`09#FDBOUT,R4`09; GET FDB ADDRESS X30$:`09MOV`09N.LEN(R0),R2`09; COPY BUFFER LENGTH X`09ASH`09#-9.,R2`09`09; CHANGE IT TO BLOCKS X`09INC`09R2`09`09; AND ROUND UP X`09CLR`09R3`09`09; CLEAR HIGH ORDER X`09ADD`09F.EFBK+2(R4),R2`09; ADD LOW ORDER CURRENT BLOCK X`09ADC`09R3`09`09; ADD CARRY INTO HIGH ORDER X`09ADD`09F.EFBK(R4),R3`09; ADD HIGH ORDER CURRENT BLOCK X;CHANGE CMP TO CMPB BELOW TO AVOID TROUBLES... X;ONLY 8 BITS OF HIGH BLK ALLOCATED CAN REALLY BE THERE... X`09CMPB`09R3,F.HIBK(R4)`09; COMPARE ULTIMATE HIGH ORDER TO X`09`09`09`09; AMOUT ALLOCATED ALREADY X`09BLO`0980$`09;IF LO, KNOW ALL OK X`09BHI`0940$`09`09; IF HIGH, MUST EXTEND X`09CMP`09R2,F.HIBK+2(R4)`09; COMPARE ULTIMATE LOW ORDER X`09BLO`0980$`09`09; IF LOW, THERE IS ROOM X40$:`09MOV`09R0,-(SP)`09; PUSH NODE ADDRESS ON STACK X`09MOV`09R4,R0`09`09; COPY FDB ADDRESS X`09MOV`09SALOC,R1`09; GET SECONDARY ALLOCATION VALUE X`09MOV`09#203,R2`09`09; SET CONTROL BITS FOR ENABLE, CONTIGUOUS X`09`09`09`09; (BUT FILE IS NOW NON-CONTIGUOUS) X`09BIT`09#CONMSK,CSIFLG`09; IS /CO SET? X`09BNE`0950$`09`09; YES, HENCE WANTED CONTIGUOUS X`09BIC`09#7,R2`09`09; CHANGE CONTROL INDICATORS TO NON-CONTIGUOUS X; X; THERE SEEMS TO BE A PROBLEM ABOVE 65536 BLOCKS ON DISK... X; CHANGE OF CMP TO CMPB ABOVE MAY OR MAY NOT FIX IT. X; GCE 11/5/82 X; X50$:`09CALL`09.EXTND`09`09; DO THE EXTEND X;.EXTND BETTER RESET F.HIBK SO THE THING DOESN'T JUST GOBBLE DISK... X`09BCC`0960$`09`09; IF NO ERROR FROM EXTEND, GO ON X`09MOV`09#ERR,FLAGS`09; FLAG AN ERROR X`09TST`09(SP)+`09`09; POP STACK X`09JMP`09TDDONE`09`09; GET OUT X60$:`09MOV`09(SP)+,R0`09; RESTORE NODE ADDRESS IN R0 X`09BR`0930$`09`09; GO BACK TO CHECK THAT INCREMENT WAS ENOUGH X80$:`09MOV`09(SP)+,R2`09; RESTORE R2 X`09MOV`09R0,R1`09`09; COPY NODE ADDRESS TO R1 X`09ADD`09#N.IOST,R1`09; R1 = IO STATUS BLOCK ADDRESS X`09MOV`09#FDBOUT,R3`09; R3 = OUTPUT FDB POINTER X`09MOV`09N.BUF(R0),R4`09; R4 = BUFFER ADDRESS X`09MOV`09N.LEN(R0),R5`09; R5 = BUFFER LENGTH X`09MOV`09F.BKVB(R3),N.BKH(R0)`09; MOVE BLOCK# INTO NODE X`09MOV`09F.BKVB+2(R3),N.BKL(R0)`09; ... X`09QIO$S`09#IO.WVB,#OUTLUN,,,R1,OUTVEC, X`09ADD`09DSKFCT,F.BKVB+2(R3)`09; UPDATE BLOCK NUMBER TO NEXT WRITE X`09ADC`09F.BKVB(R3)`09`09; ... X`09MOV`09F.BKVB(R3),F.EFBK(R3)`09; UPDATE EOF BLOCK# X`09MOV`09F.BKVB+2(R3),F.EFBK+2(R3) ; ... X X; X; QUEUE UP MAGTAPE FOR MORE INPUT IF BUFFER IS EMPTY X; X XQUEMTR:`09TST`09N.IOST+2(R2)`09; ANY MORE DATA TO XFER FROM THIS BUFFER? X`09BEQ`0910$`09`09; NO X`09JMP`09TPDKDQ`09`09; TRY TO DEQUEUE MORE WORK X10$:`09BIT`09#EOV,FLAGS`09; DONE? X`09BEQ`0920$`09`09; NO - CONTINUE X`09BIS`09#DONE,FLAGS`09; YES - FLAG IT X`09MOV`09#DSKLHD,R0`09; R0 = DISK LISTHEAD ADDRESS X`09CMP`09R0,(R0)`09`09; ANY ENTRIES IN LIST? X`09BEQ`09TDDONE`09`09; NO - DONE X`09MOV`09(R0),R0`09`09; R0 = DISK NODE ADDRESS X`09CMP`09N.BUF(R0),N.PTR(R0) ; ANY DATA IN BUFFER? X`09BNE`09DSKWRT`09`09; YES - GO WRITE IT OUT X`09BEQ`09TDDONE`09`09; GO RESUME MAIN TASK & EXIT X X20$:`09MOV`09R2,R5`09`09; COPY NODE ADDR TO R5 X`09CALL`09NODDEL`09`09; DELETE THE NODE X`09MOV`09R2,R3`09`09; COPY NODE ADDRESS TO R3 X`09ADD`09#N.IOST,R3`09; R3 = IO STATUS ADDR X`09MOV`09N.BUF(R2),R4`09; R4 = BUFFER ADDRESS X`09TST`09(R4)+`09`09; ADVANCE OVER 1ST WORD IN BUFFER X`09MOV`09N.LEN(R2),R5`09; R5 = LENGTH (MAX) FOR READ X`09SUB`09#2,R5`09`09; REDUCE BY AMOUNT BUFFER WAS ADVANCED X`09BIT`09#1,D2DMSK`09;READING DISK AS TAPE? X`09BEQ`0930$`09`09;IF EQ NO,NORMAL X`09MOV`09#512.,R5`09;YES, SET 1 BLOCK X`09CMP`09LOHI,ENDBK`09;ALL BLKS ALREADY SENT? X`09BLO`0930$`09`09;IF LOWER THAN END, MORE TO DO X`09CMP`09LOLO,ENDBK+2`09;ARE LOW ORDER BLKS SAME? X`09BLO`0930$`09`09;IF LOWER ALL'S WELL X`09SUB`09#1,LOLO`09`09;SINCE WE PASSED END, BACK UP 1 X`09SBC`09LOHI X30$: X`09QIO$S`09#IO.RLB,#INLUN,,,R3,INVEC, X`09BIT`09#1,D2DMSK X`09BEQ`0940$`09`09;SKIP INC UNLESS DSK-DSK X`09ADD`09#1,LOLO X`09ADC`09LOHI`09`09;BUMP BLOCK NUMBER (IGNORED BY TAPE DRIVER) X40$:`09JMP`09TPDKDQ`09`09; TRY TO DEQUEUE MORE WORK X X50$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X XTDDONE:`09RESUME`09`09`09; RESUME THE MAIN TASK X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X; X; COMPARE TAPE BUFFER WITH DISK BUFFER X; READ NEW DISK BUFFERS AS NEEDED X; XCMPBUF: X`09CMP`09(R4)+,(R5)+`09;+AF3 Same? X`09BNE`09BADCMP`09`09;+AF3 No, give error message X`09SOB`09R3,CMPBUF`09;+AF3 Test next word X X`09MOV`09R5,N.PTR(R0)`09;+AF3 Set next word pointer X`09MOV`09R4,N.PTR(R2)`09;+AF3 *** X X`09SUB`09N.BUF(R0),R5`09;+AF3 Get length used X`09CMP`09R5,N.LEN(R0)`09;+AF3 Compare with total available length X`09BLO`0910$`09`09;+AF3 Some still left, go read more mag tape X X`09MOV`09R0,R5`09`09;+AF3 Save node pointer X`09CALL`09NODDEL`09`09;+AF3 Delete disk node from list X X`09MOV`09R0,R1`09`09;+AF3 Node pointer X`09ADD`09#N.IOST,R1`09;+AF3 Point at IOSB for this buffer X`09MOV`09N.BUF(R0),R4`09;+AF3 Buffer address X`09MOV`09N.LEN(R0),R5`09;+AF3 # of bytes to read X`09MOV`09#FDBOUT,R3`09;+AF3 Get address of disk FDB X`09QIO$S`09#IO.RVB,#OUTLUN,,,R1,OUTVEC, X`09ADD`09DSKFCT,F.BKVB+2(R3)`09;+AF3 Update VBN X`09ADC`09F.BKVB(R3)`09;+AF3 High order VBN X10$: X`09JMP`09QUEMTR`09`09;+AF3 Do another mag tape read X; X; X; XBADCMP: X`09BIS`09#CMPERR!ERR,FLAGS`09;+AF3 Flag error condition X`09QIOW$S`09#IO.KIL,#OUTLUN,#1,,#IOST`09;+AF3 Kill all remaining disk reads X`09QIOW$S`09#IO.KIL,#INLUN,#1,,#IOST`09;+AF3 Kill all remaining tape reads X`09RESUME`09`09`09;+AF3 Resume main program X X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X`09.SBTTL`09Disk to tape operations X; X; DISK TO TAPE X; X;`09This function transfers data from the disk file to magtape. The X;`09magtape is rewound prior to processing. All reads from disk are X; `09multi-block QIO'S (also multi-buffered) to take advantage of the X;`09higher throughput of the disk. Magtape operations are also multi- X;`09buffered. X; X XDSKTTP:`09CLR`09FLAGS`09`09; RESET ALL FLAGS X`09CLR`09DSKERR`09`09; RESET DISK ERROR VALUE X`09CLR`09MTERR`09`09; RESET MAGTAPE ERROR X`09MOV`09#DSKIN,INVEC`09; SETUP INPUT VECTOR X`09MOV`09#TAPOUT,OUTVEC`09; & OUTPUT VECTOR X`09BIT`09#2,D2DMSK`09;SKIP CONTROL QIO'S? X`09BEQ`0910$`09`09;IF NOT LEAVE IN X`09BIT`09#40,D2DMSK X`09BEQ`0950$ X10$: X`09QIOW$S`09#IO.ATT,#OUTLUN,#1`09; ATTACH TO TAPE UNIT X`09BIT`09#NRMSK,CSIFLG X`09BNE`0920$`09`09;DID HE SAY NO REWIND? X`09QIOW$S`09#IO.RWD,#OUTLUN,#1`09; REWIND TAPE X20$:`09CLR`09R0`09`09;800 BPI DEFAULT X`09BIT`09#HDMSK,CSIFLG`09;1600 BPI TAPE? X`09BEQ`0930$`09`09;IF NOT LEAVE 800 X`09MOV`09#4000,R0`09;IF SO SAY 1600BPI X30$:`09BIT`09#SCMSK,CSIFLG`09;DID HE SET OTHER CHARACTERISTICS? X`09BEQ`0940$`09`09;IF EQ NO, JUST SET CHARACS. X`09BIS`09SCVAL,R0`09;ELSE OR IN OTHER BITS HE WANTS X40$: X`09QIOW$S`09#IO.STC,#OUTLUN,#1,,,, ; SET TO 800BPI OR 1600BPI X50$: X; X; INITIALIZE & PALACE ALL TAPE BUFFERS IN OUTPUT QUEUE X; X X`09MOV`09#TPLHD,R0`09; R0 = TAPE BUFFER LISTHEAD X`09MOV`09R0,R4`09`09; R4 = SAVED LISTHEAD ADDR X`09MOV`09R4,(R0)+`09; SET LISTHEAD TO NULL X`09MOV`09R4,(R0)+`09; ... X X60$:`09MOV`09R0,R5`09`09; R5 = BUFFER NODE ADDRESS X`09CALL`09NODADD`09`09; ADD TAPE BUFFER TO LIST X`09MOV`09N.BUF(R5),N.PTR(R5)`09; INIT THE POINTER X`09CLR`09N.WRK(R5)`09; RESET 'NUMBER REMAINING BYTES' COUNT X`09ADD`09#N.SIZE,R0`09; ADVANCE TO NEXT BUFFER X`09CMP`09R0,#TPLND`09; AT END OF TAPE BUFFERS? X`09BLO`0960$`09`09; NO - CONTINUE X X; X; INITATE DISK I/O OPERATIONS FOR ALL AVAILABLE DISK BUFFERS X; X X`09MOV`09#DSKLHD,R0`09; R0 = DISK LISTHEAD POINTER X`09MOV`09R0,R1`09`09; R1 = SAVE LISTHEAD ADDR X`09MOV`09R1,(R0)+`09; INITIATE THE LISTHEAD TO NULL X`09MOV`09R1,(R0)+`09; ... X X80$:`09MOV`09N.BUF(R0),R2`09; R2 = BUFFER ADDRESS X`09MOV`09R2,N.PTR(R0)`09; INIT THE BUFFER POINTER X`09MOV`09N.LEN(R0),R3`09; R3 = LENGTH OF READ X X;***`09BIT`09#3,D2DMSK`09; READ DISKS 1 BLK AT A TIME X;***`09BEQ`09240$ X;***`09MOV`09#512.,R3`09; I.E. 512 BYTES X X;240$: X`09MOV`09R0,R1`09`09; R1 = IO STATUS BLOCK ADDR X`09ADD`09#N.IOST,R1`09; ... X`09MOV`09#FDBINP,R5`09; R5 = INPUT FDB ADDRESS X`09QIO$S`09#IO.RVB,#INLUN,,,R1,INVEC, X`09ADD`09DSKFCT,F.BKVB+2(R5) ; UPDATE THE NEXT BLOCK NO. X`09ADC`09F.BKVB(R5)`09; ... X`09ADD`09#N.SIZE,R0`09; ADVANCE TO NEXT BUFFER NODE X`09CMP`09R0,#DSKLND`09;+AF3 Past end? X;????`09CMP`09R0,#DSKLND`09;+AF3 Past end? X`09BLO`0980$`09`09; CONTINUE IF IN RANGE X`09JMP`09WAIT`09`09; ELSE GO WAIT FOR XFER TO COMPLETE X`09.page X`09.SBTTL`09DSKIN`09- Disk input AST routine X; X; DSKIN - Handle disk I/O done AST X; X XDSKIN: X`09JSR`09R5, ASTQIO`09;+AF4 Save registers & call us back with X`09`09`09`09;+AF4 AST parameter in R3 X`09MOV`09R3, R5`09`09;+AF4 R5 = I/O STATUS ADDRESS X`09SUB`09#4,R5`09`09; POINT R5 TO NODE BEGINNING X`09BIT`09#,FLAGS ; ANY ERRORS OR IS I/O COMPLETE? X`09BNE`0985$`09`09; YES - JUST EXIT THE AST X`09TSTB`09N.IOST(R5)`09; WAS THERE AN ERROR ON THIS XFER? X`09BPL`0920$`09`09; NO - CONTINUE X`09CMPB`09#IE.EOF,N.IOST(R5)`09; WAS IT EOF? X`09BNE`0940$`09`09; NO - REAL ERROR X`09BIT`09#3,D2DMSK`09; THIS A DSK-DISK XFER? X`09BEQ`0910$`09`09; IF EQ NO X`09CMP`09ENDIO,ENDBK`09; IF NE YES, BE SURE OUTPUT DONE X`09BHI`0910$`09`09; SET EOF WHEN DONE X`09BLO`0920$ X`09CMP`09ENDIO+2,ENDBK+2`09; CHECK DBL PREC. X`09BLO`0920$`09`09; IF NOT AT END IGNORE EOF INPUT X10$: X`09BIS`09#EOF,FLAGS`09; FLAG EOF X`09BR`0985$`09`09; & IGNORE AST X X20$:`09MOV`09N.IOST+2(R5),N.WRK(R5)`09; COPY THE # BYTES XFERRED X`09ADD`09N.BUF(R5),N.WRK(R5)`09; POINT TO END BYTE + 1 X`09MOV`09N.BUF(R5),N.PTR(R5)`09; SETUP THE BEGINNING PTR X`09MOV`09DSKLHD+2,R4`09; R4 = PRIOR (LAST) NODE IN LIST ADDR X`09CALL`09NODADD`09`09; ADD NODE TO END OF QUEUE X; X;+AF3 Here we get sneeky. If this is a compare operation, this AST X;+AF3 is being used by the tape-to-disk routine, but for read operations. X; X`09TST`09CMPPAS`09`09;+AF3 Is this a compare pass? X`09BEQ`0930$`09`09;+AF3 No, skip and do normal stuff X`09JMP`09TPDKDQ`09`09;+AF3 Yes, go to tape-to-disk dequeue routine X30$: X`09JMP`09DKTPDQ`09`09; GO TO MAIN DE-QUEUING ROUTINE X X40$:`09TST`09CMPPAS`09`09;+AF3 Doing compare? X`09BEQ`0950$`09`09`09;+AF3 No,skip X`09QIOW$S`09#IO.KIL,#OUTLUN,#1,,#IOST ; CANCEL ALL OTHER DISK I/O'S X`09BR`0960$ X50$: X`09QIOW$S`09#IO.KIL,#INLUN,#1,,#IOST ; CANCEL ALL OTHER DISK I/O'S X60$: X`09BIS`09#ERR,FLAGS`09; FLAG THE ERROR X`09MOVB`09N.IOST(R5),DSKERR ;+AF1 SAVE DISK ERROR CODE X`09BPL`0980$`09`09;+AF1 SKIP IF POSITIVE (NOT LIKELY) X`09MOVB`09#-1,DSKERR+1`09;+AF1 ELSE MAKE HI BYTE NEGATIVE ALSO X80$: X`09RESUME`09`09`09; CONTINUE THE MAIN TASK X X85$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X`09.SBTTL`09TAPOUT`09- Tape output I/O done AST routine X; X; TAPOUT - Tape output I/O done routine X; X XTAPOUT: X`09JSR`09R5, ASTQIO`09;+AF4 Save registers & call us back with X`09`09`09`09;+AF4 AST parameter in R3 X`09MOV`09R3, R5`09`09;+AF4 R5 = I/O STATUS ADDRESS X`09BIT`09#,FLAGS`09; ERRORS OR DONE? X`09BEQ`0910$ X`09JMP`0985$`09`09; YES - JUST EXIT X10$: X`09ADD`09#1,ENDIO+2`09;COUNT I/O DONES X`09ADC`09ENDIO X`09BIT`09#2,D2DMSK X`09BEQ`0920$ X`09CMP`09ENDIO,ENDBK X`09BLO`0920$`09`09;PAST END? X`09BHI`0940$ X`09CMP`09ENDIO+2,ENDBK+2 X`09BHIS`0940$`09`09;TREAT AS EOF X20$: X`09SUB`09#N.IOST,R5`09; ADJUST R5 TO POINT TO NODE X`09BIT`09#ERMSK,CSIFLG`09;TRYING TO IGNORE TAPE ERRORS? X`09BEQ`0930$`09`09;IF NOT, LOOK AT ALL X`09CMPB`09N.IOST(R5),#IE.PRI ;TAPE UNMOUNTED? X`09BEQ`0960$`09`09;IF SO THEN DONE. IGNORE OTHER ERRORS X; X; NOTE: The /EV or /ER switches can make tape run off reel. Too bad X; if so (user ought to know better...) X; X`09BIT`09#EVMSK,CSIFLG X`09BNE`0924$ X`09CMPB`09N.IOST(R5),#IE.EOT X`09BEQ`0960$ X`09CMPB`09N.IOST(R5),#IE.EOV X`09BEQ`0960$`09`09;ALLOW PRIV, EOT, OR EOV AS REAL. X24$:`09BR`0950$`09`09;SKIP NORMAL TEST THEN X30$:`09TSTB`09N.IOST(R5)`09; WAS THERE AN ERROR ON THE XFER? X`09BMI`0960$`09`09; YES - SO INDICATE X`09BR`0950$ X40$:`09BIT`09#40,D2DMSK`09;UNLESS SPECIAL FLAG SET X`09BNE`0950$ X`09BIS`09#DONE,FLAGS`09;ON DSK-DSK, DONE WHEN FINISHED XFER X`09MOV`09N.BUF(R5),N.PTR(R5)`09; SETUP THE BUFFER POINTER X`09CLR`09N.WRK(R5)`09; RESET THE NO. BYTES LEFT TO XFER X`09MOV`09TPLHD+2,R4`09; R4 = PRIOR (LAST) EXISTING NODE ADDR X`09CALL`09NODADD`09`09; ADD THE NODE TO FREE TAPE BUFFER LIST X`09QIOW$S`09#IO.KIL,#OUTLUN,#1,,#IOST ; CANCEL ALL CURRENT I/O'S X`09BR`0980$ X50$: X`09MOV`09N.BUF(R5),N.PTR(R5)`09; SETUP THE BUFFER POINTER X`09CLR`09N.WRK(R5)`09; RESET THE NO. BYTES LEFT TO XFER X`09MOV`09TPLHD+2,R4`09; R4 = PRIOR (LAST) EXISTING NODE ADDR X`09CALL`09NODADD`09`09; ADD THE NODE TO FREE TAPE BUFFER LIST X`09JMP`09DKTPDQ`09`09; GO TO THE MAIN DE-QUEUING ROUTINE X X60$: X`09QIOW$S`09#IO.KIL,#OUTLUN,#1,,#IOST ; CANCEL ALL CURRENT I/O'S X`09BIS`09#ERR,FLAGS`09; FLAG THE ERROR X`09MOVB`09N.IOST(R5),MTERR ;+AF1 Save error code X`09BPL`0980$`09`09;+AF1 Skip if positive (not likely) X`09MOVB`09#-1,MTERR+1`09;+AF1 else make HI byte negative also X80$: X`09RESUME`09`09`09; CONTINUE EXECUTION OF MAIN TASK X X85$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X`09.SBTTL`09DKTPDQ`09- Disk to tape dequeue routine X; X; DKTPDQ- X; X;`09This routine interfaces the data coming in a continuous stream X;`09from the disk (in multi-block buffers) to the magtape output. As X;`09the tape is blocked 512., it is desirable to keep a constant no. X;`09of I/O requests queued up to the tape drive, thereby allowing X;`09this program to pay for itself. X; X XDKTPDQ:`09MOV`09#DSKLHD,R0`09; R0 = DISK LISTHEAD POINTER X`09CMP`09(R0),R0`09`09; NULL LIST? X`09BEQ`0910$`09`09; YES - WAIT FOR WORK X`09MOV`09(R0),R0`09`09; R0 = THE 1ST NODE ADDR IN LIST X X`09MOV`09#TPLHD,R2`09; R2 = TAPE OUTPUT LISTHEAD ADDR X`09CMP`09(R2),R2`09`09; ANY NODES FREE FOR OUTPUT? X`09BEQ`0910$`09`09; NO - WAIT FOR SOME TO FREE UP X`09MOV`09(R2),R2`09`09; R2 = ADDR OF 1ST FREE TAPE NODE X`09BR`0920$`09`09; CONTINUE X X10$: X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X; X; Transfer data from the current disk buffer to the current tape buffer X; (note that this might be the resumption of a transfer begun earlier). When X; the tape buffer is filled (or the operation type determined if EOF), the X; the tape node is dequeued & the output initiated. When a disk buffer is X; empty, the next one in the queue is serviced. X; X X20$:`09MOV`09N.WRK(R2),R3`09; R3 = REMAINING BYTES IF PARTIAL XFER X`09BNE`0930$`09`09; WAS A PARTIAL - CONTINUE IT X`09MOV`09@N.PTR(R0),R3`09; ELSE, START OF NEW RECORD X`09ADD`09#2,N.PTR(R0)`09; ADVANCE OVER CONTROL WORD X`09MOV`09R3,N.WRK(R2)`09; SAVE IT AS SIZE REQ'D X`09BNE`0930$ X`09JMP`09160$`09`09; ZERO - GO WRITE EOF X X30$:`09MOV`09N.WRK(R0),R1`09; R1 = ENDING DISK BUFFER ADDR X`09SUB`09N.PTR(R0),R1`09; R1 = # BYTES LEFT IN BUFFER X`09BNE`0950$ X40$:`09JMP`09210$`09`09; NO BYTES LEFT IN BUFFER! X50$: X`09CMP`09R1,R3`09`09; WILL THIS BE A PARTIAL COPY? X`09BHIS`0960$`09`09; NO - ALL OF DATA IN DISK BUFFER X`09SUB`09R1,R3`09`09; R3 = AMOUNT STILL REQ'D X`09MOV`09R3,N.WRK(R2)`09; UPDATE TAPE BUFFER REMAINING COUNT X`09MOV`09R1,R3`09`09; R3 = ACTUAL NUMBER OF BYTES TO XFER X`09BR`0980$`09`09; CONTINUE X X60$:`09CLR`09N.WRK(R2)`09; INDICATE WHOLE XFER GOOD X X80$:`09MOV`09N.PTR(R0),R4`09; R4 = FROM POINTER X`09MOV`09N.PTR(R2),R5`09; R5 = TO POINTER X`09ASR`09R3`09`09; R3 = WORD XFER COUNT X X85$:`09MOV`09(R4)+,(R5)+`09; COPY THE DARA X`09SOB`09R3,85$`09`09; ... X X`09MOV`09R4,N.PTR(R0)`09; UPDATE THE DISK POINTER X`09MOV`09R5,N.PTR(R2)`09; & THE TAPE POINTER X`09TST`09N.WRK(R2)`09; DO WE WRITE THE TAPE BUFFER? X`09BNE`0940$`09`09; NO - SEE ABOUT DISK X`09MOV`09N.BUF(R2),R4`09; R4 = TAPE BUFFER ADDRESS X`09SUB`09R4,R5`09`09; R5 = NO. BYTES DATA IN BUFFER X`09MOV`09R2,R3`09`09; R3 = THE IO STATUS ADDR X`09ADD`09#N.IOST,R3`09; ... X`09BIT`09#3,D2DMSK X`09BEQ`0995$ X`09CMP`09LOHI,ENDBK X`09BHI`09100$ X`09BLO`0995$ X`09CMP`09LOLO,ENDBK+2 X`09BHIS`09100$ X95$: X`09QIO$S`09#IO.WLB,#OUTLUN,,,R3,OUTVEC, X100$: X`09BIT`09#3,D2DMSK X`09BEQ`09110$ X`09ADD`09#1,LOLO X`09ADC`09LOHI`09`09;COUNT BLK # TO DO X110$: X`09BIC`09#EOV,FLAGS`09; RESET THE END-OF-VOLUME TEST BIT X; X;GCE02 - For ANSI tape set HDRLVL or ANSCNT and don't set EOV status X; if inside ANSI area where 2 EOFS are * NOT * EOV. X; X`09BIT`09#1,ANSFLG`09; /ANSI TAPE FLAG SEEN? X`09BEQ`09150$`09`09; IF EQ NO, NORMAL X`09BIT`09#4,ANSFLG`09;IS THIS /RT11 ANSI VERSION (NOT 80 BYTE LABELS) X`09BNE`09120$`09`09;IF SO SKIP LENGTH CHECK X`09CMP`09R5,#80.`09`09;WRITING 80 BYTES? X`09BNE`09150$`09`09;IF NOT THIS ISN'T OF INTEREST X120$:`09CMP`09(R4),LITEO`09; EOV OR EOF2? X`09BNE`09140$`09`09; IF NOT CHECK FOR HDR2 X;COULD BE AN EOV OR EOF2 X`09CMPB`092(R4),LITVV`09; IS IT EOV? X`09BNE`09130$`09`09;IF NE NO X; SAW EOV1 SO BUMP ANSCNT X`09INC`09ANSCNT`09`09;COUNT EOV1 X`09BR`09200$ X130$:`09CLR`09ANSCNT`09`09;2 EOV1 IN A ROW ARE REAL END X`09CMP`092(R4),LITF2`09; SEE IF EOF2 RECORD X`09BNE`09200$`09`09; IF NE NO, JUST SKIP ANY SPECIAL STUFF X`09DEC`09HDRLVL`09`09;ELSE COUNT DOWN HEADER LEVEL X`09BGE`09200$`09`09;AND X`09CLR`09HDRLVL`09`09;...CLAMP IT POSITIVE OR 0 X`09BR`09200$ X140$:`09CMP`09(R4),LITHD`09;COULD THIS BE HDR2? X`09BNE`09200$`09`09;IF NOT, JUST BYPASS X`09CMP`092(R4),LITR2`09;IF REALLY HDR2 THIS WILL BE EQ X`09BNE`09200$ X`09INC`09HDRLVL`09`09;SO COUNT UP LEVEL X150$: X; END GCE02 X`09BR`09200$`09`09; CONTINUE X X160$:`09MOV`09R2,R3`09`09; R3 = IO STATUS ADDR X`09ADD`09#N.IOST,R3`09; ... X`09BIT`09#3,D2DMSK`09;DSK-DSK? X`09BEQ`09170$ X`09BIT`09#40,D2DMSK X`09BNE`09170$ X`09BR`09180$ X170$: X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3,OUTVEC X180$: X`09BIT`09#EOV,FLAGS`09; WAS EOV FLAG SET LAST TIME? X`09BNE`09230$`09`09; YES - TWO EOF'S = EOV X`09BIT`09#1,ANSFLG`09; /ANSI TAPE? `09;GCE02 X`09BEQ`09190$`09`09; IF EQ NO, JUST SET EOV X`09CMP`09ANSCNT,#2`09; SAW EOV1 AND EOV2 RECORDS ALREADY? X`09BHIS`09190$`09`09;IF SO SET EOV FLAG FOR NEXT EOF X`09TST`09HDRLVL`09`09;BUT IF BETWEEN HDR2 AND EOF2 INSIDE VOL... X`09BNE`09200$`09`09;...THEN DON'T SET EOV FLAG X190$: X;END GCE02 X`09BIS`09#EOV,FLAGS`09; NO - SO SET IT FOR THIS EOF X X200$:`09MOV`09R2,R5`09`09; R5 = NODE ADDRESS FOR DELETE X`09CALL`09NODDEL`09`09; DELETE THE NODE FROM THE QUEUE X X; X; DETERMINE WHETHER CURRENT DISK BUFFER IS EMPTY & INITIATE A NEW READ IF SO X; X X210$:`09CMP`09N.WRK(R0),N.PTR(R0)`09; BUFFER EMPTY? X`09BLOS`09220$ X`09JMP`09DKTPDQ`09`09; NO - CONTINUE DEQUEUEING X220$: X`09MOV`09R0,R5`09`09; R5 = NODE ADDR X`09CALL`09NODDEL`09`09; DELETE THE NODE FROM DISK QUEUE X`09MOV`09R0,R1`09`09; R1 = IO STATUS ADDR X`09ADD`09#N.IOST,R1`09; ... X`09MOV`09N.BUF(R0),R4`09; R4 = BUFFER ADDR X`09MOV`09N.LEN(R0),R5`09; R5 = NO. BYTES TO READ X X;***`09BIT`09#3,D2DMSK`09; READ DISKS 1 BLK AT A TIME... X;***`09BEQ`09382$ X;***`09MOV`09#512.,R5 X X;382$: X`09MOV`09#FDBINP,R3`09; R3 = FDB ADDR X`09QIO$S`09#IO.RVB,#INLUN,,,R1,INVEC, X`09ADD`09DSKFCT,F.BKVB+2(R3) ; UPDATE NEXT BLOCK# X`09ADC`09F.BKVB(R3)`09; ... X`09JMP`09DKTPDQ`09`09; CONTINUE X X230$:`09BIS`09#DONE,FLAGS`09; FLAG I/O DONE X`09.IF`09NDF,XXEOF X`09BIT`09#2,D2DMSK X`09BEQ`09240$ X`09BIT`09#40,D2DMSK X`09BEQ`09250$ X240$: X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3,OUTVEC X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3,OUTVEC X`09QIO$S`09#IO.EOF,#OUTLUN,,,R3,OUTVEC X; X;NOW HAVE 5 EOF'S OUT TO DO. THUS WE NEED TO BACKSPACE OVER 4 RECORDS X;TO LEAVE TAPE IN POSITION AFTER THE FIRST EOF. DO IT THUS: X; X`09.MCALL`09QIOW$S X`09QIOW$S`09#IO.SPF,#OUTLUN,#20.,,R3,OUTVEC,#-4`09;BACKSPACE OVER 4 EOFS X`09BIT`09#20,D2DMSK`09;/FR FINAL REWIND WANTED? X`09BEQ`09250$`09`09;IF NOT SKIP IT X`09QIOW$S`09#IO.RWD,#OUTLUN,#20.,,R3,OUTVEC`09;DO THE REWIND X250$: X; X; Note the wait to ensure we get done. X; This will prevent the IO.KIL from clobbering the EOF writes that are X; outstanding. X; X`09.ENDC X`09RESUME`09`09`09; CONTINUE THE MAIN TASK X`09Return`09`09`09;+AF4 Return to ASTQIO to restore registers X`09`09`09`09;+AF4 and exit the AST via ASTX$S X X`09.page X X`09.SBTTL`09--SUBROUTINES-- X`09.SBTTL`09NODADD`09- Add node to deque X; X; NODADD-`09Add node to deque list X; X; Inputs:`09R5 = Node address X;`09`09R4 = Prior node address X; X; Outputs:`09same X; X XNODADD:`09MOV`09R4,2(R5)`09; SETUP BACKWARD POINTER X`09MOV`09(R4),(R5)`09; SETUP FORWARD POINTER X`09MOV`09R5,(R4)`09`09; SETUP PRIOR FORWARD POINTER X`09MOV`09(R5),R5`09`09; POINT R5 TO NEXT NODE X`09MOV`09(R4),2(R5)`09; SETUP NEXT BACKWARD POINTER X`09MOV`09(R4),R5`09`09; RESTORE R5 X`09RETURN X X X`09.SBTTL`09NODDEL`09- Delete node from deque X; X; NODDEL-`09Delete node from dequeue list X; X; Inputs:`09R5 = Node address X; X; Outputs:`09same X; X XNODDEL:`09MOV`09(R5),@2(R5)`09; POINT PRIOR TO NEXT X`09MOV`09(R5),-(SP)`09; SAVE NEXT ADDRESS X`09ADD`09#2,(SP)`09`09; POINT TO NEXT BACWARD POINTER X`09MOV`092(R5),@(SP)+`09; POINT NEXT BACKWARD TO PRIOR X`09RETURN X X X`09.Page X`09.SBTTL`09ASTSAV - AST Register Save/Restore X X;+AF4`09ASTSAV routine added to TPC on 26-Jun-91 to fix a problem with X;+AF4`09the AST routines not saving/restoring the registers. Aaaaack!!! X;+AF4`09It took 14 years (and a super-fast disk controller) to find this bug V! X X;+ X; Save registers from AST and call caller back as a co-routine. X; On return from the user's code, restore the registers and X; exit the AST. Some entries set R3 to the optional parameter X; (while removing it from the stack). These are ASTQIO, ASTTIM X; ASTCLI, and ASTSTS. X; X; Call with:`09JSR`09R5, ASTxxx X; X; Exit with:`09AST dismissed X;- X X`09.Enabl`09LSB X XASTQIO::`09`09`09; QIO Completion XASTTIM::`09`09`09; Mark Time XASTCLI::`09`09`09; Command Arrival XASTSTS::`09`09`09; Offspring Status X`09Mov`09R3, -(SP)`09; Save R3 X`09Mov`094(SP), R3`09; Get optional parameter X`09Mov`092(SP), 4(SP)`09; Save R5 X`09Mov`09R4, 2(SP)`09; Save R4 X`09Br`091000$`09`09; and continue X XASTPWF::`09`09`09; Power Recovery XASTRCV::`09`09`09; Receive Data XASTRRF::`09`09`09; Receive-by-Reference XASTEXI::`09`09`09; Task Exit (non-extended) X`09Mov`09R4, -(SP)`09; Save R4 X`09Mov`09R3, -(SP)`09; ... R3 X1000$: X`09Mov`09R2, -(SP)`09; ... R2 X`09Mov`09R1, -(SP)`09; ... R1 X`09Mov`09R0, -(SP)`09; ... R0 X`09Call`09(R5)`09`09; Call caller back X; X; Return here via RTS PC after AST has been processed X; X`09Mov`09(SP)+, R0`09; Restore R0 X`09Mov`09(SP)+, R1`09; ... R1 X`09Mov`09(SP)+, R2`09; ... R2 X`09Mov`09(SP)+, R3`09; ... R3 X`09Mov`09(SP)+, R4`09; ... R4 X`09Mov`09(SP)+, R5`09; ... R5 X`09ASTX$S`09`09`09; Exit AST X X`09.Dsabl`09LSB X X .END BEGIN`09`09;JKN02 $ CALL UNPACK TPC.MAC;3 1333186793 $ v=f$verify(v) $ EXIT