.MCALL .MODULE .MODULE BUPIMA,VERSION=15,IDENT=NO,COMMENT= ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL Disk-to-disk image copy ; 05-Jan-88 RHH V5.5 Work ; Macro References: .MCALL .PRINT, .CLOSE .MCALL .HERR, .SERR, .EXIT, .CSTAT, .PURGE, .WRITW .MCALL .WAIT, .READ, .FPROT, .DATE, .GTIM, .ASSUME .MACRO ...... .ENDM ; Offsets into BUQ prefix block BQ.S1LN =: 30 ; 1st section length BQ.SILN =: 32 ; intermediate section length BQ.SLLN =: 34 ; last section length BQ.TLLN =: 36 ; total saveset length (w/o prefixes) BQ.NOSC =: 40 ; number of sections in saveset BQ.SECN =: 42 ; section number BQ.DATE =: 46 ; saveset date BQ.TIME =: 50 ; saveset time (4 words) .PSECT IMADAT,D ; The following definitions describe the structure of the BUQ Prefix block ; Do not change the order of any values between the dashed lines. ; ------------------------------------------------------------------------- HDRARE: ; Header Area NPREFB: .WORD 1 ; No. of prefix blocks .RAD50 /BUP / ; Format ID of prefix block .WORD 5., 60. ; Major/Minor version numbers .WORD 0,0,0 ; Reserved words SSNAME: .BLKW 3 ; Saveset Name .WORD 0 ; SEC1LN: .WORD 0 ; First section length INTMLN: .WORD 0 ; Intermediate section lengths SECNLN: .WORD 0 ; Final section length TOTLLN: .WORD 0 ; Total saveset length NOSECS: .WORD 0 ; No. of sections in saveset THISEC: .WORD 0 ; This section number .WORD 0 ; SSDATE: .WORD 0 ; Date of backup HOUR: .WORD 0 ; Time-of-day MINUTE: .WORD 0 SECOND: .WORD 0 TICKS: .WORD 0 CMDPRE: .BLKW 41. ; Command line buffer HDREND =: . ; ------------------------------------------------------------------------- ; End of order-specific Prefix block data .SBTTL Local Data INITED::.WORD 0 ; Flag for comm with BUPINI DEVAVA: .WORD 0 ; Available Space on Out Device ENTGOT: .WORD 0 ; .ENTER Space in current out file DATEWD: .WORD 0 ; Date word JTIME: .BLKW 2 ; Place for time-ticks CVTBLK: .WORD 5 ; Arg block for CVTTIM .WORD JTIME .WORD HOUR .WORD MINUTE .WORD SECOND .WORD TICKS ; Variables for VERIFY ACTBLK: .WORD 0 ; Actual no. of blocks in transfer OVBLK: .WORD 0 ; BUP dev's block number for transfer LAST1: .WORD 0 ; current bad verification block OFFSET: .WORD 0 ; no. of blocks into buffer ; Text Strings .NLIST BEX BUPINF: .ASCII /?BUP-I-/<200> CREMSG: .ASCII /Creating/<200> APPMSG: .ASCII /Appending to/<200> ONVOL: .ASCII / output volume /<200> PROTFG: .BYTE 0 ; File protected flag .EVEN .SBTTL IMAGE - Main disk-to-disk BACKUP control code .PSECT IMACOP,I ;+ ; Begin a disk-to-disk backup operation. Get the input and output ; device names set up for messages, get the time/date, fetch handlers, ; open input, open first output volume. ;- .ENABL LSB IMAGEO:: MOV #OUTASC,R1 ; Get address of ASCII dev name MOV #DEVICE,R4 ; Get message address CALL SETNAM ; Copy output device names etc.. MOV #OUTASC,R1 ; Get address of ASCII dev name MOV #INIDEV,R4 ; Get message address CALL SETNAM ; Copy output device names etc.. CALL SETRES ; Setup "Mount input" message MOV #1,VOLNUM ; assume 1st volume is #1 .GTIM #EMTARE,#JTIME ; get system time MOV #CVTBLK,R5 MOV #CVTTIM,R0 CALL CALL$F ; Convert time to hours, min, sec .DATE ; get system date MOV R0,DATEWD MOV #CMDLIN,R0 ; Point to entered command line MOV #CMDPRE,R1 ; and to area in prefix block MOV #41.,R2 ; for length of command line, 10$: MOV (R0)+,(R1)+ ; copy it in to prefix block area DEC R2 BGT 10$ MOV #1,NPREFB ; Normally, use 1 prefix block MOV OUTFIL,DEVSPC MOV NHDRAD,R1 ; Get handler load address CALL FETHAN ; Fetch output device handler MOV R0,NHDRAD ; Update hdr addr for next handler. ; Open the (first) input file or device CALL INLOAD ; Go open input BCS 40$ ; On error, quit. CALL CPYINI ; Initialize buffer pointers MOV #1,THISEC ; Initialize section number ; Open the first output volume TSTB GIV.R ; /SUBSET? BPL 20$ ; Branch if not. MOV FILSIZ,ENTSIZ ; Request one file of exact size CLR NPREFB ; No prefix blocks BR 70$ ...... 20$: TSTB GIV.Z ; /INITIALIZE? BPL 30$ ; Branch if not. MOV #1,VOLNUM ; If so, set VOLUME_NUMBER = 1 30$: TSTB GIV.Y ; /NOQUERY? BMI 50$ ; skip 1st MOUNT OUTPUT prompt IMAPRO: CMP THISEC,#1 ; section 1? BHI CNTCPY ; If not, continue below. CALL PROM1 ; "Mount output volume" PROMPT routine BCC 50$ ; Branch if YES entered. 40$: RETURN ; Otherwise quit. ...... 50$: CALL OPENOV ; Open output volume, (NFS) BCS 40$ ; Quit on errors 60$: CALL CHKSTA ; Check status & maybe init outdev ROR R1 ; Save status of check (C-bit) .CLOSE OUTCHA ; Close it (NFS) ROL R1 ; Get CHKSTA result BCS IMAPRO ; Repeat prompt if not suitable. MOV #-1,ENTSIZ ; For 1st section, request largest 70$: JMP STRTOV ; Skip forced init for 1st section ...... ;+ ; Continuation of the copy loop. (Section > 1). Initialize the new ; output volume and then close the channel. Do a .ENTER to create ; the SAVESET. (This code is not executed for the first section) ;- 80$: .PURGE OUTCHA ; free channel CNTCPY: CALL PROM1 ; "Mount next output vol" prompt BCC 90$ ; Branch if YES entered CALL QABOR ; Double check abort BR CNTCPY ; Repeat message ...... 90$: CALL OPENOV ; Open Output Volume, NFS BCC 100$ ; branch on success JMP OUTERR ; on error, try another volume ...... 100$: CLR INITED ; Assume no initialize will happen CALL INITD3 ; Initialize NEXT Output Volume BCS 80$ ; Quit on error ...... ;+ ; The next output volume is mounted, inited, and ready to go. Determine ; the length of this saveset section. Close the NFS channel, and create ; the saveset section file. ;- 110$: MOV INTMLN,R0 ; Use INTERMEDIATE section length CMP THISEC,NOSECS ; unless doing the FINAL BLO 120$ ; section. In that case, MOV SECNLN,R0 ; use the FINAL length. 120$: MOV R0,BLKCOP ; No. of data blocks to xfer ADD NPREFB,R0 ; add in no. of prefix blocks MOV R0,ENTSIZ ; for .ENTER size. .CLOSE OUTCHA ; Close (NFS opened) BCC STRTOV JMP 40$ ; On error, quit. ...... ; The output disk is ready with a valid directory and home block. ; Create BACKUP Saveset on the output disk. STRTOV: MOV #OUTFIL,R3 ; point to DBLK for .ENTER MOV OUTCHA,R2 ; output channel CALL ENTERD ; Open OUTPUT file BCS 130$ ; If it fails, try another. MOV R0,ENTGOT ; Save #blocks available CMP R0,CONBLK ; entire container portion must fit BHIS 150$ ; Branch if it does. 130$: .PURGE OUTCHA ; If not, get rid of it TSTB GIV.R ; /SUBSET? BPL 140$ ; Branch if not. JMP START2 ; (error already displayed) ...... 140$: JMP IMAPRO ; and prompt for another volume. ...... ; Output saveset section is now open. If this is section 1, determine ; no. of volumes necessary, and blocks to copy. 150$: CMP THISEC,#1 ; Unless doing section 1, BHI 170$ ; BLKCOP already determined by CHKSTA CALL INPINF ; Calculate no. of sections necessary BCS 130$ ; Branch on error MOV CONBLK,REMFIL ; Get container size for zeroth file BIT #I$OPT,OPTACT ; /DEVICE? BEQ 160$ ; branch if not. MOV FILSIZ,REMFIL ; /DEVICE blocks remaining to copy 160$: MOV SEC1LN,BLKCOP ; no. of blks to copy, 1st section 170$: CLR OUTBLK ; Init. log. blk. no. of out section ; Log the transfer on the console TSTB GIV.W ; printing log stuff? BMI 180$ ; branch if not. CALL VOLLOG ; Log the transfer on the console ; Put .ENTER's DBLK in Header area 180$: MOV #,R0 MOV #SSNAME,R1 ; point to header's name field .REPT 3 MOV (R0)+,(R1)+ ; move name to header .ENDR MOV DATEWD,SSDATE ; store date ; Do the actual BACKUP to the current output volume TSTB GIV.R ; /SUBSET output? BMI 190$ ; skip doing prefix block if so CALL HDRBLK ; Output prefix block 190$: CALL SAVPOS ; Mark current position/status MOVB GIV.W,VERFYG ; Set control for log on console CALL COPY ; *** BACKUP one section *** CLRB PROTFG ; output is unprotected so far TSTB GIV.V ; Verifying? BPL 200$ ; Branch if not. CMP RETCOD,#2 ; backup is done (except for possible BNE 195$ ; errors)? MOV #OUTFIL,R3 ; point to DBLK for .LOOKUP MOV OUTCHA,R2 .CLOSE R2 ; make output permanent .FPROT #EMTARE,R2,#OUTFIL,#1 ; Protect it. INCB PROTFG ; remember that it's protected already CALL LOOKD ; and look it up again for verify 195$: MOVB #377,VERFYG ; Turn off console logging CALL VERIFY ; *** VERIFY the section *** BCS OUTERR ; If verify found read errors, re-do. CALL AFTVER ; restore variables after VERIFY 200$: .CLOSE OUTCHA ; Make output file permanent TSTB PROTFG ; Already protected? BNE 210$ ; Skip next if so .FPROT #EMTARE,OUTCHA,#OUTFIL,#1 ; Protect output section ;+ ; The code placed in RETCOD by "COPY" (BUPSRM) is: ; RETCOD = 0: copying finished (for 1 output volume) ; 1: Hardware error on write ; 2: Backup done ;- 210$: MOV RETCOD,R0 ; Convert return ASL R0 ; table entry JMP @JMPTBL(R0) ; CASE Dispatch. ...... JMPTBL: .WORD NEXVOL ; Continue on next output volume. .WORD OUTERR ; Output error. .WORD BUPDON ; Backup done. ; CASE: Continue on next output volume... NEXVOL: INC THISEC ; Bump output section count, INC VOLNUM ; Bump output volume count, JMP CNTCPY ; Continue copying. ...... ; CASE: Backup is all done... BUPDON: CALL BAKDON ; Display "-I-Backup complete" 220$: CALL PURGTM ; Purge and corrupt temporary file .CLOSE INCHAN ; Close input file RETURN ; quit BUPIMA ...... ; CASE: Hard error on write to output... OUTERR: .PURGE OUTCHA .ERR #ERRARE,#WR2,LEVEL=ERROR,RETURN=YES,FILE=#OUTFIL TSTB GIV.R ; was this a /SUBSET backup? BMI 220$ ; return immediately if so. CALL GETPOS ; restore copy parameters JMP IMAPRO ...... ; Open output volume, Non-File-Structured OPENOV: MOV OUTFIL,DEVSPC ; Get output device MOV #DEVSPC,R3 MOV OUTCHA,R2 ; output channel CALL LOOKD ; open output volume NFS RETURN ...... .DSABL LSB .SBTTL Check output device status ;+ ; Get size of output (BACKUP) volume. ; Determine the number of blocks available to the saveset. ; Initialize the volume. ;- .ENABL LSB CHKSTA: CALL GSIZE1 ; Get size of output device BCC 10$ ; Branch if no error TST (SP)+ ; Bump stack pointer RETURN ; No, return ...... 10$: MOV R1,OUTSIZ ; Save the output size SUB #RESBLK,R1 ; Subtract reserved blocks MOV R1,DEVAVA ; Save for header MOV R1,BLKCOP ; Save available blocks CLR INITED ; Assume no initialize will happen CALL INITD2 ; Go try initializing BCC 20$ ; No errors on init, branch .PURGE OUTCHA ; Errors, purge and ... SEC ; Indicate failure on initialize 20$: RETURN ; Return to caller ...... .DSABL LSB .SBTTL CPYINI - Initialize buffer pointers ;+ ; Initialize before starting the actual copy operation. ; Compute size of each of the 2 buffers... ;- CPYINI: MOV TOPADD,R0 ; Compute size TST (R0)+ SUB BUFADD,R0 ; in bytes. ASR R0 ; in words (sign bit cleared below!) BIC #100777,R0 ; Make exact multiple of 256.*2 words ; and clear sign bit for ; intended unsigned divide above. MOV R0,BUFBYT ; Save this value. ASR R0 ; Convert to word count. (Sign bit 0 ; from BIC above.) SWAB R0 ; Convert size from words to blocks. MOV R0,BUFBLK ; Save this value. RETURN ; Return to caller. ...... .DSABL LSB .SBTTL INPINF - Get information about input file/device ;+ ; For DISK-to-DISK backups only. ; Calculate the number of output volumes required. ; Calculate the size of the saveset section on the first and last volumes. ; This information is saved on the output volume's homeblock. ; ; Calculate: the number of volumes required, ; number of blocks on volume 1 (SEC1LN) ; number of blocks on intermediate volumes (INTMLN) ; number of blocks on last volume (SECNLN) ;- .ENABL LSB INPINF: MOV FILSIZ,R3 ; No. of blocks to be backed up MOV #1,R1 ; Init output volume counter MOV ENTGOT,R0 ; blocks avail on 1st volume SUB NPREFB,R0 ; account for what header blk requires CMP R0,R3 ; will it all fit on one volume? BHIS ONEVOL ; Branch if so. MOV R0,SEC1LN ; save length of section 1 SUB R0,R3 ; Account for what does fit. MOV DEVAVA,R0 ; Now get avail space on empty volume SUB NPREFB,R0 ; Account for header blocks MOV R0,INTMLN ; Save intermediate section length 10$: INC R1 ; Add another volume to count SUB R0,R3 ; take away what fits on each BCC 10$ ; keep going until enough volumes ADD R0,R3 ; get remainder BNE 20$ ; if zero, MOV R0,SECNLN ; set LAST = INTERMEDIATE BR 30$ ...... 20$: MOV R3,SECNLN ; save length of last volume BR 30$ ...... ONEVOL: MOV R3,SEC1LN ; save length of section 1 CLR INTMLN CLR SECNLN 30$: MOV R1,NOSECS ; Number of file sections MOV FILSIZ,TOTLLN ; Total length of saveset CLC ; Indicate no error 40$: RETURN ...... .DSABL LSB .SBTTL HDRBLK - Write Prefix Block ;+ ; Copy the prefix block information to the LBLBUF area, clear the ; remainder of it, and the write it to block zero of the saveset ; file. ;- .ENABL LSB HDRBLK: MOV R2,-(SP) MOV #HDRARE,R0 MOV #LBLBUF,R1 MOV #</2>,R2 10$: MOV (R0)+,(R1)+ DEC R2 BGT 10$ MOV #<256.-</2>>,R2 20$: CLR (R1)+ DEC R2 BGT 20$ .WRITW #EMTARE,OUTCHA,#LBLBUF,#256.,#0 BCS 40$ 30$: INC OUTBLK 40$: MOV (SP)+,R2 RETURN ...... .DSABL LSB .SBTTL VERIFY - Do Verify of Volume just copied ;+ ; Perform verification of disk-to-disk backup ;- .ENABL LSB VERIFY: TSTB GIV.W ; /NOLOG active? BMI 10$ ; If so, no message .PRINT #MESVER ; Otherwise, print "verifying" 10$: CALL GETVER ; Back up all pointers to start MOV NPREFB,OVBLK ; Start with block after prefix MOV #-1.,LAST1 ; Init this. 20$: MOV BLKVER,R3 ; Determine how many blocks to do. CMP R3,BUFBLK ; blocks yet to go .LE. buffer size? BLOS 30$ ; branch if so. MOV BUFBLK,R3 ; otherwise, use one buffer's worth 30$: MOV R3,ACTBLK ; Actual no. of blocks to transfer SWAB R3 ; make a word count MOV BUFADD,R1 ; Set up MOV R1,R4 ; buffer pointers R1 ADD BUFBYT,R4 ; and R4 ; Initiate read of blocks from backup device... .READ #EMTARE,OUTCHA,R4,R3,OVBLK BCC 40$ .ERR #ERRARE,#RE2,LEVEL=ERROR,RETURN=YES,FILE=#OUTFIL ;; <-E-input error dev:outdev.ext> ; Read blocks from source disk ; R1 = buffer address ; R2 = block number ; R3 = word count 40$: MOV INBLK,R2 ; starting block number MOV R1,-(SP) CALL GINBLK ; Read blocks from source disk MOV (SP)+,R1 .WAIT OUTCHA ; Wait for backup device BCC 50$ ; Branch if no error ; Bad read on backup volume. That's no good. Return to caller, indicating ; that another volume should be used. .ERR #ERRARE,#RE2,LEVEL=ERROR,RETURN=YES,FILE=#OUTFIL ;; <-E-input error dev:file.ext> SEC ; Indicate problem RETURN ...... ; Compare block contents... 50$: CLR R2 ; Counter for sensing block boundaries CLR OFFSET 60$: CMP (R1)+,(R4)+ ; Compare the buffers BEQ 70$ ; Branch if no error. CMP INBLK,LAST1 ; same bad block as last time? BEQ 70$ ; if so, resume without message MOV R4,-(SP) MOV INBLK,R4 MOV R4,LAST1 ; otherwise, save it and MOV R2,-(SP) MOV OFFSET,R2 CALL PVERER ; Print verify message MOV (SP)+,R2 MOV (SP)+,R4 INC VBAD ; Chalk one up. CMP VBAD,..MBAD ; Did we hit the maximum? BLO 70$ MOV #MIS,R1 ; Too many errors. JMP FATAL ; Use global fatal exit. 70$: INC R2 ; Block boundary crossed? BIT #377,R2 BNE 80$ ; Branch if not. INC INBLK ; next block number INC OFFSET ; " " " 80$: DEC R3 ; end of compare loop BGT 60$ ; next word... 90$: ADD ACTBLK,OVBLK SUB ACTBLK,BLKVER ; More blocks to do? BLOS 100$ ; Branch up if so. JMP 20$ ...... 100$: CLC ; Indicate good verify RETURN ...... .DSABL LSB .SBTTL VOLLOG - Print log of new output volume on console ; Print log of new output volume on console .ENABL LSB VOLLOG: MOVB GIV.W,R0 ; /NOLOG in effect? BISB GIV.R,R0 ; /SUBSET in effect? BMI 30$ ; If so, skip message .PRINT #BUPINF TST INITED ; Volume just initialized? BEQ 10$ ; Branch if not to APPEND msg MOV #CREMSG,R0 ; "Creating" BR 20$ 10$: MOV #APPMSG,R0 ; "Appending to" 20$: .PRINT .PRINT #ONVOL MOV VOLNUM,R2 ; "volume number m" CALL DECIMA .PRINT #CRLF 30$: RETURN ...... .DSABL LSB .SBTTL Patch space ;+ ; Patch space for module BUPIMA and BUPINI ;- .PSECT PATCH,RW,I PATIMA::.BLKW 32. .END