8 Inquiry Command Example

Contents of this section

One of the most basic SCSI commands is the INQUIRY command, used to identify the type and make of the device. Here is the definition from the SCSI-2 specification (for details refer to the SCSI-2 standard).

                            Table 44: INQUIRY Command
+=====-========-========-========-========-========-========-========-========+
|  Bit|   7    |   6    |   5    |   4    |   3    |   2    |   1    |   0    |
|Byte |        |        |        |        |        |        |        |        |
|=====+=======================================================================|
| 0   |                           Operation Code (12h)                        |
|-----+-----------------------------------------------------------------------|
| 1   | Logical Unit Number      |                  Reserved         |  EVPD  |
|-----+-----------------------------------------------------------------------|
| 2   |                           Page Code                                   |
|-----+-----------------------------------------------------------------------|
| 3   |                           Reserved                                    |
|-----+-----------------------------------------------------------------------|
| 4   |                           Allocation Length                           |
|-----+-----------------------------------------------------------------------|
| 5   |                           Control                                     |
+=============================================================================+

The output data are as follows:

                     Table 45: Standard INQUIRY Data Format
+=====-========-========-========-========-========-========-========-========+
|  Bit|   7    |   6    |   5    |   4    |   3    |   2    |   1    |   0    |
|Byte |        |        |        |        |        |        |        |        |
|=====+==========================+============================================|
| 0   | Peripheral Qualifier     |           Peripheral Device Type           |
|-----+-----------------------------------------------------------------------|
| 1   |  RMB   |                  Device-Type Modifier                        |
|-----+-----------------------------------------------------------------------|
| 2   |   ISO Version   |       ECMA Version       |  ANSI-Approved Version   |
|-----+-----------------+-----------------------------------------------------|
| 3   |  AENC  | TrmIOP |     Reserved    |         Response Data Format      |
|-----+-----------------------------------------------------------------------|
| 4   |                           Additional Length (n-4)                     |
|-----+-----------------------------------------------------------------------|
| 5   |                           Reserved                                    |
|-----+-----------------------------------------------------------------------|
| 6   |                           Reserved                                    |
|-----+-----------------------------------------------------------------------|
| 7   | RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe  |
|-----+-----------------------------------------------------------------------|
| 8   | (MSB)                                                                 |
|- - -+---                        Vendor Identification                    ---|
| 15  |                                                                 (LSB) |
|-----+-----------------------------------------------------------------------|
| 16  | (MSB)                                                                 |
|- - -+---                        Product Identification                   ---|
| 31  |                                                                 (LSB) |
|-----+-----------------------------------------------------------------------|
| 32  | (MSB)                                                                 |
|- - -+---                        Product Revision Level                   ---|
| 35  |                                                                 (LSB) |
|-----+-----------------------------------------------------------------------|
| 36  |                                                                       |
|- - -+---                        Vendor Specific                          ---|
| 55  |                                                                       |
|-----+-----------------------------------------------------------------------|
| 56  |                                                                       |
|- - -+---                        Reserved                                 ---|
| 95  |                                                                       |
|=====+=======================================================================|
|     |                       Vendor-Specific Parameters                      |
|=====+=======================================================================|
| 96  |                                                                       |
|- - -+---                        Vendor Specific                          ---|
| n   |                                                                       |
+=============================================================================+

The next example uses the low-level function handle_SCSI_cmd to perform the Inquiry SCSI command.

We first append the command block to the generic header, then call handle_SCSI_cmd. Note that the output buffer size argument for the handle_SCSI_cmd call excludes the generic header size. After command completion the output buffer contains the requested data, unless an error occurred.

#define INQUIRY_CMD     0x12
#define INQUIRY_CMDLEN  6
#define INQUIRY_REPLY_LEN 96
#define INQUIRY_VENDOR  8       /* Offset in reply data to vendor name */

/* request vendor brand and model */
static unsigned char *Inquiry ( void )
{
  unsigned char Inqbuffer[ SCSI_OFF + INQUIRY_REPLY_LEN ];
  unsigned char cmdblk [ INQUIRY_CMDLEN ] = 
      { INQUIRY_CMD,  /* command */
                  0,  /* lun/reserved */
                  0,  /* page code */
                  0,  /* reserved */
  INQUIRY_REPLY_LEN,  /* allocation length */
                  0 };/* reserved/flag/link */

  memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );

  if (handle_SCSI_cmd(sizeof(cmdblk), 0, cmd, 
                      sizeof(Inqbuffer) - SCSI_OFF, Inqbuffer )) {
      fprintf( stderr, "Inquiry failed\n" );
      exit(2);
  }
  return (Inqbuffer + SCSI_OFF);
}

The example above follows this structure. The Inquiry function copies its command block behind the generic header (given by SCSI_OFF). Input data is not present for this command. Handle_SCSI_cmd will define the header structure. We can now implement the function main to complete this working example program.

void main( void )
{
  fd = open(DEVICE, O_RDWR);
  if (fd < 0) {
    fprintf( stderr, "No access to "DEVICE".\n" );
    exit(1);
  }

  /* print the result of Inquiry */
  printf( "%s\n", Inquiry() + INQUIRY_VENDOR );
}

We first open the device, check for errors, and then call the higher level subroutine. Then we print the results in human readable format including the vendor, product, and revision.

Next Chapter, Previous Chapter

Table of contents of this chapter, General table of contents

Top of the document, Beginning of this Chapter