-- File: DiskIODefs.mesa -- Last edited by Levin: 24-Nov-80 13:30:15 DIRECTORY AltoDefs USING [MaxFilePage, PageNumber], AltoFileDefs USING [DISK, eofDA, fillinDA, SN, vDA, vDC]; DiskIODefs: DEFINITIONS = BEGIN -- A brief discourse on the design and intended use of this interface: -- This interface is intended to be a functional replacement for the DiskDefs -- interface of Alto/Mesa, which in turn is a version of the low-level parts of -- the original BCPL BFS package. The major difference is that DiskIODefs, as -- distinct from Mesa's DiskDefs, offers asynchronous disk transfers. The package -- is capable of queuing multi-page transfer requests at once, and can take -- advantage of the chaining tricks used in the BFS. However, this interface does -- not force its clients to understand how disk control blocks are constructed and -- manipulated. Thus, the BFS concepts of 'CBZone' and a 'CB' are not needed here. -- All disk transfer requests that this interface supports are expressed in a -- 'DiskRequest', defined below. The implicit assumptions in the design of this -- structure are the following (it may be helpful to refer to the definition of -- 'DiskRequest' while reading this list): -- 1) Each DiskRequest transfers a sequence of consecutive pages within a single -- file. (Exception: in the case of operations used for file extension, some -- pages may not (yet) be part of the file.) -- 2) A file is uniquely identified by its file ID (FID), and a page within the -- file is uniquely identified by a page number. These are the standard -- conventions of the Alto file system. -- 3) Pages are transfered strictly in the order that they appear in the 'xfers' -- array, that is, in order of increasing page number within the file. -- 4) A CompletionProcedure will be invoked as each page transfer completes. (For -- an exception, see item 6, below.) If the transfer produces an error, the -- transfer will be retried an appropriate number of times. Thus, the -- CompletionProcedure will be invoked only when the transfer has either completed -- successfully or when a permanent error has occurred. (However, a permanent -- error causes all subsequently queued transfers to be inhibited. These -- inhibited requests will cause the completion procedure to be invoked with -- status = neverStarted.) -- 5) A VerboseCompletionProcedure should be used only when the requestor wishes -- to obtain information stored in the header or label of the disk page. Calling -- a VerboseCompletionProcedure requires substantially more computation than -- calling a NormalCompletionProcedure. -- 6) 'xfers[i]' identifies a page to be transferred. These pages are implicitly -- sequential in the file, the first being 'firstPage+pagesToSkip'. Each -- XferSpec contains a pointer to the buffer for the page, the associated disk -- address, and an identifier supplied by the caller which will identify the page -- to the CompletionProcedure. If the disk address is 'fillInvDA', the disk -- driver will attempt to deduce the address from the label of the previous page -- in the file. This implies that if xfers[0].vDA is 'fillInvDA', the disk -- driver must read pages from the disk beginning at 'firstPage' and continuing -- for 'pagesToSkip-1' pages in order to determine the disk address. If a -- VerboseCompletionProcedure has been specified, it will be called for each -- such read operation. The 'id' parameter in this case will be the value -- 'request.nonXferID', which the client should ensure is distinct from all -- 'xfers[i].id'. A NormalCompletionProcedure will not be invoked for such -- reads. (The buffer used to hold the data for such reads is supplied -- by the disk driver.) -- 7) If 'pagesToSkip' is non-zero, the client must supply the disk address -- corresponding to 'fileID' and 'firstPage' in 'firstPagevDA'. In this case, -- xfers[i].vDA should be 'fillInvDA', and the disk driver behaves as described -- in item 6 above. If 'pagesToSkip' is zero, 'firstPagevDA' is ignored and -- xfers[0].vDA cannot be 'fillInvDA'. Some initial subsequence of the 'xfers' -- must have valid addresses in their vDA fields. Once xfers[k].vDA equals -- 'fillInvDA', for some k, xfers[i].vDA should be 'fillInvDA' for all i>k. -- 8) DiskRequests that specify writing of labels (WriteHLD or WriteLD) must -- furnish additional information to complete the label field. The 'next' and -- 'prev' fields of the variant record are used by the disk driver to complete -- the labels at the ends of the consecutive page sequence described by 'xfers'. -- The 'lastByteCount' field permits the last page of the file to be partially -- used; it will be ignored unless 'next' is 'eofvDA'. In addition, 'pagesToSkip' -- must be zero and all elements of 'xfers' must contain explicit disk addresses -- (NOT 'fillInvDA') when either WriteHLD or WriteLD is specified. This -- requirement is imposed because the disk driver will overwrite the labels -- instead of reading them, and therefore cannot use the existing links in -- them for chaining purposes. For related reasons, the same restrictions on -- 'pagesToSkip' and vDA fields apply to ReadHLD. (Clients that write labels -- should be careful not to violate the invariants of the Alto File System.) -- 9) The client of this interface can freely release the storage used to hold the -- DiskRequest or XferSpecs immediately after InitiateDiskIO returns. -- Specifically, these data structures need not be retained until -- CompletionProcedures are invoked. -- Types and Related Constants -- vDA: TYPE = AltoFileDefs.vDA; vDC: TYPE = AltoFileDefs.vDC; SN: TYPE = AltoFileDefs.SN; DISK: TYPE = AltoFileDefs.DISK; FID: TYPE = MACHINE DEPENDENT RECORD [version: CARDINAL, serial: SN]; PageCount: TYPE = [0..AltoDefs.MaxFilePage]; eofvDA: vDA = AltoFileDefs.eofDA; fillInvDA: vDA = AltoFileDefs.fillinDA; DiskRequest: TYPE = RECORD [ firstPage: AltoDefs.PageNumber, fileID: FID, firstPagevDA: vDA, pagesToSkip: PageCount, nonXferID: RequestID, xfers: DESCRIPTOR FOR ARRAY OF XferSpec, proc: CompletionProcedure, noRestore: BOOLEAN, command: SELECT action: vDC FROM ReadHLD, ReadLD, ReadD, WriteD, SeekOnly, DoNothing => NULL, WriteHLD, WriteLD => [next, prev: vDA, lastByteCount: CARDINAL], ENDCASE]; XferSpec: TYPE = RECORD [buffer: POINTER, diskAddress: vDA, id: RequestID]; CompletionProcedure: TYPE = RECORD [ SELECT tag: * FROM normal => [proc: NormalCompletionProcedure], verbose => [proc: VerboseCompletionProcedure], ENDCASE]; NormalCompletionProcedure: TYPE = PROCEDURE [id: RequestID, status: CompletionStatus]; VerboseCompletionProcedure: TYPE = PROCEDURE [ id: RequestID, status: CompletionStatus, header: POINTER TO vDH, label: POINTER TO vDL]; CompletionStatus: TYPE = { noStatus, ok, neverStarted, checkError, checksumError, diskOffline, dataLate, seekFailure, badDiskAddress}; RequestID: TYPE = UNSPECIFIED; vDH: TYPE = MACHINE DEPENDENT RECORD [packID: CARDINAL, diskAddress: vDA]; vDL: TYPE = MACHINE DEPENDENT RECORD [ next, prev: vDA, undefined1: UNSPECIFIED, bytes: CARDINAL, undefined2: [0..1], page: AltoDefs.PageNumber, fileID: FID]; RequestError: TYPE = {badvDA, illegalvDASequence, tooManyTransfers, illegalTransfer}; -- Procedures and Signals -- InitializeDiskIO: PRIVATE PROCEDURE [minOps: CARDINAL] RETURNS [nOps: CARDINAL]; -- initializes the disk IO package with a minimum of 'minOps' page transfers -- permitted simultaneously. The actual number permitted is returned. Note that this -- procedure is PRIVATE, and should therefore be called only by knowledgeable clients -- (i.e., the VM level). FinalizeDiskIO: PRIVATE PROCEDURE; -- finalizes the disk IO package. Note that this is a private procedure, and should -- therefore be called only by knowledgeable clients (i.e., the VM level). ResetDiskShape: PRIVATE PROCEDURE [disk: DISK]; -- resets the parameters that describe the shape of the disk. Note that this -- procedure is PRIVATE, and should therefore be called only by knowledgeable clients -- (i.e., the VM level). InitiateDiskIO: PROCEDURE [operation: POINTER TO DiskRequest]; -- initiates the requested disk transfers and returns to the caller. The -- CompletionProcedure in the argument DiskRequest is invoked as each transfer -- terminates. If 'operation' is somehow invalid or malformed, 'BogusDiskRequest' -- will be raised. BogusRequest: ERROR [reason: RequestError, operation: POINTER TO DiskRequest]; -- raised by InitiateDiskIO because the disk request is invalid for some reason. -- The 'reason' parameter indicates why the request is unacceptable. DiskError: ERROR [status: CompletionStatus]; -- a convenient signal for use by higher levels (strange as that may seem). END.