DIRECTORY Ascii, Basics USING [BytePair], Disk USING [Channel, DoIO, DriveAttributes, Label, PageCount, PageNumber, Request, Status], DiskFace USING [DeviceHandle, DiskAddress], ExtraIagoOps USING [GetAddress], ExtraIagoUtils, File USING [Error, FindVolumeFromID, FindVolumeFromName, FP, Handle, Info, nullVolumeID, Open, PageCount, PageNumber, Read, Volume, VolumeFile, VolumeID, wordsPerPage], FileInternal USING [Handle, FindRun, TranslateLogicalRun], FS USING [Error], FSBackdoor USING [Version], FSFileOps USING [GetNameBodyAndVersion], IagoOps USING [Confirm, FileError], IO, PhysicalVolume USING [GetSubVolumes, Physical, SubVolumeDetailsObject, SubVolumes], Rope, VM USING [AddressForPageNumber, Allocate, Free, Interval, nullInterval, PagesForWords, SwapIn, Unpin], VolumeFormat USING [Attributes, LogicalPage, LogicalRun, RelID]; ExtraIagoUtilsImpl: CEDAR PROGRAM IMPORTS Basics, Disk, ExtraIagoOps, File, FileInternal, FS, FSFileOps, IagoOps, IO, PhysicalVolume, VM EXPORTS ExtraIagoUtils = BEGIN OPEN IO, ExtraIagoUtils; STREAM: TYPE = IO.STREAM; ROPE: TYPE = Rope.ROPE; StatusToRope: PUBLIC PROC[status: Disk.Status] RETURNS[r: ROPE, wasOK: BOOL] = { wasOK _ FALSE; WITH s: status SELECT FROM changed => r _ "drive's ChangeCount changed; no IO performed"; unchanged => SELECT s.status FROM inProgress => r _ "inProgress"; goodCompletion => {r _ "good Completion"; wasOK _ TRUE}; notReady => r _ "notReady"; recalibrateError => r _ "recalibrateError"; seekTimeout => r _ "seekTimeout"; headerCRCError => r _ "headerCRCError"; labelCRCError => r _ "labelCRCError"; dataCRCError => r _ "dataCRCError"; headerNotFound => r _ "headerNotFound"; labelVerifyError => r _ "labelVerifyError"; dataVerifyError => r _ "dataVerifyError"; overrunError => r _ "overrunError"; writeFault => r _ "writeFault"; memoryError => r _ "memoryError"; memoryFault => r _ "memoryFault"; clientError => r _ "clientError"; operationReset => r _ "operationReset"; otherError => r _ "otherError"; ENDCASE; ENDCASE; }; ReportStatus: PUBLIC PROC[out: STREAM, status: Disk.Status, dontReportOK: BOOL _ TRUE] = { r: ROPE; wasOK: BOOL; [r, wasOK]_ StatusToRope[status]; IF dontReportOK AND wasOK THEN RETURN; out.PutF["\n\n **********Status reported as: %g **********", rope[r]]; }; OKStatusForWrite: PUBLIC PROC[status: Disk.Status, in, out: STREAM] RETURNS[ok: BOOL] = { WITH s: status SELECT FROM changed => RETURN[FALSE]; unchanged => SELECT s.status FROM labelCRCError => NULL; goodCompletion, dataCRCError, dataVerifyError => RETURN[TRUE]; inProgress, notReady, recalibrateError, seekTimeout, headerCRCError, headerNotFound, labelVerifyError, overrunError, writeFault, memoryError, memoryFault, clientError, operationReset, otherError => RETURN[FALSE]; ENDCASE; ENDCASE; out.PutRope["\n LabelCRCError reported; attempt the write anyway?"]; ok _ IagoOps.Confirm[in, out]; }; ChannelToDeviceHandle: PUBLIC PROC[c: Disk.Channel] RETURNS[d: DiskFace.DeviceHandle] = { ordinal: CARDINAL _ Disk.DriveAttributes[c].ordinal; d _ LOOPHOLE[ordinal, DiskFace.DeviceHandle]; }; VolumeFileToRope: PUBLIC PROC[which: File.VolumeFile] RETURNS[ROPE] = { RETURN[SELECT which FROM checkpoint => "Checkpoint", microcode => "Microcode", germ => "Germ", bootFile => "BootFile", debugger => "Debugger", debuggee => "Debuggee", VM => "VM", VAM => "VAM", client => "FS-root", alpine => "Alpine-root", ENDCASE => "Other-root"]; }; AttributesToRope: PUBLIC PROC[attributes: VolumeFormat.Attributes] RETURNS[ROPE] = { RETURN[SELECT attributes FROM physicalRoot => "PhysicalRoot", badPageList => "BadPageList", badPage => "BadPage", subVolumeMarker => "SubVolumeMarker", logicalRoot => "LogicalRoot", freePage => "FreePage", header => "HeaderPage", data => "DataPage", lastCedar => "LastCedarAttribute", ENDCASE => "UnknownType"]; }; DescribeOnePage: PUBLIC PROC[ logicalPage: VolumeFormat.LogicalPage, vol: File.Volume, in, out: STREAM] = TRUSTED { pageSpace: VM.Interval _ VM.nullInterval; { ENABLE UNWIND => FreeSpace[pageSpace]; initLabel: Disk.Label; data: LONG POINTER; label: Disk.Label _ initLabel; request: Disk.Request; status: Disk.Status; attr: VolumeFormat.Attributes; realPage: Disk.PageNumber; val: WORD; run: VolumeFormat.LogicalRun; channel: Disk.Channel; [pageSpace, data]_ GetSpace[1]; run _ [[logicalPage], 1]; [channel, realPage]_ FileInternal.TranslateLogicalRun[run, vol ! File.Error => { out.PutF["\nFile.Error (%g) during TranslateLogicalRun of logical page %g\n", IO.rope[IagoOps.FileError[why]], IO.int[logicalPage]]; GOTO doQuit; }; ]; BEGIN ENABLE File.Error => { out.PutF["\n File.Error (%g) reading page %g (physical page %g)\n", rope[IagoOps.FileError[why]], int[logicalPage], int[realPage]]; GOTO keepGoing; }; request _ [diskPage: [realPage], data: data, incrementDataPtr: FALSE, command: [verify, read, read], count: 1]; [status, ]_ Disk.DoIO[channel: channel, label: @label, request: @request]; attr _ LOOPHOLE[label.attributes]; IF attr = freePage THEN { out.PutF["\n Page %g (physical page %g) is free, with status %g", int[logicalPage], int[realPage], rope[StatusToRope[status].r]]; RETURN }; IF attr = data OR attr = header THEN { fp: File.FP _ LOOPHOLE[label.fileID.relID]; handle: File.Handle _ File.Open[vol, fp]; nameBody: Rope.Text; version: FSBackdoor.Version; [nameBody, version]_ FSFileOps.GetNameBodyAndVersion[f: handle ! FS.Error => { out.PutF["\n Page %g (physical page %g),\n\t***FS error: \"%g\"\n", int[logicalPage], int[realPage], rope[error.explanation] ]; out.PutF["\tFile.FP is: [id: %g (%bB), da: %g (%bB)]\n", IO.card[LOOPHOLE[fp.id]], IO.card[LOOPHOLE[fp.id]], IO.card[LOOPHOLE[fp.da]], IO.card[LOOPHOLE[fp.da]]]; out.PutF["\tIs %g page %g of some file", IF attr = data THEN rope["data"] ELSE rope["header"], IO.int[label.filePage] ]; CONTINUE}]; IF nameBody # NIL THEN { out.PutF["\n Page %g (physical page %g), with status %g\n", int[logicalPage], int[realPage], rope[StatusToRope[status].r]]; out.PutF[" *** is %g page %g of file %g, version %g", IF attr = data THEN rope["data"] ELSE rope["header"], int[label.filePage], rope[nameBody], int[version]]; }; RETURN; }; val _ LOOPHOLE[label.attributes]; out.PutF["\nOther type of page: logical: %g (physical %g), attributes: %g (%06b)\n", IO.int[logicalPage], int[realPage], IO.rope[AttributesToRope[attr]], IO.card[val]]; EXITS keepGoing => NULL; END; FreeSpace[pageSpace]; EXITS doQuit => FreeSpace[pageSpace]; }; }; CheckPages: PUBLIC PROC[handle: File.Handle, name: ROPE, out: STREAM] = { ENABLE FS.Error => { out.PutRope[" ... "]; IF error.code = $invalidPropertyPage THEN out.PutRope["not an FS file"] ELSE out.PutRope[error.explanation]; CONTINUE }; size: File.PageCount _ File.Info[handle].size; didStop: BOOL _ FALSE; diskPage: Disk.PageNumber; channel: Disk.Channel; pageSpace: VM.Interval _ VM.nullInterval; numPages: INT = 25; { ENABLE UNWIND => FreeSpace[pageSpace]; data: LONG POINTER; [pageSpace, data]_ GetSpace[numPages]; out.PutF["\nReading pages from %g file (%g pages)\n", IO.rope[name], IO.int[size]]; TRUSTED { i: File.PageCount _ 0; WHILE i < size DO IF i # 0 THEN IF i MOD 100 = 0 THEN IF i MOD 1000 = 0 THEN out.PutF["(%g)", IO.int[i]] ELSE out.PutChar['~]; File.Read[handle, [i], numPages, data ! File.Error => {IF why # unknownPage THEN didStop _ TRUE; EXIT}]; i _ i + numPages; ENDLOOP; IF didStop THEN { ff: FileInternal.Handle; badPage: INT _ -1; FOR j: File.PageCount IN [i..i+numPages) DO File.Read[handle, [j], 1, data ! File.Error => { out.PutF["\nFile error reading page %g\n", IO.int[j]]; out.PutRope[" ... "]; out.PutRope[IagoOps.FileError[why]]; badPage _ j; EXIT}]; ENDLOOP; ff _ LOOPHOLE[handle]; [diskPage, , channel]_ FileInternal.FindRun[[badPage], 1, ff.runTable]; out.PutChar['\n]; PrintPageAndDiskAddr[diskPage, ChannelToDeviceHandle[channel], out]; ReadAndReport[NIL, out, diskPage, 1, channel, none]; }; }; FreeSpace[pageSpace]; }; }; LogicalToPhysicalPage: PUBLIC PROC[logicalPage: VolumeFormat.LogicalPage, volName: ROPE] RETURNS[page: Disk.PageNumber] = { vol: File.Volume = File.FindVolumeFromName[volName]; IF vol = NIL THEN RETURN[[-1]]; [ , page] _ FileInternal.TranslateLogicalRun[[logicalPage, 1], vol]; }; PhysicalToLogicalPage: PUBLIC PROC[p: PhysicalVolume.Physical, page: Disk.PageNumber] RETURNS[logicalPage: VolumeFormat.LogicalPage, vol: File.Volume] = { sv: PhysicalVolume.SubVolumes = PhysicalVolume.GetSubVolumes[p]; FOR i: CARDINAL IN [0..sv.count) DO addr: INT = sv[i].address; IF page >= addr AND page < addr+sv[i].size THEN { logicalPage _ [page-addr]; vol _ File.FindVolumeFromID[sv[i].id]; RETURN }; ENDLOOP; RETURN[[0], File.FindVolumeFromID[File.nullVolumeID]]; }; PrintPageAndDiskAddr: PUBLIC PROC[ page: Disk.PageNumber, d: DiskFace.DeviceHandle, out: STREAM] = { addr: DiskFace.DiskAddress _ ExtraIagoOps.GetAddress[d, page]; IF addr.cylinder = LAST[CARDINAL] THEN { out.PutF[" Drive %g doesn't exist", int[LOOPHOLE[d, INTEGER]]]; RETURN}; out.PutF[" Page: %g (%bB),", int[page], card[page]]; out.PutF[" [cyl: %g (%bB), head: %g, sector: %g]", card[addr.cylinder], card[addr.cylinder], card[addr.head], card[addr.sector]]; }; ReadAndReport: PUBLIC PROC[in, out: STREAM, first, count: INT, d: Disk.Channel, howToShowData: HowToShowData] = TRUSTED { pageSpace: VM.Interval _ VM.nullInterval; { ENABLE UNWIND => FreeSpace[pageSpace]; origin: Disk.PageNumber; initLabel: Disk.Label; data: LONG POINTER; [pageSpace, data]_ GetSpace[1]; FOR i: INT IN [0 .. count) DO label: Disk.Label _ initLabel; val: WORD; request: Disk.Request; status: Disk.Status; countDone: INT; attr: VolumeFormat.Attributes; origin _ [first + i]; request _ [diskPage: origin, data: data, incrementDataPtr: FALSE, command: [verify, read, read], count: 1]; [status, countDone]_ Disk.DoIO[channel: d, label: @label, request: @request]; ReportStatus[out, status]; out.PutF["\n\n *******Label for disk page %g is:\nFileID: ", int[first+i]]; FOR i: INT IN [0..5) DO val _ LOOPHOLE[@label + i, LONG POINTER TO CARDINAL]^; out.PutF[" %06b", IO.card[val]]; ENDLOOP; attr _ LOOPHOLE[label.attributes]; IF attr = data OR attr = header THEN { relID: VolumeFormat.RelID _ LOOPHOLE[label.fileID.relID]; da: VolumeFormat.LogicalPage _ LOOPHOLE[relID.da]; out.PutF["\n Logical Address of Header: %g", int[da]]; }; val _ LOOPHOLE[label.attributes]; out.PutF["\nfilePage: %g, attributes: %g (%06b)\n", IO.int[label.filePage], IO.rope[AttributesToRope[attr]], IO.card[val]]; IF howToShowData # none THEN { ptr: LONG POINTER TO CARDINAL _ LOOPHOLE[data]; valsPerLine: INT = 8; -- so its easy to change numLines: INT _ 256/valsPerLine; out.PutF["\n *****Data for that page is:\n"]; IF howToShowData = all THEN { FOR i: INT IN [0..numLines) DO out.PutF["%03b/ ", IO.int[i*valsPerLine]]; FOR j: INT IN [0..valsPerLine) DO val _ (ptr+ j)^; out.PutF[" %06b", IO.card[val]]; ENDLOOP; out.PutRope[" "]; -- some white space FOR j: INT IN [0..valsPerLine) DO bytes: Basics.BytePair; val _ (ptr+ j)^; bytes _ LOOPHOLE[val, Basics.BytePair]; out.PutChar[CheckChar[LOOPHOLE[bytes.high, CHAR]]]; out.PutChar[CheckChar[LOOPHOLE[bytes.low, CHAR]]]; ENDLOOP; out.PutChar['\n]; ptr _ ptr + valsPerLine; ENDLOOP; } ELSE FOR i: INT IN [0 .. 256) DO bytes: Basics.BytePair; val _ (ptr+ i)^; bytes _ LOOPHOLE[val, Basics.BytePair]; out.PutChar[CheckChar[LOOPHOLE[bytes.high, CHAR]]]; out.PutChar[CheckChar[LOOPHOLE[bytes.low, CHAR]]]; ENDLOOP; }; ENDLOOP; FreeSpace[pageSpace]; }; }; CheckChar: PUBLIC PROC[ch: CHAR] RETURNS[CHAR] = { OPEN Ascii; xx: CARDINAL [0 .. 377B]; IF ch = NUL THEN RETURN[' ]; IF ch IN [ControlA .. ControlZ] THEN RETURN['*]; IF (xx _ LOOPHOLE[ch]) IN [200B .. 377B] THEN RETURN['!]; RETURN[ch] }; GetSpace: PROC[num: INT] RETURNS[space: VM.Interval, data: LONG POINTER] = TRUSTED { space _ VM.Allocate[VM.PagesForWords[num*File.wordsPerPage]]; data _ VM.AddressForPageNumber[space.page]; VM.SwapIn[interval: space, kill: TRUE, pin: TRUE]; }; FreeSpace: PROC[space: VM.Interval] = TRUSTED { IF space = VM.nullInterval THEN RETURN; VM.Unpin[space]; VM.Free[space]; space _ VM.nullInterval; }; END. BExtraIagoUtilsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Willie-Sue, May 21, 1986 4:13:07 pm PDT Russ Atkinson (RRA) March 11, 1985 8:39:34 pm PST * * * * * * * * * * * * * * * * * Utility Procedures * * * * * * * * * * * * * * * * * * * * * * * commands implementation * * * * * * * * Ê­˜codešœ™Kšœ Ïmœ1™˜>šœ žœ ž˜!Kšœ˜Kšœ2žœ˜8Kšœ˜Kšœ+˜+Kšœ!˜!Kšœ'˜'Kšœ%˜%Kšœ#˜#Kšœ'˜'Kšœ+˜+Kšœ)˜)Kšœ#˜#Kšœ˜Kšœ!˜!Kšœ!˜!Kšœ!˜!Kšœ'˜'Kšœ˜—Kšžœ˜—Kšžœ˜K˜—K˜š Ÿ œžœžœžœ%žœžœ˜ZKšœžœ˜Kšœžœ˜ Kšœ!˜!Kšžœžœžœžœ˜&K˜FKšœ˜—K˜š Ÿœžœžœžœžœžœ˜Yšžœ žœž˜Kšœ žœžœ˜šœ žœ ž˜!Kšœžœ˜Kšœ1žœžœ˜>K˜KšœD˜DKšœH˜HKšœ8žœžœ˜F—Kšžœ˜—Kšžœ˜K˜DK˜Kšœ˜—K˜šŸœžœžœ˜3Kšœžœ˜&Kšœ žœ#˜4Kšœžœ!˜-Kšœ˜—K˜š Ÿœžœžœžœžœ˜Gšžœžœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ ˜ Kšžœ ˜ Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜—K˜š Ÿœžœžœ&žœžœ˜Tšžœžœ ž˜Kšœ˜Kšœ˜Kšœ˜Kšœ%˜%Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"Kšžœ˜—Kšœ˜—K˜K˜Kšœ7™7K˜šŸœžœžœ˜KšœDžœžœ˜WKšœ žœ žœ˜)šœžœžœ˜(K˜Kšœžœžœ˜K˜K˜Kšœ˜K˜Kšœ˜Kšœžœ˜ Kšœ˜Kšœ˜K˜Kšœ˜šœP˜PšœM˜MKšžœžœ˜6Kšžœ˜ K˜—Kšœ˜—šžœžœ˜˜CKšœ?˜?—Kšžœ ˜K˜—šœ?žœ˜EKšœ)˜)—KšœJ˜JKšœžœ˜"šžœžœ˜˜AKšœ?˜?Kšž˜—K˜—šžœ žœžœ˜&Kšœ žœžœ˜+Kšœ)˜)Kšœ˜Kšœ˜šœAžœ ˜NšœC˜CKšœ;˜;—˜8Kšžœžœ žœžœ ˜3Kšžœžœ žœžœ ˜4—šœ(˜(Kšžœ žœžœ˜5Kšžœ˜—Kšžœ˜ —šžœ žœžœ˜˜;Kšœ?˜?—šœ:˜:Kšžœ žœžœ˜5Kšœ˜Kšœ˜Kšœ˜—K˜—Kšžœ˜K˜—Kšœžœ˜!šœT˜TKšžœ"žœžœ ˜S—šž˜Kšœ žœ˜—Kšžœ˜Kšœ˜šž˜Kšœ˜—Kšœ˜—K˜—K˜š Ÿ œžœžœžœžœ˜Išžœžœ ˜K˜šžœ"˜$Kšžœ˜"Kšžœ ˜$—Kšž˜Kšœ˜—Kšœ.˜.Kšœ žœžœ˜Kšœ˜Kšœ˜Kšœ žœ žœ˜)Kšœ žœ˜šœ˜Kšžœžœ˜&Kšœžœžœ˜K˜&Kšœ6žœ žœ ˜Sšžœ˜ Kšœ˜šžœ ž˜š žœžœžœžœ ž˜#Kš žœžœ žœžœ žœ˜I—šœ5˜5Kš œžœžœ žœžœ˜2—K˜Kšžœ˜—šžœ žœ˜Kšœ˜Kšœ žœ˜šžœžœž˜+šœ˜šœ˜Kšœ+žœ ˜6Kšœ:˜:Kšœ ˜ Kšžœ˜——Kšžœ˜—Kšœžœ ˜KšœG˜GK˜K˜DKšœžœ#˜4K˜—Kšœ˜—K˜Kšœ˜—Kšœ˜—K˜K˜šŸœžœžœ1žœ˜Xšžœ˜"Kšœ4˜4Kšžœžœžœžœ˜KšœD˜DK˜——K˜šŸœžœžœ3˜UKšžœ=˜DKšœ@˜@šžœžœžœž˜#Kšœžœ˜šžœžœžœ˜1Kšœ˜Kšœ&˜&Kšž˜K˜—Kšžœ˜—Kšžœ0˜6Kšœ˜—K˜šŸœžœžœ˜"Kšœ7žœ˜BKšœ>˜>šžœžœžœž˜&Kšœ*žœžœžœ˜J—Kšœ6˜6šœ2˜2K˜N—Kšœ˜—K˜š Ÿ œžœžœ žœžœ3žœ˜yKšœ žœ žœ˜)šœ˜Kšžœžœ˜&Kšœ˜K˜Kšœžœžœ˜K˜K˜šžœžœžœž˜K˜Kšœžœ˜ K˜Kšœ˜Kšœ žœ˜K˜Kšœ˜šœ;žœ˜AKšœ)˜)—KšœM˜MKšœ˜KšœK˜Kšžœžœžœž˜Kš œžœ žœžœžœžœ˜6Kšœžœ ˜ Kšžœ˜—K˜Kšœžœ˜"šžœ žœžœ˜&Kšœžœ˜9Kšœžœ ˜2K˜;K˜—Kšœžœ˜!šœ3˜3Kšžœžœžœ ˜G—šžœžœ˜Kš œžœžœžœžœžœ˜/Kšœ žœÏc˜/Kšœ žœ˜ Kšœ-˜-šžœ˜šžœ˜šžœžœžœž˜Kšœžœ˜*šžœžœžœž˜!Kšœ#žœ ˜1Kšžœ˜—Kšœ ˜(šžœžœžœž˜!Kšœ˜Kšœ˜Kšœžœ˜'Kšœžœ žœ˜3Kšœžœ žœ˜2Kšžœ˜—Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜—šž˜šžœžœžœ ž˜Kšœ˜Kšœ˜Kšœžœ˜'Kšœžœ žœ˜3Kšœžœ žœ˜2Kšžœ˜———Kšœ˜—Kšžœ˜—K˜Kšœ˜—Kšœ˜—K˜š Ÿ œžœžœžœžœžœ˜2Kšžœ˜ Kšœžœ ˜Kšžœžœžœžœ˜Kšžœžœžœžœ˜0Kš žœžœžœžœžœ˜9Kšžœ˜ Kšœ˜—K˜šŸœžœžœžœžœžœžœžœ˜TKšœžœ žœ'˜=Kšœžœ"˜+Kšžœžœžœ˜2Kšœ˜—K˜šŸ œžœžœ žœ˜/Kšžœ žœžœžœ˜'Kšžœ˜Kšžœ ˜Kšœžœ˜Kšœ˜—K˜Kšžœ˜—…—/>ÿ