// 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) ]