The SCSI standard provides a mechanism for SCSI devices to return
manufacturer data. This is accomplished using the SCSI <INQUIRY>
command.
A simple program is appended that makes use of this command to
query devices.
The program has two modes of operation. The invoker can specify a
device (which must be a character device that supports ioctl(S)s)
using the -d flag:
# ./scsiQuery -d /dev/rcd0
/dev/rcd0: CD-ROM: SONY : CD-ROM CDU-561 : 1.9i:
# ./scsiQuery -d /dev/xStp0
/dev/xStp0: Sequential-access: WANGTEK : 5525ES SCSI REV7: 3J :
Or, the command can be invoked without arguments:
# ./scsiQuery
/dev/rhd00: Direct-access: IBM OEM : 0662S12 : 1011: 0017465345G9816
/dev/rhd10: Direct-access: IBM OEM : 0662S12 : 1011: 0017504645G9816
/dev/rhd20: No such file or directory
When invoked in this manner, the program attempts to determine
the details of the following devices:
/dev/rhd00
/dev/rhd10
/dev/rhd20
/dev/rhd30
These are, by convention, the first four disks on the system.
NOTE:
The program ('scsiQuery') relies on the use of the SCSIUSERCMD
ioctl(S). Not all SCSI host adapter drivers, or all SCSI device
drivers, support this ioctl(S).
This program must be invoked by the superuser (root).
Compilation of this program requires that the appropriate
development system is installed.
SEE ALSO:
SCO Advanced Hardware Developer's Kit, scsi_usercmd(K_SCSI).
# ---8<------- cut here 8<------- 8<------- 8<------- 8<-------
8<-------
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/scsi.h>
#include <sys/scsicmd.h>
#include <stdio.h>
/*
Mostly extracted from the AHDK example,
scsi/odt_3.0/user_cmd/awre.
*/
/* for is_write bit */
#define READ 0
#define WRITE 1
struct inquiry_cdb {
uchar_t opcode;
uchar_t evpd:1;
uchar_t :4;
uchar_t lun:3;
uchar_t page_code;
uchar_t reserved;
uchar_t length;
uchar_t control;
};
typedef struct inquiry {
uchar_t device_type:5;
uchar_t periph_qual:3;
uchar_t dev_type_mod:7;
uchar_t rmb:1;
uchar_t ansi:3;
uchar_t ecma:3;
uchar_t iso:2;
uchar_t data_fmt:4;
uchar_t :2;
uchar_t term_iop:1;
uchar_t aenc:1;
uchar_t addl_len;
uchar_t reserved[2];
uchar_t sft_re:1;
uchar_t cmd_que:1;
uchar_t :1;
uchar_t linked:1;
uchar_t sync:1;
uchar_t wbus16:1;
uchar_t wbus32:1;
uchar_t reladr:1;
uchar_t vendor[8];
uchar_t product[16];
uchar_t revision[4];
uchar_t specific[60];
} inquiry_t;
char *device_types[] = {
"Direct-access",
"Sequential-access",
"Printer",
"Processor",
"Write-once",
"CD-ROM",
"Scanner",
"Optical memory",
"Medium changer",
"Communications",
"<0Ah>(graphic arts pre-press device)",
"<0Bh>(graphic arts pre-press device)",
"<0Ch>",
"<0Dh>",
"<0Eh>",
"<0Fh>",
"<10h>",
"<11h>",
"<12h>",
"<13h>",
"<14h>",
"<15h>",
"<16h>",
"<17h>",
"<18h>",
"<19h>",
"<1Ah>",
"<1Bh>",
"<1Ch>",
"<1Dh>",
"<1Eh>",
"No device connected"
};
struct scsicmd scsicmd;
struct inquiry inquiry;
inquiryCmd(char * device, struct scsicmd * ptr, struct inquiry * iptr)
{
int fd;
if((fd = open( device, O_RDONLY )) == -1)
{
perror( device );
exit( 1 );
};
memset( ptr, '\0', sizeof( struct scsicmd ) );
ptr->data_len = sizeof( struct inquiry );
ptr->data_ptr = (char *) iptr;
ptr->is_write = READ;
ptr->cdb[0] = INQUIRY_CMD;
ptr->cdb[4] = sizeof( struct inquiry );
if ( ioctl( fd, SCSIUSERCMD, ptr ) < 0 )
{
fprintf(stderr, "inquiryCmd(%s): ioctl(S) failed\n", device);
}
else
printf("%s: %s: %.8s: %.16s: %.4s: %.50s\n",
device,
device_types[inquiry.device_type],
inquiry.vendor,
inquiry.product,
inquiry.revision,
inquiry.specific
);
close( fd );
}
char * USAGE="USAGE: scsiQuery\n : scsiQuery -d raw-device\n";
int main(int argc, char * argv[], char ** envp)
{
int fd;
int c;
int i;
char buf[128];
char * device = NULL;
extern char * optarg;
extern int optind;
while(( c = getopt( argc, argv, "d:" ) ) != -1)
{
switch( c )
{
case 'd': device = optarg;
break;
default: fprintf(stderr, USAGE );
exit( 2 );
}
}
if ( device != NULL )
inquiryCmd( device, &scsicmd, &inquiry );
else
for(i=0; i < 4; i++)
{
sprintf( buf, "/dev/rhd%1.1d0", i );
inquiryCmd( buf, &scsicmd, &inquiry );
}
}
|