;;; -*- Mode:Info; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ZINFONT ) -*-


Generated on Friday the thirty-first of January, 1986; 8:51:07 pm by dg from DJ: L.TAPE; NEWTAPE.BOTEX#90 with Experimental Grunch 1.4

 Node: *4The Generic Tape Device*; Previous: *4Design of the New Tape System*; Up: *4NEWTAPE

*     Support for tape devices has been designed to be very modular, complete and easy to use.
Devices as flavor objects need to support a relatively small number of operations, which can be
performed as efficently (or as complexly), as the device can handle, but whose interface is simple
enough to accomodate a variety of higher level formatting software, providing support for various
standard tape formats.

     This chapter outlines the operations each tape device must support along with the
characteristics particular to each operation to ensure the complete modularity of tape devices.

*3basic-tape-device* *7FFFFFFFEDd*1Flavor
*         This is the base flavor upon which all tape devices should be built.  It defines no methods or
        instance variables, it simply *1requires* the necessary methods and instance variables for the
0        *definition of the device.  Tape devices expected to be used with the general tape software,
0        **2must* be built on this flavor, as it is used as the type specifier by routines in the general tape
0        *software to check the validity of tape-device objects.  It is defined as an
0        **3:abstract-flavor*.

     The values of the following instance variables should be *1gettable* and *1settable*.  The latter
should only be used within the object's method definitions, which is assumed to be accurate with
respect to the limitations of the parameters.  All changes of the parameters from an external source
should be made through the *3:set-options* method explained below.

*3unit* *7FFFFFFECc*1Instance variable of tape-devices
*        The current unit selected by the device object.  

*3density* *7FFFFFFD*1Instance variable of tape-devices
*        The selected density (speed in some cases) of the drive.  

     These methods provide the interface to the device as specified:

*3:initialize* &rest *1init-options*7FFFFEb*1Operation on tape-devices
*         This method is responsible for setting up the device before any of the supported operations
0        *can be performed.  The initial values of device parameters may be supplied in *1options*.

*3:lock-device* *7FFFFFFDc*1Operation on tape-devices
*         This is method should lock the device so that no other processes or processors can use it
0        *when locked.  The locking scheme used and its implementation is completely up to the
0        *implementor.  All that is required is that no other object/process can use the physical device
0        *after this operation has been executed, until a *3:unlock-device* operation is executed and
0        *terminates.  *2See the section on Device Locking for a discussion on this topic.

*3:unlock-device* *7FFFFFFa*1Operation on tape-devices
*         This method undoes the action of the *3:lock-device* operation.

*3:device-locked-p* *7FFFFFECg*1Operation on tape-devices
*         This should return *3t* if the device is currently locked for this object, or *3nil* if not.

*3:set-options* &rest *1options-and-args*7FFFEDd*1Operation on tape-devices
*         *1options-and-args* should be of the form:  *3(*1option arg*3 ...)*.  This should set each of the
0        *options to its corresponding argument, checking the validity of the arguments beforehand.  If
0        *an incorrect option is specified, an error should be signalled.  The return value is *3t* if the
0        *options were correctly set.  If no options are specified, this method may, at the implementor's
0        *wish, pop-up a menu for the device options to change, or otherwise query the user.

*3:reset* *7FFFFFFFCa*1Operation on tape-devices
*         This operation should reset the physical device associated with the flavor object.

*3:status* *7FFFFFFF*1Operation on tape-devices
*         This should return a list of status descriptors which indicate the state of the device.  Each
0        *descriptor can be a keyword which implies logical truth of the condition or a list whose car is
0        *the keyword and cdr is a list of information about the condition.  The supported status
0        *descriptors are as follows:

*3   *                *3:write-protected
        *                *3:busy
        *                *3:off-line
        *                *3:on-line
        *                *3:physical-end-of-tape
        *                *3:load-point
        *                *3:end-of-file
        *                *3(:error . condition-object)


:speed-threshold* *7FFFFFECg*1Operation on tape-devices
*         Since many tape drives have two transport speeds, and the reposition time plays an
0        *important factor in the overall performance of the read and write operations, this method has
0        *been provided to allow optimization of certain operations by specifying the threshold (in
0        *bytes) above which high speed can be used.  The operations that currently allow speed
0        *specification are the spacing operations and search filemark operations this optimization is
0        **3:search-filemark* and *3:search-filemark-reverse*.

*3:rewind* &optional *1(wait-p* *1t)*7FFFFEDb*1Operation on tape-devices
*         This should rewind the tape to BOT.  If *1wait-p* is non-*3nil*, the method will wait for the tape
        to reach its load point, then return, otherwise it will return immediately.  The return value
0        *should be ignored.

*3:unload* *7FFFFFFF*1Operation on tape-devices
*         This unloads the tape and/or puts the device *3:off-line*, depending on the characteristics
0        *of the physical tape drive.  It does not wait for the tape to rewind.

*3:space* *1number-of-records* &optional *1(speed* *1:low)* *7FFEa*1Operation on tape-devices
*         This should move the tape forward the specified number of records.  This operation will
0        *space over a filemark on the tape, counting it as a record.  The *1speed* argument allows the
0        *user to specify how fast the drive spaces over records for drives that are dual speed.  Valid
0        *values are *3:high* or *3:low*.  This allows faster searching of the filemark when it is expected
0        *to be far from the current tape position, but the *3:low* speed increses efficency for short
0        *files, as tape reposition time increases with transport speed.

*3:space-reverse* *1number-of-records* &optional *1(speed* *1:low)*7FDCg*1Operation on tape-devices
*         This is the same as space but moves in the reverse direction.

*3:search-filemark* *1number-of-sequential-filemarks* &optional *1(speed* *1:low)*7Cb*1Operation on tape-devices
*         This should move forward until the specified number of sequential filemarks have been
0        *reached.  The tape should be positioned after the last of the filemarks found.  Eventually, if
0        *the filemarks are not found, a normal end-of-tape error will be signalled.  The *1:speed* argument
        is like for :Space.

*3:search-filemark-reverse* *1number-of-sequential-filemarks* &optional *1(speed* *1:low)*7Cb*1Operation on tape-devices
*         This is just like *3:search-filemark* but in reverse.

*3:optimal-chunk-size* *1record-size*7FFFFf*1Operation on tape-devices
*         This should return the optimal amount of data (in bytes) for read/write array operations for
0        *the specified record-size.  It must be some multiple of *1record-size*.

*3:read-block* *1dma-buffer* *1record-size*7FFFEDCd*1Operation on tape-devices
*         This should read one record from the tape into *1dma-buffer*.  The number of bytes expected
0        *to be in the record on tape is specified as *1record-size*.  The return value is the actual number
        of bytes that were in the record on tape.  If this is larger than the specified record size, the
0        *dma-buffer will have only been filled up to the requested record size.  If it is smaller, the
0        *dma-buffer will have only been filled up to the number of bytes in the record on tape.  As no
0        *error is signalled in either case, the requestor is expected to check the return value against
0        *the expected record-size.  In general, if the user does not know what the size of the next
0        *record will be, a large buffer can be used.  Although the overhead increases slightly with a
0        *larger block, this is a perfectly safe thing to do.  In most cases, the larges block size that can
        be used is 64k bytes (sometimes less).

*3:write-block* *1dma-buffer* *1record-size*7FFFEDc*1Operation on tape-devices
*         This should write one record, *1record-size* bytes long, of data from *1dma-buffer* on the tape.

*3:read-array* *1array* *1number-of-records* *1record-size*7FFDCf*1Operation on tape-devices
*         This should read the specified number of record-size records into *1array* from tape.  This
0        *method should be able to handle the following array types:  *3art-8b*, *3art-16b*, and
0        **3art-string*.  Record-size must be an even multiple of 1024.  The return value should be
0        *ignored.

*3:write-array* *1array* *1number-of-records* *1record-size*7FFDe*1Operation on tape-devices
*         This is just like *3:read-array* only it writes from the array to tape.

*3:read-to-disk* *1starting-address* *1number-of-blocks* *1record-size*7Fg*1Operation on tape-devices
*         This should transfer the specified number of disk blocks from the tape to the disk starting at
        *1starting-address*.  Care must be used in checking the arguments, as a reference to a
0        *non-existent disk address on the Lambda will make the machine crash.  *1Record-size* must be
0        *an even multiple of 1024.  The return values are the number of blocks actually written on disk
        and an error condition or NIL as in :read-array.

*3:write-from-disk* *1starting-address* *1number-of-blocks* *1record-size*7ECd*1Operation on tape-devices
*         This is the similar to *3:read-to-disk* except the direction of data transfer is reversed.

