// IfsScavPass1.bcpl
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified November 26, 1981 3:25 PM by Taft
get "IfsScavenger.decl"
get "IfsVMem.decl"
get "Disks.d"
get "Tfs.d"
external
[
// outgoing procedures
Pass1; PVRR; PVWR
// incoming procedures
Pass1Phase1; Pass1Phase2; Pass1Phase3
Pass1Phase4; Pass1Phase5; Scratch
OpenVFileFromFP; CloseVFile; @VRR2; @VWR2
Allocate; Free; IFSError; Zero; DoubleAdd
OpenFile; DeleteFile; Closes
JumpToFa; GetCurrentFa; TruncateDiskStream
OpenDisk; TFSInit; CloseDisk
OpenLPT; CloseLPT; GetLptFa
Ws; ScavConfirm
// outgoing statics
plme; bpl; maxVDA
bytesPerPage; wordsPerPage
ifsPackFlag
// incoming statics
scratchDisk; scavDisk
dsp; keys; sysZone; lpt
debugFlag; initLptFlag; justFixDirFlag; pass
]
static
[
plme; bpl; maxVDA
bytesPerPage; wordsPerPage
ifsPackFlag = true
plmVmd
]
//----------------------------------------------------------------------------
let Pass1(drive; numargs na) = valof
//----------------------------------------------------------------------------
// If called from the top level, there will be no arguments.
// If called from Scavenge() there will be one argument.
[
pass = 1
if scratchDisk eq 0 then unless Scratch(nil) resultis false
// open Scavengee
test drive eq -1 % na eq 0
ifso scavDisk = OpenDisk("*NScan pack on drive ", 0, true, false)
ifnot scavDisk = TFSInit(sysZone, 0, drive, 0, true)
if scavDisk eq 0 resultis false
ifsPackFlag = na eq 0? ScavConfirm("*NIs this an IFS pack?"), true
drive = scavDisk>>DSK.driveNumber
let model = scavDisk>>TFSDSK.model
let fs = scavDisk>>TFSDSK.firstVTrack eq 0? 0, 1
wordsPerPage = 1 lshift scavDisk>>DSK.lnPageSize
bytesPerPage = wordsPerPage lshift 1
maxVDA = (scavDisk>>TFSDSK.nVTracks * scavDisk>>TFSDSK.nHeads *
scavDisk>>TFSDSK.nSectors) -1
unless justFixDirFlag do
[
// Page Link Map (PLM) file
// max size of the PLM in vPages (256 words) is 2048
let fpPLM = vec lFP; Zero(fpPLM, lFP)
let plm = OpenFile("IfsScavenger.plm", 0, 0, 0, fpPLM, 0, 0, 0, scratchDisk)
if plm eq 0 then IFSError(ecScratchFile, "IfsScavenger.plm")
Closes(plm)
let vPagesPerDPage = 1 lshift (scratchDisk>>DSK.lnPageSize-8)
plmVmd = OpenVFileFromFP(fpPLM, scratchDisk, 2048/vPagesPerDPage, 256)
PVRR(maxVDA) //extend the plm to full length
]
// Here is where the work gets done
lpt = OpenLPT("IfsScavenger.lpt", initLptFlag)
let ok = valof
[
unless justFixDirFlag do
bpl = Allocate(sysZone, wordsPerPage)
ok = Pass1Phase1()
unless justFixDirFlag do
[
if ok then ok = Pass1Phase2()
if ok & na eq 0 then
ok = ScavConfirm("*NMay I alter the disk? ")
if ok then ok = Pass1Phase3()
Free(sysZone, bpl)
if ok then ok = Pass1Phase4(fs lshift 8 + drive)
]
if ok & ifsPackFlag then ok = Pass1Phase5(fs lshift 8 + drive)
// clean up leader page table
unless ok % debugFlag do
[
JumpToFa(lpt, GetLptFa(lpt))
TruncateDiskStream(lpt)
]
GetCurrentFa(lpt, GetLptFa(lpt))
// advance to next logical file system on pack
if scavDisk ne 0 then scavDisk = CloseDisk(scavDisk, true)
if fs ne 0 % model ne 300 % ok ne -1 % na eq 0 resultis ok
fs = fs +1
scavDisk = TFSInit(sysZone, 0, fs lshift 8+drive, 0, true) //gently...
if scavDisk eq 0 resultis ok
] repeat
// clean up and go away
if lpt ne 0 then lpt = CloseLPT(lpt, false)
unless justFixDirFlag do
[
CloseVFile(plmVmd)
DeleteFile("IfsScavenger.plm", 0, 0, 0, 0, scratchDisk)
]
Ws("*NPass1 complete*N")
resultis ok
]
// Page Link Map VMem routines
//----------------------------------------------------------------------------
and PVRR(vda) = valof
//----------------------------------------------------------------------------
[
let addr = vec 1
addr!0 = vda rshift 13
addr!1 = vda lshift 3
let base = vec 1
base!0 = plmVmd>>VMD.base rshift 8
base!1 = plmVmd>>VMD.base lshift 8
DoubleAdd(addr, base)
resultis VRR2(addr!0, addr!1)
]
//----------------------------------------------------------------------------
and PVWR(vda) = valof
//----------------------------------------------------------------------------
[
let addr = vec 1
addr!0 = vda rshift 13
addr!1 = vda lshift 3
let base = vec 1
base!0 = plmVmd>>VMD.base rshift 8
base!1 = plmVmd>>VMD.base lshift 8
DoubleAdd(addr, base)
resultis VWR2(addr!0, addr!1)
]