Hardware manual
(The address, lvRealDA, is passed because a real disk address may occupy more than 1 word.) This
procedure returns eofDA if the real disk address is zero (end-of-file), and fillInDA if the real disk address
does not correspond to a legal virtual disk address in this file system.
RealDiskDA(disk, virtualDA, lvRealDA) computes the real disk address and stores it in rv lvRealDA. The
function returns true if the virtual disk address is legal, i.e. within the bounds of disk addresses for the
given "disk." Otherwise, it returns false.
7. Lower-level Disk Access
The transfer routines described previously have the property that all disk activity occurs during calls to the
routines; the routines wait for the requested disk transfers to complete before returning. Consequently,
disk transfers cannot conveniently be overlapped with computation, and the number of pages transferred
consecutively at full disk speed is generally limited by the number of buffers that a caller is able to supply
in a single call.
It is also possible to use the disk routines at a lower level in order to overlap transfers with computation
and to transfer pages at the full speed of the disk (assuming the file is consecutively allocated on the disk
and the amount of computation per page is kept relatively small). The necessary generic disk operations
and other information are available to permit callers to operate the low-level disk routines in a device-
independent fashion for most applications.
This level makes used of a Command Block Zone (CBZ), part of whose structure is public and defined in
Disks.d, and the rest of which is private to the implementation. The general idea is that a CBZ is set up
with empty disk command blocks in it. A free block is obtained from the CBZ with GetDiskCb and sent to
the disk with DoDiskCommand. When it is sent to the disk, it is also put on the queue which GetDiskCb
uses, but GetDiskCb waits until the disk is done with the command before returning it, and also checks for
errors.
If you plan to use these routines, read the code for ActOnDiskPages to find out how they are intended to
be called. An example of use of these routines in a disk-independent fashion (i.e., using only the public
definitions in Disks.d) may be found in the DiskStreamsScan module of the Operating System. Only in
unusual applications should it be necessary to make use of the implementation-dependent information in
Bfs.d or Tfs.d.
InitializeDiskCBZ(disk, cbz, firstPage, length, retry, lvErrorRoutine). CBZ is the address of a block of
length words which can be used to store CBs. It takes at least three CBs to run the disk at full speed; the
disk object contains the values DSK.lengthCBZ (fixed overhead) and DSK.lengthCB (size of each
command block) which may be used to compute the required length (that is, length should be at least
lengthCBZ+3*lengthCB). FirstPage is used to initialize the currentPage field of the cbz. Retry is a label
used for an error return, as described below. lvErrorRoutine is an error routine for unrecoverable errors,
described below; it defaults to a routine that simply invokes SysErr. The arguments after firstPage can be
omitted if an existing CBZ is being reinitialized, and they will remain unchanged from the previous
initialization.
cb = GetDiskCb(disk, cbz, dontClear[false], returnIfNoCB[false]) returns the next CB for the CBZ. If the
next CB is empty (i.e., it has never been passed to DoDiskCommand), GetDiskCb simply zeroes it and
returns it. However, if the next CB is still on the disk command queue, GetDiskCb waits until the disk has
finished with it. Before returning a CB, GetDiskCb checks for errors, and handles them as described
below. If there is no error, GetDiskCb updates the nextDA and currentNumChars cells in the CBZ, then
calls cbz>>CBZ.cleanupRoutine(disk, cb, cbz). Next, unless dontClear is true, the CB is zeroed. Finally,
the CB is returned as the value of GetDiskCb. If returnIfNoCB is true, GetDiskCb returns zero if there
are no CBs in the CBZ or the next CB is still on the disk command queue.
If the next CB has suffered an error, then GetDiskCb instead takes the following actions. First it
increments cbz>>CBZ.errorCount. If this number is ge the value disk>>DSK.retryCount, GetDiskCb calls
Disks & Bfs August 10, 1980 59
For Xerox Internal Use Only -- December 15, 1980










