DiskFace.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell May 3, 1983 1:41 pm
Russ Atkinson (RRA) January 29, 1985 0:45:13 am PST
Doug Wyatt, February 26, 1985 5:21:21 pm PST
Controllers
ControllerHandle: TYPE[1];
nullControllerHandle:
READONLY ControllerHandle;
GetNextController:
PROC [ControllerHandle]
RETURNS [ControllerHandle];
GetControllerAttributes:
PROC [ControllerHandle]
RETURNS [globalStateSize:
CARDINAL];
InitializeController:
PROC [controller: ControllerHandle,
globalState:
LONG
POINTER, mask:
WORD];
"globalState" is in first 64K of VM. "mask" indicates naked notify channels
InitializeCleanup:
PROC [ControllerHandle];
Reset:
PROC [ControllerHandle];
Restore the controller (as nearly as possible) to the state existing immediately after InitializeController. Clients may see operations associated with a reset controller coming back as operationReset.
Devices
nullDeviceHandle:
READONLY DeviceHandle;
GetNextDevice:
PROC [DeviceHandle]
RETURNS[DeviceHandle];
Type:
TYPE =
MACHINE
DEPENDENT {
null(0),
sa800(1),
sa1000(2),
sa4000(3),
cdc9730(4),
ethernet(5),
(LAST[CARDINAL])
};
GetDeviceType:
PROC [DeviceHandle]
RETURNS [Type];
DeterminationMode:
TYPE = { quickReadOnly, longReadOnly, writeEnabled };
DetermineDiskShape:
PROC [device: DeviceHandle, operation: OperationPtr,
mode: DeterminationMode, buffer:
LONG
POINTER ←
NIL]
RETURNS [nowKnown:
BOOL];
unknownAttribute:
CARDINAL =
LAST[
CARDINAL];
Returned by GetDeviceAttributes or GetTrueDeviceAttributes for an unknown attribute.
GetDeviceAttributes:
PROC [DeviceHandle]
RETURNS [cylinders, movingHeads, fixedHeads, sectorsPerTrack:
CARDINAL];
Before DetermineDiskShape has returned TRUE, some or all attributes may be unknownAttribute.
GetTrueDeviceAttributes:
PROC [DeviceHandle]
RETURNS [cylinders, movingHeads, fixedHeads, sectorsPerTrack:
CARDINAL];
Returns true physical device characteristics, not those as seen by Cedar. This information is not of interest to any high level software, but only to low level software such as diagnostics. (Thus, for a T80 disk as the system disk on a Dorado, it will have 815 cylinders, 5 moving heads, 0 fixed heads, and 28 sectors. GetDeviceAttributes would report the Cedar "virtual" physical attributes as the same except there would be 4075 cylinders (815*5) and only 1 moving head.) Before DetermineDiskShape has returned TRUE, some or all attributes may be unknownAttribute.
Tries:
TYPE = (0..400B];
An indication of how hard the head should work when retrying a failed operation. Increasing values of "Tries" indicates that extra effort should be expended in trtrying the operation. Retrying includes device specific error recovery (ECC, recalibrates, ...).
SuggestedTries:
PROC [DeviceHandle]
RETURNS [Tries];
Value of "Tries" to cause the default error recovery algorithm for the device.
Recalibrate:
PROC [DeviceHandle];
Forces a recalibrate at the beginning of the next operation. The Head may also voluntarily supply recalibrates as part of its retry logic.
Operations
DiskAddress:
TYPE =
MACHINE
DEPENDENT
RECORD[
cylinder(0): CARDINAL,
head(1:0..7): [0..256),
sector(1:8..15): [0..256)
];
Op:
TYPE =
MACHINE
DEPENDENT { noOp, read, write, verify };
Command:
TYPE =
MACHINE
DEPENDENT
RECORD[header, label, data: Op];
Label:
TYPE =
MACHINE
DEPENDENT
RECORD[
fileID(0): FileID,
filePage(5): INT,
attributes(7): Attributes,
dontCare(8): DontCare
];
The fields "fileID", "attributes" and "dontCare" have opaque types and are not interpreted by the Head, only by the higher level software. When verifying a label, all fields except "dontCare" must match. When the head/microcode moves to next page of a run, label.filePage is incremented.
FileID:
TYPE =
MACHINE
DEPENDENT
RECORD[
id(0):
SELECT
OVERLAID *
FROM
rel => [relID(0): RelID, fill4(4): CARDINAL ← 0],
abs => [absID(0): AbsID],
ENDCASE
];
RelID: TYPE[4];
DontCare:
TYPE[2];
Ignored in label verification.
Typically used for boot chain links, in which case it's actually a DiskAddress.
DeviceOpStatus:
TYPE[2];
device-dependent status information about an operation; used only inside the head.
operationSize:
READONLY
CARDINAL;
The storage pointed to by an OperationPtr should be at least operationSize words long (i.e. must be longer than SIZE[Operation]), to allow extra words for use by the Head.
OperationPtr:
TYPE =
LONG
POINTER
TO Operation;
Operation:
TYPE =
MACHINE
DEPENDENT
RECORD[
-- 16-word aligned and in first 64K of VM
clientHeader(0): DiskAddress, -- address of first sector of request
labelPtr(2): LONG POINTER TO Label, -- first label of request. Must not be NIL.
dataPtr(4): LONG POINTER, -- first (VM page aligned) data address of operation
incrementDataPtr(6:0..0): BOOL, -- increment dataPtr after each successful data r/w/v
unused(6:1..1): [0..1] ← NULL,
command(6:2..7): Command,
tries(6:8..15): Tries, -- indication of how hard to retry after errors
pageCount(7): CARDINAL, -- number of (remaining) sectors for this operation
deviceStatus(10B): DeviceOpStatus ← NULL, -- used by the Head
diskHeader(12B): DiskAddress ← NULL, -- if command.header=read, places result here
device(14B): DeviceHandle
];
Initiate:
PROC [OperationPtr];
Note a new disk request and arrange for its eventual execution. Note that the client has no control over what controller services the operation. Each controller will notify its naked notify channels when an operation serviced by that controller completes.
Status:
TYPE = {
inProgress,
goodCompletion,
notReady,
recalibrateError,
seekTimeout,
headerCRCError,
labelCRCError,
dataCRCError,
headerNotFound,
labelVerifyError,
dataVerifyError,
overrunError,
writeFault,
memoryError,
memoryFault,
clientError,
operationReset,
otherError
};
Poll:
PROC [ControllerHandle]
RETURNS [status: Status, op: OperationPtr, retriedCount:
CARDINAL];
Poll a particular controller. Polling an idle controller will result in the result [clientError, NIL]. Operations will not necessarily come back in the order they were submitted, and an error in a particular operation does not abort the rest.