/*****************************************************************************
** acptlib.c:  This source file contains functions to fill in sctl_io structs
**             for use with the passthru driver in order to allow applications
**             to issue passthru SCSI commands without needing to be aware of
**             the specifics of CDB formats.  Jon Hirota 10/94
**
**      Unpublished Confidential Information of Hewlett-Packard
**      Company. Do not disclose.  Copyright (c) Hewlett-Packard
**      Company 1995. All rights reserved
** 
** The contents of this software are proprietary and confidential to
** the Hewlett- Packard Company, and are limited in distribution to
** those with a direct need to know.  Individuals having access to
** this software are responsible for maintaining the confidentiality
** of the content and for keeping the software secure when not in use.
** Transfer to any party is strictly forbidden other than as expressly
** permitted in writing by Hewlett-Packard Company.  Unauthorized
** transfer to or possession by any unauthorized party may be a
** criminal offense.
**
**                  RESTRICTED RIGHTS LEGEND
**
**      Use,  duplication,  or disclosure by the U. S. Government is
**      subject to restrictions as set forth in subparagraph (c) (1)
**      (ii) in the Rights in Technical Data and Computer Software
**      clause in DFARS 252.227-7013 or any other successor clause.
**
**                      HEWLETT-PACKARD COMPANY
**                      3000 Hanover St.
**                      Palo Alto, CA  94304 U.S.A.
**
**      Rights for non-DOD U.S. Government Departments and Agencies
**      are as set forth in FAR 52.227-19 (c) (1,2) or any other
**      successor clause.
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/scsi.h>                   
#include "acptlib.h"

#ifndef lint
static char rcsid[] = "$Header: acptlib.c,v 1.3 95/10/25 17:27:43 hmgr Exp $";
#endif

/*****************************************************************************
** acpt_exchange():  Formats a sctl_io structure for the SCSI EXCHANGE MEDIUM
**                   command.
**
** Return values:  returns 0 on success, -1 on failure (NULL pointer param)
*****************************************************************************/

#ifndef __STDC__
int
acpt_exchange(sctl_io,transport,source,dest1,dest2,invert1,invert2)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             transport;              /* Transport address for exchange */
int             source;                 /* Source element address */
int             dest1;                  /* First destination element address */
int             dest2;                  /* Second destination element address */
int             invert1;                /* First invert bit specifier */
int             invert2;                /* Second invert bit specifier */
#else
int
acpt_exchange
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             transport,              /* Transport address for exchange */
int             source,                 /* Source element address */
int             dest1,                  /* First destination element address */
int             dest2,                  /* Second destination element address */
int             invert1,                /* First invert bit specifier */
int             invert2                 /* Second invert bit specifier */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBexchange_medium;
    sctl_io->cdb[0] = ACCMDexchange_medium;
    sctl_io->cdb[2] = BYTE1(transport);
    sctl_io->cdb[3] = BYTE0(transport);
    sctl_io->cdb[4] = BYTE1(source);
    sctl_io->cdb[5] = BYTE0(source);
    sctl_io->cdb[6] = BYTE1(dest1);
    sctl_io->cdb[7] = BYTE0(dest1);
    sctl_io->cdb[8] = BYTE1(dest2);
    sctl_io->cdb[9] = BYTE0(dest2);
    sctl_io->cdb[10] |= (invert1 ? 0x01 : 0x00);
    sctl_io->cdb[10] |= (invert2 ? 0x02 : 0x00);
    sctl_io->max_msecs = ACTIMEOUTexchange_medium; 

    return 0;
}

/*****************************************************************************
** acpt_init_element_status():  Formats an sctl_io struct for a SCSI
**                              INITIALIZE ELEMENT STATUS command.
**
** Return values:  0 on success, -1 on failure (NULL pointer parameter)
*****************************************************************************/

#ifndef __STDC__
int
acpt_init_element_status
(
struct sctl_io  *sctl_io                /* User struct to be filled in */
)
#else
int
acpt_init_element_status
(
struct sctl_io  *sctl_io                /* User struct to be filled in */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBinit_element_status;
    sctl_io->cdb[0] = ACCMDinit_element_status;
    sctl_io->max_msecs = ACTIMEOUTinit_element_status;

    return 0;
}

/*****************************************************************************
** acpt_inquiry():  This function formats an sctl_io struct for a SCSI INQUIRY
**                  command.
**
** The user buffer must be at least 0x3C bytes long (60 bytes)
**
** Return values:  returns 0 on success, -1 on failure (bad args)
*****************************************************************************/

#ifndef __STDC__
int
acpt_inquiry(sctl_io,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
char            *buffer;                /* Buffer space for inquiry data */
int              len;                   /* Length of the buffer */
#else
int
acpt_inquiry
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
char            *buffer,                /* Buffer space for inquiry data */
int              len                    /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->flags |= SCTL_READ;        
    sctl_io->cdb_length = ACCDBinquiry;
    sctl_io->cdb[0] = ACCMDinquiry;
    sctl_io->cdb[4] = BYTE0(len);
    sctl_io->data = buffer;
    sctl_io->data_length = len;
    sctl_io->max_msecs = ACTIMEOUTinquiry;

    return 0;
}

/*****************************************************************************
** acpt_log_sense():  This function formats an sctl_io struct for a SCSI
**                    LOG SENSE command.
**
** Return values:  returns 0 on success, -1 on failure.
*****************************************************************************/

#ifndef __STDC__
int
acpt_log_sense(sctl_io,page_code,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             page_code;              /* Log page specifier */
char            *buffer;                /* Buffer space for log sense data */
int             len;                    /* Length of the buffer */
#else
int
acpt_log_sense
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             page_code,              /* Log page specifier */
char            *buffer,                /* Buffer space for log sense data */
int             len                     /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->flags |= SCTL_READ;
    sctl_io->cdb_length = ACCDBlog_sense;
    sctl_io->cdb[0] = ACCMDlog_sense;
    sctl_io->cdb[2] = page_code;
    sctl_io->cdb[7] = BYTE1(len);
    sctl_io->cdb[8] = BYTE0(len);
    sctl_io->data_length = len;
    sctl_io->data = buffer;
    sctl_io->max_msecs = ACTIMEOUTlog_sense;

    return 0;
}

/*****************************************************************************
** acpt_mode_sense():  This function formats an sctl_io struct for a SCSI
**                     MODE SENSE command.
**
** Return values:  returns 0 on success, -1 on failure.
*****************************************************************************/

#ifndef __STDC__
int
acpt_mode_sense(sctl_io,page_code,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             page_code;              /* Mode page specifier */
char            *buffer;                /* Buffer space for mode sense data */
int             len;                    /* Length of the buffer */
#else
int
acpt_mode_sense
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             page_code,              /* Mode page specifier */
char            *buffer,                /* Buffer space for mode sense data */
int             len                     /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->flags |= SCTL_READ;
    sctl_io->cdb_length = ACCDBmode_sense;
    sctl_io->cdb[0] = ACCMDmode_sense;
    sctl_io->cdb[2] = page_code;
    sctl_io->cdb[4] = BYTE0(len);
    sctl_io->data_length = len;
    sctl_io->data = buffer;
    sctl_io->max_msecs = ACTIMEOUTmode_sense;

    return 0;
}

/*****************************************************************************
** acpt_move():  This function formats an sctl_io struct for a SCSI
**               MOVE_MEDIUM command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_move(sctl_io,transport,source,destination,invert)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             transport;              /* Transport address for move */
int             source;                 /* Source element address */
int             destination;            /* Destination element address */
int             invert;                 /* Invert bit specifier */
#else
int
acpt_move
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             transport,              /* Transport address for move */
int             source,                 /* Source element address */
int             destination,            /* Destination element address */
int             invert                  /* Invert bit specifier */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBmove_medium;
    sctl_io->cdb[0] = ACCMDmove_medium;
    sctl_io->cdb[2] = BYTE1(transport);
    sctl_io->cdb[3] = BYTE0(transport);
    sctl_io->cdb[4] = BYTE1(source);
    sctl_io->cdb[5] = BYTE0(source);
    sctl_io->cdb[6] = BYTE1(destination);
    sctl_io->cdb[7] = BYTE0(destination);
    sctl_io->cdb[10] |= (invert ? 0x01 : 0x00);
    sctl_io->max_msecs = ACTIMEOUTmove_medium; 

    return 0;
}

/*****************************************************************************
** acpt_position():  This function formats an sctl_io struct for a SCSI
**                   POSITION TO ELEMENT command.
**
** Return valus:  returns 0 on success, -1 on failure (bad args)
*****************************************************************************/

#ifndef __STDC__
int
acpt_position(sctl_io,transport,destination,invert)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             transport;              /* Transport address for position */
int             destination;            /* Destination element address */
int             invert;                 /* Invert bit specifier */
#else
int
acpt_position
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             transport,              /* Transport address for position */
int             destination,            /* Destination element address */
int             invert                  /* Invert bit specifier */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBposition_to_element;
    sctl_io->cdb[0] = ACCMDposition_to_element;
    sctl_io->cdb[2] = BYTE1(transport);
    sctl_io->cdb[3] = BYTE0(transport);
    sctl_io->cdb[4] = BYTE1(destination);
    sctl_io->cdb[5] = BYTE0(destination);
    sctl_io->cdb[8] |= (invert ? 0x01 : 0x00);
    sctl_io->max_msecs = ACTIMEOUTposition_to_element; 

    return 0;
}

/*****************************************************************************
** acpt_prevent_mr():  This function formats an sctl_io struct for a SCSI
**                     PREVENT/ALLOW MEDIA REMOVAL command.
**
** Return values:  returns 0 on success, -1 on failure (bad args)
*****************************************************************************/

#ifndef __STDC__
int
acpt_prevent_mr(sctl_io)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
#else
int
acpt_prevent_mr
(
struct sctl_io  *sctl_io                /* User struct to be filled in */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBprevent_media_removal;
    sctl_io->cdb[0] = ACCMDprevent_media_removal;
    sctl_io->cdb[4] = 0x01;
    sctl_io->max_msecs = ACTIMEOUTprevent_media_removal; 

    return 0;
}

/*****************************************************************************
** acpt_allow_mr():  This function formats an sctl_io struct for a SCSI
**                   PREVENT/ALLOW MEDIA REMOVAL command.
**
** Return values:  returns 0 on success, -1 on failure (bad args)
*****************************************************************************/

#ifndef __STDC__
int
acpt_allow_mr(sctl_io)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
#else
int
acpt_allow_mr
(
struct sctl_io  *sctl_io                /* User struct to be filled in */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBallow_media_removal;
    sctl_io->cdb[0] = ACCMDallow_media_removal;
    sctl_io->max_msecs = ACTIMEOUTallow_media_removal; 

    return 0;
}

/*****************************************************************************
** acpt_element_status():  This function formats an sctl_io struct for a SCSI
**                         READ ELEMENT STATUS command.
**
** Return values:  0 on success, -1 on failure (bad args)
*****************************************************************************/

#ifndef __STDC__
int
acpt_element_status(sctl_io,type_code,element,num_elt,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             type_code;              /* Element type code */
int             element;                /* Starting element address */
int             num_elt;                /* Number of elements */
char            *buffer;                /* Buffer for status data */
int             len;                    /* Length of the buffer */
#else
int
acpt_element_status
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             type_code,              /* Element type code */
int             element,                /* Starting element address */
int             num_elt,                /* Number of elements */
char            *buffer,                /* Buffer for status data */
int             len                     /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->flags |= SCTL_READ;
    sctl_io->cdb_length = ACCDBread_element_status;
    sctl_io->cdb[0] = ACCMDread_element_status;
    sctl_io->cdb[1] = type_code;
    sctl_io->cdb[2] = BYTE1(element);
    sctl_io->cdb[3] = BYTE0(element);
    sctl_io->cdb[4] = BYTE1(num_elt);
    sctl_io->cdb[5] = BYTE0(num_elt);
    sctl_io->cdb[7] = BYTE2(len);
    sctl_io->cdb[8] = BYTE1(len);
    sctl_io->cdb[9] = BYTE0(len);
    sctl_io->data = buffer;
    sctl_io->data_length = len;
    sctl_io->max_msecs = ACTIMEOUTread_element_status;

    return 0;
}

/*****************************************************************************
** acpt_diag_results():  Formats an sctl_io struct for a SCSI RECEIVE
**                       DIAGNOSTICS RESULTS command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_diag_results(sctl_io,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
char            *buffer;                /* Buffer for diagnostic data */
int             len;                    /* Length of the buffer */
#else
int
acpt_diag_results
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
char            *buffer,                /* Buffer for diagnostic data */
int             len                     /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->flags |= SCTL_READ;
    sctl_io->cdb_length = ACCDBreceive_diagnostic_results;
    sctl_io->cdb[0] = ACCMDreceive_diagnostic_results;
    sctl_io->cdb[3] = BYTE1(len);
    sctl_io->cdb[4] = BYTE0(len);
    sctl_io->data = buffer;
    sctl_io->data_length = len;
    sctl_io->max_msecs = ACTIMEOUTreceive_diagnostic_results;

    return 0;
}

/*****************************************************************************
** acpt_release():  This function formats an sctl_io struct for a SCSI
**                  RELEASE command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_release(sctl_io,third_pty,third_pty_id,element,resv_id)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             third_pty;              /* Third party specifier bit */
int             third_pty_id;           /* Third party ID */
int             element;                /* All-elements bit */
int             resv_id;                /* Reservation ID */
#else
int
acpt_release
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             third_pty,              /* Third party specifier bit */
int             third_pty_id,           /* Third party ID */
int             element,                /* All-elements bit */
int             resv_id                 /* Reservation ID */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBrelease;
    sctl_io->cdb[0] = ACCMDrelease;
    sctl_io->cdb[1] |= (third_pty ? 0x10 : 0x00);
    sctl_io->cdb[1] |= ((third_pty_id << 1) & 0x0E);
    sctl_io->cdb[1] |= (element ? 0x01 : 0x00);
    sctl_io->cdb[2] = resv_id;
    sctl_io->max_msecs = ACTIMEOUTrelease;

    return 0;
}

/*****************************************************************************
** acpt_request_sense():  This function formats an sctl_io struct for a SCSI
**                        REQUEST SENSE command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int 
acpt_request_sense(sctl_io,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
char            *buffer;                /* Buffer for sense data */
int             len;                    /* Length of the buffer */
#else
int 
acpt_request_sense
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
char            *buffer,                /* Buffer for sense data */
int             len                     /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->flags |= SCTL_READ;
    sctl_io->cdb_length = ACCDBrequest_sense;
    sctl_io->cdb[0] = ACCMDrequest_sense;
    sctl_io->cdb[4] = BYTE0(len);
    sctl_io->data = buffer;
    sctl_io->data_length = len;
    sctl_io->max_msecs = ACTIMEOUTrequest_sense;

    return 0;
}

/*****************************************************************************
** acpt_reserve():  This function formats an sctl_io struct for a SCSI
**                  RESERVE command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int acpt_reserve(sctl_io,element,third_pty,third_pty_id,all,resv_id,buffer)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             element;                /* Element to reserve */
int             third_pty;              /* Third party specifier bit */
int             third_pty_id;           /* Third part ID */
int             all;                    /* All-elements bit */
int             resv_id;                /* Reservation ID */
char            *buffer;                /* Buffer for resv. parameter list */
#else
int acpt_reserve
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             element,                /* Element to reserve */
int             third_pty,              /* Third party specifier bit */
int             third_pty_id,           /* Third part ID */
int             all,                    /* All-elements bit */
int             resv_id,                /* Reservation ID */
char            *buffer                 /* Buffer for resv. parameter list */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb[0] = ACCMDreserve;
    sctl_io->cdb[1] |= (third_pty ? 0x10 : 0x00);
    sctl_io->cdb[1] |= ((third_pty_id << 1) & 0x0E);
    sctl_io->cdb[1] |= (all ? 0x00 : 0x01);
    sctl_io->cdb[2] = BYTE0(resv_id);
    sctl_io->cdb[3] = BYTE1(AC_RESERVE_LIST_LENGTH);
    sctl_io->cdb[4] = BYTE0(AC_RESERVE_LIST_LENGTH);
    buffer[0] = 0;
    buffer[1] = 0;
    buffer[2] = 0;
    buffer[3] = (all ? 0 : 1);
    buffer[4] = BYTE1(element);
    buffer[5] = BYTE0(element);

    sctl_io->data = buffer;
    sctl_io->data_length = AC_RESERVE_LIST_LENGTH;
    sctl_io->max_msecs = ACTIMEOUTreserve;

    return 0;
}

/*****************************************************************************
** acpt_rezero_unit():  This function formats an sctl_io struct for a SCSI
**                      REZERO UNIT command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_rezero_unit(sctl_io)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
#else
int
acpt_rezero_unit
(
struct sctl_io  *sctl_io                /* User struct to be filled in */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBrezero_unit;
    sctl_io->cdb[0] = ACCMDrezero_unit;
    sctl_io->max_msecs = ACTIMEOUTrezero_unit;

    return 0;
}

/*****************************************************************************
** acpt_rotate_mailslot():  This function formats an sctl_io struct for a SCSI
**                          ROTATE MAILSLOT command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_rotate_mailslot(sctl_io,open)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             open;                   /* Rotate out bit */
#else
int
acpt_rotate_mailslot
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             open                    /* Rotate out bit */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL)
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBrotate_mailslot;
    sctl_io->cdb[0] = ACCMDrotate_mailslot;
    sctl_io->cdb[4] |= (open ? 0x01 : 0x00);
    sctl_io->max_msecs = ACTIMEOUTrotate_mailslot;

    return 0;
}

/*****************************************************************************
** acpt_send_diagnostic():  This function formats an sctl_io struct for a SCSI
**                          SEND DIAGNOSTIC command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_send_diagnostic(sctl_io,selftest,devofl,unitofl,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             selftest;               /* Self test bit */
int             devofl;                 /* Device off-line bit */
int             unitofl;                /* Unit off-line bit */
char            *buffer;                /* Buffer for test parameter list */
int             len;                    /* Length of the buffer */
#else
int
acpt_send_diagnostic
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             selftest,               /* Self test bit */
int             devofl,                 /* Device off-line bit */
int             unitofl,                /* Unit off-line bit */
char            *buffer,                /* Buffer for test parameter list */
int             len                     /* Length of the buffer */
)
#endif
{
    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL) ||
       (len <= 0))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBsend_diagnostic;
    sctl_io->cdb[0] = ACCMDsend_diagnostic;
    sctl_io->cdb[1] |= (selftest ? 0x04 : 0x00);
    sctl_io->cdb[1] |= (devofl ? 0x02 : 0x00);
    sctl_io->cdb[1] |= (unitofl ? 0x01 : 0x00);
    sctl_io->cdb[3] = BYTE1(len);
    sctl_io->cdb[4] = BYTE0(len);
    sctl_io->data = buffer;
    sctl_io->data_length = len;
    sctl_io->max_msecs = ACTIMEOUTsend_diagnostic;

    return 0;
}

/*****************************************************************************
** acpt_test_unit():  This function formats an sctl_io struct for a SCSI
**                    TEST UNIT READY command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int 
acpt_test_unit(sctl_io)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
#else
int 
acpt_test_unit
(
struct sctl_io  *sctl_io                /* User struct to be filled in */
)
#endif
{
    if(sctl_io == (struct sctl_io *) NULL) 
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBtest_unit_ready;
    sctl_io->cdb[0] = ACCMDtest_unit_ready;
    sctl_io->max_msecs = ACTIMEOUTtest_unit_ready;

    return 0;
}

/*****************************************************************************
** acpt_write_buffer():  This function formats an sctl_io struct for a SCSI
**                       WRITE BUFFER command.
**
** Return values:  returns 0 on success, -1 on failure (bad args).
*****************************************************************************/

#ifndef __STDC__
int
acpt_write_buffer(sctl_io,mode,bufferid,buffer_offset,buffer,len)
struct sctl_io  *sctl_io;               /* User struct to be filled in */
int             mode;                   /* Data format */
int             bufferid;               /* Which autochanger buffer */
int             buffer_offset;          /* Offset into buffer for write */
char            *buffer;                /* Buffer to write to autochanger */
int             len;                    /* Transfer length */
#else
int
acpt_write_buffer
(
struct sctl_io  *sctl_io,               /* User struct to be filled in */
int             mode,                   /* Data format */
int             bufferid,               /* Which autochanger buffer */
int             buffer_offset,          /* Offset into buffer for write */
char            *buffer,                /* Buffer to write to autochanger */
int             len                     /* Transfer length */
)
#endif
{

    if((sctl_io == (struct sctl_io *) NULL) || (buffer == (char *) NULL))
    {
        return -1;
    }
    BZERO(sctl_io,sizeof(struct sctl_io));
    sctl_io->cdb_length = ACCDBwrite_buffer;
    sctl_io->cdb[0] = ACCMDwrite_buffer;
    sctl_io->cdb[1] |= (mode & 0x07);
    sctl_io->cdb[2] = BYTE0(bufferid);
    sctl_io->cdb[3] = BYTE2(buffer_offset);
    sctl_io->cdb[4] = BYTE1(buffer_offset);
    sctl_io->cdb[5] = BYTE0(buffer_offset);
    sctl_io->cdb[6] = BYTE2(len);
    sctl_io->cdb[7] = BYTE1(len);
    sctl_io->cdb[8] = BYTE0(len);
    sctl_io->data = buffer;
    sctl_io->data_length = len;
    sctl_io->max_msecs = ACTIMEOUTwrite_buffer;

    return 0;
}
