.MCALL .MODULE .MODULE DUPIMA,VERSION=30,COMMENT=,IDENT=NO ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ; Edit History: ; ; 001 28-Jan-80 10:48 Guldenschuh, Chuck cpg [240,148] ; Correct "Volume not RT-11 format" problem ; (001) ; 002 30-Jan-80 01:52 Guldenschuh, Chuck cpg [240,148] ; Correct I/O error problem on COPY/DEVICE ; (002) ; 003 11-Nov-80 11:35 AM Fingerhut, David [240,134] ; Consider output vol size when doing COPY/DEV ; (003) ; 004 20-Mar-81 03:00 PM David Fingerhut [240,134] ; COPY with /START:0/END:0 copies entire disk ; (004) ; 005 31-Mar-81 01:08 PM David Fingerhut [240,134] ; Add cond'l ass'bly for /WAIT with IND ; (005) ; 006 15-Apr-81 03:28 PM David Fingerhut [240,134] ; Rename APCHAN to ACHAN ; (006) ; 007 22-Jul-81 09:00 AM David Fingerhut [240,134] ; Output error during COPY/DEV to input causes system halt ; (007) ; 008 30-Jul-81 11:19 AM David Fingerhut [240,134] ; COPY/DEV from large to small vol needs user confirmation ; (008) ; 009 28-Oct-81 10:32 AM David Fingerhut [40,134] ; Add COPY/DEVICE/REPLACE ; (009) ; 010 18-Dec-81 02:46 PM David Fingerhut [40,134] ; allow COPY/DEV/VERIFY to magtape ; (010) ; 011 18-Dec-81 03:38 PM David Fingerhut [40,134] ; Don't backup tape for /VER if MT is filestructured ; (011) ; 012 08-Feb-82 12:54 PM David Fingerhut [40,134] ; Fix COPY/DEV/REPL bug ; (012) ; 013 19-Jun-87 RHH Change ?DUP-W-Device Full to ?DUP-F... ; 014 05-JUL-88 GTS Restructured code. Added automatic retain ; when copying an RT-11 file structure device. Added capability ; to restore from magtape and retain BBR automatically. ; If result file structure is not RT-11, copy replacement blocks ; as well. ; 015 02-SEP-88 GTS Fix problem when /END and /FILE are used. Fix ; SDC conditionals. ; 027 24-Aug-89 George Stevens ; Added code to check for pre-V5.3 handler and fix comments ; 029 25-Sep-89 George Stevens ; Fixed error recovery for input error in CPYDAT routine ; 030 06-Nov-1990 JFW ; bracket error messages with ;+/;ERROR/.../;- .ENABL LC,GBL .SBTTL MACRO calls .MCALL .CSTAT .SBTTL PSECT definitions .IIF NDF MDUP, MDUP = 0 ;Default to no MDUP .IIF NDF M$UPD, M$UPD = 0 ;Default to no MDUP Update .IIF NDF SDC, SDC = 0 ;Default to no SDCOPY PSECT ...IFL ; Used for IMAFLG bit definitions PSECT ...ERS ; PSECT IMPURE ;Impure data PSECT .LIBD. ;Library data psect (error messages) PSECT .LIBP. ;Library pointer psect (error messages) PSECT PUREB ;[byte] Pure data PSECT IMAGE ;Code psect .SBTTL Error Messages .IF NE SDC .MACRO ERRMSG NAME,TEXT DS NAME,BYTE .PSECT .LIBD. EM.'NAME: .ASCII \TEXT\<200> .PSECT .LIBP. .WORD EM.'NAME .ENDM ERRMSG .MACRO MSGLST NAME .DSECT ...ERS,GLOBAL=NO .PSECT .LIBP. NAME: .WORD ..MAX. .ENDM MSGLST .MACRO MSGEND DS ..MAX.,BYTE .ENDM MSGEND ;+ ;ERROR MSGLST OERTAB ERRMSG VCM, ERRMSG CCM, MSGEND ;- .ENDC ;NE SDC .SBTTL Impure data PSECT IMPURE IMABFP: .WORD 0 ; Pointer to home block buffer IMAFLG: .WORD 0 ; Image copy flags FUDGEI: .WORD 0 ; SPFUN input file extra word flag FUDGEO: .WORD 0 ; SPFUN output file extra word flag .BSECT ...IFL BS INPRTS ; Input Rt-11 file structured when set BS OUTRTS ; Output RT-11 file structured when set BS RESRTS ; Result RT-11 file structured when set BS HOMMOD ; Home block being modified when set PSECT IMPURE DEVHND: .RAD50 /SY / ; Handler always resides on SY:. .WORD 0 ; Handler name plus suffix. .WORD 0 ; Always blank (zero). .RAD50 /SYS/ ; Handler extension is "SYS". BTLKBK: .WORD 0,0,0,0 ;For non file-structured lookup to boot device BTCSBK: .BLKW 6 ;For CSTAT on boot device ;+ ; The IGEOM and OGEOM tables have the following format: ; ; +-----------------------------+ ; | H.MOD from device handler | ; +---------------+-------------+ ; | 0 |H.REPL RGT.FG| Replacement table flags byte ; +-----------------------------+ ; | 0 |H.REPL RGT.PD| Replacement table pad byte ; +-----------------------------+ ; ; All data is gotten from block 0 of the device handler. See SYSTEM.MAC ; for definition of symbols. ;- ; IGEOM and OGEOM initialized by DVGEOM routine. IGEOM:: .BLKW 3 ; Area for input device geometry OGEOM:: .BLKW 3 ; Area for output device geometry DVM.DM=:2 ; SPFUN 377 & 376 returns added word FLAGS=: 2 ; Offset to flags word RGT.SM=:1 ; H.REPL bit for sometimes replacable RGT.SB=:2 ; H.REPL bit for software bad block repl. PAD=: 4 ; Offset to pad word .IF NE SDC ;Error message area block OEAREA: .BYTE 0 ; Error code byte .BYTE 0 ; Error level/return flag .WORD ERRPRE ; -> Error message prefix .WORD ERRLEV ; -> Error level byte .WORD OERTAB ; -> Error message offset table .WORD 0 ; -> File name block .WORD ABORT ; -> Abort return .ENDC ;NE SDC IOERR: .WORD 0 ;I/O error recovery in progress flag LSTMIS: .WORD -1 ;Block number of last verification error ERBLK:: .BLKW 4 ;Error and status info for SPFUN SAVIS: .WORD 0 ;Temp area for $ISFLG MSGVFE: .IF NE SDC .ASCII \?SDCOPY\ .IFF ;SDC .ASCII \?DUP\ .ENDC ;SDC .ASCII \-W-Verification error\ MSGIOE: .ASCII \ at relative block #\ BLKADR: .ASCIZ \000000\ .EVEN PSECT PUREB .NLIST BEX SYSID: .ASCII \DECRT11A \ SYSIDE: ; Used to determine length of SYSID string. ;+ ;ERROR MSGIER: .ASCII \?DUP-W-Input error \<200> MSGOER: .ASCII \?DUP-W-Output error \<200> MSGIMA: .ASCII \/Copy\<200> MSGDL3: .ASCIZ \Output device is smaller than input device\ MSGDLT: .ASCII \Output device is larger than input device\<200> MSGFST: .ASCIZ \Output file is smaller than input device\ MSGFS2: .ASCII \Output file will be truncated\<200> MSGDST: .ASCIZ \Output device is smaller than input file\ MSGDS2: .ASCII \Output device will be truncated\<200> MSGDLF: .ASCII \Output device is larger than input file\<200> ;- .EVEN .LIST BEX .SBTTL IMAGE - Image mode copy ;+ ; IMAGE ; IMAGE does an image copy of one device to another, of a file to a device, ; or of a device to a file. It will also verify the copy by reading back the ; output and comparing it with the input. Throughout this routine the ; register allocations are made: ; ; R0 - R2 - scratch ; R3 -> input buffer ; R4 = input block number ; R5 = output block number ; ; output file or device opened on OCHAN ; input file or device opened on ICHAN ; FLG.EN set in $OSFLG => output file must be closed ; ; JSR PC,IMAGE ; ; R0 - R5 modified ;- ORIGIN IMAGE MAGBFS=:8. ; Buffer size when verifying output to a magtape .ENABL LSB IMAGE:: CLR IMAFLG ; Clear image mode copy flags CLR FUDGEI ; Clear input file SPFUN extra word flag CLR FUDGEO ; Clear output file SPFUN extra word flag .IF EQ SDC SURE #OUTFIL,#MSGIMA,FG ; "Are you sure? " and FG check BEQ 10$ ; Branch if sure .PURGE #OCHAN ; Purge the output file JMP DONE ; Quit .ENDC ;EQ SDC ;+ ; Get buffer for home block to check structure type ;- 10$: .GTCOR #512.+2 ; Get buffer for home block & SPFUN xword BCS 20$ ; No blocks available CMP #512.+2,R1 ; Was at least requested size allocated? BLOS 30$ ; Branch if so 20$: JMP INSMEM ; Jump if insufficient memory 30$: MOV R0,IMABFP ; Save pointer to home block buffer CALL DVGEOM ; Get dev geometry (H.MOD H.REPL(flag & pad)) BIT #FL.FIL,$MFLAG ; File image mode? BEQ 40$ ; Branch if not BIT #FLG.EN,$OSFLG ; Creating an image file? BNE 50$ ; Branch if so. No need for FGCHEK 40$: WAIT #WAITIN,#INFILE ; Wait, if necessary WAIT #WAITOU,#OUTFIL ; For output, also 50$: .DSABL LSB ;+ ; Get the input size in INSZ ;- .ENABL LSB INPSIZ: BIT #FL.FIL,$MFLAG ; Was /FILE specified? BEQ 10$ ; Branch if not, get input device size BIT #FLG.WD,$ISFLG ; Wildcard on input ? Filespec on output ? BNE 10$ ; Branch if so, get input device size TST REDSW ; Was /END specified with input file? BEQ 60$ ; Branch if not MOV REDEND,INSZ ; Save end block number INC INSZ ; Boundaries are inclusive BR 60$ ; Branch and continue - File size in INSZ 10$: TST REDSW ; Was /END specified with input device? BNE 20$ ; Branch if so MOV #INST,R0 ; R0 -> Input file .DSTATUS ret block MOV #$ISFLG,R1 ; R1 -> Input dev/file flag word MOV #ICHAN,R2 ; R2 = Input channel number CALL GTDVSZ ; Get the size of the input device MOV R1,INSZ ; Save input size BR 30$ 20$: MOV REDEND,INSZ ; Save end block number INC INSZ ; Boundaries are inclusive ; Determine if device supports software bad block replacement 30$: BIT #RGT.SB,IGEOM+FLAGS ; Input dev support bad block replacement? BEQ 70$ ; Branch if not ; Determine structure type (RT-11 or non-RT-11) MOVB #1,SPFUNI ; Use .SPFUNs on input device BIT #DVM.DM,IGEOM ; Is extra word returned on SPFUN request? BEQ 40$ ; Branch if not MOV #2,FUDGEI ; Setup input file SPFUN extra word flag 40$: MOV #1,R1 ; R1 = Block number of home block MOV #ICHAN,R2 ; R2 = Input channel number MOV #INFILE,R3 ; R3 -> Input file spec CALL STRTYP ; Get structure type (RT or non-RT) BCC 50$ ; Branch if RT-11 file structure ; Structure is not an RT-11 file structure, copy pad blocks as well TST REDSW ; Was /END specified with input file? BNE 70$ ; Branch if so ADD IGEOM+PAD,INSZ ; Add pad blocks to blocks to be copied BR 70$ 50$: CLRB SPFUNI ; Use .READs on input device CLR FUDGEI ; Clear SPFUN extra word flag 60$: BIS #INPRTS,IMAFLG ; Set input RT-11 file structure flag 70$: SUB REDSTR,INSZ ; Sub start block - that's the size .DSABL LSB ;+ ; Determine the result structure type (RT-11 or non-RT-11) ;- .ENABL LSB RESTYP: MOV FUDGEI,-(SP) ; Save input file SPFUN extra word flag BIT #FL.FIL,$MFLAG ; Doing /FILE ? BEQ 10$ ; Branch if not BIT #FLG.WD,$OSFLG ; Filespec on output ? Wildcard on input ? BEQ 50$ ; Branch if so ; Determine if output device supports software bad block replacement ; if so, use SPFUNs on output device 10$: BIT #RGT.SB,OGEOM+FLAGS ; Output device support software BBR? BEQ 20$ ; Branch if not MOVB #1,SPFUNO ; Use .SPFUNs on output device BIT #DVM.DM,OGEOM ; Is extra word returned on SPFUN request? BEQ 20$ ; Branch if not MOV #2,FUDGEO ; Setup output file SPFUN extra word flag ; Determine if home block being modified and get new structure type 20$: MOV REDSTR,R1 ; Get read /START value CMP #1,WRTSTR ; Is home block part of transfer? BLO 40$ ; Branch if not BEQ 30$ ; Branch if so CMP #1,INSZ ; Is this a single block copy? BEQ 40$ ; Branch if so INC R1 ; Input block number to replace home block ; Determine result structure type - home block being modified 30$: BIS #HOMMOD,IMAFLG ; Set home block being modified flag MOV #ICHAN,R2 ; R2 = Input channel number MOV #INFILE,R3 ; R3 -> Input file spec CALL STRTYP ; Get structure type (RT or non-RT) BCS 70$ ; Branch if result not RT-11 file structure BIS #RESRTS,IMAFLG ; Set result RT-11 file structured flag ; Determine if output device/file contains block 2 (the home block) 40$: MOV OUTSZ,R1 ; Assume file, get size into R1 BIT #FL.FIL,$MFLAG ; Doing /FILE? BEQ 43$ ; Branch if not BIT #FLG.WD,$OSFLG ; Filspec on output ? Wildcard on input ? BEQ 46$ ; Branch if so 43$: MOV #OUTST,R0 ; R0 -> output file .DSTATUS ret block MOV #$OSFLG,R1 ; R1 -> output dev/file flag word MOV #OCHAN,R2 ; R2 = output channel number CALL GTDVSZ ; Get the size of the output device 46$: CMP #2,R1 ; Is home block on the device? BHI 70$ ; Branch if not ; Determine structure type of output device BIT #,OUTST ; Is output device directory-structured BEQ 70$ ; Branch if not MOV FUDGEO,FUDGEI ; Set FUDGEI for STRTYP MOV #1,R1 ; R1 = Block number of home block MOV #OCHAN,R2 ; R2 = output channel number MOV #OUTFIL,R3 ; R3 -> Output file spec CALL STRTYP ; Get structure type (RT or non-RT) BCS 70$ ; Branch if not RT-11 home block CLRB SPFUNO ; Use .READ/.WRITE on output device CLR FUDGEO ; Clear output file SPFUN extra word flag 50$: BIS #OUTRTS,IMAFLG ; Set output RT-11 file structured flag BIT #HOMMOD,IMAFLG ; Is home block being modified? BNE 70$ ; Branch if so 60$: BIS #RESRTS,IMAFLG ; Set result RT-11 file structured flag 70$: MOV (SP)+,FUDGEI ; Restore input file SPFUN extra word flag .DSABL LSB ;+ ; Get the output size in OUTSZ ;- .ENABL LSB OUTSIZ: BIT #FL.FIL,$MFLAG ; Doing /FILE ? BEQ 10$ ; Branch if not BIT #FLG.WD,$OSFLG ; Filespec on output ? Wildcard on input ? BEQ 20$ ; Branch if so 10$: MOV #OUTST,R0 ; R0 -> output file .DSTATUS ret block MOV #$OSFLG,R1 ; R1 -> output dev/file flag word MOV #OCHAN,R2 ; R2 = output channel number CALL GTDVSZ ; Get the size of the output device MOV R1,OUTSZ ; Save output size BIT #RESRTS,IMAFLG ; Is result RT-11 file structured? BNE 20$ ; Branch if so ADD OGEOM+PAD,OUTSZ ; Add pad blocks to blocks to be copied 20$: SUB WRTSTR,OUTSZ ; Subtract start block to get output size MOV #FREMLH,R0 ; R0 -> Free memory list head MOV #512.,R1 ; R1 = Size of block to be released MOV IMABFP,R2 ; R2 = Address of the block being released CALL $RLCB ; Release the home block buffer .DSABL LSB ;+ ; Compare input size to output size and report any size difference ; - if output is a file, output size can be greater than input size ; ; Figure out which size is smaller and put in R1 ; If either one doesn't have a size, use the other ;- .ENABL LSB CMPSIZ: TST INSZ ; Does input have a size? BNE 10$ ; Branch if so BR 30$ ; Branch if not 10$: TST OUTSZ ; Does output have a size? BNE 20$ ; Branch if so JMP USEINP ; Branch if not ; They both have sizes, use the smaller 20$: CMP OUTSZ,INSZ ; Sizes the same ? BNE 40$ ; Branch if not 30$: JMP USEOUT ; Jump if so 40$: BLO INPBIG ; Branch if output smaller JMP OUTBIG ; Jump if output bigger than input .DSABL LSB ; *** Hit here know that output is smaller than input *** ; Don't tell user about different *DEVICE* sizes if /FILE option specified ; and he's COPY/DEV/FILE *TO* a file. Tell him output file is truncated. ; If copying from a file, let him know of different sizes .ENABL LSB INPBIG: BIT #FL.FIL,$MFLAG ; Doing /FILE ? BEQ 40$ ; Branch if not BIT #FLG.WD,$ISFLG ; Wild card on input? Filespec on output? BEQ 20$ ; Branch if not - Filespec on input. ; Output file is smaller than input device, truncate output file BIT #FL.YES,$MFLAG ; /Y option specified (/NOQ)? BNE 10$ ; Branch if so - Just give message, don't ask ;+ ;ERROR .PRINT #MSGFST ; Tell user output file smaller than inp dev ;- SURE #0,#MSGFS2 ; Tell user trun output and ask 'Are you sure? BNE 50$ ; Branch if response is 'No' - Go quit BR 70$ ; Branch if response is 'Yes' ;+ ;ERROR 10$: .ERR #ERAREA,#FST,LEVEL=ERROR,RETURN=YES .ERR #ERAREA,#FS2,LEVEL=ERROR,RETURN=YES ; Output file is smaller than input device, truncated ;- BR 70$ ; and continue 20$: BIT #FL.YES,$MFLAG ; /Y option specified (/NOQ)? BNE 30$ ; Branch if so - Just give message, don't ask ;+ ;ERROR .PRINT #MSGDST ; Tell user output dev is small than input fil ;- SURE #0,#MSGDS2 ; Tell user trun output and ask 'Are you sure? BNE 50$ ; Branch if response is 'No' - Go quit BR 70$ ; Branch if response is 'Yes' ;+ ;ERROR 30$: .ERR #ERAREA,#DST,LEVEL=ERROR,RETURN=YES .ERR #ERAREA,#DLD,LEVEL=ERROR,RETURN=YES ; Output device is smaller than input file, truncated ;- BR 70$ ; and continue 40$: BIT #FL.YES,$MFLAG ; /Y option specified (/NOQ)? BNE 60$ ; Branch if so - Just give message, don't ask ;+ ;ERROR .PRINT #MSGDL3 ; Tell user output dev smaller than inp dev ;- SURE #0,#MSGDS2 ; Tell user trun output and ask 'Are you sure? BEQ 70$ ; Branch if response is 'Yes' 50$: JMP DONE ; Branch if response is 'No' - Go quit ;+ ;ERROR 60$: .ERR #ERAREA,#DL2,LEVEL=ERROR,RETURN=YES .ERR #ERAREA,#DLD,LEVEL=ERROR,RETURN=YES ; Output device smaller than input device, truncated ;- 70$: BR USEOUT ; and continue .DSABL LSB ; Hit here know that output is larger, ask him if he is sure .ENABL LSB OUTBIG: BIT #FL.FIL,$MFLAG ; Doing /FILE ? BEQ 10$ ; Branch if not BIT #FLG.WD,$ISFLG ; Wildcard on input ? Filespec on output ? BEQ 30$ ; Branch if not - Filespec on input BR USEINP ; Don't say anything if outputting to a ; file that is bigger, it will be shortened 10$: BIT #FL.YES,$MFLAG ; /Y option specified (/NOQ)? BNE 20$ ; Branch if so - Just give message, don't ask ;+ ;ERROR SURE #0,#MSGDLT ; Tell user out bigger and ask 'Are you sure ? ;- BNE 40$ ; Branch if response is 'No' - Go quit BR USEINP ; Branch if response is 'Yes' ;+ ;ERROR 20$: .ERR #ERAREA,#DLT,LEVEL=WARN,RETURN=YES ; OUTPUT DEVICE IS LARGER THAN INPUT DEVICE ;- BR USEINP ; BRANCH AND CONTINUE 30$: BIT #FL.YES,$MFLAG ; /Y option specified (/NOQ)? BNE 50$ ; Branch if so - Just give message, don't ask ;+ ;ERROR SURE #0,#MSGDLF ; Tell user out bigger and ask 'Are you sure ? ;- BEQ USEINP ; Branch if response is 'Yes' 40$: JMP DONE ; Branch if response is 'No' - Go quit ;+ ;ERROR 50$: .ERR #ERAREA,#DLF,LEVEL=WARNING,RETURN=YES ; OUTPUT DEVICE IS LARGER THAN INPUT FILE ;- .DSABL LSB ; Enter at USEINP or USEOUT depending on size determination above. ; Allocate buffers for subsequent I/O operation. .ENABL LSB USEINP: MOV INSZ,R1 ; Use input size BR 10$ USEOUT: MOV OUTSZ,R1 ; Use output size 10$: BNE 20$ ; Branch if so DEC R1 ; Make the size -1 20$: MOV R1,REDEND ; Put into REDEND MOV #-2,R1 ; Assume not verifying output to magtape BIT #DEV.MT,$OSFLG ; Writing to Magtape? BEQ 30$ ; Branch if not BIT #FL.VER,$MFLAG ; Doing a verify copy? BEQ 30$ ; Branch if not MOV #+4,R1 ; Use smaller bfr when outputting to MT 30$: .GTCOR ; Go get it BCC 40$ ; Branch if we got it ;+ ;ERROR INSMEM: .ERR #ERAREA,#FE.NOM,LEVEL=FATAL,RETURN=NO ; <-F-Insufficient memory> ;- 40$: ;CLC ; Can't get here without carry clear ROR R1 ; Make the amount words SUB #2,R1 ; Reserve 2 words for SPFUN extra word BIC #377,R1 ; Get number of blocks in hi byte BEQ INSMEM ; Branch if not enough memory BIT #FL.VER,$MFLAG ; Doing a verify copy? BEQ 50$ ; Branch if not BIC #777,R1 ; Need an even number of blocks ; R1 = bytes per buffer BEQ INSMEM ; Branch if not enough memory MOV R1,OBFBEG ; Save the offset to the compare buffer ADD #2,OBFBEG ; Reserve 1 word/buffer for SPFUN extra word ASR R1 ; Get number of words/buffer 50$: MOV R1,IOSIZ ; Save the number of words/transfer SWAB R1 ; Get the number of blocks CMP #2,R1 ; Must have at least 2 blocks BHI INSMEM ; Branch if not enough memory MOV R1,BUFSIZ ; Save it MOV R0,R3 ; R3 = start address of the input buffer MOV R0,IMABFP ; Save addres of input buffer ADD R0,OBFBEG ; Add start to compare buffer offset MOV REDSTR,R4 ; R4 = read start block number MOV WRTSTR,R5 ; R5 = write start block number .DSABL LSB ;+ ; Copy up to and including home block ; preserve home block on output media ;- .ENABL LSB CPYHOM: BIT #HOMMOD,IMAFLG ; Is home block being modified by copy? BEQ 70$ ; Branch if not BIT #RESRTS,IMAFLG ; Is result RT-11 file structured? BEQ 70$ ; Branch if not TST R5 ; Is write start block number = 0 ? BNE 10$ ; Branch if not ;********************************************************************** ; The rest of the code on this page is executed if the result will ; produce an RT-11 file structured disk and the home block is being ; modified. ;********************************************************************** ; Copy block 0 MOV IOSIZ,-(SP) ; Save # words/transfer MOV BUFSIZ,-(SP) ; Save # blocks/transfer MOV REDEND,-(SP) ; Save # block left to transfer MOV #1,REDEND ; Transfer 1 block CALL CPYDAT ; Copy block 0 only MOV (SP)+,REDEND ; Restore # blocks left to read DEC REDEND ; One block just transfered MOV (SP)+,BUFSIZ ; Restore # blocks/transfer MOV (SP)+,IOSIZ ; Restore # words/transfer ; Copy block 1 MOV IMABFP,R3 ; R3 -> input buffer 10$: TST FUDGEI ; Is extra word returned? BNE 20$ ; Branch if so ADD FUDGEO,R3 ; Allow space for extra word needed on output 20$: READ #IOAREA,#ICHAN,R3,#256.,R4 ; Read home block from input device BCC 30$ ; Branch if no error MOV #INFILE,R1 ; R1 -> Output file spec BR 40$ ; Report the error 30$: ADD FUDGEI,R3 ; Add input file SPFUN extra word flag ; R3 -> data read (excluding extra word) BIT #RGT.SB,OGEOM+FLAGS ; Does output device support software BBR? BEQ 80$ ; Branch if not - clear BBR table BIT #OUTRTS,IMAFLG ; Is output device RT-11 file structured? BEQ 80$ ; Branch if not .READW #IOAREA,#OCHAN,R3,#101,R5 ; Read output device's BBR ; table on top of input device's BBR ; table now in memory. BCS OUTRDE ; Branch if error BR 100$ ; ENTER FROM VFYHOM AT OUTRDE (OUTPUT READ ERROR) IF AN ERROR OCCURS WHILE ; EITHER READING DATA JUST WRITTEN OR FORCED RE-READ OF REPLACEMENT TABLE. OUTRDE: MOV #OUTFIL,R1 ; R1 -> Output file spec ;+ ;ERROR 40$: MOV #FE.INE,R2 50$: BIT #RGT.SB,OGEOM+FLAGS ; Does output device support software BBR? BEQ 60$ ; Branch if not - clear BBR table BIC #FL.IGN,$MFLAG ; Can't ignore this one!!!! 60$: CALL RPTERR ; Report error and maybe return ;- DEC REDEND ; One block just transfered - unsuccessfully 70$: BR CPYDAT ; Go do the rest 80$: MOV R3,R2 ; Get pointer to home block data CLR (R2)+ ; Put DW pattern into BBR table ; (0, 170000, 007777) MOV #170000,(R2)+ MOV #7777,(R2)+ MOV #101-3,R0 ; Setup count to clear rest of BBR table 90$: CLR (R2)+ ; Clear an entry SOB R0,90$ ; Loop till done ; Compute checksum for home block 100$: MOV R5,-(SP) ; Preserve R5 MOV R3,R5 ; R5 -> Home block buffer CALL CKSMHB ; Compute home block checksum MOV (SP)+,R5 ; Restore R5 ; Write out data SUB FUDGEO,R3 ; Allow for extra word if needed WRITE #IOAREA,#OCHAN,R3,#256.,R5 ; Write home block to output device BCC 110$ ; Branch if no error MOV #OUTFIL,R1 ; R1 -> Output file spec MOV #FE.OPE,R2 BR 50$ ; Go give the error 110$: ADD FUDGEO,R3 ; R3 -> data read (excluding extra word) .DSABL LSB ;+ ; Verify data just copied if verify mode enabled ;- .ENABL LSB VFYHOM: BIT #FL.VER,$MFLAG ; Doing a verify copy? BEQ 30$ ; Branch if not SWAB SPFUN ; Switch the .SPFUN flags MOV $ISFLG,SAVIS ; Save the input flag word MOV $OSFLG,$ISFLG ; Switch the flag words for $READ READ #IOAREA,#OCHAN,OBFBEG,#256.,R5 ; Read in the data BCS OUTRDE ; Branch if error SWAB SPFUN ; Restore .SPFUN flags MOV SAVIS,$ISFLG ; Restore the flag word MOV OBFBEG,R0 ; R0 -> compare buffer ADD FUDGEO,R0 ; Add output file SPFUN extra word flag MOV R3,R1 ; R1 -> input buffer MOV #256.,R2 ; R2 = number of words 10$: CMP (R0)+,(R1)+ ; Compare output to input BEQ 20$ ; Branch if the same CALL VERR ; Go process the error 20$: SOB R2,10$ ; Loop 30$: INC R4 ; R4 = read start block number INC R5 ; R5 = write start block number DEC REDEND ; REDEND = number of blocks to transfer BIT #RGT.SB,OGEOM+FLAGS ; Output device support software BBR? BEQ 40$ ; Branch if not .SPFUN #IOAREA,#OCHAN,#SF.IRT ; Force reread of bad block repl. table BCS OUTRDE ; Branch if error 40$: CLRB SPFUNO ; Use .READ/.WRITE on output device CLR FUDGEO ; Clear output file SPFUN extra word flag .DSABL LSB ;+ ; Copy remaining data from the input device to the output device ;- .ENABL LSB CPYDAT: MOV REDEND,R0 ; R0 = # of blocks to transfer BNE CPYDT1 ; Branch if not done JMP DONE ; Jump if done CPYDT1: MOV IMABFP,R3 ; R3 -> input buffer TST FUDGEI ; Is extra word returned? BNE 10$ ; Branch if so ADD FUDGEO,R3 ; Allow space for extra word needed on output 10$: CMP R0,BUFSIZ ; More blocks to transfer than in buffer? BHIS 20$ ; Branch if so MOV R0,BUFSIZ ; If not, read the remaining blocks SWAB R0 ; Make block count into word count MOV R0,IOSIZ ; Save it 20$: READ #IOAREA,#ICHAN,R3,IOSIZ,R4 ;Go read a buffer load BCC 30$ ; Branch if no error JMP CIRDER ; Jump if not - branch out of range 30$: ADD FUDGEI,R3 ; Add input file SPFUN extra word flag ; R3 -> data read (excluding extra word) MOV R0,IOSIZ ; Save the amount actually transfered ADD #377,R0 ; Round up extra words to next highest block BIC #377,R0 ; SWAB R0 ; Make word count into block count MOV R0,BUFSIZ ; Save it ADD R0,R4 ; Update the input block number .IF NE SDC BIT #FL.VER,$MFLAG ; Doing a verify? BNE 40$ ; Branch if so. Don't write .ENDC ;NE SDC SUB FUDGEO,R3 ; Allow for extra word if needed WRITE #IOAREA,#OCHAN,R3,IOSIZ,R5 ; Go write the buffer BCS COWRER ; Branch on error ADD FUDGEO,R3 ; R3 -> data read (excluding extra word) BIT #FL.VER,$MFLAG ; Doing a verify copy? BEQ 70$ ; Branch if not 40$: SWAB SPFUN ; Switch the .SPFUN flags MOV $ISFLG,SAVIS ; Save the input flag word MOV $OSFLG,$ISFLG ; Switch the flag words for $READ READ #IOAREA,#OCHAN,OBFBEG,IOSIZ,R5 ; Read in the data BCS CVRDER ; Branch if error SWAB SPFUN ; Restore .SPFUN flags MOV SAVIS,$ISFLG ; Restore the flag word MOV OBFBEG,R0 ; R0 -> compare buffer ADD FUDGEO,R0 ; Add output file SPFUN extra word flag MOV R3,R1 ; R1 -> input buffer MOV IOSIZ,R2 ; R2 = number of words 50$: CMP (R0)+,(R1)+ ; Compare output to input BEQ 60$ ; Branch if the same CALL VERR ; Go process the error 60$: SOB R2,50$ ; Loop 70$: ADD BUFSIZ,R5 ; Update the output block number CONCPY: MOV REDEND,R0 ; Get the # of blocks we have left to transfer SUB BUFSIZ,R0 ; Subtract out the number of blocks done MOV R0,REDEND ; Save the number left to transfer BNE CPYDT1 ; Branch if anything left to transfer BR CHKDON ; Jump if done - branch out or range .DSABL LSB ;+ ; Routines to handle error retry and recovery ;- ; COPY OUTPUT WRITE ERROR .ENABL LSB COWRER: MOV #OUTFIL,-(SP) ; @SP -> output file spec MOVB @#S$EERB,R1 ; Get the EMT error byte BEQ 10$ ; Branch if write past EOF MOV #FE.OPE,R2 ; Assume an output error SUB BUFSIZ,R4 ; Reset input block to start of transfer BR RDWRER ; Go check it out 10$: MOV (SP)+,R3 ; R3 -> output file spec ;+ ;ERROR .ERR #ERAREA,#FE.DVF,LEVEL=FATAL,RETURN=YES,FILE=R3 ;- BR DONE ; Done .DSABL LSB ; COPY VERIFY READ ERROR CVRDER: SWAB SPFUN ; Restore .SPFUN flags MOV SAVIS,$ISFLG ; Restore the flag word SUB BUFSIZ,R4 ; Reset input block to start of transfer MOV #OUTFIL,-(SP) ; Point to the output file name MOVB @#S$EERB,R1 ; Get the EMT error byte BNE INPERR ; Branch if it's not EOF ;+ ;ERROR .ERR #ERAREA,#FE.SYS,LEVEL=UABORT,RETURN=NO,FILE=R3 ; <-U-System error> ; The reason for this system error is that we got EOF reading what we ; just got finished writing. ;- ; COPY INPUT READ ERROR CIRDER: MOVB @#S$EERB,R1 ; Get the EMT error byte BEQ CHKDON ; Branch if EOF MOV #INFILE,-(SP) ; @SP -> input file spec ;+ ;ERROR INPERR: MOV #FE.INE,R2 ; Assume an input error .ENABL LSB RDWRER: DEC R1 ; Is that the case? BEQ 10$ ; Branch if so ;- MOV (SP)+,R3 ; R3 -> filename ;+ ;ERROR .ERR #ERAREA,#FE.CNO,LEVEL=FATAL,RETURN=NO,FILE=R3 ; <-F-Channel not open dev:filename> ; ; At this point, either an input or output error occurred. ; ; If the block size for the transfer is 1, there's really nothing to be ; done, so give an error message and skip the block on both input and ; output. Note that before getting here, the input block number is ; adjusted to be the input block number at the start of the transfer. ; ; If the block size for the transfer is > 1, then save vital variables ; and make the block size = 1. Then restart the transfer. ; ; R2 = error code ; @SP -> filename for error message ; ;- ;+ ;ERROR 10$: CMP BUFSIZ,#1 ; Already in single block transfer mode? BEQ 20$ ; Branch if so ;- MOV IOSIZ,@SP ; Save # words/transfer MOV BUFSIZ,-(SP) ; Save # blocks/transfer MOV REDEND,-(SP) ; Save # blocks left to transfer MOV BUFSIZ,R0 ; R0 = # blocks in last transfer MOV R0,REDEND ; Make it # blocks left MOV #1,R1 ; R1 = # blocks/transfer MOV R1,BUFSIZ ; Set buffer size SWAB R1 ; Make it words MOV R1,IOSIZ ; Save it INC IOERR ; Say we're processing an I/O error JMP CPYDT1 ; Go retry transfer in single block mode ;+ ;ERROR 20$: MOV (SP)+,R1 ; R1 -> filename CALL RPTERR ; Report the error and maybe return ;- BR CONCPY ; Continue with copy .DSABL LSB ;+ ; Routine to check for done. ;- .ENABL LSB CHKDON: TST IOERR ; Was error recovery in progress? BEQ 10$ ; Branch if not CLR IOERR ; Clear error recovery in progress flag MOV (SP)+,REDEND ; Restore # blocks left to read MOV (SP)+,BUFSIZ ; and # blocks/transfer MOV (SP)+,IOSIZ ; and # words/transfer BR CONCPY 10$: .IF EQ SDC DONE: RETURN .IFF ;EQ SDC BIT #FLG.EN,$OSFLG ; Creating an image file? BNE DONRET ; Branch if so DONE: BIT #FL.VER,$MFLAG ; Doing a verify? BEQ 10$ ; Branch if not CMP LSTMIS,#-1 ; Did it verify? BNE DONRET ; Branch if not ;+ ;ERROR MOV #VCM,R1 ; Say that we're done BR 20$ ; 10$: MOV #CCM,R1 ; Say that the copy is complete 20$: .ERR #OEAREA,R1,LEVEL=INFORM,RETURN=YES ;- DONRET: RETURN .ENDC ;EQ SDC .DSABL LSB .SBTTL STRTYP - Determine if media is RT-11 ;+ ; STRTYP ; This routine checks the home block to determine if it is an RT-11 ; home block. This is done by checking to see if bytes 760 thru 773 ; contains "DECRT11A " and that the first word in the home block ; is 0 or greater than or equal to 8. ; ; R1 = Block number of home block ; R2 = Channel number ; R3 -> File spec ; FUDGEI = SPFUN extra word flag ; ; CALL STRTYP ; ; C = 0 Media is an RT-11 file structure ; C = 1 Media is not an RT-11 file structure ;- .ENABL LSB STRTYP: SAVE05 ; Preserve all registers CMP #OCHAN,R2 ; Acting on output channel? BNE 10$ ; Branch if not SWAB SPFUN ; Swap SPFUNI and SPFUNO flags MOV $ISFLG,SAVIS ; Save the input flag word MOV $OSFLG,$ISFLG ; Switch the flag words for $READ 10$: READ #IOAREA,R2,IMABFP,#256.,R1 ; Read home block BCC 20$ ; Branch if no error ;+ ;ERROR .ERR #ERAREA,#FE.INE,LEVEL=FATAL,RETURN=NO,FILE=R3 ; <-F-Input error> ;- 20$: CMP #OCHAN,R2 ; Acting on output channel? BNE 30$ SWAB SPFUN ; Restore .SPFUN flags MOV SAVIS,$ISFLG ; Restore the flag word 30$: MOV IMABFP,R1 ; Get address of home block ADD FUDGEI,R1 ; Add SPFUN extra word flag TST (R1) ; Is first word equal to zero? BEQ 40$ ; Branch if so CMP #8.,(R1) ; Is First word >= 8.? BHI 60$ ; Branch if not 40$: ADD #760,R1 ; Point to system ID MOV #SYSID,R2 ; Point to expected system ID MOV #,R0 ; Setup loop count to comare ID 50$: CMPB (R1)+,(R2)+ ; Are these characters the same? BNE 60$ ; Branch if not SOB R0,50$ ; Loop till done TST (PC)+ ; Skip and clear carry 60$: SEC ; Set carry - not an RT-11 structure RETURN .DSABL LSB .SBTTL DVGEOM - Get device geometry ;+ ; DVGEOM ; This routine gets the device geometry table from the device handler. ; ; CALL DVGEOM ; ; IGEOM ; OGEOM - device geometry tables are loaded with device geometry ; information from the device handler as follows: ; ; 15 8 7 0 ; +-----------------------------+ ; | H.MOD from device handler | ; +---------------+-------------+ ; | 0 |H.REPL RGT.FG| Replacement table flags byte ; +-----------------------------+ ; | 0 |H.REPL RGT.PD| Replacement table pad byte ; +-----------------------------+ ; ; All data is gotten from block 0 of the device handler. See SYSTEM.MAC ; for definition of symbols. ;- H.MOD =: 21 H.REPL =: 32 RGT.FG =: 0 RGT.PD =: 2 DVGEOM: MOV #INFILE,R1 ; Input file name MOV #ICHAN,R2 ; Input channel CALL GTGEOM ; Get device geometry MOV #OGEOM,R1 ; R1 -> output device table MOV #IGEOM,R2 ; R2 -> input device table MOV (R1)+,(R2)+ ; Save input device table MOV (R1)+,(R2)+ ; " " " MOV (R1)+,(R2)+ ; " " " MOV #OUTFIL,R1 ; Output file name MOV #OCHAN,R2 ; Output channel .ENABL LSB GTGEOM: SAVE05 ; Preserve all registers .CSTAT #IOAREA,R2,#BTCSBK ; Get status on the device MOV BTCSBK+12,DEVHND+2 ; Assume 2 letter device name already MOV @#S$RMON,R5 ; R5 -> RMON CMP #7,BTCSBK+10 ; Is the unit number greater than 7? BHIS 30$ ; Branch if not ;+ ; Get pointer to $PNAM2 and offset to $PNAME ;- ;******** MOV S.PNAM(R5),R4 ; R4 = offset from RMON to $PNAME. ADD R5,R4 ; R4 -> $PNAME MOV R4,R3 ; R3 -> $PNAME ; Calculate $SLOT*4 by searching for -1 at end of $ENTRY table 10$: CMP (R3)+,#-1 ; Search for end of $ENTRY table. BNE 10$ ; Keep going TST -(R3) ; R3 -> end of $ENTRY table SUB R4,R3 ; R3 = bytes in combined tables ;**** ; PREVIOUS SECTION AN BE UPDATED AS FOLLOWS FOR RT-11 V5.6 ; ; MOV S.PNAM(R5),R4 ; R4 = offset from RMON to $PNAME. ; ADD R5,R4 ; R4 -> $PNAME ; MOV $SLOT2(R5),R3 ; R3 = $SLOT*2 ; ASL R3 ; R3 = $SLOT*4 ;******** ; R3 now contains the value $SLOT*4; the size of 2 tables MOV R3,R0 ; Save $SLOT*4 value ASL R3 ; Calculate offset from $PNAME ADD R0,R3 ; to $PNAM2 $SLOT*4 * 3 TST (R3)+ ; + 2 for -1 at end of $ENTRY table ADD R3,R4 ; R4 -> $PNAM2 ;+ ; Find device name in $PNAM2 - must be there since unit # greater than 7 ;- 20$: CMP BTCSBK+12,(R4)+ ; Is this the entry? BNE 20$ ; Branch if not, loop till found ;+ ; Get 2 letter device name from corresponding entry in $PNAME ;- SUB R3,R4 ; R4 -> entry in $PNAME + 2 MOV -(R4),DEVHND+2 ; Get 2 letter device name ;+ ; Open the device handler file ;- 30$: ADD S.SUFF(R5),DEVHND+2 ; Merge the handler suffix .LOOKU #IOAREA,#16,#DEVHND,#0 ; Do a lookup for the handler file .READW #IOAREA,#16,IMABFP,#256.,#0 ; We read block 0 of the handler BCC 40$ ; Branch if no error ;+ ;ERROR .ERR #ERAREA,#FE.INE,LEVEL=FATAL,RETURN=NO,FILE=R1 ; <-F-Input error> ;- 40$: .PURGE #16 ; Purge channel MOV IMABFP,R2 ; R2 -> beginning of handler block 0 MOV #OGEOM,R1 ; Point to place to store device data CMP #^RHAN,(R2) ; Is device handle pre-V5.3? BNE 70$ ; Branch if so MOVB H.MOD(R2),(R1)+ ; Get device class modifier bits CLRB (R1)+ ; Clear high byte CLR (R1)+ ; Clear output device geometry info CLR (R1) ; " " " " TST -(R1) ; R1 -> place to store geometry info TST H.REPL(R2) ; Is there a replacement geometry tbl BEQ 60$ ; No ADD H.REPL(R2),R2 ; Point to replacement geometry table MOV #2,R0 ; Number of items to move 50$: MOVB (R2)+,(R1)+ ; Set data in low byte CLRB (R1)+ ; Clear high byte SOB R0,50$ ; Loop till done 60$: BR 80$ 70$: CLR (R1)+ ; Clear goemetry info CLR (R1)+ ; " CLR (R1)+ ; " 80$: RETURN .DSABL LSB .SBTTL RPTERR - Report error from copy operation ;+ ; RPTERR ; This routine either prints a fatal error message and aborts further ; execution or prints a warning message an continues. The action ; performed depends on whether /J (/IGNORE) was specified in the command ; line or not. ; ; When a warning message is printed, the block number printed is the block ; in error on the device specified. It may be either an input or an ; output block number depending on which device had the error. ; ; R1 -> RAD50 Filespec (INFILE or OUTFIL) ; R2 = Error code (FE.INE or FE.OPE) ; R4 = Input block number ; R5 = Output block number ; ; CALL RPTERR ; ; R4 incremented by 1 ; R5 incremented by 1 ;- .ENABL LSB ;+ ;ERROR RPTERR: BIT #FL.IGN,$MFLAG ; Ignore errors? BNE 10$ ; Branch if so .ERR #ERAREA,R2,LEVEL=FATAL,RETURN=NO,FILE=R1 ; <-F-Input error DEV:> ; <-F-Output error DEV:> ; Print prefix for warning message 10$: MOV #MSGIER,R0 ; Assume 'Input error' prefix CMP #FE.INE,R2 ; Is this an input error? BEQ 20$ ; Branch if so MOV #MSGOER,R0 ; Setup 'Output error' prefix 20$: .PRINT ; Print prefix ;- ; Put block number on stack MOV R5,-(SP) ; (SP) = blk number on output device of error CMP #INFILE,R1 ; Is this the input device? BNE 30$ ; Branch if not MOV R4,(SP) ; (SP) = block number on input device of error 30$: ; Print filespec SUB #20,SP ; Allocate space to store device on stack MOV R1,R0 ; R0 -> RAD50 fielspec MOV SP,R1 ; R1 -> Area to store filespec CALL $FNASC ; Convert filespec to ASCII MOVB #200,(R1)+ ; No following MOV SP,R0 ; R0 -> ASCII filespec string .PRINT ; Print it ADD #20,SP ; Restore the stack ; Put block number of error in message MOV #BLKADR,R0 ; R0 -> storage area for ASCII block number MOV (SP)+,R1 ; R1 = block number of error ;+ ;ERROR MOV #MSGIOE,R2 ; R2 -> error message.*Flag for $CBOMG!!! CALL $CBOMG ; Convert number to ASCII CLRB @R0 ; Make it ASCIZ ; Print remainder of warning message .PRINT R2 ; Print the message ;- BISB #UE.WRN,@#S$EERB ; Set the error byte INC R5 ; Bump input block number to skip bad block INC R4 ; Bump output block number to skip bad block RETURN .DSABL LSB .SBTTL VERR - Process verification errors ;+ ; VERR ; This routine processes verification errors. If the input and output does ; not compare and a message has not been output for this block, then the ; error message is printed. ; ; R0 -> output buffer where compare failed ; R5 = block number ; LSTMIS = block number from last message (-1 on the first pass) ; ; JSR PC,VERR ; ; LSTMIS = this block number ;- .ENABL LSB VERR: SAVE05 ; Preserve all registers TST -(R0) ; R0 -> word which caused error SUB OBFBEG,R0 ; Make R0 relative pointer ADD FUDGEO,R0 ; Add output file SPFUN extra word flag CLC ; ROR R0 ; Make it words BIC #377,R0 ; Block number in high byte SWAB R0 ; R0 = block number in output buffer ADD R0,R5 ; R5 = block number of miss CMP R5,LSTMIS ; Is it the same as last time BEQ 10$ ; Branch if so. Don't give error again MOV R5,LSTMIS ; Save this block number MOV #BLKADR,R0 ; R0 -> storage area for ASCII block number MOV R5,R1 ; R1 = block number of error ;+ ;ERROR MOV #MSGVFE,R2 ; R2 -> error message.*Flag for $CBOMG!!! CALL $CBOMG ; Convert number to ASCII CLRB @R0 ; Make it ASCIZ .PRINT R2 ; Print the message ;- BISB #UE.WRN,@#S$EERB ; Set the error byte 10$: RETURN .DSABL LSB .END