Trailing-Edge
-
PDP-10 Archives
-
decuslib10-10
-
43,50524/d2d.mac
There are no other files named d2d.mac in the archive.
title D2D - disk to disk copy; Richard Denney UTAustin; 1981
subttl Definitions and accumulator assignments
search uuosym
sall ;No expansion of macro definitions.
nosym ;No symbol table listing.
; Accumulator assignments
t1=1 ;Temporary.
t2=2
t3=3
t4=4
t5=5
t6=6
t7=7
t8=10
t9=11
; Note: Be careful eliminating or reordering assignment of registers.
; IDIVs are done in this program which deposits the remainder in the
; register following the one upon which the division was done.
; Eg. a IDIV on T9 would be disastorous since MAPIDX follows it.
mapidx=12 ;First word of current MAP entry being processed.
maplst=13 ;First word of last entry in MAP.
maptmp=14 ;Temporary pointer to move about MAP.
oldidx=15 ;Monitors progress of MAPIDX for security.
wrtblk=16 ;Block address for writing to new disk.
p=17 ;Jump stack.
; Definitions
pdlen==100 ;Length of push down stack.
mapsiz==7 ;Number of words per entry in MAP.
inchnl==1 ;Input channel for reading UFDs, etc.
dmpchn==2 ;Dump channel for dumping SATs and MAP.
outchn==3 ;Output channel for writing to new disk.
blksiz==200 ;Words in a block.
; Following are indexes to data items that compose each entry of MAP.
name==0 ;Index to FileName within a MAP entry.
ext==1 ;Index to FileExtension within a MAP entry.
oldcfp==2 ;Index to old CFP within a MAP entry.
newcfp==3 ;Index to new CFP within a MAP entry.
newufd==4 ;Index to new CFP of UFD pointing to file.
nxtnod==5 ;Index to address of next node in MAP chain.
blkuse==6 ;Number of blocks used.
; End of MAP entry indexes.
define die(error) <
xlist
jrst [outstr [asciz/error/]
exit]
list
>
define savreg <
xlist
push p,t1
push p,t2
push p,t3
push p,t4
push p,t5
push p,t6
push p,t7
push p,t8
list
>
define resreg <
xlist
pop p,t8
pop p,t7
pop p,t6
pop p,t5
pop p,t4
pop p,t3
pop p,t2
pop p,t1
list
>
; NOTE: making the PJRST definition more than one line of code
; will cause problems since skip type instructions are used
; in places to skip over the PJRST. The skip instructions
; skip only a single instruction.
define pjrst(x) <
xlist
jrst x
list
>
subttl HOME Block Definitions
; Note: D2D computes logical block addresses by multiplying
; Compressed File Pointers (CFP), by Blocks Per Cluster, which
; is word HOMPBC in the HOME block. This procedure is satifactory
; as long as Super Clusters = Clusters and a disk structure consists
; of only one physical unit, eg. DSKH = rpa0.
HOMNAM==0 ; "HOM" in SIXBIT
HOMHID==1 ; SIXBIT unit id
HOMPHY==2 ; Physical address of this block,,other home block
HOMSRC==3 ; Position of this STR in SYS search list
HOMSNM==4 ; SIXBIT structure name
HOMNXT==5 ; ID of next unit in file structure
HOMPRV==6 ; ID of previous unit in file structure
HOMLOG==7 ; SIXBIT logical unit # within file structure
HOMLUN==10 ; Logical unit in STR
HOMPPN==11 ; Proj-prog # which refreshed STR
HOMHOM==12 ; LH==Logical block # within unit of Home block
; RH==Log. block # within unit for extra Home block
HOMGRP==13 ; # of blocks per group to try for
HOMBSC==14 ; # blocks per supercluster on this unit
HOMSCU==15 ; # of superclusters per unit
HOMCNP==16 ; Byte ptr for cluster count in RIBS
HOMCKP==17 ; Byte ptr for checksum in RIB
HOMCLP==20 ; Byte ptr for cluster address in RIB
HOMBPC==21 ; # blocks per cluster for this STR
HOMK4S==22 ; # K words for swapping on this unit
HOMREF==23 ; Non-zero if file must be refreshed
HOMSIC==24 ; # SAT blocks in core
HOMSID==25 ; Unit ID of next unit in active swapping list
HOMSUN==26 ; Logical unit # in active swapping list
HOMSLB==27 ; First log. block # for swapping on this unit
HOMCFS==30 ; Swapping class
HOMSPU==31 ; # SAT blocks per unit
HOMOVR==32 ; Overdrawn limit per user on this STR
HOMGAR==33 ; Upper bound on total reserved blocks
HOMSAT==34 ; SAT.SYS (Log. block within STR of first RIB)
HOMHMS==35 ; HOME.SYS
HOMSWP==36 ; SWAP.SYS
HOMMNT==37 ; MAINT.SYS
HOMBAD==40 ; BADBLK.SYS
HOMCRS==41 ; CRASH.SAV
HOMSNP==42 ; SNAP.SAV
HOMRCV==43 ; RECOV.SYS
HOMSUF==44 ; SYS UFD [1,4] UFD
HOMPUF==45 ; Printer UFD [3,3]
HOMMFD==46 ; MFD [1,1]
HOMPT1==47 ; First retrieval ptr for MFD
HOMUN1==50 ; Logical unit # where MFD starts
HOMLEN==51 ; Table of lengths of files created by refresh - 6 words
HOMEND==56 ; Last word kept in UDB copy of Home block
HOMUTP==57 ; Unit type on which HOM block was written
HOMRIP==60 ; Used by RIPOFF (That's not us)
HOMKLB==61 ; First of 20 words used by PDP-11 in KL10 systems
HOMKLE==104 ; Last of the 20 words
HOMK4C==105 ; K for CRASH.EXE file
HOMBTS==106 ; Bits in the HOM block
HOMPVS==1B35 ; Unit contained in a private STR
HOMVID==165 ; Volume ID (3 words, 12 PDP-11 bytes)
HOMOWN==170 ; Owner name (3 words, 12 PDP-11 bytes)
HOMVSY==173 ; System type (3 words, 12 PDP-11 bytes)
HOMCOD==176 ; Contains XWD 0 ,, 707070 (unlikely code)
CODHOM==707070 ; Unlikely code for HOMCOD
HOMSLF==177 ; This block # within unit
subttl RIB Definitions
RIBFIR==0 ; XWD -Nr. of retrieval ptrs ,, First pointer adress
RIBPPN==1 ; XWD Project ,, Programmer number
RIBNAM==2 ; SIXBIT file name
RIBEXT==3 ; SIXBIT file extension ,, Access date
RIBSIZ==5 ; File length in words
RIBVER==6 ; Prog # making last change ,, octal version #
RIBSPL==7 ; Spooled device
RIBEST==10 ; Estimated length of file in blocks
RIBALC==11 ; # of blocks allocated for file
RIBPOS==12 ; Log block # in STR of last group
RIBFT1==13 ; Reserved for future use by DEC
RIBNCA==14 ; Word for customer to define
RIBMTA==15 ; Tape label if file on magtape
RIBDEV==16 ; Name of STR containing file
RIBSTS==17 ; Status bits
RIBELB==20 ; Log block # where bad region begins
RIBEUN==21 ; Err unit # in STR ,, Nr bad blocks in region
RIBQTF==22 ; FCFS quota for this PPN in this STR (UFD only)
RIBQTO==23 ; Logged out quota (UFD only)
RIBQTR==24 ; Reserved quota (UFD only)
RIBUSD==25 ; Nr blocks used when job was last logged out (UFD only)
RIBAUT==26 ; Author - PPN writing the file
RIBNXT==27 ; Next STR for this file (unused level D)
RIBPRD==30 ; Previous STR for file (unused level D)
RIBPCA==31 ; Privileged arg for customer definition
RIBUFD==32 ; Block # in STR of UFD data block with ptr to this RIB
RIBFLR==33 ; First logical block in file pointed to by this RIB
; (zero if first RIB)
RIBXRA==34 ; Extended rib address
RIBTIM==35 ; Time,,Date word in universal standard
RIBLAD==36 ; Last accounting date (UFD)
RIBDED==37 ; Directory expiration date (UFD)
RIBACT==40 ; AOBJN pointer to account string
RIBENT==RIBACT ; Last arg or value on extended lookup/enter/rename
RIBCOD==176 ; Contains 777777 (unlikely code)
RIBSLF==177 ; This logical block number in STR
Subttl BRKPTx - Routine to break info out of RIB retrieval pointers.
; For RIB Retrieval Pointers on OLD pack.
; Call with (t2)=retrieval pointer.
; PUSHJ P,BRKPTO
; Return here with (t2)=address (t3)=blocks in file.
; (t4)=checksum.
brkpto: movem t2,o.ribp ;Move pointer to word that byte
;pointers look at.
ldb t2,o.ptra ;Get CFP of first cluster.
ldb t3,o.ptrc ;Get count of clusters.
ldb t4,o.ptrs ;Check Sum.
imul t2,o.home+hombpc ;Change CFP into blocks.
imul t3,o.home+hombpc ;Change clusters into blocks.
;HOMBPC is blocks per cluster.
popj p, ;And return.
; For RIB Retrieval Pointers on NEW pack.
; Call with (t2)=retrieval pointer.
; PUSHJ P,BRKPTN
; Return here with (t2)=address (t3)=blocks in file.
brkptn: movem t2,n.ribp ;Move pointer to word that byte
;pointers look at.
ldb t2,n.ptra ;Get CFP of first cluster.
ldb t3,n.ptrc ;Get count of clusters.
ldb t4,n.ptrs ;Get checksum.
imul t2,n.home+hombpc ;Change CFP into blocks.
imul t3,n.home+hombpc ;Change clusters into blocks.
;HOMBPC is blocks per cluster.
popj p, ;And return.
subttl UPDRIB - Update RIB of file with new disk information.
; Call with file's RIB in O.RIB, MAPIDX pointing to file's MAP entry.
; Updates RIBUFD, Retrieval Pointers, and RIBSLF.
; Updated RIB is kept in N.RIB.
; Consider all registers used.
; Make copy of O.RIB in N.RIB.
updrib: hrli t1,o.rib ;Prepare to BLT O.RIB into N.RIB.
hrri t1,n.rib
movei t2,n.rib+ribslf ;Last word of a RIB.
blt t1,@t2 ;Do it.
move t1,o.rib+ribslf ;Confirm BLT worked.
came t1,n.rib+ribslf ;Did it?
die(?UPDRIB: BLT failed making copy of old RIB.)
; RIBXRA.
setzm n.rib+ribxra ;Rib will not be extended.
; RIBUFD.
move t1,newufd(mapidx) ;New disk block address of UFD
movem t1,n.rib+ribufd ;that points to me.
; RIBSLF.
move t2,newcfp(mapidx) ;New disk block address of file itself.
movem t2,n.rib+ribslf
; RIBALC.
move t1,blkuse(mapidx) ;Blocks allocated to file.
movem t1,n.rib+ribalc ;Computed in DONTRY.
; Build Retrieval Pointers.
; setzm n.ribp ;Where we will build the pointer.
; CHECKSUM.
pushj p,chksum ;Called with word to be checksummed
;in N.CHKS, which is set by routine
;calling UPDRIB.
move t1,n.chks ;Checksum returned in N.CHKS.
dpb t1,n.ptrs ;Deposit into pointer.
; CLUSTER COUNT.
move t1,blkuse(mapidx) ;Blocks allocated to file.
idiv t1,n.home+hombpc ;Convert to clusters.
skipe t2 ;Remainder? Shouldn't be.
die(?UPDRIB: Blocks allocated not factor of Blocks Per Cluster.)
dpb t1,n.ptrc ;Deposit cluster count.
; CFP - Compressed File Pointer of Block Address.
move t1,newcfp(mapidx) ;New disk address.
idiv t1,n.home+hombpc ;Compute CFP.
skipe t2 ;Remainder? Shouldn't be.
die(?UPDRIB: CFP calculation bad.)
dpb t1,n.ptra ;Deposit in pointer.
; Put pointer in N.RIB.
move t2,n.ribp ;Get the built Retrieval Pointer.
hrrz t1,n.rib+ribfir ;Relative location of Retrieval Pointer
aoj t1, ;in n.rib.
movem t2,n.rib(t1) ;Put pointer in.
; Clear remaining Retrieval Pointers since this RIB isnt extended.
; T1 should be set as was after having put rib pointer in N.RIB.
updri3: aoj t1,
cail t1,ribcod ;Done?
jrst updri4 ;Yes.
setzm n.rib(t1) ;Clear it.
jrst updri3
; Here with pointer still in T2.
updri4: skipe mufd ;Working with [1,1].UFD RIB?
movem t2,n.home+hompt1 ;Yes. Put in HOME block of new disk.
setzm mufd ;Clear MFD flag.
popj p, ;Return.
subttl CHKSUM - Routine to compute checksum.
; Call with word to be checksummed in N.CHKS.
; Return with checksum in N.CHKS.
chksum: move t1,n.chks
move t2,n.chks
move t4,n.home+homckp ;Checksum pointer.
hrri t4,t2 ;Make it point to T2.
ldb t3,[point 6,t4,11] ;Get size field of checksum ptr.
movns t3 ;Make negative for upcoming LSH.
tlza t4,770000 ;Set to bit 35.
chksu1: add t2,t1 ;Add byte to rest of word.
ldb t1,t4 ;Get a byte of checksum size.
lsh t2,(t3) ;Throw away the byte.
jumpn t2,chksu1 ;Finished when no more of original
;word is left.
movem t1,n.chks
popj p, ;Done. Return.
subttl CORGET - routine to get more core for MAP.
; CORGET is called before adding entries to bottom of MAP.
; It checks to see that an entry of MAPSIZ can be added without
; exceeding .JBREL, if not it gets more core.
; Call PUSHJ P,CORGET
; Return c(maplst)=address where next entry is to start,
; c(.JBFF)=c(old .JBFF)+MAPSIZ
; Uses t1,t2
corget: move t1,.jbff ;First free word at end of MAP.
addi t1,mapsiz ;Size of one MAP entry.
camg t1,.jbrel ;Are we going to exceed our space?
jrst corgot ;No. Update parameters and return.
; Here if we need to have more core allocated.
move t2,t1
core t2, ;Request more core up to address specified.
die(?Insufficient core to build MAP. Set CORMAX up and retry.)
corgot: move maplst,.jbff ;Indicate where the start of our free core is.
movem t1,.jbff ;Update.
popj p, ;Normal return.
subttl DMPMAP - debugging routine to dump MAP to DSK:MAP.FIL
dmpmap: movei t1,.ioimg ;Open a channel for writing.
move t2,[sixbit/dsk/]
hrlzi t3,dmphdr ;Buffer control block address.
open dmpchn,t1
die(?MAP output open failed.)
enter dmpchn,entblk
die(?MAP enter failed)
outbuf dmpchn,0
; Start writing of entries with the top of MAP.
move t1,map
; Write entry pointed to t1.
dmpma2: movei t2,mapsiz ;Number of words in entry.
move t4,t1 ;Address of entry to write.
pushj p,dmpit ;Dump (t2) words starting at address (t4).
; Write out all entries pointed to by this entry.
skipn nxtnod(t1) ;Are there any?
jrst dmpma3 ;No. Got to end of this loop.
move t4,nxtnod(t1) ;Get start of entries this entry points to.
hrrz t2,ext(t1) ;Get the number of entries involved.
imuli t2,mapsiz ;Multiply time words per entry.
pushj p,dmpit ;Dump (t2) words starts at address (t4).
dmpma3: addi t1,mapsiz ;Incriment and loop back.
camg t1,maplst ;Have we done all entries in MAP?
jrst dmpma2 ;No. Loop for next.
close dmpchn, ;Yes.
popj p,
; Routine to write (t2) words starting at (t4). Uses t3.
dmpit: move t3,(t4) ;Get a word.
pushj p,dmpbyt ;Dump the word to MAP.FIL.
sosle t2 ;Written all the entries?
aoja t4,dmpit ;No. Loop for next word.
popj p, ;Yes. Done.
; Here to write the word in T3 to MAP.FIL.
dmpbyt: sosge dmpcnt ;Output buffer full?
jrst dmpby2 ;Yes. Write out what we have.
idpb t3,dmpptr ;Put character in output buffer.
popj p, ;Return to caller.
dmpby2: out dmpchn, ;Write out buffer.
jrst dmpbyt ;;Start new buffer.
entblk: sixbit/map/
sixbit/fil/
z
z
dmphdr: z
dmpptr: z
dmpcnt: z
subttl DMPSAT - Debugging routine to dump in-core SAT to disk.
dmpsat: movei t1,.iodmp ;Specify dump mode.
move t2,[sixbit/dsk/]
setz t3, ;No inbuf/outbuf in dump mode.
; Open a channel.
open dmpchn,t1
die(? Error trying to open channel for SAT block dump.)
; Enter a file.
enter dmpchn,entbl2
die(? Enter failure for SAT dump.)
; Prepare IOWD for dump.
movn t1,n.home+homspu ;Number of SATs on new disk,
imul t1,n.satw ;times words in block = words to dump.
hrls t1,t1 ;To left half.
move t2,n.sat ;Address to dump from.
soj t2, ;Address minus one.
hrr t1,t2 ;Finish the IOWD.
setz t2, ;Termination word.
out dmpchn,t1 ;Dump it.
skipa ;Good dump.
die(? Error while dumping in-core SAT.)
close dmpchn,
popj p,
entbl2: sixbit/sat/
sixbit/fil/
z
z
subttl READ - Read in dump mode from old disk.
; Assumes INCHNL has been OPENed in dump mode (.IODMP) on
; the original disk of which we are making a map.
; Call with,
; t1=block number on disk from which to read.
; t2=buffer address in core to which the data is to be dumped.
; t3=number of words to transfer.
; PUSHJ P,READ
; Return here. If errors occur it will process error and die.
; Uses t4.
; Use SUSET. to position to block.
read: hrlzi t4,inchnl ;Channel for SUSET.
lsh t4,5 ;Shift to proper place in word.
ior t4,t1 ;And the block to be read.
SUSET. t4, ;Position to block.
die(?READ: Error doing SUSET. UUO.)
; Build an I/O command list in registers to assure it will be low seg.
movns t3,t3 ;Negative number of words to read.
movs t4,t3
subi t2,1 ;Location of buffer minus 1.
hrr t4,t2
setz t5, ;A zero word to terminate IO command.
in inchnl,t4 ;Do it.
popj p, ;The read was good. Return.
die(?READ: Error doing IN.)
subttl bfread - buffer read in dump mode from disk.
; Similar to routine READ but buffers input.
; Assumes INCHNL has been OPENed in dump mode (.IODMP) on
; the original disk of which we are making a map.
; Call with,
; t1=block number on disk from which to bfread.
; t2=buffer address in core to which the data is to be dumped.
; t3=number of words to transfer.
; PUSHJ P,bfread
; Return here. If errors occur it will process error and die.
bfread: skipge inaddr ;Is Input buffer empty? (Never used).
jrst bfrea3 ;Yes. Go fill buffer.
; Here when buffer has data already in it.
; Is the data we need part of what is albfready there?
bfrea2: move t4,t1 ;Make copy.
sub t4,inaddr ;Determine relative block difference.
skipge t4 ;Equal or greater than 1st block addr?
jrst bfrea3 ;No. Buffer doesn't have block we need.
cail t4,inblks ;Less than number of blks in buffer?
jrst bfrea3 ;No. Buffer doesn't have block we need.
; Here if Input Buffer does have the block needed.
; T4 is set as index of needed block in the buffer.
imuli t4,blksiz ;From blocks to words.
addi t4,inbuf ;From index to absolute core location.
movs t4,t4 ;Prepare for BLT.
hrr t4,t2
add t2,t3 ;Compute last word of BLT transfer.
soj t2,
blt t4,@t2 ;Transfer data to specified core area.
popj p, ;Done.
; Here if buffer is empty (never been used) or if block needed is
; not in current contents of buffer.
; Use SUSET. to position to block.
bfrea3: hrlzi t4,inchnl ;Channel for SUSET.
lsh t4,5 ;Shift to proper place in word.
ior t4,t1 ;And the block to be bfread.
SUSET. t4, ;Position to block.
die(?bfread: Error doing SUSET. UUO.)
; Build an I/O command list in registers to assure it will be low seg.
movei t4,inblks ;Number of blks in Input Buffer.
imuli t4,-blksiz ;Make it negative # of words.
movs t4,t4 ;Swapped it to left half of word.
hrri t4,inbuf ;Address to bfread into,
soj t4, ;minus one.
setz t5, ;A zero word to terminate IO command.
in inchnl,t4 ;Do it.
skipa ;Read was good.
die(?BFREAD: Error doing IN.)
movem t1,inaddr ;Reset block address of first
;block in INBUF.
jrst bfrea2 ;Loop.
subttl WRITE - Write out in dump mode to new disk.
; Assumes OUTCHN has been OPENed in dump mode (.IODMP) to
; disk to which we are copying.
; WRITE buffers output to free core starting at the address
; pointed to by OUTBUF. As long as free core is available and
; the data being written is contiguous with that already in
; OUTBUF, the data will be kept in core.
; When core is exhausted or data not contiguous to contents of
; OUTBUF is to be written, OUTBUF is dumped to disk and the
; data then placed at the top of OUTBUF.
; Call with,
; t1=block number at which to begin writing.
; t2=buffer address in core of data to be written.
; t3=number of words to write.
; PUSHJ P,WRITE
; Return here. If errors occur it will process error and die.
; Compute new disk address of last block in OUTBUF.
write: move t5,.jbff ;First word after OUTBUF data.
sub t5,outbuf ;number of words used in OUTBUF.
skipge t5 ;Check for legal value.
die(?WRITE: .JBFF out of range.)
skipg t5 ;Buffer empty?
jrst write2 ;Yes.
; Here if buffer not empty.
idivi t5,blksiz ;number of words per block.
add t5,topblk ;Next contiguous block address.
came t1,t5 ;Is our data to be written contiguous?
pjrst write3 ;No.
; Here if data is contiguous to current contents of OUTBUF,
; or if buffer is empty.
write2: move t4,.jbff ;Determine core required to add data.
add t4,t3
camg t4,.jbrel ;More than we currently have?
pjrst wriadd ;No. We are doing fine. Add the data.
; Here to get more core.
core t4,200000 ;Accept physical core only.
skipa ;No more core.
pjrst wriadd ;Got it. Add data to OUTBUF.
; Here if can't get anymore core.
pushj p,wridmp ;Dump contents of OUTBUF to
jrst write2 ;disk then try again.
; Here if data to be written is NOT contiguous with current
; contents of OUTBUF.
write3: pushj p,wridmp ;Dump contents of OUTBUF to disk.
pjrst wriadd ;Now add data to emptied OUTBUF.
; Here to add data to OUTBUF.
wriadd: move t7,.jbff ;First free word in outbuf buffer area.
camge t7,outbuf
die(?WRITE: .JBFF out of range.)
camg t7,outbuf ;Is buffer empty?
movem t1,topblk ;Yes. Keep new disk address of the
;data we are adding.
hrl t7,t2 ;Current location of data.
move t8,.jbff ;Determine last word data will use.
add t8,t3
soj t8,
blt t7,@t8 ;Add it to buffer.
movem t8,.jbff ;Compute new first free.
aos .jbff
popj p, ;Return.
; Here to dump contents of OUTBUF to new disk.
; Use SUSET. to position to block.
wridmp: hrlzi t4,outchn ;Channel for SUSET.
lsh t4,5 ;Shift to proper place in word.
ior t4,topblk ;And the block to write.
SUSET. t4, ;Position to block.
die(?WRITE: Error doing SUSET. UUO.)
; Build an I/O command list in registers to assure it will be low seg.
move t5,.jbff ;Determine number of words to write.
sub t5,outbuf
movns t5,t5 ;Negative number of words to write.
movs t4,t5
move t5,outbuf ;Location of buffer,
soj t5, ;minus one.
hrr t4,t5
setz t5, ;A zero word to terminate IO command.
out outchn,t4 ;do it.
skipa ;Write was good.
die(?WRITE: Error doing OUT.)
; Set variables to reflect state of buffer.
move t4,outbuf ;Set first free word back to top.
movem t4,.jbff
setom topblk ;Clear this out.
popj p, ;Return.
subttl ALLOC - allocate disk space on new pack using in-core SAT.
; Searchs for a contiguos number of blocks and returns the disk
; address where they start. Leaves the clusters marked in SATs.
; Call with number of blocks needed in T1.
; PUSHJ P,ALLOC
; Return here with T1=0 if couldn't grant request,
; or with T1=address if found.
alloc: idiv t1,n.home+hombpc ;Convert blocks to clusters.
skipe t2 ;Was there a remainder?
die(?ALLOC: Blocks allocated is not a factor of Blocks Per Cluster.)
move t2,n.satt ;Get word in SAT with which we began
;our search last time.
alloc2: camle t2,n.sate ;Have we passed the end of SAT?
jrst [setz t1, ;No more space in SAT.
popj p,]
move t3,(t2) ;Get that top word of SAT.
aosn t3 ;Any free clusters? -1 indicates this.
aoja t2,alloc2 ;No. Get next word.
movem t2,n.satt ;Yes. Make a new n.satt for next time.
hll t2,n.satp ;Build a pointer to this location.
movem t2,n.fwdp ;Start our search for contiguous
;clusters here.
setzm n.bckp ;Indicate starting out.
; Here to look for a free cluster.
alloc3: ildb t3,n.fwdp ;Get a cluster.
hrrz t4,n.fwdp ;Get theword address.
camle t4,n.sate ;Have we passed last word in SAT?
pushj p,[ movei t3,1 ;Yes. Fake a marked cluster.
move t2,t1 ;Fake clusters found = clusters needed.
popj p,]
jumpe t3,alloc4 ;Is the cluster free?
setzm n.bckp ;No. Indicate we haven't found the
;start of our contiguos blocks yet.
jrst alloc5
; Here if cluster was free.
alloc4: skipe n.bckp ;Is this the first cluster found?
aoja t2,alloc5 ;No. Count another contiguos one.
move t2,n.fwdp ;Yes. Mark this as start of contigous
;clusters.
movem t2,n.bckp
movei t2,1 ;Set count of clusters found to one.
; Here to see if we have all the clusters needed.
alloc5: camge t2,t1 ;Is clusters found >or= to needed?
jrst alloc3 ;No. Look for another.
; Here when we have either found the number of contiguous clusters
; needed, or have failed to do so.
skipn n.bckp ;Did we fail?
jrst [setz t1, ;Yes. Indicate this and return.
popj p,]
; Here if we found the number of contiguous clusters needed.
; Calculate logical block address of disk area allocated.
; First determine logical block address of SAT block from which
; the space was allocated.
hrrz t1,n.bckp ;Address of word in in-core SAT.
sub t1,n.sat ;Make relative to top of SAT.
idiv t1,n.satw ;Divide by words in each SAT to get
;number of SATs preceding current one.
;We will use the remainder in T2 soon.
imul t1,n.satb ;finally, number of blocks per sat
;times number of SATs preceding gives
;the block address of first block of
;SAT we are allocating space from.
; After the above division, T2 will be the number of words in this block
; that precede the word we point to.
imuli t2,^d36 ;Each word represents 36 clusters,
imul t2,n.home+hombpc ;and each cluster has x number blocks.
; Finally...
hlrz t4,n.bckp ;What bit within word was pointed to?
;Calculate bits to the left of it.
lsh t4,^d-12 ;This leaves "P" portion of pointer,
movei t3,^d36 ;Bits in a word.
sub t3,t4 ;Gives bits to left plus 1.
sos t3 ;Minus 1 gives us bits to left of
;one pointed to.
imul t3,n.home+hombpc ;Each cluster(1 bit) has x no. blocks.
; The block address of contiguos blocks allocated is then...
add t1,t2 ;Block address of first block,
add t1,t3 ;plus total blocks into the area.
; Here to mark all clusters used in SATs.
movei t2,1
move t3,n.bckp ;Will point to first cluster.
skipa
alloc6: ibp t3 ;Incriment pointer to next cluster.
dpb t2,t3 ;Mark cluster as used.
came t3,n.fwdp ;Done?
jrst alloc6 ;No. Go mark next cluster.
popj p, ;Yes. Return to calling routine.
subttl Initializations
d2d: jfcl ;In case of CCL entry.
reset ;Clear channels etc..
move p,[iowd pdlen,pdlist] ;Set up stack.
; Get disk copying from and I.D. and name of disk copying to.
getdsk: setzm frompk ;Clear words where pack names are
setzm topk ;to be built.
setzm topkid
setzm name
clrbfi
; Get name of disk from which we are copying.
move t1,[point 6,frompk]
outstr [asciz/Copy from:/]
Getds1: inchwl t2 ;Get a character.
caig t2,40 ;Break character?
jrst Getds2 ;Yes. Proceed with check.
caig t2,140 ;Is char lowercase?
addi t2,40 ;No. Convert to lowercase.
idpb t2,t1 ;Add character to name being built.
jrst Getds1 ;Get another character.
getds2:
; Get name of disk to which we are copying.
move t1,[point 6,topk]
outstr [asciz/Copy to :/]
clrbfi
setzm name
Getds3: inchwl t2 ;Get a character.
caig t2,40 ;Break character?
jrst Getds4 ;Yes. Proceed with check.
caig t2,140 ;Is char lowercase?
addi t2,40 ;No. Convert to lowercase.
idpb t2,t1 ;Add character to name being built.
jrst Getds3 ;Get another character.
getds4:
; Get I.D. of pack to which we are copying.
move t1,[point 6,topkid]
outstr [asciz/I.D. of pack copying to:/]
clrbfi
setzm name
Getds5: inchwl t2 ;Get a character.
caig t2,40 ;Break character?
jrst Getds6 ;Yes. Proceed with check.
caig t2,140 ;Is char lowercase?
addi t2,40 ;No. Convert to lowercase.
idpb t2,t1 ;Add character to name being built.
jrst Getds5 ;Get another character.
getds6:
; Get characteristics of disk from which we are copying.
move t1,frompk ;Sixbit name of pack copying from.
movem t1,dsktab ;Put it in disk table.
move t1,[xwd TabLen,DskTab]
dskchr t1, ;Put disk info in dsktab.
jrst error2 ;Give a message and die.
; Get characteristics of disk to which we are copying.
move t1,topk ;Sixbit name of pack copying to.
movem t1,dsktab ;Put it in disk table.
move t1,[xwd TabLen,DskTab]
dskchr t1, ;Put disk info in dsktab.
jrst error3 ;Give a message and die.
; Check to see that proper disk is mounted on drive to which we
; will be copying.
move t1,ToPkId ;Correct disk?
came t1,DskTab+.dcuid ;I.D.s must match.
jrst error1 ;No. Give a message and die.
jrst satget ;Yes. Proceed.
; Here on errors.
Error1: outstr [asciz/?Pack I.D. given does not match that
of Pack you are copying to.
Try again.
/]
jrst getdsk
Error2: outstr [asciz/?Disk you are copying from does not exist.
Try again.
/]
jrst getdsk
Error3: outstr [asciz/?Disk you are copying to does not exist.
Try again.
/]
jrst getdsk
DskTab: z ;Physical device being checked.
block 23 ;Room for rest of table.
TabLen=.-DskTab ;TabLen is lenght of table DskTab.
subttl Build target pack's SATs in core.
; SATGET reads all SAT blocks on the target pack, building
; an in core Storage Allocation Table.
; How many words of each SAT block are actually used is dependant
; on number of blocks on the pack, cluster size, and number of SAT
; blocks. These calculations are done in this routine.
satget: movei t1,.iodmp ;Specify dump mode.
move t2,topk ;Target pack.
setz t3, ;No inbuf/outbuf in dump mode.
; Open a channel.
open inchnl,t1
die(?SATGET: Error trying to open channel for HOME block read-in.)
; Read the home block of target pack.
movei t1,1 ;Home block is block 1.
movei t2,n.home ;Where to put it in core.
movei t3,blksiz ;The number of words to read.
pushj p,read ;Get it.
move t1,n.home+homnam ;Check to see if it is a HOME block.
came t1,[sixbit/HOM/]
die(?SATGET: Logical block 1 is not a HOME block.)
; Read SAT.SYS RIB from target pack.
move t1,n.home+homsat ;Address of SAT RIB on target pack.
movei t2,n.satr ;Buffer in which to place SAT's RIB.
movei t3,blksiz ;Size of a RIB.
pushj p,read ;Read the RIB.
; Build byte pointer for RIB retrieval pointers on target pack.
move t1,n.home+homcnp ;Pointer for Cluster Count.
hllm t1,n.ptrc ;Where we will keep the pointer.
move t1,n.home+homclp ;Pointer for Adress of first cluster.
hllm t1,n.ptra ;Where we will keep the pointer.
move t1,n.home+homckp ;Pointer for checksum.
hllm t1,n.ptrs ;Where we will keep the pointer.
; Set up area for reading in target packs SATs.
move t1,.jbff
movem t1,n.sat ;Address of 1st word in SAT buffer.
;N.SAT permanently points to this.
movem t1,n.satt ;N.SATT is initialized to this address.
;It may move as space is allocated.
movem t1,n.sate ;Address of last word.
sos n.sate ;Start the end at top-1.
; Calculate number of words actually used in each SAT block.
move t1,n.home+hombsc ;Blocks per supercluster.
imul t1,n.home+homscu ;Times superclusters on pack equals
;blocks on pack.
idiv t1,n.home+hombpc ;Divided by blocks per cluster equals
;clusters on pack.
skipe t2
die(?SATGET: Calculation of clusters on pack was bad.)
idiv t1,n.home+homspu ;Divided by SATs on pack equals
skipe t2 ;Cluster per SAT.
aoj t1, ;Round up if a remainder.
movem t1,n.satb ;Save for later use.
idivi t1,^d36 ;Divided by 36(bits per word) equals
skipe t2 ;number of words actually used.
aoj t1, ;Round up if there is a remainder.
movem t1,n.satw ;Save it.
; Finally, get the core needed for the SAT buffer.
imul t1,n.home+homspu ;Words per SAT block times SATs on pack
;equals total words needed for buffer.
addb t1,.jbff ;Calculate address to expand core to.
;Update .JBFF to relect core we took.
camg t1,.jbrel ;Are we exceeding our core limit?
jrst satge1 ;No.
core t1, ;Yes. Request more.
die(?insufficient core to build SATs. Set CORMAX up and retry.)
; Also calculate number of blocks per sat.
move t1,n.home+hombpc
imulm t1,n.satb ;Blocks per SAT.
; For each pointer in SAT's RIB to a SAT block, read the block and
; use the number of words actually used(just calculated) to place
; only the used portion of each SAT block into buffer.
; T1,T5 and T6 once set by this routine are dedicated until MAPINI.
satge1: move t6,n.home+homspu ;Number of SAT blocks on target pack.
hrrz t5,n.satr+ribfir ;RIB index to 1st retrieval pointer.
addi t5,2 ;1st pointer is for RIB itself. Skip.
;2nd pointer is for 1st real SAT block.
satge2: move t2,n.satr(t5) ;Get a pointer.
pushj p,brkptn ;Break info out of pointer. Returns
;t2=block where SAT starts t3=# blocks,
;t4=checksum.
; Read the SAT block into the in-core SAT area.
move t1,t2 ;Logical block address of SAT block.
move t2,n.sate ;Last used word of in-core SAT area.
aoj t2, ;First word after SATEnd.
move t3,n.satw ;Read this many words.
savreg
pushj p,read ;Read it.
resreg
addm t3,n.sate ;New SAT block end.
; Remember the address at which this SAT block is located on new disk.
move t2,n.home+homspu ;SATs per unit,
sub t2,t6 ;minus SATs unread,
movem t1,n.dska(t2) ;is the SAT currently being read.
sosle t6 ;Have we done all SATs on unit?
aoja t5,satge2 ;No. Go read next SAT on unit.
; Fall through to SUFINI.
; Leave INCHNL open for SUFINI.
subttl SUFINI - routine to initialize [1,4].UFD
; The System UFD is treated seperately because of certain files
; there which are set up during the new disk's initialization,
; which we do not want to copy over from the old disk.
; Eg. SAT.SYS, HOME.SYS, SWAP.SYS.
; These files are to retain there same physical location on the
; new disk although the [1,4].UFD which lists them may be moved.
; Their physical location on the disk is gotten from the HOME
; block, logical block 1 on disk.
; The [1,4].UFD is built in a buffer N.SUFD and written out seperatly
; later on. This routine initialized N.SUFD with the special files
; from the new disks [1,4] area.
; Will use the channel initialzed in SATINI, INCHNL.
sufini: move t1,n.home+homsuf ;Location of SYS.UFD RIB.
aoj t1, ;Add one to get UFD block.
movei t2,n.sufd ;Where to put it.
movei t3,blksiz ;Number of words to read.
pushj p,read
; Here to find the first file entry NOT amoung our special ones.
; The special ones will be grouped at top. When we have found a file
; that is not a special one, we can clear N.SUFD from there on.
movni t1,2 ;Index for N.SUFD.
sufin2: addi t1,2 ;Next entry.
cail t1,blksiz-2 ;Check for in bounds.
die(?SUFINI: New disk SYS.UFD has suspicious number of entries.)
move t2,n.sufd(t1) ;Get a file name.
skipn t2 ;Zero means SYS.UFD is already
;just as we wish it.
jrst sufin3 ;Done.
camn t2,[sixbit/SAT/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/HOME/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/SWAP/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/MAINT/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/BADBLK/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/CRASH/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/SNAP/]
jrst sufin2 ;One of our special files.
camn t2,[sixbit/RECOV/]
jrst sufin2 ;One of our special files.
; Here when we have found the first non-special file.
; Clear N.SUFD from here down. This keeps only our special files.
movei t1,n.sufd(t1)
setzm @t1
hrls t1,t1 ;Prepare for BLT.
aoj t1,
blt t1,n.sufe ;Clear through last word.
; Done with Channel.
sufin3: close inchnl,
; Fall through to INIINI.
subttl Initialize MAP.
; Set up the MAP area.
mapini: move t1,.jbff ;Get address of first free core.
movem t1,map ;Nothing should be written after the map
;for the balance of map building section
;since it will expand to an undetermined size.
;.JBFF will be last word in MAP, plus one.
; Start the MAP out with the [1,1] UFD entry.
pushj p,corget ;Return with first available address in maplst.
move t1,[xwd 1,1]
movem t1,name(maplst) ;Moves 1,1 to FileName position of MAP.
move t1,[sixbit/ufd/]
movem t1,ext(maplst) ;Moves UFD to FileExtension position of MAP.
; To get the location of [1,1] UFD on old disk we must read HOME block.
; First prepare the open block.
movei t1,.iodmp ;Specify dump mode.
move t2,frompk ;Specify pack copying from.
setz t3, ;No inbuf/outbuf in dump mode.
; Open a channel for now and future input from old disk.
open inchnl,t1
die(? Error trying to open channel for HOME block read-in.)
; Read the home block.
movei t1,1 ;Home block is block 1.
movei t2,o.home ;Where to put it in core.
movei t3,blksiz ;The number of words to read.
pushj p,read ;Get it.
move t1,o.home+homnam ;Make sure it's a HOME block.
came t1,[sixbit/HOM/]
die(?MAPINI: Logical block 1 is not a HOME block.)
move t1,o.home+hommfd ;Get location of [1,1] UFD on old disk.
movem t1,oldcfp(maplst) ;Finish our MAP entry.
; Build byte pointer for RIB retrieval pointers.
move t1,o.home+homcnp ;Pointer for Cluster Count.
hllm t1,o.ptrc ;Where we will keep the pointer.
move t1,o.home+homclp ;Pointer for Adress of first cluster.
hllm t1,o.ptra ;Where we will keep the pointer.
move t1,o.home+homckp ;Pointer for Checksum.
hllm t1,o.ptrs ;Where we will keep the pointer.
subttl MISC Initializations.
; D2D uses a single RIB Retrieval Pointer when constructing the
; RIBs of files copied to the new disk. Consequently, the size
; of the Cluster Count field in the pointers limits the size of
; files that can be copied. Determine what that size is.
move t1,n.home+homcnp ;The pointer for Cluster Count in
;RIB Retrieval Pointers.
hrri t1,[-1] ;Point it to a word = 777777,777777
ldb t2,t1 ;T2 now has max cluster count that
;a single Retrieval Ptr can hold.
imul t2,n.home+hombpc ;Convert to blocks.
movem t2,maxfil ;Keep this value.
subttl Top level to build in core map of disk to be copied.
; Here to add to MAP everyone our initial [1,1].ufd entry points to.
bldmap: outstr [asciz/Building Map...
/]
move mapidx,map ;MAPIDX will serve as our index
;to processing entries in MAP.
move oldidx,mapidx ;Security check on MAPIDX value.
pushj p,dontry ;Start off processing [1,1].ufd.
came oldidx,mapidx ;Confirm its value.
die(?BLDMAP: MAPIDX modified in DONTRY.)
; [1,1].UFD's first entry is to itself. Rather than repeat the
; DONTRY process, make a copy of [1,1].ufd immediately following
; the one we just placed in MAP.
hrl t1,mapidx ;Prepare for BLT.
addi mapidx,mapsiz
hrr t1,mapidx
blt t1,blkuse(mapidx)
addi mapidx,mapsiz ;Now set MAPIDX to skip over the
;second [1,1].UFD entry.
; Here to finish building MAP.
bldma2: camle mapidx,maplst ;More entries to be processed?
jrst bldend ;No. Map is built.
; Here to process next entry in MAP.
move oldidx,mapidx ;Security check on MAPIDX value.
pushj p,dontry ;Process entry pointed to by MAPIDX.
came oldidx,mapidx ;Confirm its value.
die(?BLDMAP: MAPIDX modified in DONTRY.)
addi mapidx,mapsiz ;Point to next entry.
jrst bldma2 ;Loop back.
bldend: jrst wrtmap ;Here when map is built.
subttl DONTRY - a subprocess of BLDMAP
; Process the entry pointed to by MAPIDX.
; Read the RIB of file the entry represents, determine number of
; of blocks it requires on new disk, allocate space, and if the
; file is a directory add an entry to MAP for each file the UFD
; points to.
dontry: move t1,oldcfp(mapidx) ;Address of RIB on old disk.
movei t2,o.rib ;Buffer in which to place RIB.
movei t3,blksiz ;Size of a RIB.
pushj p,bfread ;Read the RIB.
move t1,o.rib+ribnam ;Do security check on name.
came t1,name(mapidx) ;RIBNAM match that in MAP?
die(?DONTRY: RIBNAM does not match that in MAP.)
; Determine how many blocks this file will need.
move t1,o.rib+ribsiz ;Size of file in words.
idivi t1,blksiz ;Convert to words.
skipe t2 ;Remainder?
aoj t1, ;Yes. Round up block count.
addi t1,2 ;Plus two RIBs.
idiv t1,n.home+hombpc ;Convert to clusters.
skipe t2 ;Remainder?
aoj t1, ;Yes. Round up cluster count.
imul t1,n.home+hombpc ;And back to blocks.
;Note that if the Blks Per Cluster on
;new disk is different from old, the
;blocks allocated will be different.
movem t1,blkuse(mapidx) ;Keep blocks used in MAP entry.
; Check that file size is such that we can copy the file.
camle t1,maxfil ;A file our RIB Retrieval Pointer
;cluster counts can handle?
die(?DONTRY: File too large for current RIB Ret. Ptr. cluster count.)
; Allocate space on new disk, updating SATS.
pushj p,alloc ;T1 contains number of blocks needed.
movem t1,newcfp(mapidx) ;Update entry.
skipn t1 ;Space allocated?
die(?DONTRY: Could not allocate space for file in SAT.)
skipg t1 ;Value in bounds?
die(?DONTRY: Value returned for logical disk address is bad.)
; Are we a directory? If so make entries for all files we point to.
move t1,ext(mapidx) ;Get file extension.
camn t1,[sixbit/UFD/] ;an UFD?
pjrst(dontr2) ;Yes.
camn t1,[sixbit/SFD/] ;an SFD?
pjrst(dontr2) ;Yes.
; Here if not a directory.
setzm nxtnod(mapidx) ;Indicate not a directory.
popj p, ;Done. Return.
; Here if a directory. Make MAP entries for each file in directory.
dontr2: move t1,o.rib+ribnam ;Check for the three special UFDs.
setzm sufd ;Assume not [1,4].
came t1,[xwd 1,1] ; [1,1].ufd?
jrst dontr3 ;No.
; Here for [1,1].ufd.
move t2,newcfp(mapidx) ;Update new disk HOME block to reflect
movem t2,n.home+hommfd ;new location of MFD.
movem t2,newufd(mapidx) ;Also, [1,1].ufd is the UFD which
;points to itself.
jrst dontr5
dontr3: came t1,[xwd 1,4] ; [1,4].ufd?
jrst dontr4 ;No.
; Here for [1,4].ufd.
setom sufd ;Set flag for later routines.
move t2,newcfp(mapidx) ;Update new disk HOME block to reflect
movem t2,n.home+homsuf ;new location of SYS UFD.
jrst dontr5
dontr4: came t1,[xwd 3,3] ; [3,3].ufd?
jrst dontr5 ;No.
; Here for [3,3].ufd.
move t2,newcfp(mapidx) ;Update new disk HOME block to reflect
movem t2,n.home+hompuf ;new location of Printer UFD.
dontr5: move t1,.jbff ;First word after end of MAP.
movem t1,nxtnod(mapidx) ;All entries from this directory will
;begin at end of MAP. Point to them.
pushj p,addmap ;Add entries to map for files.
move t1,.jbff ;Get address of end of MAP now.
sub t1,nxtnod(mapidx) ;Get difference in old .JBFF and now.
idivi t1,mapsiz ;Compute number of entries UFD has.
skipge t1 ;Check for strange value.
die(? .JBFF was reset in DONTR2. MAP has been lost.)
skipn t1 ;Has anything been added to MAP?
setzm nxtnod(mapidx) ;No. Indicate an empty UFD.
hrrm t1,ext(mapidx) ;Put in right half of file extension.
popj p,
subttl ADDMAP - add entries to MAP for files in a directory.
; ADDMAP is used by DONTRY, a subprocess of BLDMAP, to make MAP
; entries for all files pointed to by the directory being processed
; by DONTRY.
; It is possible that directory RIBs are not compressed, ie. they
; have RIB pointers that really aren't in use. Because of this
; we must use a RIBSIZ decrement counter to avoid processing such
; RIB pointers.
; Call with:
; MAPIDX pointing to MAP entry of UFD being processed by DONTRY.
; O.RIB has rib of UFD.
; Uses t1,t2,t3.
; Updates MAPEND and .JBFF as a consequence of adding to the MAP.
addmap: move t1,o.rib+ribnam ;Security check,
came t1,name(mapidx) ;RIBNAM match that in MAP?
die(?ADDMAP: RIBNAM doesn't match name in MAP.)
; Initialize RIBSIZ decrement counter.
move t1,o.rib+ribsiz ;Words written in UFD.
idivi t1,blksiz ;Make into blocks.
skipe t2 ;If a remainder,
die(?ADDMAP: RIBSIZ is not an even factor of block size.)
movem t1,totblk ;Keep the decremental counter here.
addma1: hrrz t1,o.rib+ribfir ;RIB index to 1st retrieval pointer.
addi t1,1 ;You just have to do this.
move t2,o.rib(t1) ;And get the first pointer.
pushj p,brkpto ;Break info out of pointer. Returns
;t2=block where UFD starts t3=# blocks.
aoj t2, ;The first pointer points to itself,
;so the UFD we want follows. Add 1.
soj t3, ;Which also means one less block of
;directory information for processing.
savreg
pushj p,addma3 ;Process it.
resreg
addma2: addi t1,1 ;Move to next retrieval pointer.
cain t1,ribcod ;Out of pointers?
jrst addmax ;Yes. Check if extended RIB.
move t2,o.rib(t1) ;Get next pointer.
skipn t2 ;Is it empty?
jrst addmax ;Yes. Check if extended RIB.
pushj p,brkpto ;No. Get info and process it.
;Returns t2=UFD address t3=# blocks.
savreg
pushj p,addma3
resreg
jrst addma2 ;Loop for next.
; Here to check for extended RIBs.
addmax: skipn t1,o.rib+ribxra ;Extended?
popj p, ;No. Return.
move t4,o.rib+ribnam ;For security check later.
movei t2,o.rib ;Yes. Prepare to read it.
movei t3,blksiz
savreg
pushj p,bfread ;Read the extended RIB.
resreg
came t4,o.rib+ribnam ;Do RIBNAMs match?
die(?ADDMAX: Extended RIBNAM doesn't match RIBNAM in prime RIB.)
jrst addma1 ;And loop to process it.
; ADDMA3 is a subprocess of ADDMAP.
; It is called once for each of the UFD's rib retrieval pointers.
; Called with t2=logical block number from rib retrieval pointer,
; and t3=number of blocks from the rib retrieval pointer.
; It makes an entry in MAP for each file entry in the UFD.
ADDMA3: skipg totblk ;Check RIBSIZ decrement counter.
popj p, ;We have already read as many blocks
;in this UFD as are actually used.
;The RIB retrieval pointer we have
;been asked to process must be the
;result of an Uncompressed RIB, and
;hence is not really in use. Skip it.
; Here if we haven't read all the blocks in the UFD yet.
move t1,t2 ;Logical block of start of data.
move t4,t2 ;Compute last block allocated+1.
add t4,t3
movei t2,o.ufd ;Where to read UFD block into.
movei t3,blksiz ;How many words.
; Here to read one block of UFD.
addma4: caml t1,t4 ;Processed the last blk of this ptr?
popj p, ; Yes. Return to get next retrieval ptr.
sosge totblk ;Decrement blocks used counter by one.
popj p, ; We have read all the used blocks in
; in the UFD. Return.
savreg ;No. Continue.
movem t1,ribtst ;Save for RIBSLF check later.
pushj p,bfread
resreg
; Here to process the block of the UFD just read.
setz t5, ;Index to entries in UFD.
addma5: caile t5,blksiz-2 ;Finished this block?2 words/entry.
aoja t1,addma4 ;Yes. Get next block.
move t6,o.ufd(t5) ;Get sixbit filename from UFD entry.
skipn t6 ;Zero, meaning no more data in block?
aoja t1,addma4 ;Yes. Go get another block.
; Are we dealing with [1,4].ufd?
skipn sufd ;Processing [1,4].UFD?
jrst addma7 ;No.
; Here if dealing with [1,4].ufd.
; There are certain files we will not want to copy from old to new disk,
; for example BADBLK.SYS, HOME.SYS, etc..
move t8,t5 ;T5 is index to entries in UFD block.
aoj t8, ;Was pointing to filename, now to ext.
hllz t7,o.ufd(t8) ;Get the extension.
; Is the entry of UFD block being looked at one we don't want to copy?
addhom: came t6,[sixbit/home/]
skipa
came t7,[sixbit/sys/]
skipa
jrst addma6
came t6,[sixbit/sat/]
skipa
came t7,[sixbit/sys/]
skipa
jrst addma6
came t6,[sixbit/swap/]
skipa
came t7,[sixbit/sys/]
skipa
jrst addma6
came t6,[sixbit/maint/]
skipa
came t7,[sixbit/sys/]
skipa
jrst addma6
came t6,[sixbit/badblk/]
skipa
came t7,[sixbit/sys/]
skipa
jrst addma6
came t6,[sixbit/crash/]
skipa
came t7,[sixbit/exe/]
skipa
jrst addma6
came t6,[sixbit/snap/]
skipa
came t7,[sixbit/exe/]
skipa
jrst addma6
came t6,[sixbit/recov/]
jrst addma7
came t7,[sixbit/sys/]
jrst addma7
jrst addma6
; Here to exclude certain [1,4].ufd files from MAP.
; These are files created by TWICE when the NEW disk is initialized.
addma6: addi t5,2 ;Bump index for UFD block from old
;disk being being processed.
jrst addma5 ;Go to next entry.
; Here to add entry to MAP.
addma7: savreg
pushj p,corget ;Grab core to add to MAP.
resreg ;Returns with MAPLST=next available.
movem t6,name(maplst) ;Put in MAP.
aoj t5, ;Incriment O.UFD index.
hrrz t6,o.ufd(t5) ;Get the CFP.
imul t6,o.home+hombpc ;Convert CFP to logical block address.
movem t6,oldcfp(maplst) ;Put in MAP.
hllz t6,o.ufd(t5) ;Get the sixbit file extension.
movem t6,ext(maplst) ;Put in MAP.
move t6,newcfp(mapidx) ;Get new CFP of UFD pointing to me.
movem t6,newufd(maplst) ;Put in MAP.
setzm nxtnod(maplst) ;Clear pointer.
aoja t5,addma5 ;Incriment O.UFD index. Go do next.
subttl Top level to write entries listed in MAP to new disk.
; WARNING: The remainder of free core will be now be used for
; buffering output to the target pack.
wrtmap: outstr [asciz/Copy Beginning...
/]
move t1,.jbff ;Where free core begins. This is
movem t1,outbuf ;the first word after MAP.
; Now prepare the open block.
movei t1,.iodmp ;Specify dump mode.
move t2,topk ;Specify pack copying to.
setz t3, ;No inbuf/outbuf in dump mode.
; Open output channel.
open outchn,t1
die(?WRTMAP: Error trying to OPEN channel for output to new disk.)
; Here to write out [1,1].ufd.
move mapidx,map ;MAPIDX will serve as our index
;to processing entries in MAP.
move oldidx,mapidx ;Security check on MAPIDX value.
pushj p,writit ;Start off processing [1,1].ufd.
came oldidx,mapidx ;Confirm its value.
die(?WRTMAP: MAPIDX was modified in WRITIT.)
addi mapidx,mapsiz*2 ;Since the first entry in [1,1].ufd
;is a [1,1] entry pointing to itself,
;we now have two consectutive [1,1]
;entries in MAP. Set MAPIDX to skip
;over the second.
; Here to write all other files.
wrtma2: camle mapidx,maplst ;More entries to be processed?
wrtend: jrst updhom ;No. All files copied.
;Go finish up.
; Here to process next entry in MAP.
move oldidx,mapidx ;Security check on MAPIDX value.
pushj p,writit ;Process entry pointed to by MAPIDX.
came oldidx,mapidx ;Confirm its value.
die(?WRTMAP: MAPIDX was modified in WRITIT.)
addi mapidx,mapsiz ;Point to next entry.
jrst wrtma2 ;Loop back.
; Here to write out HOME blocks to new disk.
; First, update new disk's HOME block words HOMSNM and HOMLOG.
updhom: move t1,o.home+homsnm ;SIXBIT structure name.
movem t1,n.home+homsnm
move t1,o.home+homlog ;SIXBIT logical unit name.
movem t1,n.home+homlog
; Prepare to write the HOME blocks on new pack.
movei t1,1
movei t2,n.home
movei t3,blksiz
savreg
pushj p,write
resreg
movei t1,12
savreg
pushj p,write
resreg
; Here to write out SAT blocks to new disk.
move t4,n.home+homspu ;Number of SAT blocks on new disk.
updsat: sosge t4 ;Written them all?
jrst updsuf ;Yes.
; Prepare for write.
move t1,n.dska(t4) ;Where to write.
move t5,n.satw
imul t5,t4
move t2,n.sat ;Start of 1st SAT block in core.
add t2,t5
move t3,n.satw
savreg
pushj p,write
resreg
jrst updsat
; Here to update RIBS of special files in SYS UFD.
; Update consists of putting new disk address of SYS UFD
; into the RIBUFD word of these files.
updsuf: close inchnl,
movei t1,.iodmp ;Specify dump mode.
move t2,topk ;Pack copying to.
setz t3, ;No inbuf/outbuf in dump mode.
; Open a channel.
open inchnl,t1
die(? updsuf: Error trying to open channel.)
move t1,n.home+homsat ;SAT.SYS
pushj p,updsu2
move t1,n.home+homhms ;HOME.SYS
pushj p,updsu2
move t1,n.home+homswp ;SWAP.SYS
pushj p,updsu2
move t1,n.home+hommnt ;MAINT.SYS
pushj p,updsu2
move t1,n.home+hombad ;BADBLK.SYS
pushj p,updsu2
move t1,n.home+homcrs ;CRASH.EXE
pushj p,updsu2
move t1,n.home+homrcv ;RECOV.SYS
pushj p,updsu2
pushj p,wridmp ;Flush output buffers.
pushj p,dmpmap ;dump the map into MAP.FIL.
pushj p,dmpsat ;dump the sat into SAT.FIL.
outstr [asciz/Copy complete.
/]
exit ;PROGRAM ENDS HERE.
updsu2: skipn t1 ;Address zero?
popj p, ;Yes. Skip it.
hlrz t2,t1 ;Check for junk word.
skipe t2 ;Was there junk in left half of word?
popj p, ;Yes. Skip it.
; Here to do the update.
movei t2,n.rib ;Where to read the RIB into.
movei t3,blksiz ;Size of RIB.
savreg
pushj p,read
resreg
move t4,n.home+homsuf ;New address of SYS UFD.
movem t4,n.rib+ribufd
savreg
pushj p,write ;Put it back.
resreg
add t1,n.home+hombpc ;Address of 2nd RIB.
pushj p,write ;Write it also.
popj p,
subttl WRITIT - subprocess of WRTMAP
; Top level to write single entry pointed to by MAPIDX to new disk.
; Read RIB of file. Branch to seperate code for directories and
; non-directories.
writit: move t1,oldcfp(mapidx) ;Address of RIB on old disk.
movei t2,o.rib ;Buffer in which to place RIB.
movei t3,blksiz ;Size of a RIB.
pushj p,bfread ;Read the RIB.
; Do some security checks to confirm that the MAP is pointing to
; the correct file on the old disk.
move t1,o.rib+ribnam ;Filename in RIB.
came t1,name(mapidx) ;Does it match name in MAP entry.
die(?WRITIT: Filename in RIB doesn't match that in MAP entry.)
move t1,o.rib+ribcod ;Get what should be the RIB code.
came t1,[xwd 0,777777] ;Is it?
die(?WRITIT: File pointed to by MAP entry is not a RIB.)
; Is it a directory?
hllz t1,ext(mapidx) ;Get file extension.
camn t1,[sixbit/UFD/] ;an UFD?
pjrst(doufd) ;Yes.
camn t1,[sixbit/SFD/] ;an SFD?
pjrst(doufd) ;Yes.
; Fall through if not a directory.
subttl DOFILE - a subprocess of WRITIT. Processes Files.
; Call with:
; MAPIDX pointing to MAP entry of File being processed by WRITIT.
; O.RIB has rib of File.
; Consider all registers used.
; Update and write the first RIB.
; Need to get 1st word of 1st block for RIB Retrieval Pointer Checksum.
dofile: move t1,oldcfp(mapidx) ;Address of first RIB on old disk.
aoj t1, ;Address of first data block.
movei t2,o.file
movei t3,blksiz
movem t1,ribtst ;Save for RIBSLF check later.
pushj p,bfread
move t1,o.file ;Get 1st word for checksumming.
movem t1,n.chks ;Keep it here for routine CHKSUM.
; If this file has no data, only RIBs, then the block just read
; for checksumming will be a RIB. In this instance we want a
; checksum of zero. The following checks for this.
move t1,o.file+ribcod ;The word where a RIB's RIBCOD is.
move t2,o.file+ribslf ;The word where a RIB's RIBSLF is.
camn t1,[xwd 0,777777] ;Is it a RIBCOD?
came t2,ribtst ;And is it a RIBSLF?
skipa ;Here if NOT a RIB.
setzm n.chks ;Yes. Zero the Checksum word.
; Update RIB.
pushj p,updrib ;Called with RIB in O.RIB and MAPIDX
;pointing to file's entry in MAP.
;Updated RIB will be in N.RIB.
; Write RIB.
move t1,newcfp(mapidx) ;Prepare to write the first RIB.
movei t2,n.rib
movei t3,blksiz
pushj p,write
; Process file.
move wrtblk,newcfp(mapidx) ;Incrimental keeper of the block
;address to which we last wrote a
;block of this file. Initialize to
;block address of RIB on new disk.
dofil0: hrrz t1,o.rib+ribfir ;RIB index to 1st retrieval pointer.
addi t1,1 ;You just have to do this.
move t2,o.rib(t1) ;And get the first pointer.
pushj p,brkpto ;Break info out of pointer. Returns
;t2=block where File starts t3=#blocks,
;t4=checksum.
came t2,o.rib+ribslf ;Confirm that it points to itself.
die(?DOFILE: Address from RIB retrieval pointer is bad.)
aoj t2, ;The first pointer points to itself,
;so the File we want follows. Add 1.
soj t3, ;Which also means one less block of
;data for copying.
savreg
pushj p,dofil3 ;Process it.
;First call to DOFIL3 will Update
;and write the first RIB.
;Updated RIB will be in N.RIB.
resreg
dofil1: addi t1,1 ;Move to next retrieval pointer.
caile t1,ribcod ;Check to see it's in bounds.
die(?DOFILE: RIB retrieval pointer index out of bounds.)
cail t1,ribcod ;Out of pointers?
jrst dofilx ;Yes. Check if extended RIB.
move t2,o.rib(t1) ;Get next pointer.
jumpe t2,dofilx ;Is the retrieval pointer zero?
;If so, check if RIB is extended.
pushj p,brkpto ;No. Get info and process it.
;Returns t2=File address t3=# blocks.
savreg
pushj p,dofil3 ;Process it.
resreg
jrst dofil1 ;Loop for next.
; Here to check for extended RIBs.
dofilx: skipn t1,o.rib+ribxra ;Extended?
jrst dofil2 ;No. Go finish up.
move t4,o.rib+ribnam ;Yes. For security check later.
movei t2,o.rib ;Prepare to read it.
movei t3,blksiz
savreg
pushj p,bfread ;Read the extended RIB.
resreg
came t4,o.rib+ribnam ;Do RIBNAMs match?
die(?DOFILX: Extended RIBNAM doesn't match RIBNAM in prime RIB.)
jrst dofil0 ;And loop to process it.
; Here when done to write last RIB. Updated copy in N.RIB.
dofil2: move t1,wrtblk ;Block address of last block of file.
aoj t1,
movem t1,n.rib+ribslf ;Adjust RIBSLF word of 2nd RIB to point
;to itself. Only difference from 1st.
movei t2,n.rib ;Location of RIB in core.
movei t3,blksiz ;Words to write.
pushj p,write ;Doit.
popj p, ;Return.
subttl DOFIL3 - subprocess of DOFILE.
; Read from old disk and write to new all blocks associated with
; the RIB retrieval pointer currently being processed by DOFILE.
; Called with T2=logical block address on old disk first block,
; and T3=number of blocks to be copied.
; WRTBLK is block address of where the last block of this file
; was written on new disk.
dofil3: move t1,t2 ;Logical block of start of File.
move t4,t2 ;Compute last block allocated+1.
add t4,t3
movei t2,o.File ;Where to read File block into.
movei t3,blksiz ;How many words.
; Here to read one block of File.
; NOTE: t1,t2,t3 and t4 are in use for remainder of this routine.
dofil4: caml t1,t4 ;Processed the last block?
popj p, ;Yes. Return. Get next retrieval ptr.
savreg ;No.
movem t1,ribtst ;Save for RIBSLF check later.
pushj p,bfread
resreg
; Check to see if we have just read a RIB.
; If the file doesn't have extended RIBs it will be ours.
; If the file does have extended RIBs and we are processing the last
; of the retrieval pointers, it will be ours.
; If the file does have extended RIBs but we are not processing the
; last of the retrieval poiters, it will be the 1st RIB of another file.
; Regardless of whose RIB it is, it will indicate to us that we
; should return to process the next retrieval pointer.
move t5,o.file+ribcod ;The word where a RIB's RIBCOD is.
move t6,o.file+ribslf ;The word where a RIB's RIBSLF is.
camn t5,[xwd 0,777777] ;Is it a RIBCOD?
came t6,ribtst ;And is it a RIBSLF?
skipa ;Here if NOT a RIB.
popj p, ;Yes. Return.
; Here to write the block out.
savreg ;Save registers for DOFIL4 loop.
aoj wrtblk,
move t1,wrtblk ;Where to write this block on new disk.
movei t2,o.file ;Location in core of block.
movei t3,blksiz ;Words to write.
pushj p,write ;Doit.
resreg ;Restore registers for DOFIL4 loop.
aoja t1,dofil4
subttl DOUFD - a subprocess of WRITIT. Processes UFDs.
; Call with:
; MAPIDX pointing to MAP entry of UFD being processed by WRITIT.
; O.RIB has rib of UFD.
; Uses t1,t2,t3.
; Check for special UFDs [1,1] and [1,4].
doufd: move t1,o.rib+ribnam ;Check for special cases, [1,4] [1,1].
setzm mufd ;Assume not MFD.
camn t1,[xwd 1,4] ;Is this it?
pjrst(dosufd) ;Yes. Goto routine to process it.
camn t1,[xwd 1,1] ;Check for special case, [1,1].UFD.
setom mufd ;Set [1,1].UFD flag for UPDRIB rtn.
; Here for directories other than [1,4].ufd
; Initialize RIBSIZ decrement counter.
move t1,o.rib+ribsiz ;Words written in UFD.
idivi t1,blksiz ;Make into blocks.
skipe t2 ;If a remainder,
die(?DOUFD: RIBSIZ is not an even factor of block size.)
movem t1,totblk ;Keep the decremental counter here.
; Update and write the first RIB.
; Need to get 1st word of 1st block for RIB Retrieval Pointer Checksum.
move t1,oldcfp(mapidx) ;Address of first RIB on old disk.
aoj t1, ;Address of first data block.
movei t2,o.file
movei t3,blksiz
movem t1,ribtst ;Save for RIBSLF check later.
pushj p,bfread
move t1,o.file ;Get 1st word for checksumming.
movem t1,n.chks ;Keep it here for routine CHKSUM.
; If this UFD has no data, only RIBs, then the block just read
; for checksumming will be a RIB. In this instance we want a
; checksum of zero. The following checks for this.
move t1,o.file+ribcod ;The word where a RIB's RIBCOD is.
move t2,o.file+ribslf ;The word where a RIB's RIBSLF is.
camn t1,[xwd 0,777777] ;Is it a RIBCOD?
came t2,ribtst ;And is it a RIBSLF?
skipa ;Here if NOT a RIB.
setzm n.chks ;Yes. Zero the Checksum word.
; Update RIB.
pushj p,updrib ;Called with RIB in O.RIB and MAPIDX
;pointing to file's entry in MAP.
;Updated RIB will be in N.RIB.
; Write RIB.
move t1,newcfp(mapidx) ;Prepare to write the first RIB.
movei t2,n.rib
movei t3,blksiz
pushj p,write
; Process UFD data.
move wrtblk,newcfp(mapidx) ;WRTBLK keeps new disk block
;address to which we last wrote a
;block of this file. Initialize to
;block address of RIB on new disk.
move maptmp,nxtnod(mapidx) ;@MAPTMP is address of first
;MAP entry to which current UFD entry
;being processed by MAPWRT, points.
doufd0: hrrz t1,o.rib+ribfir ;RIB index to 1st retrieval pointer.
addi t1,1 ;You just have to do this.
move t2,o.rib(t1) ;And get the first pointer.
pushj p,brkpto ;Break info out of pointer. Returns
;t2=block where UFD starts t3=# blocks,
;t4=checksum.
came t2,o.rib+ribslf ;Confirm that it points to itself.
die(?DOUFD: Address from RIB retrieval pointer is bad.)
aoj t2, ;The first pointer points to itself,
;so the UFD we want follows. Add 1.
soj t3, ;Which also means one less block of
;directory information for processing.
savreg
pushj p,doufd3 ;Process it.
;First call to DOUFD3 will update
;and wrie the first RIB.
;Updated RIB will be in N.RIB.
resreg
doufd1: addi t1,1 ;Move to next retrieval pointer.
caile t1,ribcod ;Check to see it's in bounds.
die(?DOUFD: RIB retrieval pointer index is out of bounds.)
cail t1,ribcod ;Out of pointers?
jrst doufdx ;Yes. Check if RIB is extended.
move t2,o.rib(t1) ;Get next pointer.
jumpe t2,doufdx ;Is the retrieval pointer zero?
;Yes. Go check if RIB is extended.
pushj p,brkpto ;No. Get info and process it.
;Returns t2=UFD address t3=# blocks,
;t4=checksum.
savreg
pushj p,doufd3 ;Process it.
resreg
jrst doufd1 ;Loop for next.
; Here to check for extended RIBs.
doufdx: skipn t1,o.rib+ribxra ;Extended?
jrst doufd2 ;No. Return.
move t4,o.rib+ribnam ;For security check later.
movei t2,o.rib ;Yes. Prepare to read it.
movei t3,blksiz
savreg
pushj p,bfread ;Read the extended RIB.
resreg
came t4,o.rib+ribnam ;Do RIBNAMs match?
die(?DOUFDX: Extended RIBNAM doesn't match RIBNAM in prime RIB.)
jrst doufd0 ;And loop to process it.
; Here when done to write last RIB. Updated copy in N.RIB.
doufd2: move t1,wrtblk ;Block address of last block of file.
aoj t1,
movem t1,n.rib+ribslf ;Adjust RIBSLF word of 2nd RIB to point
;to itself. Only difference from 1st.
movei t2,n.rib ;Location of RIB in core.
movei t3,blksiz ;Words to write.
pushj p,write ;Doit.
popj p,
subttl DOUFD3 - subprocess of DOUFD.
; Ccalled once for each of the UFD's rib retrieval pointers.
; Called with t2=logical block number from rib retrieval pointer,
; and t3=number of blocks from the rib retrieval pointer.
; Updates each entry in the UFD with new CFP.
doufd3: skipg totblk ;Check RIBSIZ decrement counter.
popj p, ;We have already read as many blocks
;in this UFD as are actually used.
;The RIB retrieval pointer we have
;been asked to process must be the
;result of an Uncompressed RIB, and
;hence is not really in use. Skip it.
; Here if we haven't read all the blocks in the UFD yet.
move t1,t2 ;Logical block of start of data.
move t4,t2 ;Compute last block allocated+1.
add t4,t3
movei t2,o.ufd ;Where to read UFD block into.
movei t3,blksiz ;How many words.
; Here to read one block of UFD.
; note: t1,t2,t3,t4 are in use for balance of routine.
doufd4: caml t1,t4 ;Processed the last blk of this ptr?
popj p, ; Yes. Return to get next retrieval ptr.
sosge totblk ;Decrement blocks read counter by one.
popj p, ; Have we read all the used blocks in
; in the UFD? Return.
savreg ;No. Continue.
pushj p,bfread
resreg
; Here to process the block of the UFD just read.
setz t5, ;Index to entries in UFD.
doufd5: caile t5,blksiz-2 ;Finished this block? 2 words/entry.
jrst doufd7 ;Yes. Go write this block to new disk.
move t6,o.ufd(t5) ;Get sixbit filename from UFD entry.
jumpe t6,doufd7 ;Zero, meaning no more data in block?
; Here if with t5 pointing to UFD block entry to be updated.
; Update the entry with MAP entry pointed to by MAPTMP.
; Check that the FileNames correspond for added security.
doufd6: came t6,name(maptmp) ;Same as in MAP entry?
die(?DOUFD6: UFD entry in MAP does not correspond with UFD block.)
aoj t5,
hlrz t6,ext(maptmp) ;File Exntension from MAP entry.
hlrz t7,o.ufd(t5) ;File Extension from UFD.
came t6,t7 ;Same?
die(?DOUFD6: UFD entry in MAP does not correspond with UFD block.)
move t6,newcfp(maptmp) ;File's block address on new disk.
idiv t6,n.home+hombpc ;Covert to CFP.
skipe t7 ;Remainder from division?
die(?DOUFD6: Conversion of block address to CFP not exact.)
hrrm t6,o.ufd(t5) ;Update UFD pointer to file.
addi maptmp,mapsiz ;Next entry in MAP.
aoja t5,doufd5 ;Next entry in UFD block.
; Here to write out updated UFD block.
doufd7: savreg ;Save registers for DOUFD4 loop.
aoj wrtblk,
move t1,wrtblk ;Where to write this block on new disk.
movei t2,o.ufd ;Location in core of block.
movei t3,blksiz ;Words to write.
pushj p,write ;Doit.
resreg ;Restore registers for DOUFD4 loop.
aoja t1,doufd4
subttl DOSUFD - a subprocess of WRITIT. Processes [1,4].UFD only.
; Call with:
; MAPIDX pointing to the [1,4].UFD entry in MAP.
; O.RIB has the [1,4].UFD RIB.
; WRTBLK is block address of where the 1st RIB will be on new disk.
; Uses all registers.
; t1 and t2 are dedicated indexes, not to destroyed in this routine.
; Update and write the first RIB.
; Need to get 1st word of 1st block for RIB Retrieval Pointer Checksum.
dosufd: move t1,oldcfp(mapidx) ;Address of first RIB on old disk.
aoj t1, ;Address of first data block.
movei t2,o.file
movei t3,blksiz
movem t1,ribtst ;Save for RIBSLF check later.
pushj p,bfread
move t1,o.file ;Get 1st word for checksumming.
movem t1,n.chks ;Keep it here for routine CHKSUM.
; If the SYS UFD has no data, only RIBs, then the block just read
; for checksumming will be a RIB. In this instance we want a
; checksum of zero. The following checks for this.
move t1,o.file+ribcod ;The word where a RIB's RIBCOD is.
move t2,o.file+ribslf ;The word where a RIB's RIBSLF is.
camn t1,[xwd 0,777777] ;Is it a RIBCOD?
came t2,ribtst ;And is it a RIBSLF?
skipa ;Here if NOT a RIB.
setzm n.chks ;Yes. Zero the Checksum word.
; Update RIB.
pushj p,updrib ;Called with RIB in O.RIB and MAPIDX
;pointing to file's entry in MAP.
;Updated RIB will be in N.RIB.
; Write RIB.
move t1,newcfp(mapidx) ;Prepare to write the first RIB.
movei t2,n.rib
movei t3,blksiz
pushj p,write
; Process SYS UFD data.
move wrtblk,newcfp(mapidx) ;WRTBLK keeps new disk block
;address to which we last wrote a
;block of this file. Initialize to
;block address of RIB on new disk.
setz t2, ;Find 1st free filename position
dosuf1: skipe n.sufd(t2) ;in N.SUFD.
aoja t2,dosuf1 ;Failed, try next word.
cail t2,blksiz-2 ;Check to see the word's in bounds.
die(?DOSUFD: N.SUFD has no free words in it.)
move maptmp,nxtnod(mapidx) ;First entry pointed to by [1,4].
hrrz t1,ext(mapidx) ;Number of entries.
dosuf2: sosge t1 ;For each of [1,4]'s entries do:
jrst dosuf6 ;Here when done. Go finish up.
pushj p,dosuf3 ;Add entry to UFD block being built.
addi maptmp,mapsiz ;Point to next [1,4] entry.
jrst dosuf2 ;Go process it.
; Here to add [1,4] entry pointed to by MAPTMP to UFD block.
dosuf3: caile t2,blksiz-2 ;This UFD block full?
pushj p,dosuf4 ;Yes. Write the block out, reset
;index t2, and zero out N.SUFD.
move t3,name(maptmp) ;File name.
movem t3,n.sufd(t2) ;Put in UFD block.
aoj t2, ;Incriment index to extension word.
move t3,newcfp(maptmp) ;File's address on new disk.
idiv t3,n.home+hombpc ;Change to a Compressed File Ptr.
skipe t4 ;A remainder from division?
die(?DOSUFD: Conversion from block address to CFP not exact.)
hll t3,ext(maptmp) ;and the File extension.
movem t3,n.sufd(t2) ;Add to UFD block.
aoj t2, ;Incriment index to next entry.
popj p, ;Return.
; Here to write out N.SUFD when it has become full.
; Also resets index t2 to zero, and zeroes the N.SUFD.
dosuf4: savreg ;Save registers for DOSUF2, DOSUF3.
aoj wrtblk,
move t1,wrtblk ;Where on new disk to write this block.
movei t2,n.sufd ;Blocks location in core.
movei t3,blksiz ;Number of words to write.
pushj p,write ;Doit.
resreg ;Restore registers for DOSUF2, DOSUF3
setzm n.sufd ;Zero out N.SUFD buffer.
hrli t2,n.sufd ;Prepare for BLT.
hrri t2,n.sufd+1
blt t2,n.sufe ;Zero through to end word.
setz t2, ;Reset buffer index to top.
popj p,
; Here when done to write current contents of N.SUFD and
; to write last RIB.
dosuf6: pushj p,dosuf4 ;Write out contents of N.SUFD.
; Now the RIB.
move t1,wrtblk ;Block address of last block of file.
aoj t1,
movem t1,o.rib+ribslf ;Adjust RIBSLF word of 2nd RIB to point
;to itself. Only difference from 1st.
movei t2,o.rib ;Location of RIB in core.
movei t3,blksiz ;Words to write.
pushj p,write ;Doit.
popj p,
subttl Data Storage
totblk: block 1 ;Use for counting blocks read of a UFD.
foo: block 1
Ribtst: block 1 ;Temp word used for checking if a block is a RIB.
Frompk: block 1 ;Name of pack copying from.
Topk: block 1 ;Name of pack copying to.
ToPkId: block 1 ;I.D. of pack copying to.
maxfil: block 1 ;Used to determine if a file is too large for D2D.
map: block 1 ;Will contain starting address of core map.
pdlist: block pdlen ;Push down stack.
sufd: block 1 ;Flag to indicate to MAP builder that
;SYS.UFD ([1,4]) is being processed (nonzero).
mufd: block 1 ;Flag to indicate to UPDRIB rtn that [1,1].UFD is
;bein processed.
outbuf: block 1 ;Pointer to top of free core used for buffering
;output to target disk.
;WARNING: nothing should be placed in free core
;after the point to which this word points.
topblk: block 1 ;Logical disk address on new pack of first block
;of data in buffer area pointed to by OUTBUF.
inblks==^d3 ;Number of blocks in INBUF.
inbuf: block inblks*blksiz ;Pointer to Input buffer used by BFREAD.
inaddr: -1 ;Logical disk address on first block of data
;in INBUF.
; The following apply to the old pack from which data is being copied.
o.home: block blksiz ;For reading in HOME block.
o.rib: block blksiz ;For reading in RIBs.
o.file: block blksiz ;For reading in data portion of files.
o.ufd: block blksiz ;For reading in UFDs.
o.ribp: block 1 ;RIB retrieval pointer word.
o.ptra: xwd 0,o.ribp ;Point to cluster add in retrieval pointer.
o.ptrc: xwd 0,o.ribp ;Point to cluster count in retrieval pointer.
o.ptrs: xwd 0,o.ribp ;Point to checksum in retrieval pointer.
; The following apply to the new pack to which data is being copied.
n.home: block blksiz ;For reading in HOME block.
n.rib: block blksiz ;For building new RIBs from old ones.
n.satr: block blksiz ;For target packs SAT.SYS RIB.
n.tmp: block 1 ;Misc. read-in's.
n.ribp: block 1 ;RIB retrieval Pointter word.
n.ptra: xwd 0,n.ribp ;PoinTR to cluster Address in RIBP.
n.ptrc: xwd 0,n.ribp ;PoinTR to cluster Count in RIBP.
n.ptrs: xwd 0,n.ribp ;PoinTR to checksum in RIBP.
n.sufd: block blksiz ;For building a System UFD block for new disk.
;[1,4].ufd is treated seperately because of
;certain files there not be be copied.
n.sufe: .-1 ;Last word of N.SUFD.
n.chks: block 1 ;For computing checksums.
; The following refer to the New pack's SAT which is built in-core.
n.sat: block 1 ;Permanent pointer to in-core SAT.
n.satt: block 1 ;SAT Top. Address of 1st word in-core SAT with
;free clusters. May move as space allocation proceeds.
n.dska: block 50 ;DiSK Address. c(N.DSKA+n) is the
;logical block address of the first cluster pointed to
;by SAT block n.
n.sate: block 1 ;SAT End. Address of last word in-core SAT.
n.satw: block 1 ;SAT Words. Number of words in each SAT block
;that are actually used to represent clusters.
;used to respresent clusters.
n.satp: point 1,0 ;Used for marking single bits(one cluster) in SAT.
n.bckp: block 1 ;BaCKPointer will be built here.
;It will be a pointer into the SAT area used to
;mark the Back or start of a contiguos group of
;free cluster pointers.
n.fwdp: block 1 ;ForWarDPointer will be built here.
;It will be a pointer into the SAT area used to
;search forward from where the BaCKPointer points
;to determine if there are a enough contiguous
;clusters to meet the request made on routine ALLOC.
n.satb: block 1 ;Blocks per SAT on new pack.
end d2d ;Show where to start execution.