DIRECTORY Basics, BasicTime, Disk, DiskExtras, DiskFace, DiskFaceExtras, FileExtra, FormatDisk, FSBackdoor, IagoOps, PhysicalVolume, VM, ExtraIagoOps, File, 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: BOOL _ FALSE]; 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 => { 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 { [quotient: temp, remainder: sector] _ Basics.LongDivMod[ num: page, den: physicalDiskSector ]; [quotient: track, remainder: cylinder] _ Basics.DIVMOD[ num: temp, den: physicalDiskCyl]; } ELSE { [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: BOOL _ TRUE; 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; { 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; }; 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. ŽExtraIagoImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by: Willie-Sue, May 2, 1985 1:42:42 pm PDT IagoOps USING [RegisterCommand], [page: Disk.PageNumber, correctable: BOOL] Abnormal cyl/track/sect numbering on a Dorado for Alto compatability Normal cyl/track/sect numbering Record any bad pages * * * * * * * start code ** register commands with Iago Κ ˜šœ™Icodešœ Οmœ1™˜>JšœK˜KJ˜JšœC˜CJ˜Jšœ<˜˜>JšœF˜FJšœF˜FJšœ:˜:J˜Jšœ<˜<—J™Jšžœ˜—…—" -