// IfsDiskError.bcpl -- Disk error reporting
// Copyright Xerox Corporation 1982
// Last modified October 3, 1982 2:18 PM by Taft
get "Ifs.decl"
get "IfsSystemInfo.decl"
get "IfsFiles.decl"
get "IfsDirs.decl"
get "Disks.d"
get "Tfs.d"
external
[
// outgoing procedures
InitDiskError; RecordDiskError; InterpretDiskError
// incoming procedures
VFileReadPage; VFileWritePage; LockCell; UnlockCell
Ws; PutTemplate; Plural; Zero
// outgoing statics
newDiskErrorReported
// incoming statics
infoVMD
]
static
[
newDiskErrorReported = false
]
structure DE: // hard disk errors, recorded in dePage of <System>Info
[
numErrors word // total number of errors
numSameError word // number of consecutive occurrences of this error
cb @CB // copy of disk command block at time of error
ec word // TFS error code
haveDR word // following information is valid
fsID @DirName // name of file system in which error occurred
dr @DR // copy of directory record for file suffering error
]
manifest lenDE = size DE/16
compileif lenDE gr 1 lshift logStdPageLength then
[ Barf("DE structure too large for one IFS page") ]
manifest maxLenDR = maxLenDRHeader+lenPathName+lenDIFRec
//----------------------------------------------------------------------------
let InitDiskError() be
//----------------------------------------------------------------------------
[
let de = VFileWritePage(infoVMD, dePage)
Zero(de, lenDE)
newDiskErrorReported = false
]
//----------------------------------------------------------------------------
and RecordDiskError(cb, fd, ec) be
//----------------------------------------------------------------------------
// Records a disk error that has occurred.
// cb is the disk command block for which the error occurred.
// fd, if nonzero, is alleged to designate the file in which the error occurred.
// ec is the TFS error code.
[
let de = VFileWritePage(infoVMD, dePage)
de>>DE.numErrors = de>>DE.numErrors+1
test MultEq(lv cb>>CB.diskAddress, lv de>>DE.cb.diskAddress, 3) // disk address & drive
ifso de>>DE.numSameError = de>>DE.numSameError+1
ifnot de>>DE.numSameError = 1
MoveBlock(lv de>>DE.cb, cb, lCB)
de>>DE.ec = ec
de>>DE.haveFD = false
if fd ne 0 then
[
let fs = fsQ!0
while fs ne 0 do
[
if fd>>FD.fs eq fs &
fs>>IFS.lpdt↑(fd>>FD.dr>>DR.unit) eq cb>>CB.cbz>>CBZ.disk then
[
MoveBlock(lv de>>DE.fsID, fs>>IFS.id, fs>>IFS.id>>String.length rshift 1 +1)
MoveBlock(lv de>>DE.dr, fd>>FD.dr, Min(fd>>FD.dr>>DR.length, maxLenDR))
de>>DE.haveFD = true
break
]
fs = fs!0
]
]
newDiskErrorReported = true
]
//----------------------------------------------------------------------------
and InterpretDiskError(s) be
//----------------------------------------------------------------------------
[
let de = VFileReadPage(infoVMD, dePage)
LockCell(lv de)
if de>>DE.numErrors ne 0 then
[
PutTemplate(s,
"Unrecoverable disk error (code = $UD) on drive $UD, cyl $UD, hd $UD, sec $UD*n",
de>>DE.ec, de>>DE.cb.drive, de>>DE.cb.track, de>>DE.cb.head, de>>DE.cb.sector)
PutTemplate(s,
"Command: header = $P, label = $P, data = $P*n",
InterpCmd, de>>DE.cb.CommH, InterpCmd, de>>DE.cb.CommL, InterpCmd, de>>DE.cb.CommD)
PutTemplate(s,
"Status: header = $UO, label = $UO, data = $UO*n",
de>>DE.cb.StatusH, de>>DE.cb.StatusL, de>>DE.cb.StatusD)
let block = lv de>>DE.cb.CommH
for rec = 0 to 2 do
[
let status = block>>KCBblock.Status
if (status & dstErrors) ne 0 then
[
let interp = status<<DST.ECCerror? "checksum (ECC)",
status<<DST.CompErr? "compare", 0
if interp ne 0 then
PutTemplate(s, "Interpretation: $S error in $S field*n", interp,
selecton rec into [ case 0: "header"; case 1: "label"; case 2: "data"])
]
block = block+lKCBbl
]
PutTemplate(s, "Total of $UD error$S", de>>DE.numErrors, Plural(de>>DE.numErrors))
if de>>DE.numSameError ugr 1 then
PutTemplate(s, ", including $UD consecutive occurrence$S of this error",
de>>DE.numSameError, Plural(de>>DE.numSameError))
]
UnlockCell(lv de)
]
//----------------------------------------------------------------------------
and InterpCmd(s, cmd) be
//----------------------------------------------------------------------------
PutTemplate(s, (selecton cmd into
[
case 0: "no-op"
case diskRead: "read"
case diskWrite: "write"
case diskCheck: "check"
default: "?[$UO]"
], cmd)