ExtraIagoImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited by: Willie-Sue, May 2, 1985 1:42:42 pm PDT
DIRECTORY
Basics,
BasicTime,
Disk,
DiskExtras,
DiskFace,
DiskFaceExtras,
FileExtra,
FormatDisk,
FSBackdoor,
IagoOps,
PhysicalVolume,
VM,
ExtraIagoOps,
File,
IagoOps USING [RegisterCommand],
IO,
Rope;
ExtraIagoImpl: CEDAR PROGRAM
IMPORTS
Basics, BasicTime, Disk, DiskExtras, DiskFace, DiskFaceExtras, File, FileExtra, FSBackdoor, FormatDisk, IO, PhysicalVolume, Rope, VM,
ExtraIagoOps, IagoOps =
BEGIN OPEN ExtraIagoOps, File;
-- * * * * * * * * commands implementation * * * * * * * *
ReadBootFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, bootFile]};
ReadCkptFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, checkpoint]};
ReadUCodeFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, microcode]};
ReadGermFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, germ]};
ReadDebuggerFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, debugger]};
ReadDebuggeeFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, debuggee]};
ReadVMFile: PROC[in, out: IO.STREAM] = {ReadSystemFile[in, out, VM]};
DeleteBootFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, bootFile]};
DeleteCkptFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, checkpoint]};
DeleteUCodeFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, microcode]};
DeleteGermFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, germ]};
DeleteDebuggerFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, debugger]};
DeleteDebuggeeFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, debuggee]};
DeleteVMFile: PROC[in, out: IO.STREAM] = {DeleteSystemFile[in, out, VM]};
NewFormatDisk: PROC[in, out: IO.STREAM] = {
d: Disk.Channel = IagoOps.GetDrive[in, out];
alto: BOOL = Disk.DriveAttributes[d].ordinal = 0 AND IagoOps.CheckAltoRegions[in, out];
passes: INT = IagoOps.GetNumber[in, out, 10, 999,
"\nHow many check passes should I make? ",
"? Type how often I should make transfers over the entire disk trying to find bad spots"];
IF IagoOps.ConfirmDestruction[in, out, Rope.Cat[
"the entire disk drive",
IF alto THEN " (excluding Alto regions)" ELSE NIL ] ]
THEN DoFormatOrScan[in, out, d, TRUE, passes];
};
DoFormatOrScan: PROC
[in, out: IO.STREAM, d: Disk.Channel, format: BOOL, passes: INT] = TRUSTED {
initLabel: Disk.Label;
pageSpace: VM.Interval = VM.Allocate[VM.PagesForWords[File.wordsPerPage]];
data: LONG POINTER = VM.AddressForPageNumber[pageSpace.page];
soft, hard: INT ← 0;
BadList: TYPE = LIST OF RECORD[
page: Disk.PageNumber, correctable: BOOL, dontReport: BOOLFALSE];
badPages: BadList ← NIL;
errorsThisPass: BOOL;
SweepDisk: PROC
[out: IO.STREAM, d: Disk.Channel, operation: FormatDisk.Operation] = TRUSTED {
origin: Disk.PageNumber ← [0];
label: Disk.Label ← initLabel;
IO.PutRope[out, SELECT operation FROM
format => "\nFormatting ... ",
write => "\nWriting ... ",
read => "\nReading ... ",
verify => "\nVerifying ... "
ENDCASE => ERROR];
errorsThisPass ← FALSE;
DO firstPage: Disk.PageNumber; pageCount: Disk.PageCount;
[firstPage, pageCount] ← IagoOps.NextRun[d, origin];
IF pageCount < 0 THEN EXIT;
FormatDisk.Sweep[d, operation, firstPage, pageCount, @label, data];
origin ← [firstPage+pageCount];
ENDLOOP;
IF NOT errorsThisPass THEN IO.PutRope[out, "no errors"];
};
IF format THEN CloseFSVolumes[];
{
ENABLE {
UNWIND => VM.Free[pageSpace];
FormatDisk.BadPage => {
[page: Disk.PageNumber, correctable: BOOL]
b: BadList;
FOR b ← badPages, b.rest UNTIL b = NIL DO
IF b.first.page = page THEN {
IF b.first.correctable
THEN {
IF NOT correctable
THEN { b.first.correctable ← FALSE; soft ← soft-1; hard ← hard+1 };
};
EXIT
};
REPEAT FINISHED => {
badPages ← b ←
CONS[first: [page: page, correctable: correctable], rest: badPages];
IF correctable THEN soft ← soft+1 ELSE hard ← hard+1;
}
ENDLOOP;
IF hard > 100 THEN {
IO.PutRope[out, "\nThere are over 100 hard disk errors. Continue? "];
IF NOT IagoOps.Confirm[in, out] THEN CONTINUE;
hard ← 0;
};
IF NOT b.first.dontReport THEN {
logicalDiskCyl: CARDINAL;
physicalDiskCyl, physicalDiskTrack, physicalDiskSector: CARDINAL;
cylinder, track, sector, temp: CARDINAL;
device: DiskFace.DeviceHandle ← DiskExtras.GetDeviceFromChannel[d];
IO.PutRope[out, IF errorsThisPass THEN ", " ELSE "\nDisk error(s): "];
errorsThisPass ← TRUE;
[cylinders: physicalDiskCyl, movingHeads: physicalDiskTrack, sectorsPerTrack: physicalDiskSector] ← DiskFaceExtras.GetTrueDeviceAttributes[device];
[cylinders: logicalDiskCyl] ← DiskFace.GetDeviceAttributes[device];
IF logicalDiskCyl # physicalDiskCyl
THEN {
Abnormal cyl/track/sect numbering on a Dorado for Alto compatability
[quotient: temp, remainder: sector] ← Basics.LongDivMod[
num: page, den: physicalDiskSector ];
[quotient: track, remainder: cylinder] ← Basics.DIVMOD[
num: temp, den: physicalDiskCyl];
}
ELSE {
Normal cyl/track/sect numbering
[quotient: cylinder, remainder: temp] ← Basics.LongDivMod[
num: page, den: physicalDiskSector * physicalDiskTrack];
[quotient: track, remainder: sector] ← Basics.DIVMOD[
num: temp, den: physicalDiskSector];
};
IO.PutF[out, "%bB[c:%g, t:%g, s:%g](%g)",
[integer[page]], [cardinal[cylinder]], [cardinal[track]], [cardinal[sector]],
[rope[IF correctable THEN "soft" ELSE "hard"]] ];
b.first.dontReport ← NOT correctable; -- suppress messages on subsequent passes
};
RESUME
};
};
VM.Pin[pageSpace];
IF format
THEN {
init: BOOLTRUE;
Randomize: PROC = TRUSTED {
RandomizeOne[@initLabel, SIZE[Disk.Label]];
RandomizeOne[data, File.wordsPerPage];
init ← NOT init;
};
RandomizeOne: PROC
[where: LONG POINTER, nwords: CARDINAL] = TRUSTED {
array: LONG POINTER TO ARRAY OF CARDINAL = LOOPHOLE[where];
FOR i: CARDINAL IN [0..nwords)
DO array[i] ← IF init
THEN Basics.LowHalf[BasicTime.GetClockPulses[]]
ELSE Basics.BITNOT[array[i]];
ENDLOOP;
};
Randomize[];
SweepDisk[out, d, format];
SweepDisk[out, d, verify];
THROUGH [1..passes]
DO -- First, set label and data to random values
Randomize[];
SweepDisk[out, d, write];
SweepDisk[out, d, verify];
ENDLOOP;
}
ELSE THROUGH [1..passes]
DO SweepDisk[out, d, read] ENDLOOP;
Record any bad pages
{
p: PhysicalVolume.Physical ← NIL;
IF NOT format THEN
FOR p
← PhysicalVolume.NextPhysical[NIL], PhysicalVolume.NextPhysical[p]
UNTIL p = NIL DO
IF PhysicalVolume.PhysicalInfo[p].channel = d THEN EXIT;
ENDLOOP;
IF p = NIL THEN {
IO.PutRope[out, "\nCreating a physical volume to hold the bad page table ..."];
p ← FileExtra.CreatePhysicalVolume[
where: d, name: "JustForTheBadPageTable", id: IagoOps.NewID[]];
IO.PutRope[out, "done"];
};
IF badPages # NIL THEN {
rc: PhysicalVolume.PhysicalRC ← ok;
IO.PutRope[out, "\nRecording bad pages in physical bad page table ... "];
FOR b: BadList ← badPages, b.rest UNTIL b = NIL OR rc # ok DO
IF NOT b.first.correctable THEN rc ← FileExtra.PhysicalPageBad[p, b.first.page];
ENDLOOP;
IF rc = ok THEN IO.PutRope[out, "done" ] ELSE ERROR File.Error[rc];
};
};
};
VM.Free[pageSpace];
};
CloseFSVolumes: PROC = {
FOR v: File.Volume ← File.NextVolume[NIL], File.NextVolume[v] UNTIL v = NIL DO
FSBackdoor.CloseVolume[v];
ENDLOOP;
};
* * * * * * * start code ** register commands with Iago
IagoOps.RegisterCommand[[Loophole, "Convert octal or hex to decimal"]];
IagoOps.RegisterCommand[[
AddPageToBadPageTable, "Add (Physical) Page To the BadPageTable"]];
IagoOps.RegisterCommand[[DescribeAllocated, "Describe Allocated Disk Pages"]];
IagoOps.RegisterCommand[[DescribeBadPages, "Describe Bad Pages"]];
IagoOps.RegisterCommand[[EnsureBadPagesInVAM, "Ensure Bad Pages in VAM"]];
IagoOps.RegisterCommand[[ListBadPages, "List Bad Pages"]];
IagoOps.RegisterCommand[[MarkPageAllocated, "Mark (Logical) Page as Allocated"]];
IagoOps.RegisterCommand[[ReadDiskPages, "Read Physical Page(s)"]];
IagoOps.RegisterCommand[[ReadFilePages, "Read File Page(s)"]];
IagoOps.RegisterCommand[[ReadLogicalPages, "Read Logical Volume Page(s)"]];
IagoOps.RegisterCommand[[WriteDiskPage, "Re-Write one Disk Page"]];
IagoOps.RegisterCommand[[ReadNamedFile, "Read Named File"]];
IagoOps.RegisterCommand[[ShowDiskAddress, "Show Disk Address"]];
IagoOps.RegisterCommand[[ReadBootFile, "Read BootFile"]];
IagoOps.RegisterCommand[[ReadCkptFile, "Read Checkpoint File"]];
IagoOps.RegisterCommand[[ReadUCodeFile, "Read Microcode File"]];
IagoOps.RegisterCommand[[ReadGermFile, "Read Germ File"]];
IagoOps.RegisterCommand[[ReadDebuggerFile, "Read Debugger File"]];
IagoOps.RegisterCommand[[ReadDebuggeeFile, "Read Debuggee File"]];
IagoOps.RegisterCommand[[ReadVMFile, "Read VM File"]];
IagoOps.RegisterCommand[[DeleteBootFile, "Delete BootFile"]];
IagoOps.RegisterCommand[[DeleteCkptFile, "Delete Checkpoint File"]];
IagoOps.RegisterCommand[[DeleteUCodeFile, "Delete Microcode File"]];
IagoOps.RegisterCommand[[DeleteGermFile, "Delete Germ File"]];
IagoOps.RegisterCommand[[DeleteDebuggerFile, "Delete Debugger File"]];
IagoOps.RegisterCommand[[DeleteDebuggeeFile, "Delete Debuggee File"]];
IagoOps.RegisterCommand[[DeleteVMFile, "Delete VM File"]];
IagoOps.RegisterCommand[[NewFormatDisk, "New Format Disk"]];
END.