---------------------------------------------------------------------
  CLASS:  hpACDev                                              --JKH
  PUBLIC METHODS:
 
   hpACDev() 
       Constructor and copy constructor.
  ~hpACDev()
       Destructor.
   numSectors() 
       Returns the number of sectors on the specified surface.
   sectorSize() 
       Returns the sector size of the specified surface.
   read() 
       Reads the specified number of byte from a surface at a given
       sector offset into the user's buffer.
   write() 
       Writes the specified number of bytes to a surface at a given
       sector offset from the user's buffer.
   writeWOE() 
       Writes the specified number of bytes to a surface at a given
       sector offset from the user's buffer in write-without-erase mode.
   erase() 
       Erases the specified number of sectors on a surface at a given
       sector offset.
   verifyMode() 
       Sets and gets the verify mode for a given surface (whether the
       surface is in write-with-verify mode).
   allocDrive() 
       Allocates a drive resource for a surface and places the surface
       in the drive.
   freeDrive() 
        Frees a drive resource allocated by a call to allocDrive() .
   error() 
       Returns the current error state of the hpACDev object.
   flush() 
       Flushes any cached information. (This is a nop)
   errorClear() 
       Clears the error state of the hpACDev object.  (This is a nop)
   mediaType() 
       Returns the media type (MO or WORM) for the specified surface.
   verifyBlank() 
       Verifies that the specified range of sectors on a surface are
       blank (i.e., erased, or unwritten for WORM).
   addSurface() 
       Maps a slot/side address of a surface in the jukebox to an sid_t.
   removeSurface() 
       Removes a slot/side <-> sid_t mapping from the hpACDev.
   sleepMode() 
       Gets or sets the sleep mode for a surface.  (Not implemented fully)
   addDriveMap() 
       Maps a device file to one of the drives in the jukebox.
   elementAddresses() 
       Gets element addresses (mode sense) information from the jukebox.
   elementStatus() 
       Gets element status information from the jukebox.
   senseData() 
       Gets SCSI request sense data from the jukebox.
 
  USAGE NOTES:
 
 -----------------------------------------------------------------------------

---------------------------------------------------------------------
  METHOD:  hpACDev::acCommand                                  --JKH
 
  Sends a command to the autochanger using the passthru driver.
 
  ARGS:  
 
  struct sctl_io *sctl_io  IN  Pointer to a formatted sctl_io struct to
                               specify the passthru command
 
  RETURNS:
 
  Returns 0 on success, -1 on failure.
 
  PRE-CONDS:
 
  --hpACDev has been successfully constructed
 
  POST-CONDS:
 
  ERRORS:
 
  error_None:  Function completed successfully.
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::~hpACDev                                   --JKH
 
  The destructor for the hpACDev object.
 
  ARGUMENTS:  None.
  PRECONDITIONS:  None.
  POSTCONDITIONS: 
 
  --The file descriptor corresponding to the autochanger device bound to this
    object, if open, will be closed.
  --Any surfaces still in drives, allocated or not, will be put away to their
    home slots.
 
  NOTES:  It is expected that when the hpACDev goes out of scope, the user
  will have freed all drives allocated by the object.  This method does NOT
  automatically free the SSDevice objects created by allocDrive().
 
  ERRORS:  None.
 -----------------------------------------------------------------------------

hpACDev::~hpACDev( void )


---------------------------------------------------------------------
  METHOD:  hpACDev::numSectors                                 --JKH
 
  Returns the number of sectors on the specified surface.
 
  ARGUMENTS:
 
  sid_t sid  IN  surface identifier
 
  RETURNS:
 
  Returns the number of sectors on the specified surface.  Returns 0 if the
  argument sid is invalid.
 
  PRECONDITIONS:
 
  --The hpACDev was successfully constructed.
 
  POSTCONDITIONS:  see return values.
 
  ERRORS:  
 
  error_None:  Operation completed successfully.
 -----------------------------------------------------------------------------
NSR::UINT32
hpACDev::numSectors( NSR::sid_t sid ) 


---------------------------------------------------------------------
  METHOD:  hpACDev::sectorSize                                 --JKH
 
  Returns the size, in bytes, of the specified surface.
 
  ARGUMENTS:
 
  sid_t sid  IN  surface identifier
 
  RETURNS:
 
  Returns the size, in bytes, of a sector of the specified surface.  Returns
  0 if the argument sid is invalid.
 
  PRECONDITIONS:
 
  --The hpACDev was successfully constructed.
 
  POSTCONDITIONS:  see return values
 
  ERRORS:  see return values.
 
 -----------------------------------------------------------------------------
NSR::UINT32
hpACDev::sectorSize( NSR::sid_t sid ) 


---------------------------------------------------------------------
  METHOD:  hpACDev::read                                       --JKH
 
  Reads the specified number of sectors into the buffer barr from the argument
  surface sid.  Buffering will be performed if the request length is not
  equal to a sector multiple.
 
  ARGUMENTS:
 
  sid_t sid           IN      Surface identifier
  UINT32 startsector  IN      Starting sector for the read
  UINT32 nbytes       IN      Number of bytes to read
  BYTE * buf          IN/OUT  Buffer for read data
 
  RETURNS:
 
  Returns the number of bytes read.  If -1 is returned, then an actual I/O
  error (not a blank check) occurred.  If a blank check or read past EOM
  condition occurred, a "short count" will be returned.
 
  PRE-CONDS:
 
  --The hpACDev object was successfully constructed
  --The argument sid corresponds to surface within the autochanger
  --The start sector/nbytes parameters are within physical media boundaries
 
  POST-CONDS:
 
  --The number of bytes specified by the nbytes parameter will be read from
    disk and stored in the user's buffer.
 
  ERRORS:
 
  error_None:  function completed successfully
  error_Invalid_sid:  Invalid sid
  error_No_free_store:  Could not allocate memory for buffering.
  error_Empty_path_element:  Argument buffer is invalid.
  error_Drive_blank_check:  A blank sector was encountered during the read.
  error_Read_EOM:  Attempted to read past physical EOM
  error_Drive_read:  Generic I/O failure on read
 ----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::write                                      --JKH
 
  Writes the specified number of bytes from the buffer barr to argument
  surface and starting sector.
 
  ARGS:
 
  sid_t sid           IN  Surface identifier
  UINT32 startsector  IN  Starting sector for write
  UINT32 nbytes       IN  Number of bytes to write
  BYTE * buf          IN  Buffer of data to write
 
  RETURNS:
 
  The function returns the number of bytes written.  If -1 is returned, then
  an actual I/O error occurred.  If a write past EOM condition occurred,
  a "short count" will be returned.  NOTE:  if the hpACDev is in verify
  mode, and the hpACDev cannot successfully put itself in verify mode
  for the write, the write call will fail, returning -1 and setting error
  to error_Set_verify_failed.
 
  PRE-CONDS:
 
  --The hpACDev object was successfully constructed and contains media
  --The start parameter is in the range [0,number sectors)
  --The device is writable (e.g., not write-protected, and if WORM, the
    sectors are unwritten.
 
  POST-CONDS:
 
  --The number of bytes specified by nbytes will be written to disk.
 
  ERRORS:
 
  error_None:  Function completed successfully.
  error_No_free_store:  Could not allocate memory for buffering.
  error_Empty_path_element:  Argument buffer is invalid.
  error_Write_EOM:  Attempted to write past physical EOM
  error_Drive_write:  Generic I/O failure on write
  error_Set_verify_failed:  Cannot set verify mode.
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::writeWOE                                   --JKH
 
  This method writes the specified sectors to disk from the buffer using
  write-without-erase mode.
 
  NOTE:  if the sectors to be written without erase are NOT in fact already
  erased, they will be garbaged and henceforth unreadable, and no error will
  be detected during the write!  It is very important that users using this
  method are sure that the sectors in question are actually erased.
 
  NOTE:  if the underlying drive cannot be placed into write-without-erase
  mode, the write will be attempted in write-with-erase mode and no special
  error will be flagged.
 
  ARGS:
 
  sid_t              IN  surface identifier
  UINT32 startsector IN  starting sector for the write
  UINT32 nbytes      IN  number of bytes to write
  BYTE *barr         IN  buffer to supply data for the write
 
  RETURNS:
 
  The function returns the number of bytes written.  If -1 is returned, then
  an actual I/O error occurred.  If a write past EOM condition occurred,
  a "short count" will be returned.  If the SSDevice cannot be put into
  write-without-erase mode successfully, the call will proceed in normal
  write-with-erase mode, and will not flag an error.
 
  PRE-CONDS:
 
  --The hpACDev object was successfully constructed.
  --The startsector and nbytes parameters specify a valid address range
  --The device is writable (e.g., not write-protected and, if WORM, the
    sectors are unwritten.
  --The sectors to be written are erased.
 
  POST-CONDS:
 
  --The specified bytes will be written to disk.
 
  ERRORS:
 
  error_None:  Function completed successfully.
  error_No_free_store:  Could not allocate memory for buffering.
  error_Empty_path_element:  Argument buffer is invalid.
  error_Write_EOM:  Attempted to write past physical EOM
  error_Drive_write:  Generic I/O failure on write
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::erase                                      --JKH
 
  Erases the specified sectors.
 
  ARGS:
 
  sid_t          sid  IN  Surface identifier
  UINT32 startsector  IN  Starting sector for erase
  UINT32 numsectors   IN  Number of sectors to erase
 
  RETURNS:
 
  Returns 0 on success, -1 on failure.
 
  PRE-CONDS:
 
  --The hpACDev object was successfully created and contains media
  --The executing process is the only process that has the drive open
  --The arguments specify a range of sectors physically accessible on the
    media
  --The media is erasable (e.g., not a hard disk, not WORM)
 
  POST-CONDS:
 
  --The specified sectors will be erased.
 
  ERRORS:
 
  error_None            Function completed successfully.
  error_Erase_failed    The erase failed due to an I/O error, or inability
                        to put the drive in exclusive mode.
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::verifyMode                                 --JKH
 
  Returns the verify mode of the specified surface.  A mode of 0 indicates
  write-without-verify (the default); a nonzero value indiicates all
  subsequent writes to that surface will be performed with verify.
 
  ARGS:
 
  sid_t sid      IN  Surface identifier
 
  RETURNS:
 
  Returns the current value of the verify mode for that surface.  If an
  invalid sid_t was specified, the function returns -1.
 
  PRE-CONDS:
 
  --The hpACDev was successfully constructed.
 
  POST-CONDS:
 
  --See above
 
  ERRORS:
 
  error_None:  Function completed successfully
  error_Invalid_sid:  Invalid sid specified
 -----------------------------------------------------------------------------
NSR::INT32
hpACDev::verifyMode( NSR::sid_t sid,NSR::INT32 newmode )
NSR::INT32
hpACDev::verifyMode( NSR::sid_t sid ) 


---------------------------------------------------------------------
  METHOD:  hpACDev::allocDrive                                 --JKH
 
  Allocates an SSDevice object for the specified surface.  This allocation
  implies that I/O may be performed to the surface through the returned
  SSDevice object pointer.  Generally this requires that the surface be
  placed in a drive and kept there until the resource is freed, which
  consequently may cause that drive to be unavailable for I/O for the
  allocating hpACDev object.
 
  NOTE:  The user must NOT delete the returned SSDevice object!  When the
  user no longer needs it, the user must call freeDrive().
 
  The algorithm used here is that when a drive is allocated, the requested
  surface is moved into a drive (if it is not already in one).  When
  the drive is freed, the SSDevice is deleted but the surface is left
  in the drive, to prevent unnecessary swaps between read calls, for instance,
  to the same surface.
 
  ARGS:
 
  sid_t sid        IN  Surface identifier
 
  RETURNS:
 
  Upon success, returns a pointer to an SSDevice object.  On failure (no
  drives available, or an invalid sid_t), returns NULL.
 
  PRE-CONDS:
 
  --The hpACDev was successfully constructed.
 
  POST-CONDS:  See above
 -----------------------------------------------------------------------------
NSR::SSDevice *
hpACDev::allocDrive(NSR::sid_t sid)


---------------------------------------------------------------------
  METHOD:  hpACDev::freeDrive                                  --JKH
 
  Frees a drive allocated by a previous call to allocDrive().
 
  ARGS:
 
  SSDevice *drive  IN  Drive to be freed.
 
  RETURN VALUES:
 
  Returns 0 on success, -1 on failure (invalid drive pointer)
 
  PRE-CONDS:
 
  --The argument SSDevice was allocated by a call to allocDrive()
 
  POST-CONDS:
 
  --The drive resource will be freed and made available for further allocation.
  --This method does NOT move the surface back to its home slot.
 
  ERRORS:
 
  error_None:  Function completed successfully
  error_Null_pointer:  Null pointer passed as argument
 -----------------------------------------------------------------------------
NSR::INT32
hpACDev::freeDrive(NSR::SSDevice *drivep)


---------------------------------------------------------------------
  METHOD:  hpACDev::mediaType                                  --JKH
 
  Determines whether the specified surface is WORM media.
 
  ARGUMENTS:  None.
 
  RETURNS:
 
  Returns the type of the media (NSR::media_Rewritable or NSR::media_Worm)
 
  PRE-CONDS:
 
  --The hpACDev object was successfully constructed
  --The argument sid corresponds to surface within the autochanger
 
  POST-CONDS:  See Returns.
 ----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::verifyBlank()                          --JKH
 
  Verifies that the given sectors are blank (erased).
 
  ARGUMENTS:
 
  sid_t   sid       IN   Surface identifier
  UINT32  start     IN   Starting sector to verify
  UINT32  nsectors  IN   Number of sectors to verify
  UINT32 *where     OUT  If a written sector is encountered, this variable
                         is filled in with the written sector address.
  RETURNS:
 
  Returns True if all of the sectors are blank, False otherwise.
 
  PRECONDITIONS:
 
  --The hpACDev object was successfully constructed.
 
  POSTCONDITIONS:  see returns.
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::addSurface                                 --JKH
 
  Creates a mapping between an sid_t and specified surface given by slot
  position in the autochanger and side.
 
  ARGS:
 
  INT32 slot    IN  Which slot in the autochanger the cartridge resides in.
                    Slots are numbered from 1 to increasing values.
  INT32 side    IN  Which side of the cartridge.  0 = A side, 1 = B side.
 
  RETURNS:
 
  Returns an allocated sid_t on success.  If the specified surface device
  file does not exist or is otherwise invalid, the call returns and sid_t
  value SID_T_INVALID.
 
  PRE-CONDS:
 
  --The hpACDev was successfully constructed.
  --The specified slot in the autochanger is occupied.
 
  POST-CONDS:  see return values
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::removeSurface                              --JKH
 
  Removes a mapping between an sid_t and (slot,side) surface specification.
 
  ARGS:
 
  sid_t sid  IN  Surface identifier to be removed from the internal mapping
 
  RETURNS:
 
  returns 0 on success, -1 on failure (invalid sid_t)
 
  PRE-CONDS:
 
  --The hpACDev was successfully constructed.
  --The sid_t was allocated by a previous call to addSurface().
 
  POST-CONDS:  see return values
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::sleepMode                                  --JKH
 
  Returns the sleep mode for the autochanger.  If nonzero, sleeping is allowed
  on any operation that requires a drive resource.  The hpACDev will go into
  a polling loop to wait for a drive resource.  If zero, the default, any
  operation that requires a drive resource that cannot be allocated one will
  fail immediately with an error_Drive_not_available.
 
  ARGS:  None
 
  RETURNS:
 
  Returns the previous value of the sleep mode.  
 
  PRE-CONDS:
 
  --The hpACDev was successfully constructed.
 
  POST-CONDS:
 
  --See above
 
  ERRORS:
 
  error_None:  Function completed successfully
 -----------------------------------------------------------------------------
NSR::INT32
hpACDev::sleepMode( void ) const


---------------------------------------------------------------------
  METHOD:  hpACDev::addDriveMap                                --JKH
 
  Creates a mapping between a drive device file and its hardware address.
 
  ARGS:
 
  INT32 id       IN  SCSI target ID of the drive
  INT32 lun      IN  SCSI LUN ID of the drive
  const String&  IN  Pathname for the disk character device file
 
  RETURNS:
 
  0 on success, -1 on failure (invalid hardware address specified.)
 
  PRE-CONDS:
 
  --The hpACDev was successfully constructed.
  --The specified drive is in the autochanger.
 
  POST-CONDS:  see return values
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::elementAddresses
 
  Returns element addresses (mode sense) information.
 
  ARGS:
 
  struct element_addresses& el  OUT   Struct to hold element addresses info.
 
  RETURNS:
 
  Returns 0 on success, -1 on failure
 
  PRE-CONDS:
 
  --The autochanger was successfully constructed
 
  POST-CONDS:  See return values
 -----------------------------------------------------------------------------
NSR::INT32 
hpACDev::elementAddresses( struct element_addresses& eltaddr )


---------------------------------------------------------------------
  METHOD:  hpACDev::elementStatus
 
  Returns status information about an element in the autochanger
 
  ARGS:
 
  INT32  element                  IN   Element to get status for
  struct element_status& eltstat  OUT  Status information
 
  RETURNS:
 
  Returns 0 on success, -1 on failure
 
  PRE-CONDS:
 
  --The autochanger was successfully constructed
 
  POST-CONDS:  See return values
 -----------------------------------------------------------------------------


---------------------------------------------------------------------
  METHOD:  hpACDev::senseData
 
  Returns the sense data from the last SCSI command if any.
 
  ARGS:
 
  struct sense_2_aligned& sense  OUT  Struct for the sense data
 
  RETURNS:
 
  Returns the number of bytes of sense data available.  If 0, the last SCSI
  command executed succeeed.
 
  PRE-CONDS:
 
  --The autochanger was successfully constructed.
 
  POST-CONDS:  see return values
 -----------------------------------------------------------------------------