DIRECTORY DiskFace USING [Command, DeterminationMode, DeviceHandle, DontCare, Label, PageCount, PageNumber, Status, Tries, Type]; Disk: CEDAR DEFINITIONS = BEGIN PageNumber: TYPE = DiskFace.PageNumber; PageCount: TYPE = DiskFace.PageCount; Add: PROC [p: PageNumber, n: PageCount] RETURNS [PageNumber] = INLINE { RETURN[ [p+n] ] }; Channel: TYPE = LONG POINTER TO ChannelObject; ChannelObject: TYPE; NextChannel: PROC [prev: Channel, wait: BOOL _ FALSE] RETURNS [Channel]; InspectDiskShape: PROC [channel: Channel, mode: DiskFace.DeterminationMode] RETURNS [BOOL]; SameDrive: PROC [a, b: Channel] RETURNS [BOOL]; GetDeviceFromChannel: PROC [channel: Channel] RETURNS [DeviceHandle: DiskFace.DeviceHandle]; Valid: PROC [channel: Channel] RETURNS [BOOL]; DriveAttributes: PROC [channel: Channel] RETURNS [type: DiskFace.Type, ordinal: INT, ready: BOOL, nPages: PageCount]; Command: TYPE = DiskFace.Command; Label: TYPE = DiskFace.Label; Tries: TYPE = DiskFace.Tries; defaultTries: Tries = 24; Request: TYPE = RECORD[ diskPage: PageNumber, -- disk page number of first page of transfer -- data: LONG POINTER, -- first data page incrementDataPtr: BOOL _ TRUE, -- if TRUE, increment data pointer after each successful page. command: Command, tries: Tries _ defaultTries, count: PageCount, -- number of pages -- seek: PageNumber _ [0] -- optional address for initiating a seek after the transfer ]; Status: TYPE = RECORD[ SELECT type: * FROM changed => NULL, unchanged => [status: DiskFace.Status], ENDCASE ]; ok: Status = [unchanged[goodCompletion]]; -- transfer completed successfully labelCheck: Status = [unchanged[labelVerifyError]]; -- label verify was requested and failed notReady: Status = [unchanged[notReady]]; -- drive was not ready at some point in transfer invalid: Status = [changed[]]; -- drive's ChangeCount changed; no IO performed DoIO: UNSAFE PROC [channel: Channel, label: LONG POINTER TO Label, request: LONG POINTER TO Request] RETURNS [status: Status, countDone: PageCount]; GetBootChainLink: PROC [channel: Channel, diskPage: PageNumber] RETURNS [DiskFace.DontCare]; GetPageNumber: PROC [channel: Channel, link: DiskFace.DontCare] RETURNS [PageNumber]; Pulses: TYPE = LONG CARDINAL; GetStatistics: PROC RETURNS [active, total: Pulses, reads, writes, readPages, writePages: INT]; END. †Disk.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Andrew Birrell July 8, 1983 1:25 pm Russ Atkinson (RRA) January 30, 1985 9:41:28 pm PST Doug Wyatt, February 27, 1985 8:47:10 am PST This is the lowest level of shared access to the disks. All drives and controllers are owned by DiskImpl, and must be accessed only through this interface. This interface allows interleaved access to drives, and allows multiple clients to access any particular drive. IO operations provided here are synchronous: the caller is suspended until the IO completes. However, multiple clients may initiate operations without waiting for another client's operation to complete. Lower levels are responsible for suitable device-dependent retries to handle soft errors; errors reported here are hard. Access to the drives is in terms of a "Channel", which corresponds to an occurence of a drive coming online. A channel remains usable for IO transfers until, and only until, the corresponding drive goes offline. Presenting an invalid channel to DoIO causes return code "invalid". may be negative Enumerates valid handles, in order of their drives coming online. Note that a handle may rapidly become invalid. If "prev" is NIL, returns the oldest online handle. If "wait" and "prev" is the most recent handle, waits until another handle is available, i.e. until some drive comes online. Ascertains and remembers the characteristics of the drive and currently mounted pack (if any). Returns FALSE if determination requires drive to be ready and it isn't, or if the shap can't be determined according to the mode. Tells whether the handles are for the same drive. Given a channel, return the device it is for Assuming the handle was once valid, tells whether it is still valid. nPages = 0 implies that the actual number isn't known. To get the actual number, call InspectDiskShape and persuade that procedure to return TRUE, then call DriveAttributes again. Other values of Status reflect hardware error or caller software bug. Translates a page number into the form suitable for use as a boot chain link in a label. "active" and "total" are measured in fine-grain clock pulses (PrincOpsUtils.GetClockPulses[]). If [a1, t1] and [a2, t2] are results of successive calls of this procedure, then the fraction of time that the disk channel has had requests on a controller queue between the calls is given by (a2-a1)/(t2-t1). ΚQ˜codešœ ™ Kšœ Οmœ1™˜]K˜K˜Kšœ‘˜'Kšœ‘<˜SKšœ˜—K˜šœžœžœ˜šžœ ž˜Kšœ žœ˜K˜'Kšž˜—Kšœ˜—K˜Kšœ*‘"˜LKšœ4‘(˜\Kšœ*‘0˜ZKšœ‘/˜NKšœE™EK˜Kš œžœžœžœžœžœžœžœžœ žœ(˜–K˜š œžœ*žœ˜]KšœX™X—K˜Kš  œžœ-žœ˜UK˜Kšœžœžœžœ˜K˜š  œžœžœ?žœ˜_Kšœ±™±—K˜Kšžœ˜—…— υ