.MCALL .MODULE .MODULE DUP,VERSION=70,COMMENT=,AUDIT=YES ; 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:28 Guldenschuh, Chuck cpg [240,148] ; Correct "Volume not RT-11 format problem" ; (001) ; 002 18-Feb-80 17:00 Metsch, James (29602) [240,122] ; Add 'No V4 boot on volume' error message ; (002) ; 003 11-Nov-80 11:34 AM Fingerhut, David [240,134] ; Initializing former RSX disk fails ; (003) ; 004 20-Mar-81 02:59 PM David Fingerhut [240,134] ; INIT/BAD does /REPLACE rather than create FILE.BAD's ; (004) ; 005 31-Mar-81 01:07 PM David Fingerhut [240,134] ; Add conditional assembly for /WAIT with IND ; (005) ; 006 19-Aug-81 09:00 AM David Fingerhut [40,134] ; Multiple options with /WAIT gives too many prompts. 11-40025 ; (006) ; 007 27-Aug-81 10:35 AM David Fingerhut [40,134] ; Make "No" a possible answer for 'Continue[1,23]' during /WAIT ; (007) ; 008 10-Nov-81 04:06 PM David Fingerhut [40,134] ; Changes for RTEM ; (008) ; 009 26-Jan-82 02:14 PM David Fingerhut [40,134] ; Use .PVAL, .GVAL, .PEEK, and .POKE ; (009) ; 010 02-Feb-82 11:19 AM David Fingerhut [40,134] ; Clear BUP area in homeblock ; (010) ; 011 01-Mar-82 09:51 AM David Fingerhut [40,134] ; Use DSTAT to check for multisize volumes ; (011) ; 012 12-Mar-82 12:21 PM David Fingerhut [40,134] ; update version number ; (012) ; ;24-JUL-84 George Thissell ; Update version number ; ; V05.08 MBG 11-Sep-84 Change to DUPZRO to check for odd count of ; extra bytes in the directory header when ; saving directory info in home block on INIT. ; ;1-NOV-84 George Thissell ; Add /V option for MDUP ; ; V05.24 MBG 31-Mar-86 Fixed soft booting problem for non-KT11 ; machines. ; ; 053 4-MAY-89 George Stevens ; Added C2.BUS symbol for CTI bus type testing ; 057 24-Aug-89 George Stevens ; Added code to modules DUPBOT and DUPIMA to check for pre-V5.3 handler ; 061 25-Sep-89 George Stevens ; Fixed error recovery for input error in DUPIMA's CPYDAT routine ; 063 24-Oct-89 George Stevens ; Fixed MDUP conditionals in DUPZRO ; 064 13-Dec-89 L. Banche ; Updated MTFILE to use RT11SB and removed TT.SYS from MDUP build ; 065 6-Jun-90 L. Banche ; Change STARTA.COM to STRTAI.COM for V5.6 MDUP ; ; 067 6-Nov-1990 JFW ; bracket error messages in ;+/;ERROR/.../;- ; ; 068 21-Nov-1990 JFW ; disallow VBGEXE ; ; (069) 07-Mar-91 MBG Fixed comments relating to REALDV ; ;070 ; 070 22-Sep-1996 Tim Shoppa ;070 ; Fix MDUP Build to allow arbitrary memory sizes and SB monitor ;070 ; ;070 .SBTTL General Comments ;005 ;+ ; Notes of Major Importance ; ; 1) Most overlays which contain impure data other than EMT area blocks ; and .ERR area blocks depend upon the fact that the area will be ; reset when the overlay is read in. Thus, if something is moved to ; the root, be sure that the impure data gets initialized as needed. ; ; 2) Comments of the form "*DCL*" indicate code needed because of the ; strange command lines the KMON sometimes passes to DUP. ; ; 3) Several routines (or similar versions) exist in more than one ; module to keep the root as small as possible. Should a bug be ; found, make sure it is patched in all modules. The routines are: ; ; Routine Modules ; SETHOM DUPZR1,DUPZMC ; ; 4) Whenever possible, device dependent requirements are table driven ; so that they may be extended with a patch rather than a source ; change. "*"'ed addresses should be documented in the RELEASE NOTES. ; The others are only to allow an easy patch to appease any irate ; customers. The global symbols for these areas are listed below: ; ; Address Old New Comment ; PATLEV 040 ??? Patch level. ; VERCHK 002005 000405 Check R1-11 version. REQUIRES next patch. ; *** Unclear why VERCHK patch requires REALDV patch -----^^^^^^^^ *** ; REALDV 010046 000241 Convert logical device name to ; REALDV+2 ?????? 000207 physical. ; VOLPT ?????? 000240 Allow /VOL:anything ; RETPT ?????? 000240 Allow (/BAD,/RET):anything ; * MSDPS 000000 dev id 5 bytes for devices w/multi-sized volumes ; * MTDPS 000000 dev id 5 bytes for magtapes. ; * ARDPS 000000 dev id 5 bytes for devices w/bbr on all blocks. ; * SRDPS 000000 dev id 5 bytes for devices w/bbr on some blocks. ; FBAD+2 023364 ?????? Filename for INITIALIZE/BAD (word 1) ; FBAD+6 017500 ?????? Filename for INITIALIZE/BAD (word 2) ; SEGTBL 001000 ?????? Devices with this many blocks or less ; SEGTBL+2 000001 ?????? get 1 segment by default ; SEGTBL+4 004000 ?????? Devices with this many blocks or less ; SEGTBL+6 000004 ?????? get 4 segments by default ; SEGTBL+10 030000 ?????? Devices with this many blocks or less ; SEGTBL+12 000020 ?????? get 16 segments by default ; SEGTBL+14 177777 ?????? Devices with this many blocks or less ; SEGTBL+16 000037 ?????? get 31 segments by default ; SEGTBL+20 000000 000000 5 2-word entries for further break down. ; SYCHK 001037 000437 Remove special INIT SY: check. ; ; 5) Because of several very uncouthful routines, (such as LOOKUP) ; DUP will never run as a foreground job or a virtual job. ; ; Building MDUP ; ; To build MDUP.Mx ; ; 1) Boot the distributed SJ system in 12kw. ; 2) Load all handlers to be supported by magtape distribution. ; 3) Load ONE of the magtape handlers. Must be hardware handler ; to have room. ; 4) .R MDUP ; 5) *dev:MDUP.Mx=/H ; ; The last two steps must be hand typed as strange things happen if they ; are in indirect command files. ; ; "dev" in step 5 must be a PHYSICAL device name. ; ; Building a bootable magtape ; ; To build a bootable magtape: ; ; .INITIALIZE/FILE:MBOOT.BOT Mx: ; ; Place the following files on the tape. Order is important. ; ; MSBOOT.BOT ; SWAP.SYS ; RT11SB.SYS ; TT.SYS (NO MORE TT.SYS FOR V5.6) ; all disk handlers supported ; all magtape handlers supported ; LP.SYS ; PIP.SAV ; DUP.SAV ; DIR.SAV ; any other files ;- .SBTTL RT-11 V04 Home Block Format ;+ ; RT-11 V04 Home Block Format ; ; 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 ; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ;000 |a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a| ;040 |a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a| ;100 |a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a| ;140 |a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a|a| ;200 |a|a| | |b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b| ;240 |b|b|b|b|b|b|b|b|b|b|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l|l| | | | | ;010 ;300 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;340 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;400 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;440 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;500 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;540 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;600 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;640 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ;700 |c|c|d|d| | | | | | | | | | | | | | |e|e|f|f|g|g|h|h|h|h|h|h|h|h| ;740 |h|h|h|h|i|i|i|i|i|i|i|i|i|i|i|i|j|j|j|j|j|j|j|j|j|j|j|j| | |k|k| ; ;Field Location Contents Default ; ; a 000 - 201 Bad block replacement table ; b 204 - 251 INITIALIZE/RESTORE data area ; l 252 - 273 BUP information area (000000);010 ; c 700 - 701 RAD50 RTE (RTEM) (000000);008 ; d 702 - 703 Block number of first user file (RTEM) (000000);008 ; e 722 - 723 Pack cluster size (000001) ; f 724 - 725 Block number of first directory segment (000006) ; g 726 - 727 System version (RAD50 V3A) ; h 730 - 743 Volume ID (RT11Abbbbbbb) ; i 744 - 757 Owner name (bbbbbbbbbbbb) ; j 760 - 773 System ID (DECRT11Abbbb) ; k 776 - 777 Checksum ; ;All other areas in the home block are reserved for future system use. ;The contents of all other areas are undefined. ;- .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 .IIF NDF IND, IND = 0 ;Default to no IND ;005 .AUDIT .DUPPRE,.DUPCRE,.DPIN1,.DPIN2,.DUPSCN,.DUPWBT,.DUPBOT,.DUPZRO .IF EQ MDUP .AUDIT .DUPIMA,.DUPMRG,.DPOV1,.DPOV2,.DPOV5,.DPOV7,.DUPSQU,.DUPUNI .AUDIT .DUPVOL,.DUPZMC .ENDC ;EQ MDUP .ENABL LC,GBL .SBTTL MACRO definitions ;+ ; MACROS ; The macros are defined here to get them listed. In all other modules, ; the macros are defined in DUPPRE. ;- .MCALL .CLOSE, .CSISPC,.DATE, .DSTATU,.ENTER, .FETCH .MCALL .GTIM, .GTLIN, .GVAL, .HERR, .LOCK, .LOOKUP .MCALL .PRINT, .PURGE, .READW, .RCTRLO,.RELEAS,.SCCA .MCALL .SERR, .SETTOP,.SPFUN, .TTYIN, .UNLOCK,.WRITW .MCALL .SAVES, .REOPEN,.TRPSET,.PVAL, .CHAIN. .CSTAT, .TRPSET .MCALL .ASSUME SOB .MACRO .BSECT NAME ..BS.. = 1 .ENDM .BSECT .MACRO .DSECT NAME ..DS.. = 0 .ENDM .DSECT .MACRO .ERR AREA,CODE,LEVEL,RETURN,FILE,TABLE,PREFIX,LEVBYT,RETRY,ASCII .IF NB AREA .IF DIF ,AREA MOV AREA,R0 .ENDC .ENDC .IF NB CODE MOVB CODE,@R0 .ENDC .RET.. = 0 ...... = 0 .IF NB RETURN .IRPC ..RET., .IF EQ ...... .IIF IDN ..RET., .RET.. = 200 ...... = 1 .ENDC .ENDM .ENDC .ASC.. = 0 .IIF NB .ASC.. = 40 ...... = 0 .IRPC ..LEV., .IF EQ ...... MOVB #''..LEV.!.RET..!.ASC..,1(R0) ...... = 1 .ENDC .ENDM .IIF NB MOV PREFIX,2(R0) .IIF NB MOV LEVBYT,4(R0) .IIF NB MOV TABLE,6(R0) .IF NB MOV FILE,10(R0) .IIF NB .ERROR ; F I L E and A S C I I can not both be specified; .IFF .IF NB MOV ASCII,10(R0) .IFF CLR 10(R0) .ENDC .ENDC .IIF NB MOV RETRY,12(R0) JSR PC,$ERROR .ENDM .ERR .MACRO .GTCOR SIZE MOV #FREMLH,R0 .IF NB SIZE MOV SIZE,R1 .ENDC CALL $RQCB .ENDM .GTCOR .MACRO BS NAME .IF NB NAME NAME == ..BS.. .ENDC ..BS.. = ..BS.. * 2 .ENDM BS .MACRO CM1... AREA,CHAN ...CM5 .IF IDN ,<#0> CLRB @R0 .IFF .IF NB MOVB CHAN,@R0 .ENDC .ENDC .ENDM CM1... .MACRO DS NAME,TYPE,SIZE .IF NB NAME NAME == ..DS.. .ENDC .IF NB TYPE .IF IDN TYPE, .IF B SIZE ..DS.. = ..DS.. + 1 .IFF ..DS.. = ..DS.. + SIZE .ENDC .IFF .IF B SIZE ..DS.. = ..DS.. + 2 .IFF ..DS.. = ..DS.. + .ENDC .ENDC .IFF .IF B SIZE ..DS.. = ..DS.. + 2 .IFF ..DS.. = ..DS.. + .ENDC .ENDC .ENDM DS .MACRO .BSECT NAME=...ABS,HILO=LOW,GLOBAL=YES PSECT , .IF NDF NAME NAME: .ENDC ;NDF NAME .. = . .IF IDN , . = . + NAME - . + 400 .IFF ;IDN , . = . + NAME - . + 1 .ENDC ;IDN , GLBL.. = 0 .IIF IDN ,, GLBL.. = 1 .MACRO BS NAME1,GLOBAL PSECT NAME .IF NB NAME1: .BLKB . .IF B .IIF NE GLBL.., .GLOBL NAME1 .IFF ;B .GLOBL NAME1 .ENDC ;B .IFF ;NB .BLKB . .ENDC ;NB .ENDM BS .ENDM .BSECT .MACRO .DSECT NAME=...ABS,N=0,GLOBAL=YES PSECT , .IF NDF NAME NAME: .ENDC ;NDF NAME .IF DIF , . = . + NAME - . + N .ENDC ;DIF , ..GLBL = 0 .IIF IDN ,, ..GLBL = 1 .MACRO DS NAME1,UNIT,SIZE=1,GLOBAL PSECT NAME .IF NB .IF B NAME1: .BLKW SIZE .IFF ;B NAME1: .BLKB SIZE .ENDC ;B .IF B .IIF NE ..GLBL, .GLOBL NAME1 .IFF ;B .GLOBL NAME1 .ENDC ;B .IFF ;NB .IF B .BLKW SIZE .IFF ;B .BLKB SIZE .ENDC ;B .ENDC ;NB .ENDM DS .ENDM .DSECT .MACRO UNORG .ENDM UNORG .MACRO ORIGIN SECT,LIST .MACRO UNORG .LIST BEX PSECT SECT, .ENDM UNORG PSECT , .NLIST BEX .ENDM ORIGIN .MACRO PSECT SECT,LIST .LIST BEX .IF IDN SECT,<*> UNORG .NLIST BEX .MEXIT .IFF .IF NB .PSECT SECT,LIST .IFF .PSECT SECT .ENDC .ENDC .NLIST BEX .ENDM PSECT .MACRO SAVE02 JSR R2,$SAVVR ;Save R0-R2 .ENDM SAVE02 .MACRO SAVE05 JSR PC,$SAVAL ;Save R0-R5 .ENDM SAVE05 .MACRO SAVE35 JSR R5,$SAVRG ;Save R3-R5 .ENDM SAVE35 .MACRO SURE FILE,PROMPT,FG .IF EQ .IF NB FILE MOV FILE,R0 .ENDC .IF NB PROMPT MOV PROMPT,RUSPRM .ENDC .IF NB FG MOV SP,R1 .IFF CLR R1 .ENDC CALL RUSURE .ENDC ;EQ .ENDM .MACRO READ AREA,CHAN,BUF,WCNT,BLK .MCALL .MACS .MACS CM1... , ...CM2 , 2 ...CM2 , 4 ...CM2 , 6 CALL $READ .ENDM READ .MACRO WAIT PROMPT,DEV .IF EQ .IF NB PROMPT MOV PROMPT,WAITPR .ENDC .IF NB DEV MOV DEV,R0 .ENDC CALL WAITCK .ENDC ;EQ .ENDM .MACRO WRITE AREA,CHAN,BUF,WCNT,BLK .MCALL .MACS .MACS CM1... , ...CM2 , 2 ...CM2 , 4 ...CM2 , 6 CALL $WRITE .ENDM WRITE .SBTTL PSECT definitions ;+ ; The PSECT's are defined here to give them the desired ordering. ; Consider the ordering critical. Several of the PSECT's contain ; stoppers for lists in the previous PSECT. ;- PSECT ...AFL ; PSECT ...BAD ; PSECT ...CSW ; PSECT ...DIR ; PSECT ...DST ; PSECT ...ERS ; ;001 PSECT ...IOF ; PSECT ...MFL ; PSECT IMPURE ;Impure data psect PSECT .LIBD. ;Data (library routines) SWPUSR:: ;Reference label (USR swap location) PSECT .LIBP. ;Data (library routines) PSECT PURE ;Pure data PSECT PUREB ;[byte] Pure data PSECT ACTABL ;Action routine table PSECT .LIBC. ;Library routines PSECT .LIBO. ;Library overlay code PSECT DUP ;Main code psect PSECT PATCH ;Patch psect .BLKW 64. ;Root patch space .SBTTL Symbolic definitions .SBTTL System symbolics S$STRT == 40 ;Job start address S$JSW == 44 ;Job status word JS.NTG == 10 ; Non-terminating .GTLIN bit JS.REE == 20000 ; Re-enter bit JS.TTLC == 40000 ; Lower case console input bit S$USRL == 46 ;Floating USR load address S$HLMT == 50 ;Job high limit S$EERB == 52 ;EMT error byte ER.PRO == 3 ; Protected file exists ER.IUN == 6 ; Invalid unit number S$UERB == 53 ;User error byte UE.SUC == 1 ; Success UE.WRN == 2 ; Warning UE.ERR == 4 ; Error UE.SEV == 10 ; Severe S$RMON == 54 ;Base of RMON S$TFIL == 56 ;Terminal character and fill count S.BLKY == 256 ;Offset from RMON to BLKEY S.USRL == 266 ;Offset from RMON to USR load address S.VER == 276 ;Offset from RMON to monitor version number S.UPD == 277 ;Offset from RMON to monitor update number S.CNF1 == 300 ;Offset from RMON to configuration word #1 C1.FGL == 200 ; Set => foreground loaded C1.USW == 1000 ; Set => USR set NOSWAP ;070 S.IFSW == 366 ;Offset from RMON to indirect file state word IF.RTT == 100 ; Set => revert to TT from IF when ^C seen S.CNF2 == 370 ;Offset from RMON to configuration word #2 C2.PRO == 20000 ; PRO 300 series architecture (pseudo 11) C2.KXJ == 4000 ; KXJ11-CA C2.BUS == 100 ; BUS type (CTI, QBUS, UNIBUS, OTHER) S.PNAM == 404 ;Offset from RMON to offset to PNAME$ S.MNAM == 406 ;Offset from RMON to RAD50 monitor name S.SUFF == 412 ;Offset from RMON to handler suffix S.MEMS == 420 ;Offset from RMON to memory size ;070 S.CHAN == 500 ;Offset from RMON to chain info area KB$CSR == 177560 ;Console keyboard status register IENABL == 100 ; Interrupt enable ;008 .SBTTL ;008 .SBTTL RTEM-11 Global definitions ;008 ;008 $RTELK == 250 ; Address of pointer to host system link;008 $RTEID == 252 ; Address of RTEM identifier (.RAD50 "RT;008 RTE$ID == <^RRTE> ; RTEM system identifier (.RAD50 "RTE") ;008 ;008 .SBTTL ;008 .SBTTL Channel status offsets and symbolics .DSECT ...CSW,GLOBAL=YES DS C.CSW ;Offset to channel status word CSW.HE == 1 ; Hard error bit CSW.DI == 76 ; Device index mask CSW.RF == 100 ; Rename in progress flag CSW.EN == 200 ; File was .ENTERed CSW.DS == 17400 ; Directory segment containing file mask CSW.EF == 20000 ; EOF encountered CSW.CA == 100000 ; Channel active flag DS C.SBLK ;Offset to starting block number of file DS C.LENG ;Length of file or empty DS C.USED ;Actual data length DS C.DEVQ,,0 ;Device word DS C.NREQ,BYTE ;Number of outstanding I/O requests DS C.UNIT,BYTE ;Device unit number .SBTTL Program symbolics OCHAN == 0 ;Output channel number ICHAN == 1 ;Input channel number HICHAN == 1 ;Highest channel in use MAXSEG == 37 ;Maximum number of directory segments MAXBYT == 356 ;Maximum number of extra bytes MTBFSZ == <4 * 512.> ;Size needed for image copy to or from MT MX.MEM == 4400. ;Maximum amount of memory required by program BADSIZ == 10 ;Size of .BAD linked list element .BSECT ...IOF,GLOBAL=YES BS DEV.DK ;Disk flag BS DEV.MT ;Magtape flag BS DEV.CT ;Cassette flag BS DEV.MS ;"Device accepts multi-sized volumes" BS DEV.SD ;Strange device flag BS DEV.DR ;Non-RT-11 directory structured (MT, CT) BS DEV.RO ;Read only device BS DEV.WO ;Write only device BS DEV.AR ;All bad blocks are replaceable BS DEV.SR ;Some bad blocks are replaceable BS DEV.SC ;Scan device with .SPFUN's BS DEV.DU ;Device is MSCP disk (quick fix for V5.3) BS FLG.EN ;"Enter file" flag BS FLG.FL ;Indicates a file spec was given BS FLG.DV ;Indicates a device spec was given BS FLG.WD ;Indicates a wild card was given .SBTTL Home block and VOL1 offsets and symbolics HOMBLK == 1 ;Home block for disks DK.SAV == 66.*2 ;INIT/RESTORE save area DK.BUP == 252 ;BUP information area ;010 DK.RX1 == 700 ;Offset to RT/RSX word 1 GOD$ID== -1 ;If DW, disk is V5.3 structure BAD$ID== -2 ;If DW, disk is corrupted ; RTE$ID==^RRTE ;RTEM initialized disk (by JOAT) DK.RX2 == 702 ;Offset to RT/RSX word 2 DK.UN2 == 704 ;Offset to 7 word unused area DK.VRN == 726 ;Offset to system version (disk) DK.VID == 730 ;Offset to vol id (disk) DK.OWN == 744 ;Offset to owner name (disk) DK.UN3 == 774 ;Offset to 1 word unused area DK.CSM == 776 ;Offset to home block checksum word DK.VLN == 12. ;Size of disk vol id (and owner name) MT.VID == 4 ;Offset to vol id (magtape) MT.OWN == 40. ;Offset to owner name (magtape) MT.VLN == 6 ;Size of magtape vol id MT.OLN == 10. ;Size of magtape owner name DW.CD1 == 170000 ;Special code word for sizing DW hard disks DW.CD2 == 007777 ;Special code word for sizing DW hard disks .SBTTL Directory offsets and symbolics SEGSIZ == <2 * 256.> ;Size of a directory segment in words .SBTTL Disk directory header offsets .DSECT ...DIR,GLOBAL=YES DS DH.AVL ;Number of available directory segments DS DH.NXT ;Pointer to next directory segment DS DH.HI ;Highest directory segment open DS DH.EXB ;Number of extra bytes in directory entries DS DH.STB ;Starting block number for files in segment DS DH.SIZ,,0 ;Size of directory header words .SBTTL Disk directory entry offsets and symbolics .DSECT ...DIR,GLOBAL=YES DS DE.ST ;Entry status DS DE.FN1 ;Offset to first word of filename DS DE.FN2 ;Offset to second word of filename DS DE.TYP ;Offset to filetype DS DE.LEN ;Offset to filesize DS DE.CHN,BYTE ;Offset to channel DS DE.JOB,BYTE ;Offset to job number DS DE.DAT ;Offset to file creation date DS DE.SIZ ;Size of directory entry .BSECT ...DIR,HIGH,GLOBAL=YES BS DS.TNT ; 1 => tentative entry BS DS.EMP ; 1 => empty entry BS DS.PRM ; 1 => permanent entry BS DS.EOS ; 1 => end-of-segment entry BS BS BS BS DS.PRO ; 1 => protected file .SBTTL Bad block scan symbolics MAXBAD == 128. ;Maximum number of bad blocks BADHSZ == 2 ;Size of the table header .DSECT ...BAD,GLOBAL=YES DS BT.TYP ;Offset to type of bad block DS BT.BLK ;Block number of bad block DS BT.LEN ;Size of bad area. DS BT.SIZ ;Size of a bad block table entry .BSECT ...BAD,GLOBAL=YES BS BAD.NR ;Non-replaceable bad block BS BAD.RP ;Replaceable bad block BS BAD.SW ;Soft bad block BS BAD.PS ;Possible bad block RTF.RP == 200 ;Flag returned by DM to indicate BSE or HVRC RTF.FE == 40000 ;Flag for forced error MAXREP == 32. ;Maximum number of replaceable blocks .SBTTL ASCII symbolics LF == 12 ;ASCII CR = 15 ;ASCII BLANK == 40 ;ASCII blank .SBTTL RAD50 symbolics R50AST == 132500 ;RAD50 '* ' (unused character code) .SBTTL .CSI offsets OUSPSZ == 12 ;Size of CSI output spec in bytes INSPSZ == 10 ;Size of CSI input spec in bytes SPCSIZ == + ;Size of CSI file spec area .SBTTL .DSTATUS offsets and symbolics .DSECT ...DST,GLOBAL=YES DS DS.HID,BYTE ;Handler ID byte DS DS.HFL,BYTE ;Handler flag byte DS DS.HSZ ;Handler size DS DS.HLA ;Handler load address + 6 DS DS.SIZ ;Size of device .BSECT ...DST,HIGH,GLOBAL=YES BS DSH.MS ;Device uses multi-size volumes ;011 BS BS DSH.SF ;Device accepts .SPFUN's BS BS DSH.ND ;Non-RT-11 directory structured BS DSH.WO ;Write only device BS DSH.RO ;Read only device BS DSH.RA ;Random access device RKID == 0 ;RK dstatus code DTID == 1 ;DT dstatus code DLID == 5 ;DL dstatus code DYID == 6 ;DY dstatus code MTID == 11 ;MT dstatus code RFID == 12 ;RF dstatus code CTID == 13 ;CT dstatus code DSID == 16 ;DS dstatus code MMID == 20 ;MM dstatus code DPID == 21 ;DP dstatus code DXID == 22 ;DX dstatus code DMID == 23 ;DM dstatus code DDID == 34 ;DD dstatus code MSID == 35 ;MS dstatus code DUID == 50 ;DU dstatus code MUID == 60 ;MU dstatus code VSID == 200 ;VS dstatus code (RTEM) ;008 ; CT, MT, MM, MS codes ;**-1 SF.RDV == 370 ;.SPFUN code to read (MM,MT) SF.WTV == 371 ;.SPFUN code to write (MM,MT) SF.RWD == 373 ;.SPFUN code to rewind (CT,MM,MT) SF.WTM == 377 ;.SPFUN code to write tape mark (MM,MT) ; DL, DM, DY, DX codes SF.GSZ == 373 ;.SPFUN code to get device size SF.IRT == 374 ;.SPFUN code to initializing replacement table SF.WPS == 376 ;.SPFUN code to write physical sector (DX) SF.WRT == 376 ;.SPFUN code to write SF.RED == 377 ;.SPFUN code to read BTIME ==. BDATE ==BTIME+4 BUFFB ==BDATE+2 KISDR0 ==172300 ;KERNEL I-SPACE DESCRIPTION REGISTER 0 PS ==177776 ;PROCESSOR STATUS WORD (NOT ON LSI-11) UISAR0 ==177640 ;USER I-SPACE ADDRESS REGISTER 0 SR0 ==177572 ;MMU STATUS REGISTER 0 PR7 ==340 ;PRIORITY 7 KISAR0 ==172340 ;KERNEL I-SPACE ADDRESS REGISTER 0 KISAR1 ==172342 ;KERNEL I-SPACE ADDRESS REGISTER 1 V.MPTY ==114 ;MEMORY PARITY ERROR VECTOR AP$ACF ==77406 ;ACTIVE PAGE REG.-8K W/NO SYS TRAP/ABORT ;ACTION SET UISDR0 ==177600 ;USER I-SPACE DESCRIPTOR REGISTER 0 PMODE ==30000 ;PREVIOUS MODE MASK SR3 ==172516 V.TRP4 ==4 .SBTTL Pure data PSECT PUREB .SBTTL Prompts and such .NLIST BEX .IF NE MDUP VERSON::.ASCII "M" .NLCSI .IFF ;MDUP .IF NE IND VERSON::.NLCSI PART=NAME,TYPE=I .ASCII "IND " .NLCSI PART=RLSVER .IFF ;EQ IND VERSON::.NLCSI .ENDC ;SDC .ENDC ;MDUP PATLEV=:.-2 CRLF:: .BYTE 0 .IF EQ MSGCON::.ASCII \; Continue? \<200> MSGRUS::.ASCII \; Are you sure? \<200> MSGFGL::.ASCII \Foreground loaded\<200> .ENDC ;EQ .IF NE IND MSGCNT::.ASCII <12><12><15>\ Press the "RETURN" key when ready to continue.\<200> .ENDC ;NE IND .LIST BEX .SBTTL Error Messages ;+ ;ERROR ; ; All error message given by DUP are listed here for completeness. The ; comment following some of them give the module where that message is ; defined. The first argument to the ERRMSG macro is the 3 character ; name of the message. The second argument is the message text. The ; messages are given a number which is the index into a table which points ; to the message text. The table's name is defined by the MSGLST macro. ; The first word of the table is the maximum number of message. The ; MSGEND macro must be invoked after the last message. Message of the ; form "FE.xxx" are all found in the module ULB033. ;- .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=YES .PSECT .LIBP. NAME: .WORD ..MAX. .ENDM MSGLST .MACRO MSGEND DS ..MAX.,BYTE .ENDM MSGEND ;+ ;ERROR MSGLST ERRTAB ERRMSG CSO, ERRMSG DIE, ERRMSG DOE, ERRMSG ERT, ERRMSG ILC, ERRMSG ILD, ERRMSG NBD, ERRMSG NBF, ERRMSG SFF, ERRMSG TMB, ERRMSG NBO, ;002 ERRMSG ONC, ;007 ERRMSG DLD, ERRMSG DL2, ERRMSG DLT, ERRMSG FST, ERRMSG FS2, ERRMSG DST, ERRMSG DLF, .IF NE MDUP ERRMSG BSA, ERRMSG DIO, ERRMSG NAI, ERRMSG ILO, ERRMSG IOV, ERRMSG NBB, ERRMSG NRF, ERRMSG TP4, ERRMSG TP1, ERRMSG USW, ;070 .ENDC ;NE MDUP ;ERRMSG BBD, ;DUPSN2 ;ERRMSG NSE, ;DUPCRE ;ERRMSG OFE, ;DUPCRE ;ERRMSG RTO, ;DUPZR1 ;ERRMSG VCM, ;DUPIMA ;ERRMSG VFE, ;DUPIMA ;ERRMSG CCM, ;DUPIMA ;ERRMSG VIT, ;DUPVOL ;ERRMSG ONT, ;DUPVOL ; ; The following message names are actually FE.xxx ; ;ERRMSG CIU, ;ULB033 ;ERRMSG CNO, ;ULB033 ;ERRMSG DFL, ;ULB033 ;ERRMSG DVF, ;ULB033 ;ERRMSG EOF, ;ULB033 ;ERRMSG FER, ;ULB033 ;ERRMSG FNF, ;ULB033 ;ERRMSG ILD, ;ULB033 ;ERRMSG INE, ;ULB033 ;ERRMSG NOM, ;ULB033 ;ERRMSG OPE, ;ULB033 ;ERRMSG SYS, ;ULB033 ;ERRMSG OFP, MSGEND ;- .SBTTL Filename entries for MDUP .IF NE MDUP .MACRO FILE NAME,TYPE .RAD50 \NAME\ .RAD50 \TYPE\ .ASCII \NAME\ .ASCII \.\ .ASCII \TYPE\ .ENDM FILE PSECT IMPURE SAVMEM: .WORD 0 ;-> 6 blocks of buffer for WBOOT and BOOT MTFILE:: FILE ;Swap file MONAME: FILE ;Monitor file ;.IF EQ M$UPD ; FILE ;TT handler ;.ENDC ;EQ M$UPD NEWDEV:: FILE ;System device handler NEWMT:: FILE ;Magtape handler .IF EQ M$UPD FILE ;Line printer handler .ENDC ;EQ M$UPD FILE ;PIP FILE ;DUP .IF EQ M$UPD FILE ;DIR .ENDC ;EQ M$UPD .WORD 0 FILE
;DL: FILE ;DM: FILE ;DU: .IF EQ M$UPD FILE ;STRTAI FILE ;IND FILE ;FORMAT FILE ;TERMID FILE ;CONFIG .IFF ;EQ M$UPD FILE ;IND FILE ;UPDATE FILE ;LD: FILE ;CONFIG .ENDC ;EQ M$UPD MTFPAT:: .BLKB <<10.+6.>*5> ;End of table and patch space .ENDC ;NE MDUP .SBTTL Impure data PSECT IMPURE ;+ ; IMPURE ; All global impure data will be found here. Non-global impure data ; is defined in the routines which have major access. ;- $AFLAG::.WORD 0 ;Action option flag word .ASSUME $DIRTY EQ $AVAIL+24 .ASSUME $STBLK EQ $AVAIL+22 ;Order dependent!!! .ASSUME $NXTSG EQ $AVAIL+20 ;If these are reordered or added to, the lists .ASSUME $NXTFL EQ $AVAIL+16 ;in both DUPSQU and DUPSQ1 must be modified!!! .ASSUME $LSTLN EQ $AVAIL+14 .ASSUME $HISEG EQ $AVAIL+12 .ASSUME $EXTBY EQ $AVAIL+10 .ASSUME $DIRSG EQ $AVAIL+06 .ASSUME $DIRCH EQ $AVAIL+04 .ASSUME $DIRBF EQ $AVAIL+02 $AVAIL::.WORD 0 ;Number of directory segments available $DIRBF::.WORD 0 ;-> directory buffer $DIRCH::.WORD 0 ;Directory channel number $DIRSG::.WORD 0 ;Block number of current directory segment $EXTBY::.WORD 0 ;Number of extra bytes in directory entries $HISEG::.WORD 0 ;Highest segment in use $LSTLN::.WORD 0 ;Length of previous file returned by NEXTFL $NXTFL::.WORD 0 ;-> next file in directory segment $NXTSG::.WORD 0 ;Segment number of next directory segment $STBLK::.WORD 0 ;Start block number for file from NEXTFL $DIRTY::.WORD 0 ;Flag that segment must be written DDATSZ == <. - $AVAIL> / 2 ;Size of directory munger's impure area .ASSUME $IDIRT EQ $IAVAL+24 .ASSUME $ISTBL EQ $IAVAL+22 .ASSUME $INXSG EQ $IAVAL+20 .ASSUME $INXFL EQ $IAVAL+16 .ASSUME $ILSLN EQ $IAVAL+14 .ASSUME $IHISG EQ $IAVAL+12 .ASSUME $IEXBY EQ $IAVAL+10 .ASSUME $IDRSG EQ $IAVAL+06 .ASSUME $IDRCH EQ $IAVAL+04 .ASSUME $DIRB2 EQ $IAVAL+02 $IAVAL::.WORD 0 $DIRB2::.WORD 0 $IDRCH::.WORD 0 $IDRSG::.WORD 0 $IEXBY::.WORD 0 $IHISG::.WORD 0 $ILSLN::.WORD 0 $INXFL::.WORD 0 $INXSG::.WORD 0 $ISTBL::.WORD 0 $IDIRT::.WORD 0 .ASSUME DDATSZ EQ <<. - $IAVAL> / 2> .IF EQ MDUP .ASSUME $ODIRT EQ $OAVAL+24 .ASSUME $OSTBL EQ $OAVAL+22 .ASSUME $ONXSG EQ $OAVAL+20 .ASSUME $ONXFL EQ $OAVAL+16 .ASSUME $OLSLN EQ $OAVAL+14 .ASSUME $OHISG EQ $OAVAL+12 .ASSUME $OEXBY EQ $OAVAL+10 .ASSUME $ODRSG EQ $OAVAL+06 .ASSUME $ODRCH EQ $OAVAL+04 .ASSUME $DIRB3 EQ $OAVAL+02 $OAVAL::.WORD 0 $DIRB3::.WORD 0 $ODRCH::.WORD 0 $ODRSG::.WORD 0 $OEXBY::.WORD 0 $OHISG::.WORD 0 $OLSLN::.WORD 0 $ONXFL::.WORD 0 $ONXSG::.WORD 0 $OSTBL::.WORD 0 $ODIRT::.WORD 0 .ASSUME DDATSZ EQ <<. - $OAVAL> / 2> .ENDC ;EQ MDUP .ASSUME $OSFLG EQ $ISFLG+2 $ISFLG::.WORD 0 ;Input file spec flag $OSFLG::.WORD 0 ;Output file spec flag $MFLAG::.WORD 0 ;Modification option flag word BADLHD::.WORD 0 ;.BAD linked list head BOOWHO::.WORD 0 ;COPY/BOOT:xx value CTRLC:: .WORD 0 ;^C intercept flag DATE:: .WORD 0 ;System date .ASSUME BFPTR EQ EXTSIZ BFPTR:: ;Output buffer pointer. SCAN EXTSIZ::.WORD 0 ;/T size FREMLH::.WORD 0 ;Free memory list head for INITDM,$RQCB,$RLCB .WORD 0 ; MUST be 0 REDEND::.WORD 0 ;/E value REDSTR::.WORD 0 ;/G value (input) REDSW:: .WORD 0 ;/END specified? ;004 RETAIN:: RETBAD::.BYTE 0 ;/B :RET state indicator RETREP::.BYTE 0 ;/R :RET state indicator RUSPRM::.WORD 0 ;Prefix prompt for "are you sure?" SCCNT:: .WORD 0 ;CTRL/C intercept counter SEGMNT::.WORD 0 ;Number of segments, /N value .ASSUME SPFUN EQ SPFUNI .ASSUME SPFUNI+1 EQ SPFUNO SPFUN:: ;Indicates .SPFUN .READx/.WRITx to be done SPFUNI::.BYTE 0 ;.SPFUN .READx flag SPFUNO::.BYTE 0 ;.SPFUN .WRITx flag SYSDEV::.WORD 0 ;RAD50 system device and unit number .IF EQ MDUP VOLFLG::.WORD 0 ;/V state indicator WAITPR::.WORD 0 ;Disk (sys, in, out) prompt for "continue?" .IFF ;EQ MDUP DOCMND::.WORD 0 ; /V state indicator ; low byte 0 -- no (never) {/V|/V:n} ; low byte 1 -- {/V|/V:n} encountered ; high byte 0 -- /V w/o value ; high byte +1 -- /V:n, n fits in memory ; high byte -1 -- /V:n, n does not fit in mem ; if high byte is -1, skip command processing ; (decode) ; if high byte is +1, use RT11AI (copymt) ; if high byte is +1, do second list (copymt) DIDV:: .WORD 0 ; Flag for /V switch TRUVM:: .WORD 0 ; Storage for amount of VM .ENDC ;EQ MDUP WRTSTR::.WORD 0 ;/G value (output) XTRBYT::.WORD 0 ;Number of extra bytes, /Z value *2 LIMITS::.LIMIT ;Program high and low limits TIME:: .BLKW 2 ;System time DEFEXT::.BLKW 4 ;No default extension REPBUF::.WORD 0 ;*** -> replacement table buffer for SCAN IBFBEG::.WORD 0 ;*** -> input buffer. Various routines OUTBUF::.WORD 0 ;*** -> output buffer. SCAN OBFBEG::.WORD 0 ;*** -> output buffer. Various BUFEND::.WORD 0 ;*** -> end of output buffer SCAN IOSIZ:: .WORD 0 ;*** # words/transfer. IMAGE BSIZE:: .WORD 0 ;*** size of scan buffer. SCAN BUFSIZ::.WORD 0 ;*** size of input buffer in blocks. IMAGE SAVSIZ::.WORD 0 ;Device size save area for ZERO SQUSYS::.WORD 0 ;System device being squeezed flag INST:: .BLKW 4 ;Input file .DSTATUS block OUTST:: .BLKW 4 ;Output file .DSTATUS block STBLK: .BLKW 5 ;.SAVEST/.REOPEN block .IF NE IND ;005 APIN:: .BLKW 256. ;Buffer for text from AP.TMP ;005 APSZ:: .WORD 256. ;Size of APIN ;005 APBLK:: .WORD 0 ;AP.TMP block number ;005 ACHAN:: .WORD 2. ;Channel number for AP.TMP ;006 .ENDC ; .IF NE IND .IF NE MDUP OEAREA:: ;Error message area for "overlays" .ENDC ;NE MDUP ;Error message area block ERAREA::.BYTE 0 ; Error code byte .BYTE 0 ; Error level/return flag .WORD ERRPRE ; -> Error message prefix .WORD ERRLEV ; -> Error level byte .WORD ERRTAB ; -> Error message offset table .WORD 0 ; -> File name block .WORD ABORT ; -> Abort return IOAREA::.BLKW 10 ;EMT area block OUTFIL::.BLKB ;CSI output file spec area INFILE::.BLKB ;CSI input file spec area CMDBUF::.BLKB 82. ;CSI command buffer, VOL ID/OWNER area OUTSZ:: .WORD 0 ;Output device size INSZ:: .WORD 0 ;Input device size LDCHN: .RAD50 \SY \ ;Program to chain to LDDEV: .RAD50 \LD \ .RAD50 \ \ .RAD50 \SYS\ .WORD 0 ;for RSTS .RAD50 \SY \ ;Program to return to .RAD50 \DUP\ .RAD50 \ \ .RAD50 \SAV\ .ASCIZ \/C:-1\ ;Switch for LD .EVEN CHNSIZ = 12. ;Number of words in chain info .NLIST BEX .IF NE MDUP ERRPRE::.ASCII \?MDUP-\ ;Error message prefix string .IFF ;MDUP .IF NE SDC ERRPRE::.ASCII \?SDCOPY-\ ;Error message prefix string .IFF ;SDC ERRPRE::.ASCII \?DUP-\ ;Error message prefix string .ENDC ;SDC .ENDC ;MDUP ERRLEV::.ASCII \x-\<200> ;Error message level string ERROPT::.ASCII \ \<200> ;Invalid option letter .EVEN .IF EQ MDUP CSTAT:: .BLKW 6. ;Area for channel status information .ENDC ;EQ MDUP .LIST BEX .SBTTL Start-up and re-entry code .SBTTL DUP - Main entry point .ASECT $JSX=4 NOVBG$=100 . = $JSX .WORD NOVBG$ . = S$JSW ;Set up the JSW .WORD JS.REE ; Re-enterable ORIGIN DUP PSECT IMPURE SAVESP: .WORD 0 ;SP save area DOIT: .WORD 0 ;Action flag work area PSECT * BR RETRY ;Re-entry point DUP:: MOV SP,SAVESP ;Save the initial stack pointer RETRY:: MOV SAVESP,SP ;Restore the initial stack pointer CALL INIT ;Initialize the state .IF EQ SDC .CSISPC #OUTFIL,#DEFEXT,#0,#CMDBUF ;Get the command line .IFF ;SDC CALL SDGTLN ;Go build the command .CSISPC #OUTFIL,#DEFEXT,#CMDBUF ;Parse the command line .ENDC ;SDC BCS RETRY ;Try again on error TSTB CMDBUF ;Anything there? BNE 1$ ;Branch if not .PRINT #VERSON ; else print the version BR RETRY ;And get another line 1$: BR 2$ ;*DBG* .PRINT #CMDBUF ;*DBG* 2$: CALL DECODE ;Parse the command line .IF NE MDUP BCS RETRY ;Ignore command .ENDC ;NE MDUP CALL DEFALT ;Set up any defaults and do some more command ; checking CALL FILES ;Do any file processing CALL INITDM ;Initialize dynamic memory MOV #ACTLST,R5 ;Point the action routines MOV $AFLAG,DOIT ;Copy the action flag 3$: CLC ; ASR DOIT ;Shift out a flag bit, maybe BCS 5$ ;It was set. Go call the routine BEQ RETRY ;Branch if done 4$: TST (R5)+ ;Point to next routine BR 3$ ;Try again 5$: JSR PC,@(R5) ;Call the routine ABORT:: .IF EQ BIT #NOTSYS,MNTFLG ;Is the system device down? ;007 BEQ 10$ ;Branch if not. No need to wait WAIT #WAITSY,#SYSDEV ;Wait for system device to be mounted (maybe) 10$: BIT #FL.SQU,$AFLAG ;Doing SQUEEZE? BEQ RETRY ;Branch if not .DSTAT #INST,#LDDEV ;Check for LD BCS RETRY ;Branch if LD is not known .GVAL #IOAREA,#S.SUFF ;Get the suffix in R0 ADD R0,LDDEV ;Add in the M or X suffix to LD MOV #S.CHAN,R0 ;R0 -> Chain info area MOV #LDCHN,R1 ;R1 -> Info or chain MOV #CHNSIZ,R2 ;R2 = Number of words of chain info 11$: MOV (R1)+,(R0)+ ;Move in information SOB R2,11$ ;Move in each word .CHAIN ;Go fix up logical disks .IFF ;NE MDUP BR RETRY ;Get next command .ENDC ;EQ .SBTTL Support routines .IF EQ .SBTTL YESCHK - Get a response from the console ;+ ; YESCHK ; This routine gets a response from the console terminal, rather than any ; indirect command file that may be running. It does this for the ; "are you sure" and "continue" prompts. The entire purpose for taking input ; from the console is to protect the user from himself. ; ; JSR PC,YESCHK ; ; R0 = 1 if the console input = Y* ;007 ; R0 = -1 if the console input = N* or double Control/C ;007 ; R0 = 0 if the console input <> Y* or N* (other) ;007 ; ;007 ; also, ;007 ; Z-bit = 1 if the console input = Y* ;- YESCHK:: .TTYIN ;Get a character from the terminal .IF NE IND CMPB R0,#CR ;Was it just a return? BNE 11$ ;Branch if not MOV #1,R0 ;Make return same as Y* .TTYIN ;Get the line feed BR 4$ ;Return .ENDC ;NE IND 11$: MOV R0,-(SP) ;Save it 1$: .TTYIN ;Collect the rest of the stuff TST CTRLC ;Double Control/c's? ;007 BEQ 12$ ;No ;007 CLR R0 ;Clear out the Control/C ;007 BR 25$ ;Same as N* ;007 12$: CMPB R0,#LF ;Is it a ? ;007 BNE 1$ ;Branch if not. Get rest of line CLR R0 ;Default is neither Y* nor N* ;007 CMPB #'a,(SP) ; Between a and z ? BHI 5$ ; No, branch CMPB #'z,(SP) ; Between a and z ? BLO 5$ ; No, branch BICB #40,(SP) ; Capitalize it 5$: CMPB #'Y,(SP) ;Is it a Y? ;007 BNE 2$ ;No ;007 INC R0 ;It's Y* ;007 2$: CMPB #'N,(SP) ;Is it a N? ;007 BNE 3$ ;No ;007 25$: DEC R0 ;It's N* ;007 CLR CTRLC ;Clear SCCA status word ;007 3$: CMPB #'Y,(SP)+ ;Set the Z-bit if it's Y* ;007 4$: RETURN .SBTTL RUSURE - Do the "are you sure" prompt ; ; "Never underestimate the power of human stupidity." ; - Robert Anson Heinlein, "Time Enough for Love" ; ;+ ; RUSURE ; This routine prints the "dev:/option; Are you sure?" prompt. ; ; R0 <> 0 -> File name for prompt ; = 0 => no filename for prompt ; R1 = 0 => no check for FG ; <> 0 => check for FG ; RUSPRM -> Prompt ; ; JSR PC,RUSURE ; ; Z-bit = 1 if the console input = Y* ; or /Y (/NOQUERY) specified ; ; R0, R1 modified ; CMDBUF modified ;- .ENABL LSB RUSURE:: BIT #FL.YES,$MFLAG ;/Y in effect? BNE 2$ ;Branch if so MOV R0,-(SP) ;Save -> filename TST R1 ;Check for foreground? BEQ 1$ ;Branch if not .GVAL #IOAREA,#S.CNF1 ;Get the first config word BIT #C1.FGL,R0 ;Is the foreground loaded BEQ 1$ ;Branch if not .PRINT #MSGFGL ;Print the message .PRINT #CRLF ;Print a 1$: MOV (SP)+,R0 ;Restore -> filename BEQ RSURE1 ;Branch if no filename to print MOV #CMDBUF,R1 ;R1-> file spec buffer CALL $FNASC ;Convert filename to ASCII MOVB #200,(R1)+ ;No .PRINT #CMDBUF ;Print the filename RSURE1:: .PRINT RUSPRM ;Print the prompt .PRINT #MSGRUS ;Print "; Are you sure? " BR YESCHK ;Check for "Y". Return from YESCHK 2$: SEZ ;Flag /Y RETURN .SBTTL FGCHEK - Check for a loaded foreground job ;+ ; FGCHEK ;- FGCHEK:: BIT #FL.YES,$MFLAG ;/Y specified? BNE 2$ ;Branch if so. Return with Z-bit set .GVAL #IOAREA,#S.CNF1 ;Get 1st config word BIT #C1.FGL,R0 ;Is a foreground job loaded? BEQ 2$ ;Branch if not ;+ ;ERROR .PRINT #MSGFGL ;Print the message .PRINT #MSGRUS ;Print "are you sure?" ;- BR YESCHK ;Check the response and return .DSABL LSB .SBTTL WAITCK - Wait for a disk to be mounted ;+ ; WAITCK ; This routine will wait for the system device to be replaced with the output ; device, if /W (/WAIT) was given. It will prompt the user to type "Y". If ; anything other than "Y" is typed, the user is prompted again. ; If an N is typed, the user wants to abort. So, if the system disk is ;007 ; currently mounted, it is mounted, and the operation is aborted. ;007 ; ; R0 -> RAD50 device filename block ; WAITPR -> Prompt ; ; JSR PC,WAITCK ; ; R0 modified ;- PSECT PUREB .EVEN WAITMV::.ASCII \next output\<200> ;011 .IF EQ IND ;007 MNTPRM: .ASCII \Mount \<200> VINPRM: .ASCII \ volume in \<200> WAITIN::.ASCII \input\<200> WAITSY::.ASCII \system\<200> WAITOU::.ASCII \output\<200> .IFF ;007 MNTPRM::.ASCII <12>\ Mount \<200> .EVEN VINPRM: .ASCII \ in \<200> ;007 .EVEN WAITIN::.ASCII \ \ ;011 WAITSY::.ASCII \ \ ;011 WAITOU::.ASCII \ \ WTINVL::.ASCII \ \ WTOUVL::.ASCII \ \ WTSYVL::.ASCII \ \ .ENDC ;EQ IND ;007 ;005 ;005 PSECT IMPURE DEVPRM: .BLKB 6 ;ASCII device name storage TMPDEV: .WORD 0 ;RAD50 device name .WORD 0 ;Must be 0 .BLKW 2 ; ;007 MNTFLG::.WORD 0 ;Flag word for /WAIT ;007 NOTSYS = 1 ;"System volume not mounted" flag ;007 MNTINP = 2 ;"Input volume mounted" flag ;007 ABT = 4 ;User typed N*: abort ;007 ;007 PSECT * WAITCK:: BIC #ABT,MNTFLG ;Clear abort flag ;007 BIT #FL.WAT,$MFLAG ;/W given? BEQ 3$ ;Branch if not. Immediate return .IF NE IND ;005 CMPB @WAITPR,#'* ;Is the prompt a *? ;005 BEQ 3$ ;Yes, don't print it ;005 .ENDC ;.IF NE IND ;005 CMP WAITPR,#WAITIN ;Is this for input? ;006 BNE 4$ ;No ;006 CMP SYSDEV,@R0 ;Are input and system devs the same? BEQ 39$ ;Yes - so get it may not be mounted BIT #MNTINP,MNTFLG ;Has the input device been mounted? ;007 BNE 3$ ;Yes - it already has 39$: BIS #MNTINP,MNTFLG ;Say it's been mounted ;007 4$: MOV R1,-(SP) ;Preserve R1 MOV #DEVPRM,R1 ;Point to RAD50/ASCII conversion area MOV @R0,TMPDEV ;Get the device name MOV #TMPDEV,R0 ;R0 -> device name CALL $FNASC ;Convert to ASCII (removes blanks) MOVB #200,@R1 ;No , please MOV (SP)+,R1 ;Restore R1 1$: .PRINT #MNTPRM ;Print "Mount " .PRINT WAITPR ;Print the disk prompt (system, input, output) .PRINT #VINPRM ;Print " volume in " .PRINT #DEVPRM ;Print the device name .IF EQ IND .PRINT #MSGCON ;Print "; Continue? " .IFF ;EQ IND .PRINT #MSGCNT ;Print " Press return to continue" .ENDC ;EQ IND CALL YESCHK ;Get a response ;007 ; BNE 1$ ; or wait until you do ;007 TST R0 ;What's the response? ;007 BGE 11$ ;Branch if it's not N* ;007 CMP WAITPR,#WAITSY ;Mounting SYSTEM? BEQ 10$ ;Branch if so BIS #ABT,MNTFLG ;We want to abort ;007 10$: CMP SYSDEV,TMPDEV ;Was this to dismount the system device? BEQ 13$ ;Yes - prompt to remount system device BIT #NOTSYS,MNTFLG ;Is the system mounted? ;007 BEQ 19$ ;Yes - go ahead and abort ;007 13$: MOV #WAITSY,WAITPR ;Set up prompt to mount system volume ;007 MOV #SYSDEV,R0 ;Device for system volume ;007 BR 4$ ;Go mount system volume ;007 11$: BEQ 1$ ;Not Y* or N* - go reprompt ;007 .IF NE IND CALL VOLCHK ;Check for proper volume id BCS 1$ ;Wrong volume - reprompt .ENDC ;NE IND BIT #ABT,MNTFLG ;Answer was yes - Are we aborting? ;007 BEQ 12$ ;No it's just a normal mount ;007 BIC #NOTSYS,MNTFLG ;System volume is back up ;007 ;+ ;ERROR 19$: .ERR #ERAREA,#ONC,LEVEL=ERROR,RETURN=YES ;007 ; <-E-Operation not completed> ;007 ;- JMP RETRY ;Get a new command line ;007 12$: CMP WAITPR,#WAITSY ;Are we putting the system device back u;007 BNE 2$ ;Branch if not BIC #NOTSYS,MNTFLG ;Say we've got it back ;007 CALL NOSCCA ;Turn off CTRL/C intercept BR 3$ ; 2$: CMP SYSDEV,TMPDEV ;Are we dismounting the system device? BNE 3$ ;Branch if not. CALL SCCA ;Intercept CTRL/C's BIS #NOTSYS,MNTFLG ;Say the system device isn't there ;007 3$: RETURN .ENDC ;EQ .SBTTL VOLCHK - Verify volume id after volume is mounted. ;+ ;VOLCHK ;This procedure checks the volume id of a volume after it is mounted for ;a /WAIT operation. It is used in conjuction with the APPRMT procedure in ;DUPIMA. That procedure contains a more detailed description of how to use ;VOLCHK and APPRMT. ; ; Input: ; DEVPRM = ASCII device name storage ; WAITPR ->Prompt ; TMPDEV = RAD50 device name ; ; CALL VOLCHK ; ; Output: ; C BIT SET -> Wrong volume was mounted ; C BIT CLEAR -> Correct volume was mounted ;- .IF NE IND PSECT PUREB .EVEN .IF EQ IND MSGWVL: .ASCII \Wrong volume mounted in \<200> .IFF ;EQ IND MSGWVL: .ASCII <12><15>\ Wrong volume mounted in \<200> .ENDC ;EQ IND MGEND: .ASCIZ <12><15> PSECT IMPURE DBLK: .BLKW 4 ;Device name block for .LOOKUP PSECT * VOLCHK: JSR R2,$SAVVR ;Save R0-R2 .LOOKUP #IOAREA,ACHAN,#TMPDEV ;Open the device non-filestructured BCC 1$ ;Branch if no error ;+ ;ERROR .ERR ;what does this do? ;- 1$: .READW #IOAREA,ACHAN,#APIN,APSZ,#HOMBLK BCC 2$ ;Branch if no error ;+ ;ERROR .ERR #ERAREA,#FE.INE,LEVEL=FATAL,RETURN=NO,FILE=#TMPDEV ; <-F-Input error: dev> ;- 2$: .CLOSE ACHAN ;Close the channel MOV #APIN,R1 ;R1-> home block ADD #DK.VID,R1 ;R1-> volume id CMP WAITPR,#WAITIN ;Is it for input volume? BNE 3$ ;Branch if not MOV #WTINVL,R2 ;R2 -> vol id for input volume BR 5$ 3$: CMP WAITPR,#WAITOU ;Is it for output volume? BNE 4$ ;Branch if not MOV #WTOUVL,R2 ;R2 -> vol id for output volume BR 5$ 4$: MOV #WTSYVL,R2 ;R2 -> vol id for system volume 5$: MOV #6,R0 ;Number of words in vol id 6$: CMP (R1)+,(R2)+ ;Compare the vol ids BNE 7$ ;Branch if they differ SOB R0,6$ ;continue CLC ;Say they match BR 9$ ;And return 7$: .PRINT #MSGWVL ;"Wrong volume mounted in " .PRINT #DEVPRM ;Device name .PRINT #MGEND ;CRLF SEC ;Say they didn't match 9$: RETURN .ENDC ;NE IND .SBTTL NOSCCA - Drop CTRL/C intercept ;+ ; NOSCCA ; This routine backs up one level of .SCCA. When the count goes to 0, ; CTRL/C intercept is disabled. ; ; CALL NOSCCA ; ; R0 = random ; SCCNT = SCCNT - 1 ;- .ENABL LSB NOSCCA:: DEC SCCNT ;Decrement the .SCCA count BGT 2$ ;Branch if it should still be in effect CLR SCCNT ;Don't allow it to go negative MOV R1,-(SP) ;Preserve R1 CLR R1 ;Set up to turn off CTRL/C intercept BR 1$ ;Go turn off CTRL/C .SBTTL SCCA - Set CTRL/C intercept ;+ ; SCCA ; This routine bumps the .SCCA count and sets CTRL/C intercept ; ; CALL SCCA ; ; R0 = random ; SCCNT = SCCNT + 1 ;- SCCA:: MOV R1,-(SP) ;Preserve R1 MOV #CTRLC,R1 ;R1 -> CTRL/C flag word INC SCCNT ;Bump the count 1$: .SCCA #IOAREA,R1 ;Set/clear the intercept MOV (SP)+,R1 ;Restore R1 2$: RETURN .DSABL LSB .SBTTL GTDVSZ - Get the size of a device ;+ ; GTDVSZ ; This routine returns the actual size of a device in blocks. ; ; R0 -> Dstatus return block (set up by DSTAT) ; R1 -> File flag word ($OSFLG or $ISFLG) ; R2 = Channel number device is opened on ; ; JSR PC,GTDVSZ ; ; R0 modified ; R1 = size of the device ; ; Errors: ; SFF ;NOT returned to caller ;- PSECT IMPURE SIZBUF: .WORD 0 ;.SPFUN size buffer PSECT * GTDVSZ:: BIT #DEV.MS,@R1 ;Does this device accept multi-sized volumes? BNE 1$ ;Branch if so MOV DS.SIZ(R0),R1 ;Else get the device size BR 3$ ; and return 1$: .SPFUN #IOAREA,R2,#SF.GSZ,#SIZBUF,#1,#0,#0 ;Get the size of the ; device (DY,DM, or DL) BCC 2$ ;Branch if no error ;+ ;ERROR .ERR #ERAREA,#SFF,LEVEL=FATAL,RETURN=NO ; <-F-Size function failed> ;- 2$: MOV SIZBUF,R1 ;Copy the device size 3$: RETURN .SBTTL REALDV - Get the real device name .IF EQ MDUP ;+ ; REALDV ; This routine returns the real device name of the device associated with ; a channel. ; ; R0 = channel number ; R1 -> location to place the RAD50 device name ; ; CALL REALDV ; ; C-bit = 0 => success ; R0 random ; (R1) = RAD50 device and unit number ; ; C-bit = 1 => failure - cannot happen ; ; Errors: ; FE.CNO ;NOT returned to caller ; WVR ;C-bit set (cannot happen) ;- REALDV:: MOV R0,-(SP) .CSTAT #IOAREA,(SP)+,#CSTAT ;Get channel status BCC 1$ ;Branch if channel is open ;+ ;ERROR .ERR #ERAREA,#FE.CNO,LEVEL=UABORT,RETURN=NO ; <-U-Channel not open> ;- 1$: MOV R2,-(SP) ;Save R2 MOV R1,-(SP) ;Save buffer pointer MOV CSTAT+8.,R1 ;Copy the unit number MOV CSTAT+10.,R0 ;Copy physical device name CALL $DEVTR ;Translate to RAD50 device spec MOV (SP)+,R1 ;Restore buffer address MOV R0,@R1 ;Store RAD50 device spec in buffer MOV (SP)+,R2 ;Restore R2 CLC RETURN .ENDC ;EQ MDUP .SBTTL CKSMHB - Calculate the checksum for the home block ;+ ; This routine calculates the checksum for the home block. ; ; R5 -> Home block buffer ; ; CALL CKSMHB ;- CKSMHB::SAVE02 ; Save volatile registers CLR R0 ; Clear accumulator MOV R5,R1 ; Point to homeblock data MOV #255.,R2 ; Add up this many words 60$: ADD (R1)+,R0 SOB R2,60$ MOV R0,@R1 ; Store it in homeblock RETURN .SBTTL I/O Routines .SBTTL $READ - Input routine .SBTTL $WRITE - Output routine ;+ ; $READ and $WRITE ; These routines do all the I/O in DUP. They determine whether or not a ; .READW/.WRITW or a .SPFUN should be issued. ; ; SPFUNI = 0 => normal .READW ; <> 0 => .SPFUN read ; SPFUNO = 0 => normal .WRITW ; <> 0 => .SPFUN write ; R0 -> EMT area block ; ; JSR PC,$READ ; JSR PC,$WRITE ; ; R0 modified ; C-bit set on error ;- REDCOD = 10 WRTCOD = 11 SPFCOD = 32 PSECT PURE READIT: .WORD REDCOD ;Read EMT code .WORD SPFUNI ;Input .SPFUN flag byte .WORD $ISFLG ;Input device/file flag word .WORD ;DL, DM, and DY .SPFUN read function code .WORD ;Magtape .SPFUN read function code WRITIT: .WORD WRTCOD ;Write EMT code .WORD SPFUNO ;Output .SPFUN flag byte .WORD $OSFLG ;Output device/file flag word .WORD ;DL, DM, and DY .SPFUN write function code .WORD ;Magtape .SPFUN read function code PSECT IMPURE FUNC: .WORD 0 ;EMT code to execute PSECT * .ENABL LSB $READ:: SAVE35 ;Save non-volatile registers MOV #READIT,R3 ;R3 -> Read functions BR 1$ ;Go do common code $WRITE:: SAVE35 ;Save non-volatile registers MOV #WRITIT,R3 ;R3 -> Write functions 1$: MOV (R3)+,FUNC ;Get the function (.READx or .WRITx) CLR R5 ;Clear the function (completion routine) MOV (R3)+,R4 ;Get the special function flag TSTB @R4 ;Do .SPFUN? BEQ 2$ ;Branch if not MOV #SPFCOD,FUNC ;Do a .SPFUN MOV (R3)+,R4 ;Get the device/file flag word MOV (R3)+,R5 ;Assume a disk .SPFUN BIT #DEV.MT,@R4 ;Doing a magtape? BEQ 2$ ;Branch if not MOV (R3)+,R5 ;Do a magtape .SPFUN 2$: MOVB FUNC,1(R0) ;Set up the EMT code MOV R5,10(R0) ;Set up the .SPFUN (or completion routine) CLR 12(R0) ;Clear .SPFUN completion routine EMT 375 ;Do the EMT RETURN .DSABL LSB .SBTTL WRTnTM - Write tape marks .IF EQ ;+ ; WRTnTM ; The following routines write tape marks to magtape. The different entries ; are for writing different numbers of tape marks. ; ; R1 = channel number ; ; CALL WRTnTM ;- WRT3TM:: ;3 tape mark entry point CALL WRT1TM ;Write 1 tape mark WRT2TM:: ;2 tape mark entry point JSR PC,@PC ;Write 2 tape marks WRT1TM:: ;1 tape mark entry point .SPFUN #IOAREA,R1,#SF.WTM,#0,#0,#0,#0 ;Write a tape mark RETURN .ENDC ;EQ .SBTTL Directory Manipulation Routines .SBTTL WRTDIR - Write out a directory segment ;+ ; WRTDIR ; This routine writes out a directory segment on ICHAN. Before doing so, ; it locks the USR in core, sets control C intercept, and purges the USR's ; directory buffer. ; ; $DIRBF -> directory buffer ; $DIRSG = physical block number of this segment ; $DIRCH = channel number directory opened on. ; ; JSR PC,WRTDIR ; ; R0 modified ; C-bit = 1 if an output error occurred ;- WRTDIR:: ; MOVB SPFUNO,-(SP) ;Save SPFUNO ;003 [-GTS] MOV SPFUN,-(SP) ;Save SPFUN [+GTS] CLR SPFUN ;No special function writes CALL SCCA ;Intercept CTRL/C ; MOV @#S$RMON,R0 ;R0 -> base of RMON ;009 ; CLR S.BLKY(R0) ;Clear BLKEY to purge USR directory buff;009 .PVAL #IOAREA,#S.BLKY,#0 ;Clear BLKEY ;009 WRITE #IOAREA,$DIRCH,$DIRBF,#SEGSIZ,$DIRSG ;Write out the segm ROR -(SP) ;Save the return status MOV @#S$EERB,-(SP) ;And the error code CALL NOSCCA ;Turn off CTRL/C intercept MOV (SP)+,@#S$EERB ;Restore the return error code ROL (SP)+ ; and the status ; MOVB (SP)+,SPFUNO ;Restore SPFUNO ;003 [-GTS] MOV (SP)+,SPFUN ;Restore SPFUN [+GTS] RETURN .SBTTL FNDPRM - Find a permanent file directory entry .SBTTL FNDEMP - Find an unused directory entry .SBTTL FNDPRO - Find a protected file directory entry .SBTTL FNDEOT - Find an unused or tentative directory entry .SBTTL FNDEOS - Find an end-of-segment directory entry ;+ ; FNDPRM ; This routine finds a permanent entry whose filename matches that pointed to ; by R0. It starts at the current position in the directory buffer. ; ; R0 -> 3 word RAD50 filename block ; $DIRBF -> directory buffer ; $DIRCH = channel number for directory I/O ; ; CALL FNDPRM ; ;+ ; FNDEMP ; This routine finds the next empty entry in the directory. ; ; $DIRBF -> directory buffer ; $DIRCH = channel number for directory I/O ; ; CALL FNDPRO ; ;+ ; FNDPRO ; This routine finds the next protected file in the directory. ; ; $DIRBF -> directory buffer ; $DIRCH = channel number for directory I/O ; ; CALL FNDPRO ; ;+ ; FNDEOT ; This routine finds the next protected file in the directory. ; ; $DIRBF -> directory buffer ; $DIRCH = channel number for directory I/O ; ; CALL FNDEOT ; ;+ ; FNDEOS ; This routine finds the next end-of-segment entry. ; ; $DIRBF -> directory buffer ; $DIRCH = channel number for directory I/O ; ; CALL FNDEOS ; ; All routines exit with: ; ; C-bit = 0 => no error ; R0 <> 0 => R0 -> requested entry ; R0 = 0 => no entry found ; ; C-bit = 1 => directory input error ; R0 = error code ; ; Errors: ; DIE ; DOE ; ILD ;- PSECT PURE ASTAST: .WORD R50AST,0,R50AST ;'*.*' for FNDEMP, FNDEOS, and FNDPRO PSECT IMPURE SEGCHK: .WORD 0 ;Looping directory check word PSECT * .ENABL LSB FNDPRM:: SAVE35 ;Save non-volatile registers MOV #DS.PRM,R4 ;Look for a permanent entry MOV R0,R5 ;R5 -> filename block BR 2$ ; FNDEMP:: SAVE35 ;Save non-volatile registers MOV #DS.EMP,R4 ;Look for an empty entry BR 1$ ;*.* is the filename FNDPRO:: SAVE35 ;Save non-volatile registers MOV #DS.PRO,R4 ;Look for a protected file BR 1$ ;*.* is the filename FNDEOT:: SAVE35 ;Save non-volatile registers MOV #,R4 ;Look for an empty or tentative entry BR 1$ ;*.* is the filename FNDEOS:: SAVE35 ;Save non-volatile registers MOV #DS.EOS,R4 ;Look for the EOS entry 1$: MOV #ASTAST,R5 ;*.* is the filename 2$: MOV #MAXSEG+1,SEGCHK ;Assume a new directory 3$: CALL NEXTFL ;Get the next entry 4$: BCS 11$ ;Branch on error TST R0 ;Did we get an entry? BEQ 11$ ;Branch if not. End of directory BIT #DS.EOS,@R0 ;Is this an end-of-segment entry? BEQ 5$ ;Branch if not DEC SEGCHK ;Count down the segments BNE 5$ ;Branch if directory still valid ;+ ;ERROR MOV #ILD,R0 ;Set up the error code BR 10$ ;Return error ;- 5$: BIT R4,@R0 ;Is the entry type correct? BEQ 3$ ;Branch if not MOV R0,R3 ;R3 -> directory entry TST (R3)+ ;R3 -> filename MOV R5,-(SP) ;Preserve R5 CMP @R5,#R50AST ;Filename we looking for = '*'? BNE 6$ ;Branch if not CMP (R5)+,(R5)+ ;Skip the filename CMP (R3)+,(R3)+ ;Both places BR 7$ ;Go check filetype 6$: CMP (R5)+,(R3)+ ;First word of name match? BNE 8$ ;Branch if not CMP (R5)+,(R3)+ ;Second word? BNE 8$ ;Branch if not 7$: CMP @R5,#R50AST ;Filetype = '*'? BEQ 9$ ;Branch if so. We have a match CMP @R5,@R3 ;Filetypes match? BEQ 9$ ;Branch if so. We have a match 8$: MOV (SP)+,R5 ;Restore R5 BR 3$ ;Try again 9$: TST (SP)+ ;Clean the stack TST (PC)+ ;No error ;Clear carry 10$: SEC 11$: RETURN .DSABL LSB .SBTTL NEXTFL - Get the next file entry ;+ ; NEXTFL ; This routine returns the next entry in a directory. If there are no more ; it returns C-bit set. ; ; $NXTFL -> next entry in directory. Caller should set this to 0 ; to force the next segment to be read ; $NXTSG = segment number of the next directory segment. Caller ; should set this to 1 to force the directory to be read ; from the beginning ; $DIRCH = channel number to read the directory on ; $DIRBF -> buffer to read directory into. 512. words. ; $DIRTY = 1 => write the current directory segment before reading ; the next one. ; ; CALL NEXTFL ; ; C-bit = 0 => no error ; R0 <> 0 => R0 -> directory entry ; $STBLK = starting block number for the entry ; ; R0 = 0 => no more entries in directory ; ; C-bit = 1 => error ; R0 = error code ; ; Errors: ; DIE ; DOE ; ILD ;- .ENABL LSB NEXTFL:: SAVE35 ;Save registers 3-5 1$: MOV $NXTFL,R0 ;R0 -> next directory entry BNE 5$ ;Branch if we have one MOV $NXTSG,R5 ;R5 = next segment number. BEQ 7$ ;Branch if no more TST $DIRTY ;Do we need to re-write this segment? BEQ 2$ ;Branch if not CALL WRTDIR ;Else do so BCC 2$ ;Branch if no error ;+ ;ERROR MOV #DOE,R0 ;Set the error code BR 8$ ;Return to caller ; <-F-Directory output error> ;- 2$: CLR $DIRTY ;Clear the directory re-write flag MOV $DIRBF,R4 ;R4 -> directory input buffer MOV R4,$NXTFL ;Copy it ADD #DH.SIZ,$NXTFL ;$NXTFL -> first entry ASL R5 ;Directory segments are 2 blocks long ADD #4,R5 ;And start at block 6 MOV R5,$DIRSG ;Save the block number for WRTDIR READ #IOAREA,$DIRCH,R4,#SEGSIZ,R5 ;Read the segment BCC NXTFL1 ;Branch if no error ;+ ;ERROR MOV #DIE,R0 ;Set the error code BR 8$ ; ; <-F-Directory input error> ;- NXTFL1: MOV DH.NXT(R4),$NXTSG ;Save the block number of the next segment MOV DH.STB(R4),$STBLK ;Save the start block for files in this seg. BEQ 4$ ;Branch if invalid CLR $LSTLN ;Clear the length of the last file CMP #6,R5 ;This the first segment? BNE 1$ ;Branch if not MOV DH.HI(R4),$HISEG ;Save the highest segment open MOV DH.AVL(R4),$AVAIL ;and the highest available BLE 4$ ;Branch if Invalid CMP #MAXSEG,$AVAIL ;Is it good? BLO 4$ ;Branch if not 3$: MOV DH.EXB(R4),$EXTBY ;Save # of extra bytes CMP #MAXBYT,$EXTBY ;Valid? BLO 4$ ;Branch if not BIT #1,$EXTBY ;Is it odd? BEQ 1$ ;Branch if not ;+ ;ERROR 4$: MOV #ILD,R0 ;Return error code SEC ;Indicate error BR 8$ ; ; <-F-Invalid directory> ;- 5$: BIT #DS.EOS,@R0 ;End-of-segment? BEQ 6$ ;Branch if not CLR $NXTFL ;Force next call to read next segment BR 7$ ;Done 6$: ADD #DE.SIZ,$NXTFL ;Point to next entry ADD $EXTBY,$NXTFL ;Don't forget extra bytes ADD $LSTLN,$STBLK ;Point to the start of this file MOV DE.LEN(R0),$LSTLN ;Save the size of this file 7$: CLC ;Indicate no errors 8$: RETURN .DSABL LSB .SBTTL LOOKUP - "Lookup" a file without the USR ;+ ; LOOKUP ; This routine fakes a .LOOKUP of a file. The channel must be open on the ; device non-file-structured. The routine does not work on magtapes or ; cassettes. ; ; R3 -> RAD50 device/filename (4 words) ; R4 = channel number to use ; $DIRCH = channel number to read directory on ; $DIRBF -> 2 block directory buffer ; ; CALL LOOKUP ; ; C-bit = 0 => success ; ; C-bit = 1 => failure ; R0 = error code ; R3 = 0 if R0 = FE.SYS ; 2(R3) - 6(R3) = 0 if R0 = DIE, DIO or ILD ; ; Errors: ; DIE ; DOE ; FE.FNF ; ILD ; FE.SYS ;- .ENABL LSB LOOKUP:: SAVE35 ;Save non-volatile registers TST (R3)+ ;Skip the device name CLR $NXTFL ;No next file for directory scanner MOV #1,$NXTSG ;Force scan to start at beginning MOV R3,R0 ;R0 -> filename CALL FNDPRM ;Find the file BCC 1$ ;Branch if no error CLR (R3)+ ;Only print device name CLR (R3)+ ; CLR @R3 ; BR 6$ ;Return to caller 1$: TST R0 ;Did we find the file? BNE 2$ ;Branch if so ;+ ;ERROR MOV #FE.FNF,R0 ;Set up the error code BR 6$ ;Return error to caller ;- 2$: MOV #STBLK,R5 ;R5 -> .SAVESTATUS return block MOV R0,-(SP) ;Save R0 .SAVEST #IOAREA,R4,R5 ;Get the channel status block MOV (SP)+,R0 ;Restore R0 BCC 5$ ;Branch if no error ;+ ;ERROR 3$: MOV #FE.SYS,R0 ;Channel not open or .ENTERed or magtape!!! 4$: CLR 2(SP) ;Don't give filename BR 6$ ;Give the error ;- 5$: MOV $STBLK,C.SBLK(R5) ;Set up the start block of the file MOV DE.LEN(R0),C.LENG(R5) ;Set up the file size .REOPEN #IOAREA,R4,R5 ;Reopen the file BCS 3$ ;Branch if error TST (PC)+ ;Clear carry 6$: SEC ;Indicate error RETURN .SBTTL PURGE - "Purge" a channel ;+ ; PURGE ; This routine changes the channel status information of a channel to make ; it appear as though a non-file-structured .LOOKUP had been performed. ; ; R3 -> RAD50 device/filename (4 words) ; R4 = channel number to use ; ; CALL PURGE ; ; C-bit = 0 => success ; ; C-bit = 1 => failure ; R0 = error code ; R3 = 0 ; ; Errors: ; FE.SYS ;- PURGE:: SAVE35 ;Save non-volatile registers MOV #STBLK,R5 ;R5 -> .SAVESTATUS return block .SAVEST #IOAREA,R4,R5 ;Get channel status block BCS 3$ ;Branch on error CLR C.SBLK(R5) ;Make it non-file-structured CLR C.LENG(R5) ;Clear the file size .REOPEN #IOAREA,R4,R5 ;Reopen the channel BCS 3$ ;Branch on error CLC RETURN .DSABL LSB .SBTTL Overlay Load Routines ;+ ; These routines are use to get from one overlay to another and possibly ; back. They are especially needed when the /WAIT option is being used. ;- .IF EQ S1LINK:: ;This entry point called from ZERO CALL CHKSYS ;Make sure the system device is mounted JSR PC,SCAN ;Do a bad block scan CALL CHKSYS ;Make sure the system device is mounted JMP ZERO1L ;Go back to zero V1LINK:: ;This entry point called from ZERO CALL CHKSYS ;Make sure the system device is mounted CALL VOLID ;Do /V stuff Z2LINK:: ;This entry point called from ZERO CALL CHKSYS ;Make sure the system device is mounted JMP ZERO2L ;Go back to zero C1LINK:: ;This entry point called from ZERO2L CALL CHKSYS ;Make sure the system device is mounted CALL CREBAD ;Go create .BAD files CALL CHKSYS ;Make sure the system device is mounted JMP ZERO3L ;Go back to zero .ENDC ;EQ .IF NE MDUP C1LINK:: CALL CREBAD ;Create .BAD entries for /Z JMP ZERO3L S1LINK:: CALL SCAN ;Do /B scan JMP ZERO1L ;Return to /Z Z2LINK:: JMP ZERO2L ;Do second half of /Z .IFF ;NE MDUP .IF EQ SDC CHKSYS:: BIT #NOTSYS,MNTFLG ;Is the system volume mounted? ;007 BEQ 1$ ;Branch if so WAIT #WAITSY,#SYSDEV ;Wait for the system device to be mounted 1$: RETURN .ENDC ;EQ SDC .ENDC ;NE MDUP .SBTTL MDUP Subroutines .IF NE MDUP .SBTTL BUILD - Build MDUP.Mx ;+ ; BUILD ; This routine builds the MDUP.Mx file. Note that the system must be booted ; on a 24kw system (or larger) but be patched to use only 16kw of that space. ;- BUILD:: .GTCOR #<512.*6.> ;Get memory buffer space BCC 1$ ;+ ;ERROR .ERR #ERAREA,#FE.NOM,LEVEL=FATAL,RETURN=NO ; <-F-Insufficient memory> ;- 1$: MOV R0,IBFBEG ;Save pointer to buffer MOV R0,SAVMEM ;Save for WBOOT and BOOT .GVAL #IOAREA,#S.CNF1 ;Check configuration word ;070 BIT #C1.USW,R0 ;to see if USR has been set NOSWAP ;070 BNE 104$ ;If USR is SWAP, user must NOSWAP it ;070 ;+ ;070 ;ERROR ;070 .ERR #ERAREA,#USW,LEVEL=FATAL,RETURN=NO ;070 ; <-F-Must SET USR NOSWAP first> ;070 ;- ;070 ;070 104$: .GVAL #IOAREA,#S.MEMS ;Put MEMTOP/64. (bytes) into R0 ;070 MOV R0,R1 ;and into R1 ;070 ASR R0 ;Divide R0 by 8 to get ;070 ASR R0 ;the number of blocks needed ;070 ASR R0 ;to store image ;070 BIT #7,R1 ;If MEMTOP was an exact mult ;070 BNE 110$ ;of 512 bytes then ;070 DEC R0 ;we need one less block ;070 110$: MOV R0,R5 ;R5 is number of blocks-1 ;070 WRITE #IOAREA,#OCHAN,#0,#1,R5 ;Write last block of file ;070 BCS 3$ ;Branch on error ;**-1 .CLOSE #OCHAN ;Close the channel .TRPSET #IOAREA,#TRP410 ;Handle our own traps to 4 and 10 .SERR ;Trap errors MOV #4015,@#S$TFIL ;Set for slow terminals MOV #MDUPST,@#S$STRT ;Mung the start address for MSBOOT CALL SCCA ;Intercept ^C MOV #,NOSCCA ; permanently (stuff with RTS PC) MOV IBFBEG,R4 ;R4 -> location of system buffer ;070 CLR R1 ;R1 -> first word to move ;**-2 CLR R3 ;R3 = block # 122$: MOV #256.,R2 ;Always do a block at a time ;070 MOV R4,R0 ;R0 -> location of system buffer ;**-1 2$: MOV (R1)+,(R0)+ ;Move the system SOB R2,2$ ;Loop .LOOKUP #IOAREA,#OCHAN,#OUTFIL ;Lookup the output file BCS 4$ ;Branch on error WRITE #IOAREA,#OCHAN,R4,#256.,R3 ;Write out this block ;070 BCS 3$ ;Branch on error ;070 .CLOSE #OCHAN ;Close the channel ;**-2 CMP R3,R5 ;Are we done writing file? ;070 BEQ 6$ ;Yes, exit ;070 INC R3 ;Point to next block ;070 BR 122$ ;and do it ;070 ;070 ;+ ;**-5 ;ERROR 3$: MOV #FE.OPE,R1 ;Set up the error code BR 5$ ;Give the error 4$: MOV #FE.FNF,R1 ;Set up the error code 5$: .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES,FILE=#OUTFIL ; <-F-Output error dev:filename> ;**-1 ; <-F-File not found dev:filename> ;070 ; ;070 ;- 6$: .EXIT ;Get out .SBTTL MDUPST - MDUP entry point .ENABL LSB NOP ;Re-entry point (HA) MDUPST:: BIS #IENABL,@#KB$CSR ;Enable keyboard interrupts .PRINT #VERSON ;Tell the user who we are 1$: JMP RETRY ;Start up .SBTTL TRP410 - Trap to 4 and 10 handler TRP410: BCS 2$ ;C-bit set if trap to 10 ;+ ;ERROR MOV #TP4,R1 ;Set the error code BR 3$ ;Give the error 2$: MOV #TP1,R1 ;Trap to 10 3$: .ERR #ERAREA,R1,LEVEL=FATAL,RETURN=YES ;- BR 1$ ;Restart .DSABL LSB .SBTTL COPYMT - Copy magtape files to disk ;+ ; COPYMT ;- COPYMT:: MOV SAVMEM,R5 ;R5 -> I/O buffer MOV R5,IBFBEG ;R5 -> I/O buffer .PURGE #OCHAN ;Purge the output channel MOV OUTFIL,R0 ;R0 = output device name MOV #NEWDEV,R1 ;R1 -> location for ASCII name CALL CONVRT ;Convert the name for file search and .ENTER MOV INFILE,R0 ;R0 = input device name MOV #NEWMT,R1 ;R1 -> location for ASCII name of magtape CALL CONVRT ;Convert it 99$: JSR R5,SPFUN1 ;Rewind the magtape .WORD SF.RWD ;Magtape rewind code CLR SPFUN ;Make sure we do real .WRITW's to the disk MOV #MTFILE,R2 ;Point to beginning of file list for copy CMPB #+1,DOCMND+1 ;doing auto-install? BNE 1$ ;No, branch .IF EQ M$UPD MOV #MONAME,R2 ;Point to beginning of file list for copy MOV #^R1AI,MONAME+2 ;Use AI monitor MOV #"AI,MONAME+10. ; .IFF ;EQ M$UPD MOV #^R1UP,MONAME+2 ;Use Update monitor MOV #"UP,MONAME+10. ; .ENDC ;EQ M$UPD 1$: MOV #OUTFIL+2,R1 ;R1 -> output filename MOV (R2)+,(R1)+ ;Copy the 1st word of the filename BEQ 10$ ;Branch if done MOV (R2)+,(R1)+ ;Copy the 2nd word of the filename MOV (R2)+,(R1)+ ;Copy the filetype .ENTER #IOAREA,#OCHAN,#OUTFIL,#-1 ;Enter the file BCC 4$ ;Branch if no error ;+ ;ERROR .ERR #ERAREA,#DIO,LEVEL=FATAL,RETURN=NO,FILE=#OUTFIL ; <-F-Directory I/O error dev:filename> ;- 2$: MOV #3,R4 ;Space forward past 3 tapemarks 3$: CALL READMT ;Read tape records BCC 3$ ;loop while no error. No TM encountered. SOB R4,3$ ;Count-down TM's until done 4$: CALL READMT BCS 9$ ;Error here indicates LEOT MOV R5,R4 ;R4 -> buffer CMP (R4)+,#"HD ;Header label? BNE 4$ ;Branch if not CMP (R4)+,#"R1 ;Yes, but is it HDR1? BNE 4$ ;Branch if not MOV R2,R0 ;R0 -> ASCII filename MOV #10.,R1 ;R1 = character count 5$: CMPB (R0)+,(R4)+ ;Is this the file? ; BNE 2$ ;Branch if not BEQ 58$ ;BRANCH IF CHARACTERS MATCH CMPB -1(R0),#40 ;compare failed because of blank? BNE 2$ ;Branch if not DEC R4 ;if so, back up tape buffer pointer 58$: SOB R1,5$ ;Loop till done ; JSR R5,SPFUN1 ;Read TM and ignore error ; .WORD SF.RDV CALL READMT ;Read TM and ignore error CLR R4 ;Clear output block number 6$: CALL READMT ;Read the data block ; JSR R5,SPFUN1 ;Read the data ; .WORD SF.RDV BCC 8$ ;Branch if no error .CLOSE #OCHAN ;Close the output channel ; JSR R5,SPFUN1 ;Skip EOF label ; .WORD SF.RDV ; JSR R5,SPFUN1 ;Skip next TM ; .WORD SF.RDV CALL READMT ;Skip EOF label CALL READMT ;Skip next TM 7$: ADD #10.,R2 ;R2 -> next filename BR 1$ ;Go do next file 8$: WRITE #IOAREA,#OCHAN,R5,#256.,R4 BCS 9$ ;Branch on error INC R4 ;Bump the output block number BR 6$ ;Go read some more 9$: .PURGE #OCHAN ;Purge the output file JSR R5,SPFUN1 ;Rewind the magtape .WORD SF.RWD BR 7$ ;Skip this file 10$: .PURGE #OCHAN ;Purge the output file JSR R5,SPFUN1 ;Rewind the magtape .WORD SF.RWD DECB DOCMND+1 ;Decrement high byte BEQ 1$ ;Go process more files CALL SETUP1 ;Get I/O channels opened NFS MOV #MONAME,R0 ;R0 -> RAD50 monitor name MOV (R0)+,(R2)+ ;Copy 1st word of filename MOV (R0)+,(R2)+ ; and the 2nd word MOV @R0,@R2 ; and the filetype CALL WBOOT ;Write the bootstrap CALL SETUP1 ;Do it again for BOOT JMP BOOT ;Go boot the new system .SBTTL CONVRT - Convert RAD50 device name to ASCII filename ;+ ; CONVRT ;- CONVRT:: MOV R0,R2 ;Save RAD50 device name MOV R1,R3 ;Save -> RAD50 name ADD #6,R1 ;R1 -> storage for ASCII name CALL $R50ASC ;Convert it to ASCII CLR R0 ;Set up for MOVB MOVB -(R1),R0 ;Get unit number if any CMP #BLANK,R0 ;Is there a unit number BEQ 1$ ;Branch if not MOVB #BLANK,@R1 ;Get rid of it in the ASCII name SUB #'0,R0 ;DeASCIIfy the character ADD #<^R 0>,R0 ;RAD50'fy it SUB R0,R2 ;Get rid of the unit number in RAD50 name 1$: MOV R2,@R3 ;Save it MOV R3,R1 ;Restore R1 RETURN .SBTTL SETUP1 - Set up code for WBOOT and BOOT ;+ ; SETUP1 ;- SETUP1: .PURGE #ICHAN ;Purge the input channel .PURGE #OCHAN ; and the output channel MOV #INFILE,R2 ;R2 -> input file spec MOV #OUTFIL,R1 ;R1 -> output file spec MOV @R1,@R2 ;Copy the device names CLR 2(R1) ;Clear any filename CLR 2(R2) ;Both places .LOOKUP #IOAREA,#OCHAN,R1 ;Lookup the device non-file-structured BCC 2$ ;Branch if no error ;+ ;ERROR 1$: .ERR #ERAREA,#DIE,LEVEL=FATAL,RETURN=NO,FILE=R1 ; <-F-Directory input error dev:> ;- 2$: .LOOKUP #IOAREA,#ICHAN,R2 ;Lookup on both channels BCS 1$ ;Branch on error MOV SAVMEM,IBFBEG ;Set up pointer to I/O buffer CMP (R1)+,(R2)+ ;Skip past the device name RETURN .SBTTL SPFUN1 - Issue magtape special function ;+ ; SPFUN1 ; JSR R5,SPFUN1 ; .WORD function_code ;- SPFUN1: .SPFUN #IOAREA,#ICHAN,@R5,IBFBEG,#256.,#ERRBLK,#0 BITB (R5)+,(R5)+ ;Skip function code ;Leave C-bit alone RTS R5 READMT: JSR R5,SPFUN1 ;Read a magtape block .WORD SF.RDV SHORTB: bcc 30$ tstb @#52 ;Check system error byte beq 20$ ;Error 0 here indicates EOF cmp errblk,#6 ;short block? bne 20$ ;error if not. 10$: tst (PC)+ ;return C clear 20$: sec 30$: return ERRBLK: .BLKW 4 ;Error and status block .ENDC ;NE MDUP .END DUP