HP OpenVMS I/O User’s Reference Manual: OpenVMS Version 8.4 > Chapter 8 Using the OpenVMS Generic SCSI Class Driver
8.10 Call a Generic SCSI Class Driver
Example 8-1 is
an application that uses the generic SCSI class driver to send a SCSI
INQUIRY command to a device. Example 8-1 Generic SCSI Class Driver Call Example |
/*
**
* © 2009 Hewlett-Packard Development Company, L.P.
*
* Confidential computer software. Valid license from HP and/or its
* subsidiaries required for possession, use, or copying.
*
* Consistent with FAR 12.211 and 12.212, Commercial Computer Software,
* Computer Software Documentation, and Technical Data for Commercial Items
* are licensed to the U.S. Government under vendor's standard commercial
* license.
*
* Neither HP nor any of its subsidiaries shall be liable for technical or
* editorial errors or omissions contained herein. The information in this
* document is provided "as is" without warranty of any kind and is subject
* to change without notice. The warranties for HP products are set forth
* in the express limited warranty statements accompanying such products.
* Nothing herein should be construed as constituting an additional
* warranty.
*
*/
#ifdef VAX
#module gktest "V01-03"
#else
#pragma module gktest "V01-03"
#endif
/*
**++
** FACILITY: SYS$EXAMPLES
**
** MODULE DESCRIPTION:
**
** GKTEST -- Generic SCSI device inquiry example. This program
** uses the SCSI generic class driver to send an inquiry command
** to a device on the SCSI bus and send the resulting status to
** stdout. PHY_IO and DIAGNOSE privileges are needed to run this
** program.
**
|
|
|
** AUTHORS:
**
** Hewlett-Packard
**
** CREATION DATE: 28-Aug-2009 (adapted from previous OpenVMS version)
**
** DESIGN ISSUES:
**
** To be appropriately upwardly-compatible, it would be better
** that this module use a SCSI descriptor structure definition
** from an appropriate header file (something like scsidef.h).
** At the time of most recent modification, no such file was
** available for OpenVMS.
**
**
** MODIFICATION HISTORY:
**
** X-1 DCP001 28-Aug-2009
** Use structure members that are more "type-sensitive".
**
** X-2 DCP002 11-Sep-2009
** Modifications to platform-specific macro names.
** X-3 05-Oct-2009
** Modify status checking to return proper error code from
** $qio.
**--
*/
/*
**
** INCLUDE FILES
**
*/
#include <stdio.h>
#include <ctype.h>
#include <iodef.h>
#include <descrip.h>
#include <starlet.h>
/*
** "De-comment" (and if necessary modify) the following if the
** appropriate header file becomes available:
#include <scsidef.h>
*/
/*
**
** MACRO DEFINITIONS
**
*/
#define GK_EFN 0 /* Event flag number */
#define INQUIRY_OPCODE 0x12 /* Operation code for SCSI inquiry */
#define INQUIRY_DATA_LENGTH 0x24 /* Length of inquiry buffer */
/*
** SCSI definitions:
**
** Ideally, these definitions should come from a header file provided
** with the system. At the time that this example was written and at
** the time of last update, no such file was available. For now, we
** define right here fields we need from the SCSI descriptor for this
** example; this should be replaced with the appropriate #include,
** should such a header file become available. The reader should note
** that some of the field names and types in that header file may
** differ slightly from what's shown here; when and if the header file
** becomes available, code which does depend on the names should use
** the appropriate header file names. Code which depends on getting
** the types right may need to re-cast these members when referencing
** them.
*/
/* Generic SCSI command descriptor */
struct SCSI$DESC {
unsigned int SCSI$L_OPCODE; /* SCSI Operation Code */
unsigned int SCSI$L_FLAGS; /* SCSI Flags Bit Map */
char * SCSI$A_CMD_ADDR; /* ->SCSI command buffer */
unsigned int SCSI$L_CMD_LEN; /* SCSI command length, bytes */
char * SCSI$A_DATA_ADDR; /* ->SCSI data buffer */
unsigned int SCSI$L_DATA_LEN; /* SCSI data length, bytes */
unsigned int SCSI$L_PAD_LEN; /* SCSI pad length, bytes */
unsigned int SCSI$L_PH_CH_TMOUT; /* SCSI phase change timeout, sec */
unsigned int SCSI$L_DISCON_TMOUT; /* SCSI disconnect timeout, sec */
unsigned int SCSI$L_RES_1; /* Reserved */
unsigned int SCSI$L_RES_2; /* Reserved */
unsigned int SCSI$L_RES_3; /* Reserved */
unsigned int SCSI$L_RES_4; /* Reserved */
unsigned int SCSI$L_RES_5; /* Reserved */
unsigned int SCSI$L_RES_6; /* Reserved */
} ;
/* SCSI Input/Output Status Block */
#ifdef __ALPHA
#pragma member_alignment save
#pragma nomember_alignment
#endif
struct SCSI$IOSB {
unsigned short int SCSI$W_VMS_STAT; /* VMS status code */
unsigned long int SCSI$L_IOSB_TFR_CNT; /* Actual #bytes transferred */
char SCSI$B_IOSB_FILL_1;
unsigned char SCSI$B_IOSB_STS; /* SCSI device status */
};
#ifdef __ALPHA
#pragma member_alignment restore
#endif
/* SCSI status codes and flag field constants */
#define SCSI$K_GOOD_STATUS 0
#define SCSI$K_READ 0X1 /* direction of transfer=read */
#define SCSI$V_FL_ENAB_DIS 1 /* enable disconnects */
#define SCSI$K_FL_ENAB_DIS 0X2 /* enable disconnects */
/* end of SCSI definitions */
/* data declarations */
char scsi_status,
inquiry_command[6] = {INQUIRY_OPCODE, 0, 0, 0,
INQUIRY_DATA_LENGTH, 0},
inquiry_data[INQUIRY_DATA_LENGTH],
gk_device[] = {"GKA0"};
main ()
{
unsigned short int gk_chan,
transfer_length;
int i,
status;
/* Set up the descriptor with the SCSI information to be sent to the target */
struct SCSI$DESC gk_desc = { 1, /* Pass-through - the only code defined */
SCSI$K_READ|SCSI$K_FL_ENAB_DIS, /* flags */
&inquiry_command[0], /* command addr */
6, /* command length*/
&inquiry_data[0], /* data addr */
INQUIRY_DATA_LENGTH, /* data length */
0, /* pad length */
180, /* phase timeout */
60, /* disconnect timeout */
0, 0, 0, 0, 0, 0 }; /* reserved */
struct SCSI$IOSB gk_iosb ;
$DESCRIPTOR (gk_device_desc, gk_device);
/* Assign the device channel */
status = sys$assign ( &gk_device_desc, &gk_chan, 0, 0);
if (!(status & 1))
{
printf ("Unable to assign channel to %s", &gk_device[0]);
sys$exit (status);
}
/* Issue the QIO to send the inquiry command and receive the inquiry data */
status = sys$qiow ( GK_EFN, gk_chan, IO$_DIAGNOSE, &gk_iosb, 0, 0,
&gk_desc, 15*4, 0, 0, 0, 0);
/* Check the various returned status values */
if (!(status & 1)) sys$exit (status);
/* Was VMS Status OK from QIO? */
if (!(gk_iosb.SCSI$W_VMS_STAT & 1))
sys$exit (gk_iosb.SCSI$W_VMS_STAT);
/* Yes, was SCSI Status OK from QIO? */
if (gk_iosb.SCSI$B_IOSB_STS != SCSI$K_GOOD_STATUS)
{
printf ("Bad SCSI status returned: %02.2x\n", gk_iosb.SCSI$B_IOSB_STS);
sys$exit (1);
}
/* The command succeeded. Display the SCSI data returned from the target */
transfer_length = gk_iosb.SCSI$L_IOSB_TFR_CNT;
printf ("SCSI inquiry data returned %lu bytes of data: ", transfer_length);
for (i=0; i<transfer_length; i++)
{
if (isprint (inquiry_data[i]))
printf ("%c", inquiry_data[i]);
else
printf (".");
}
printf ("\n");
}
|
|
|