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
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;
Disk formatting and checking
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]];
Initial microcode
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
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
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;
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] =
This returns what the BasicTime interface calls a "Pup time".
MACHINE CODE {PrincOps.zEXCH};
maxNameLength: CARDINAL = 40;
Reserved disk areas
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)
Initialization
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 ← DiskFace.GetDeviceAttributes[device].movingHeads;
altoRegionsMax← cylinders/815; -- terrible kludge !!!!!
END;