DIRECTORY BasicTime USING [FromPupTime, GMT, OutOfRange], ConvertUnsafe USING [ToRope], Disk USING [Channel, Command, defaultTries, DoIO, GetBootChainLink, Label, PageCount, PageNumber, Request, Status], DiskFace USING [DeviceHandle, DontCare, GetDeviceAttributes, GetNextDevice, nullDeviceHandle], FormatDisk, PrincOps USING [zEXCH], Rope USING [ROPE], VM USING [AddressForPageNumber, Allocate, Free, Interval, Pin, Unpin]; FormatDiskDorado: MONITOR -- only one guy in here at a time! IMPORTS BasicTime, ConvertUnsafe, DiskFace, Disk, VM EXPORTS FormatDisk = BEGIN OPEN FormatDisk; BadPage: PUBLIC SIGNAL [page: Disk.PageNumber, correctable: BOOLEAN] = CODE; Error: PUBLIC ERROR [page: Disk.PageNumber, status: Disk.Status] = CODE; Sweep: PUBLIC ENTRY PROC [channel: Disk.Channel, operation: Operation, firstPage: Disk.PageNumber, pageCount: Disk.PageCount, label: LONG POINTER TO Disk.Label, data: LONG POINTER] = BEGIN Transfer[channel: channel, firstPage: firstPage, pageCount: pageCount, command: commandTable[operation], label: label, data: data, reportSoftErrors: TRUE]; END; commandTable: ARRAY Operation OF Disk.Command = [ format: [write, write, write], write: [verify, write, write], read: [verify, read, read], verify: [verify, verify, verify]]; MicrocodeInstallFailure: PUBLIC SIGNAL [why: FailureType] = CODE; InstallInitialMicrocode: PUBLIC ENTRY PROC [channel: Disk.Channel, getPage: PROC [ptr: LONG POINTER] RETURNS [ok: BOOLEAN]] = BEGIN vmInterval: VM.Interval _ VM.Allocate[count: 1]; pageBuffer: LONG POINTER _ VM.AddressForPageNumber[vmInterval.page]; thisPage: Disk.PageNumber _ hardUCodeStart; prevPage: Disk.PageNumber _ [hardUCodeStart-1]; VM.Pin[vmInterval]; BEGIN ENABLE UNWIND => {VM.Unpin[vmInterval]; VM.Free[vmInterval]}; DO label: Disk.Label _ initialMicrocodeLabel; ok: BOOLEAN; IF (ok _ getPage[pageBuffer]) THEN BEGIN ENABLE BadPage, Error => IF thisPage=hardUCodeStart THEN GOTO firstPageBad ELSE {thisPage _ [thisPage+1]; RETRY}; IF thisPage>=hardUCodeStart+hardUCodeSize THEN ERROR MicrocodeInstallFailure[microcodeTooBig]; label.dontCare _ LOOPHOLE[LONG[0]]; label.filePage _ thisPage-hardUCodeStart; Transfer[channel: channel, firstPage: thisPage, pageCount: 1, command: [verify, write, write], label: @label, data: pageBuffer]; label.filePage _ thisPage-hardUCodeStart; Transfer[channel: channel, firstPage: thisPage, pageCount: 1, command: [verify, verify, verify], label: @label, data: pageBuffer]; END; IF thisPage#Disk.PageNumber[prevPage+1] OR ~ok THEN BEGIN ENABLE BadPage, Error => GOTO flakeyPageFound; label.filePage _ prevPage-hardUCodeStart; Transfer[channel: channel, firstPage: prevPage, pageCount: 1, command: [verify, verify, read], label: @label, data: pageBuffer]; label.filePage _ prevPage-hardUCodeStart; label.dontCare _ IF ok THEN channel.GetBootChainLink[thisPage] ELSE eofLink; Transfer[channel: channel, firstPage: prevPage, pageCount: 1, command: [verify, write, write], label: @label, data: pageBuffer]; IF Disk.PageNumber[prevPage+1] < hardUCodeStart+hardUCodeSize THEN BEGIN label _ nullLabel; Transfer[channel: channel, firstPage: Disk.PageNumber[prevPage+1], pageCount: 1, command: [verify, write, write], label: @label, data: pageBuffer ! BadPage, Error => CONTINUE]; END; END; IF ~ok THEN EXIT; thisPage _ [(prevPage _ thisPage)+1]; REPEAT firstPageBad => ERROR MicrocodeInstallFailure[firstPageBad]; flakeyPageFound => ERROR MicrocodeInstallFailure[flakeyPageFound]; ENDLOOP; END; VM.Unpin[vmInterval]; VM.Free[vmInterval]; END; IdentifyInitialMicrocode: PUBLIC ENTRY PROC [channel: Disk.Channel] RETURNS [microcodeInstalled: BOOLEAN, time: BasicTime.GMT, name: Rope.ROPE] = BEGIN label: Disk.Label _ initialMicrocodeLabel; vmInterval: VM.Interval _ VM.Allocate[count: 1]; uCodeHeader: LONG POINTER TO MicrocodeHeader _ VM.AddressForPageNumber[vmInterval.page]; VM.Pin[vmInterval]; microcodeInstalled _ FALSE; BEGIN Transfer[channel: channel, firstPage: hardUCodeStart, pageCount: 1, command: [verify, verify, read], label: @label, data: uCodeHeader ! BadPage, Error => GOTO error]; IF uCodeHeader.name.length IN [1..uCodeHeader.name.maxlength] AND uCodeHeader.name.maxlength<=maxNameLength THEN BEGIN time _ BasicTime.FromPupTime[GMTFromBCPLTime[uCodeHeader.createDate] ! BasicTime.OutOfRange => GOTO error]; name _ ConvertUnsafe.ToRope[@uCodeHeader.name]; microcodeInstalled _ TRUE; END; EXITS error => NULL; END; VM.Unpin[vmInterval]; VM.Free[vmInterval]; END; hardUCodeFileID: ARRAY [0..5) OF CARDINAL = [0, 0, 0, 064732B, 064732B]; -- boot microcode knows this ID initialMicrocodeLabel: Disk.Label = [fileID: [abs[LOOPHOLE[hardUCodeFileID]]], filePage: 0, attributes: LOOPHOLE[0], dontCare: LOOPHOLE[LONG[0]]]; -- boot microcode knows this label nullFileID: ARRAY [0..5) OF CARDINAL = [0, 0, 0, 0, 0]; nullLabel: Disk.Label = [fileID: [abs[LOOPHOLE[nullFileID]]], filePage: 0, attributes: LOOPHOLE[0], dontCare: LOOPHOLE[LONG[0]]]; nullLink: DiskFace.DontCare = LOOPHOLE[LONG[0]]; eofLink: DiskFace.DontCare = LOOPHOLE[LONG[-1]]; MicrocodeHeader: TYPE = MACHINE DEPENDENT RECORD [ version (0): CARDINAL, mustBeZero (1): LONG CARDINAL, createDate (3): BCPLTime, name (5): StringBody]; BCPLTime: TYPE = RECORD [LONG CARDINAL]; GMTFromBCPLTime: PROCEDURE [BCPLTime] RETURNS [LONG CARDINAL] = MACHINE CODE {PrincOps.zEXCH}; maxNameLength: CARDINAL = 40; hardUCodeStart: PUBLIC Disk.PageNumber _ [4]; hardUCodeSize: PUBLIC Disk.PageCount _ 3*28-4; -- 3 cylinders overhead altoRegionJargon: PUBLIC Rope.ROPE _ "partitions"; altoRegionsMax: PUBLIC INT; -- computed by Start altoRegionsStart: PUBLIC Disk.PageNumber _ [0]; -- overlaps with initial microcode altoRegionsSize: PUBLIC Disk.PageCount _ 815*28; -- one surface of the disk altoRegionsBottomUp: PUBLIC BOOL _ FALSE; -- prefer highest partition (5 or 19) Start: PUBLIC PROC = BEGIN device: DiskFace.DeviceHandle = DiskFace.GetNextDevice[DiskFace.nullDeviceHandle]; cylinders: CARDINAL; IF device=DiskFace.nullDeviceHandle THEN ERROR; cylinders_ DiskFace.GetDeviceAttributes[device].cylinders; -- moving heads is ALWAYS 1 for a "system" disk (RD0), so the following call doesn't work altoRegionsMax_ cylinders/815; -- terrible kludge !!!!! END; Transfer: PROC [channel: Disk.Channel, firstPage: Disk.PageNumber, pageCount: Disk.PageCount, command: Disk.Command, label: LONG POINTER TO Disk.Label, data: LONG POINTER, reportSoftErrors: BOOLEAN _ FALSE] = BEGIN retrying: BOOLEAN _ FALSE; WHILE pageCount>0 DO request: Disk.Request _ [diskPage: firstPage, data: data, incrementDataPtr: FALSE, command: command, tries: IF reportSoftErrors AND ~retrying THEN 1 ELSE Disk.defaultTries, count: IF retrying THEN 1 ELSE pageCount]; countDone: Disk.PageCount; status: Disk.Status; [status: status, countDone: countDone] _ channel.DoIO[label: label, request: @request]; WITH s: status SELECT FROM changed => ERROR Error[firstPage, status]; unchanged => SELECT s.status FROM goodCompletion => IF retrying THEN {retrying _ FALSE; SIGNAL BadPage[firstPage, TRUE]}; notReady, recalibrateError, seekTimeout, memoryError, memoryFault, clientError, operationReset => ERROR Error[firstPage, status]; ENDCASE => BEGIN IF ~retrying THEN retrying _ TRUE ELSE BEGIN retrying _ FALSE; SIGNAL BadPage[firstPage, FALSE]; countDone _ countDone+1; -- skip over the bad page label.filePage _ label.filePage+1; END; END; ENDCASE => ERROR; pageCount _ pageCount-countDone; firstPage _ [firstPage+countDone]; ENDLOOP; END; END. FormatDiskDorado.mesa Last Edited by: Andrew Birrell December 6, 1983 1:15 pm Last Edited by: Taft, January 31, 1984 11:54:45 am PST Last Edited by: Willie-Sue, February 24, 1984 6:15:42 pm PST Disk formatting and checking Initial microcode Write different label at page after EOF or break in run so as to assure that a label check error will occur during reading and the bootChainLink will be noticed This returns what the BasicTime interface calls a "Pup time". Reserved disk areas Initialization altoRegionsMax _ DiskFace.GetDeviceAttributes[device].movingHeads; Private ! BadPage, Error; The idea here is as follows. If reportSoftErrors=FALSE then we just make a normal call and let the disk channel (and head) do all the error recovery. But if reportSoftErrors=TRUE, we initially request the disk channel (and head) to perform only one try so that we get to find out the exact address of any error. When an error occurs, we then retry just that one page with full error recovery enabled in order to discover whether the error is correctable. ΚΓ– "cedar" style˜headšœ™Ibodyšœ8™8Lšœ6™6J™<code2šΟk ˜ Mšœ œ ˜/Mšœœ ˜Mšœœi˜sMšœ œP˜^M˜ Mšœ œ ˜Mšœœœ˜Mšœœ>˜F——šœœΟc"˜