/* ** COPYRIGHT (c) 1993 BY ** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS. ** ALL RIGHTS RESERVED. ** ** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED ** ONLY IN ACCORDANCE OF THE TERMS OF SUCH LICENSE AND WITH THE ** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER ** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY ** OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY ** TRANSFERRED. ** ** THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE ** AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT ** CORPORATION. ** ** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS ** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. */ #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: ** ** Digital Equipment Corporation ** ** CREATION DATE: 28-Jan-1993 (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-Jan-1993 ** Use structure members that are more "type-sensitive". ** ** X-2 DCP002 11-Mar-1993 ** Modifications to platform-specific macro names. ** X-3 05-Oct-1993 ** Modify status checking to return proper error code from ** $qio. **-- */ /* ** ** INCLUDE FILES ** */ #include #include #include #include #include /* ** "De-comment" (and if necessary modify) the following if the ** appropriate header file becomes available: #include */ /* ** ** 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