// CopyDiskBfs.bcpl // Copyright Xerox Corporation 1979, 1980, 1981, 1982 // Last modified May 14, 1982 1:14 PM by Boggs get "AltoDefs.d" get "AltoFileSys.d" get "CopyDisk.decl" get "CopyDiskBfs.decl" external [ // outgoing procedures InitCopyDiskBfs; ReportBfsError // incoming procedures from other CopyDisk modules DeclareDevice; DeclareDiskParams; FatalError BfsTryDisk; BfsReader; BfsWriter; DataCompare // incoming procedures from OS and packages Zero; MoveBlock; MultEq; BlockEq Allocate; Free; Block; MulDiv PutTemplate; Wss; Puts; Confirm Idle; Noop; ExtractSubstring; StringCompare // incoming statics debugFlag; model44Flag; seriousErrors dsp; CtxRunning; sysZone ] structure String [ length byte; char^1,1 byte ] //---------------------------------------------------------------------------- let InitCopyDiskBfs() be //---------------------------------------------------------------------------- [ DeclareDiskParams(AltoDiablo, BfsPrintDiskParams) DeclareDevice("DP0", MakeBFSSS) DeclareDevice("DP1", MakeBFSSS) DeclareDevice("BFS", MakeBFSSS) DeclareDevice("BFS0", MakeBFSSS) let eng = (table [ 61014b; 1401b ])()<>DA.disk @mouseY = (diskAddress>>DA.cylinder ls 0? 0, 20 + MulDiv(808-40-16, diskAddress>>DA.cylinder, 406)) Block() ] //---------------------------------------------------------------------------- and MakeBFSSS(device, write) = valof //---------------------------------------------------------------------------- [ let drive, partition, fs = nil, nil, nil let l = device>>String.length test StringCompare("DP", device) eq -2 ifso //DPxy -- x is partition, y drive [ fs = false drive = device>>String.char^l - $0 partition = device>>String.char^(l-1) ] ifnot //BFSx -- x is partition [ fs = true drive = 0 partition = device>>String.char^l ] partition = (partition ge $0 & partition le $5)? partition-$0, 0 unless BfsTryDisk(partition, drive, 0, 0) do [ Wss(dsp, "- doesn't respond"); resultis false ] let dShape = vec lDSHAPE; Zero(dShape, lDSHAPE) if fs & not write then //read DSHAPE property in leader page of sysDir [ // set up disk command block let kcb = vec lKCB; Zero(kcb, lKCB) kcb>>KCB.headerAddress = lv kcb>>KCB.header kcb>>KCB.header.diskAddress.sector = 1 let label = vec lDL; Zero(label, lDL) kcb>>KCB.labelAddress = label label>>DL.numChars = 512 label>>DL.version = 1 label>>DL.directory = 1 label>>DL.sn2 = 144b kcb>>KCB.dataAddress = Allocate(sysZone, 256) kcb>>KCB.command = readD kcb>>KCB.command.partition = partition let ok = valof [ @diskCommand = kcb while kcb>>KCB.status eq 0 loop if (kcb>>KCB.status & DSTgoodStatusMask) ne DSTgoodStatus then [ Wss(dsp, "- can't find SysDir's leader page"); resultis false ] // search for the DSHAPE property let data = kcb>>KCB.dataAddress if data>>LD.propertyBegin ge offset LD.leaderProps/16 & data>>LD.propertyBegin + data>>LD.propertyLength le (offset LD.leaderProps + size LD.leaderProps)/16 then [ let fProp = data + data>>LD.propertyBegin let maxFProp = fProp + data>>LD.propertyLength until fProp>>FPROP.type eq 0 do [ let length = fProp>>FPROP.length if length eq 0 % fProp+length gr maxFProp break if fProp>>FPROP.type eq fpropTypeDShape then [ MoveBlock(dShape, fProp+1, lDSHAPE) resultis true ] fProp = fProp + length ] ] Wss(dsp, "- can't find DSHAPE property") resultis false ] Free(sysZone, kcb>>KCB.dataAddress) unless ok resultis false if dShape>>DSHAPE.nDisks eq 2 then unless BfsTryDisk(partition, 1, 0, 0) do [ Wss(dsp, "- drive 1 doesn't respond"); resultis false ] ] // MakeBFSSS (cont'd) let ss = Allocate(sysZone, lenBFSSS); Zero(ss, lenBFSSS) Idle = BfsIdle ss>>SS.read = BfsReader ss>>SS.write = BfsWriter ss>>SS.destroy = DestroyBFSSS ss>>SS.printDA = PrintCurrentDA ss>>SS.compatible = fs? BfsCompatible, DPCompatible ss>>SS.compare = BfsCompare ss>>SS.printBlock = BfsPrintBlock ss>>SS.lenBuffer = lenBFSBuffer ss>>SS.device = ExtractSubstring(device) ss>>SS.type = ssDisk ss>>BFSSS.cbz = Allocate(sysZone, lenCBZ) ss>>BFSSS.retryCount = 8 ss>>BFSSS.driveNumber = drive ss>>BFSSS.partition = partition // error block let length = lenErrors + lenBFSErrors let cd = Allocate(sysZone, length); Zero(cd, length) ss>>SS.errors = cd cd>>CD.length = length cd>>CD.type = hereAreErrors cd>>CD.errors.diskType = AltoDiablo // disk parameters length = lenDiskParams + lenBFSDiskParams cd = Allocate(sysZone, length); Zero(cd, length) ss>>SS.dp = cd cd>>CD.length = length cd>>CD.type = hereAreDiskParams cd>>CD.diskParams.diskType = AltoDiablo let dp = lv cd>>CD.diskParams.params test fs & not write ifso [ dp>>BFSDiskParams.nDisks = dShape>>DSHAPE.nDisks dp>>BFSDiskParams.nCylinders = dShape>>DSHAPE.nTracks dp>>BFSDiskParams.nHeads = dShape>>DSHAPE.nHeads dp>>BFSDiskParams.nSectors = dShape>>DSHAPE.nSectors ] ifnot [ dp>>BFSDiskParams.nDisks = (fs & write)? (BfsTryDisk(partition, 1, 0, 0)? 2, 1), 1 dp>>BFSDiskParams.nCylinders = BfsTryDisk(partition, 0, 203, 0)? 406,203 dp>>BFSDiskParams.nHeads = 2 dp>>BFSDiskParams.nSectors = BfsTryDisk(partition, 0, 0, 13)? 14, 12 ] Puts(dsp, $*N); BfsPrintDiskParams(cd) resultis ss ] //---------------------------------------------------------------------------- and DestroyBFSSS(ss) = valof //---------------------------------------------------------------------------- [ Free(sysZone, ss>>BFSSS.cbz) Free(sysZone, ss>>SS.errors) Free(sysZone, ss>>SS.dp) Free(sysZone, ss>>SS.device) Free(sysZone, ss) Idle = Block resultis 0 ] //---------------------------------------------------------------------------- and DPCompatible(srcSS, snkSS) = valof //---------------------------------------------------------------------------- [ let srcDPs = lv srcSS>>SS.dp>>CD.diskParams.params let snkDPs = lv (snkSS>>SS.dp>>CD.diskParams.diskType eq 0? srcSS, snkSS)>>SS.dp>>CD.diskParams.params let sectors = 12 let srcSecs = srcDPs>>BFSDiskParams.nSectors let snkSecs = snkDPs>>BFSDiskParams.nSectors if (srcSecs eq 12 % snkSecs eq 12) & srcSecs ne snkSecs then Wss(dsp, "*NI will treat the 14-sector disk as a 12-sector disk") if srcSecs eq 14 & snkSecs eq 14 then sectors = srcSS>>SS.type eq ssNetLog? 14, (Confirm("*NShall I pretend this is a 12-sector disk?")? 12, 14) srcDPs>>BFSDiskParams.nSectors = sectors let cylinders = 203 let srcCyls = srcDPs>>BFSDiskParams.nCylinders let snkCyls = snkDPs>>BFSDiskParams.nCylinders if (srcCyls eq 203 % snkCyls eq 203) & srcCyls ne snkCyls then Wss(dsp, "*NI will treat the model-44 disk as a model-31 disk") if srcCyls eq 406 & snkCyls eq 406 then cylinders = srcSS>>SS.type eq ssNetLog % model44Flag? 406, (Confirm("*NShall I pretend this is a model-31 disk?")? 203, 406) srcDPs>>BFSDiskParams.nCylinders = cylinders resultis CreateXferParams(srcDPs) ] //---------------------------------------------------------------------------- and BfsCompatible(srcSS, snkSS) = valof //---------------------------------------------------------------------------- [ let srcDPs = lv srcSS>>SS.dp>>CD.diskParams.params let snkDPs = lv (snkSS>>SS.dp>>CD.diskParams.diskType eq 0? srcSS, snkSS)>>SS.dp>>CD.diskParams.params if srcDPs>>BFSDiskParams.nDisks gr snkDPs>>BFSDiskParams.nDisks % srcDPs>>BFSDiskParams.nCylinders gr snkDPs>>BFSDiskParams.nCylinders % srcDPs>>BFSDiskParams.nHeads gr snkDPs>>BFSDiskParams.nHeads % srcDPs>>BFSDiskParams.nSectors gr snkDPs>>BFSDiskParams.nSectors then [ Wss(dsp, "*NSource filesystem larger than destination disk."); resultis 0 ] resultis CreateXferParams(srcDPs) ] //---------------------------------------------------------------------------- and CreateXferParams(srcDPs) = valof //---------------------------------------------------------------------------- [ let length = lenXferParams + lenBFSXferParams let cd = Allocate(sysZone, length); Zero(cd, length) cd>>CD.length = length let lastDA = lv (lv cd>>CD.xferParams.params)>>BFSXferParams.lastDA lastDA>>DA.disk = srcDPs>>BFSDiskParams.nDisks -1 lastDA>>DA.cylinder = srcDPs>>BFSDiskParams.nCylinders -1 lastDA>>DA.head = 1 lastDA>>DA.sector = srcDPs>>BFSDiskParams.nSectors -1 resultis cd ] //---------------------------------------------------------------------------- and BfsCompare(ss, buf1, buf2) = valof //---------------------------------------------------------------------------- [ if buf1>>BFSBuffer.type eq endOfTransfer % buf2>>BFSBuffer.type eq endOfTransfer resultis true if buf1>>BFSBuffer.header.diskAddress ne buf2>>BFSBuffer.header.diskAddress then [ Wss(dsp, "*N[BfsCompare] Buffer DAs not equal") ss>>SS.fatalFlag = true resultis false ] let length = lenBFSHeader + lenBFSLabel + ((buf1>>BFSBuffer.length eq lenFreePage % buf2>>BFSBuffer.length eq lenFreePage)? 0, lenBFSData) test BlockEq(lv buf1>>BFSBuffer.header, lv buf2>>BFSBuffer.header, length) ifso resultis true ifnot [ Wss(dsp, "*NData compare error at ") BfsPrintDA(dsp, buf1>>BFSBuffer.header.diskAddress, ss) if debugFlag then DataCompare(lv buf1>>BFSBuffer.header, lv buf2>>BFSBuffer.header, length) resultis false ] ] //---------------------------------------------------------------------------- and PrintCurrentDA(stream, ss) be //---------------------------------------------------------------------------- BfsPrintDA(stream, ss>>BFSSS.currentDA, ss) //---------------------------------------------------------------------------- and BfsPrintDA(stream, da, ss) be //---------------------------------------------------------------------------- PutTemplate(stream, "$S: un $D cyl $3F0D hd $D sec $2F0D", ss>>SS.device, da<>CDCtx.ss let bfsErrors = lv ss>>SS.errors>>CD.errors.errors switchon type & 177400b into [ case EtHard: [ PutTemplate(dsp, "*NHard $S error at ", (type & 377b) eq EtWrite? "write","read") BfsPrintDA(dsp, daOrCb>>CB.diskAddress, ss) PutTemplate(dsp, ", SN $EUO", lv daOrCb>>CB.labelAddress>>DL.sn1) bfsErrors>>BFSErrors.hardError = bfsErrors>>BFSErrors.hardError +1 endcase ] case EtSoft: [ if debugFlag then [ PutTemplate(dsp, "*NSoft $S error at ", (type & #377) eq EtWrite? "write","read") BfsPrintDA(dsp, daOrCb, ss) ] bfsErrors>>BFSErrors.softError = bfsErrors>>BFSErrors.softError +1 endcase ] ] ] //---------------------------------------------------------------------------- and BfsPrintBlock(ss, cd) be //---------------------------------------------------------------------------- [ if cd eq 0 return switchon cd>>CD.type into [ case no: [ Wss(dsp, lv cd>>CD.codeString.string) seriousErrors = true endcase ] case hereAreErrors: [ if cd>>CD.errors.diskType eq 0 endcase let printedDevice = false let bfse = lv cd>>CD.errors.errors if bfse>>BFSErrors.softError ne 0 & debugFlag then [ unless printedDevice do PutTemplate(dsp, "*N$S: ", ss>>SS.device) printedDevice = true PutTemplate(dsp, "$UD soft errors ", bfse>>BFSErrors.softError) ] if bfse>>BFSErrors.hardError ne 0 then [ unless printedDevice do PutTemplate(dsp, "*N$S: ", ss>>SS.device) printedDevice = true PutTemplate(dsp, "$UD hard errors ", bfse>>BFSErrors.hardError) seriousErrors = true ] endcase ] case storeDisk: case retrieveDisk: [ let tp = lv cd>>CD.xferParams.params Wss(dsp, "*N FirstDA: ") BfsPrintDA(dsp, tp>>BFSXferParams.firstDA, ss) Wss(dsp, "*N LastDA: ") BfsPrintDA(dsp, tp>>BFSXferParams.lastDA, ss) endcase ] case hereAreDiskParams: [ BfsPrintDiskParams(cd) endcase ] ] ] //---------------------------------------------------------------------------- and BfsPrintDiskParams(cd) be //---------------------------------------------------------------------------- [ if cd>>CD.diskParams.diskType eq 0 return let dp = lv cd>>CD.diskParams.params let nDisks = (cd>>CD.length eq lenBFSDiskParams+lenDiskParams-1)? 1, dp>>BFSDiskParams.nDisks PutTemplate(dsp, "Type: Diablo, Dsk: $D, Cyl: $D, Hd: $D, Sec: $D", nDisks, dp>>BFSDiskParams.nCylinders, dp>>BFSDiskParams.nHeads, dp>>BFSDiskParams.nSectors) ]