Hi
How can I programmatically get the scsi serial number & vendor id of a
scsi device (vital product data)?
I read a little about scsi-2 "inquiry" command, but is there a system
library that provides access to it? Is this command available on
scsi-3?
Thanks
|
|
0
|
|
|
|
Reply
|
hamadani
|
10/1/2003 4:51:05 PM |
|
In article <bb6f754a.0310010851.d01b62e@posting.google.com>,
babak <hamadani@uclink.berkeley.edu> wrote:
>Hi
>How can I programmatically get the scsi serial number & vendor id of a
>scsi device (vital product data)?
>I read a little about scsi-2 "inquiry" command, but is there a system
>library that provides access to it? Is this command available on
>scsi-3?
>Thanks
man scsi_inquiry(9S)
-Raf
|
|
0
|
|
|
|
Reply
|
raf
|
10/1/2003 5:20:08 PM
|
|
In article <bb6f754a.0310010851.d01b62e@posting.google.com>,
hamadani@uclink.berkeley.edu (babak) writes:
> Hi
> How can I programmatically get the scsi serial number & vendor id of a
> scsi device (vital product data)?
> I read a little about scsi-2 "inquiry" command, but is there a system
> library that provides access to it? Is this command available on
> scsi-3?
> Thanks
There isn't a function that does just that, but there is an ioctl that
will allow one to use all sorts of SCSI commands, although it's a bit
tedious to use. Newer versions (8 and later for sure) of Solaris document
it in the uscsi(7i) man page. And you have to be root to use the USCSICMD
ioctl, because it's potentially quite dangerous.
But it's no big deal to write a function to make it easier to use; in
fact, I just did it now (although I did have some similar code handy to
get it done faster). The first item below is just such a function. The
second is a simple main() function to exercise it, and finally there's
some sample output.
I don't think it cares what flavor of supported SCSI is involved. In
fact, it will even work on IDE or USB CD-ROM drives, although at present
it appears that it will _not_ work on IDE disk drives.
=========================== cut here ===========================
/* scsi-inquiry.c - wrap USCSICMD ioctl to make doing a SCSI inquiry easier */
/* Returns: -1 if error, else 0 */
#include <unistd.h>
#include <string.h>
#include <sys/scsi/generic/commands.h>
#include <sys/scsi/generic/inquiry.h>
#include <sys/scsi/impl/uscsi.h>
int
scsi_inquiry(int fd, struct scsi_inquiry *inq)
{
struct uscsi_cmd ucmd;
union scsi_cdb cdb;
memset(&cdb,0,sizeof(cdb));
memset(inq,0,sizeof(*inq));
memset(&ucmd,0,sizeof(ucmd));
ucmd.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
cdb.scc_cmd = SCMD_INQUIRY;
ucmd.uscsi_bufaddr = (caddr_t)inq;
ucmd.uscsi_buflen = cdb.g0_count0 = sizeof(*inq);
ucmd.uscsi_cdb=(caddr_t)&cdb;
ucmd.uscsi_cdblen=CDB_GROUP0;
return ioctl(fd, USCSICMD,&ucmd) == -1?-1:0;
}
=========================== cut here ===========================
=========================== cut here ===========================
/* scsi-inquiry-demo.c - a little main() to demonstrate scsi-inquiry.c */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
/* following required for scsi inquiry data structure */
#include <sys/scsi/generic/inquiry.h>
/* declaration of my function, assuming it may be in another object file */
extern int scsi_inquiry(int, struct scsi_inquiry *);
/* flavors or perror() that take extra args to be a bit more informative */
void perror3(const char *s1, const char *s2, const char *s3)
{
static const char colon_space[]={ ':',' '};
if (s1!=NULL && *s1!='\0') {
write(2,s1,strlen(s1));
write(2,colon_space,sizeof colon_space);
}
if (s2!=NULL && *s2!='\0') {
write(2,s2,strlen(s2));
write(2,colon_space,sizeof colon_space);
}
perror(s3);
}
void perror2(const char *s1, const char *s2)
{
static const char colon_space[]={ ':',' '};
if (s1!=NULL && *s1!='\0') {
write(2,s1,strlen(s1));
write(2,colon_space,sizeof colon_space);
}
perror(s2);
}
int
main(int argc, char **argv)
{
int fd, arg, err=0;
struct scsi_inquiry inq;
struct stat statb;
if (argc<2) {
fprintf(stderr,"usage: %s scsi_dev ...\n",argv[0]);
return 1;
}
for (arg=1;arg<argc;arg++) {
if ((fd=open(argv[arg],O_RDONLY)) == -1) {
perror3(argv[0],argv[arg],"open() failed");
++err;
continue;
}
if ((fstat(fd,&statb)) == -1) {
perror3(argv[0],argv[arg],"stat() failed");
++err;
close(fd);
continue;
}
if (!S_ISCHR(statb.st_mode)) {
fprintf(stderr,"%s: %s: not a character special device\n",
argv[0],argv[arg]);
++err;
close(fd);
continue;
}
if (scsi_inquiry(fd,&inq) == -1) {
perror3(argv[0],argv[arg],"scsi inquiry failed");
++err;
close(fd);
continue;
}
/* max field width as a parameter for the fields since they may not
be null-terminated */
printf("%s:\n\tVendor ID:\t%.*s\n\tProduct ID:\t%.*s\n\tRevision:\t%.*s\n\tSerial number: %.*s\n",
argv[arg],
sizeof(inq.inq_vid),inq.inq_vid,
sizeof(inq.inq_pid),inq.inq_pid,
sizeof(inq.inq_revision),inq.inq_revision,
sizeof(inq.inq_serial),inq.inq_serial);
close(fd);
}
if (err) /* i.e. 1 is for usage, anything higher is error count + 1 */
return err+1;
return 0;
}
=========================== cut here ===========================
sample output:
# scsi-inquiry /dev/rdsk/c0t0d0s2
/dev/rdsk/c0t0d0s2:
Vendor ID: SEAGATE
Product ID: ST31200N SUN1.05
Revision: 8722
Serial number: 00494102
(that was on a SPARC 10, running Solaris 8; probably not an original drive)
# scsi-inquiry /dev/rdsk/c0t1d0s2
/dev/rdsk/c0t1d0s2:
Vendor ID: LITEON
Product ID: DVD-ROM LTD163
Revision: GH4W
Serial number:
(that was on a Sun Blade 100 running Solaris 9, on which the original
LITEON CD-ROM was replaced with a LITEON DVD-ROM drive; note: I may have
reshuffled where the device was when I added an extra disk drive)
# scsi-inquiry /dev/rdsk/c1t0d0s2
/dev/rdsk/c1t0d0s2:
Vendor ID: IOMEGA
Product ID: CDRW960207DA1110
Revision: 0Sab
Serial number:
(that was on the same Sun Blade 100, showing an attached Iomega Predator
model CDRW9602EXT-B USB CDRW drive; for both the DVD-ROM and CDRW drives,
volume management was turned off to make this simpler, although it also
worked (but still only as root) with volume management on, as in
# scsi-inquiry /vol/dev/rdsk/c0t1d0/sol_9_803_sparc/s0
)
--
mailto:rlhamil@mindwarp.smart.net http://www.smart.net/~rlhamil
|
|
0
|
|
|
|
Reply
|
Richard
|
10/1/2003 8:01:31 PM
|
|
In article <c1Eeb.9099$UK3.5372@newssvr32.news.prodigy.com>,
raf@lapietra.org (Raf LaPietra) writes:
> In article <bb6f754a.0310010851.d01b62e@posting.google.com>,
> babak <hamadani@uclink.berkeley.edu> wrote:
>>Hi
>>How can I programmatically get the scsi serial number & vendor id of a
>>scsi device (vital product data)?
>>I read a little about scsi-2 "inquiry" command, but is there a system
>>library that provides access to it? Is this command available on
>>scsi-3?
>>Thanks
>
>
> man scsi_inquiry(9S)
Did you read it before posting? That just describes the data structure.
Section 9* commands describe material of interest to device driver writers
or others poking around at the innards of the kernel, not material of
interest to folks writing normal user-space programs.
--
mailto:rlhamil@mindwarp.smart.net http://www.smart.net/~rlhamil
|
|
0
|
|
|
|
Reply
|
Richard
|
10/1/2003 8:54:46 PM
|
|
Hi Richard
This is the result that I get:
> scsi-inquiry-demo /dev/dsk/c0t6d0s0
scsi-inquiry-demo: /dev/dsk/c0t6d0s0: open() failed: Device busy
Exit 2
Is there anything I can do about it?
Thanks
Richard.L.Hamilton@mindwarp.smart.net (Richard L. Hamilton) wrote in message news:<vnmckrc0gokbeb@corp.supernews.com>...
> In article <bb6f754a.0310010851.d01b62e@posting.google.com>,
> hamadani@uclink.berkeley.edu (babak) writes:
> > Hi
> > How can I programmatically get the scsi serial number & vendor id of a
> > scsi device (vital product data)?
> > I read a little about scsi-2 "inquiry" command, but is there a system
> > library that provides access to it? Is this command available on
> > scsi-3?
> > Thanks
>
> There isn't a function that does just that, but there is an ioctl that
> will allow one to use all sorts of SCSI commands, although it's a bit
> tedious to use. Newer versions (8 and later for sure) of Solaris document
> it in the uscsi(7i) man page. And you have to be root to use the USCSICMD
> ioctl, because it's potentially quite dangerous.
>
> But it's no big deal to write a function to make it easier to use; in
> fact, I just did it now (although I did have some similar code handy to
> get it done faster). The first item below is just such a function. The
> second is a simple main() function to exercise it, and finally there's
> some sample output.
>
> I don't think it cares what flavor of supported SCSI is involved. In
> fact, it will even work on IDE or USB CD-ROM drives, although at present
> it appears that it will _not_ work on IDE disk drives.
>
> =========================== cut here ===========================
> /* scsi-inquiry.c - wrap USCSICMD ioctl to make doing a SCSI inquiry easier */
> /* Returns: -1 if error, else 0 */
> #include <unistd.h>
> #include <string.h>
> #include <sys/scsi/generic/commands.h>
> #include <sys/scsi/generic/inquiry.h>
> #include <sys/scsi/impl/uscsi.h>
>
> int
> scsi_inquiry(int fd, struct scsi_inquiry *inq)
> {
> struct uscsi_cmd ucmd;
> union scsi_cdb cdb;
>
> memset(&cdb,0,sizeof(cdb));
> memset(inq,0,sizeof(*inq));
> memset(&ucmd,0,sizeof(ucmd));
>
> ucmd.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
> cdb.scc_cmd = SCMD_INQUIRY;
> ucmd.uscsi_bufaddr = (caddr_t)inq;
> ucmd.uscsi_buflen = cdb.g0_count0 = sizeof(*inq);
> ucmd.uscsi_cdb=(caddr_t)&cdb;
> ucmd.uscsi_cdblen=CDB_GROUP0;
>
> return ioctl(fd, USCSICMD,&ucmd) == -1?-1:0;
> }
> =========================== cut here ===========================
>
>
> =========================== cut here ===========================
> /* scsi-inquiry-demo.c - a little main() to demonstrate scsi-inquiry.c */
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <string.h>
> #include <unistd.h>
>
> /* following required for scsi inquiry data structure */
> #include <sys/scsi/generic/inquiry.h>
> /* declaration of my function, assuming it may be in another object file */
> extern int scsi_inquiry(int, struct scsi_inquiry *);
>
> /* flavors or perror() that take extra args to be a bit more informative */
> void perror3(const char *s1, const char *s2, const char *s3)
> {
> static const char colon_space[]={ ':',' '};
> if (s1!=NULL && *s1!='\0') {
> write(2,s1,strlen(s1));
> write(2,colon_space,sizeof colon_space);
> }
> if (s2!=NULL && *s2!='\0') {
> write(2,s2,strlen(s2));
> write(2,colon_space,sizeof colon_space);
> }
> perror(s3);
> }
> void perror2(const char *s1, const char *s2)
> {
> static const char colon_space[]={ ':',' '};
> if (s1!=NULL && *s1!='\0') {
> write(2,s1,strlen(s1));
> write(2,colon_space,sizeof colon_space);
> }
> perror(s2);
> }
>
> int
> main(int argc, char **argv)
> {
> int fd, arg, err=0;
> struct scsi_inquiry inq;
> struct stat statb;
>
> if (argc<2) {
> fprintf(stderr,"usage: %s scsi_dev ...\n",argv[0]);
> return 1;
> }
>
> for (arg=1;arg<argc;arg++) {
> if ((fd=open(argv[arg],O_RDONLY)) == -1) {
> perror3(argv[0],argv[arg],"open() failed");
> ++err;
> continue;
> }
> if ((fstat(fd,&statb)) == -1) {
> perror3(argv[0],argv[arg],"stat() failed");
> ++err;
> close(fd);
> continue;
> }
> if (!S_ISCHR(statb.st_mode)) {
> fprintf(stderr,"%s: %s: not a character special device\n",
> argv[0],argv[arg]);
> ++err;
> close(fd);
> continue;
> }
> if (scsi_inquiry(fd,&inq) == -1) {
> perror3(argv[0],argv[arg],"scsi inquiry failed");
> ++err;
> close(fd);
> continue;
> }
> /* max field width as a parameter for the fields since they may not
> be null-terminated */
> printf("%s:\n\tVendor ID:\t%.*s\n\tProduct ID:\t%.*s\n\tRevision:\t%.*s\n\tSerial number: %.*s\n",
> argv[arg],
> sizeof(inq.inq_vid),inq.inq_vid,
> sizeof(inq.inq_pid),inq.inq_pid,
> sizeof(inq.inq_revision),inq.inq_revision,
> sizeof(inq.inq_serial),inq.inq_serial);
> close(fd);
> }
> if (err) /* i.e. 1 is for usage, anything higher is error count + 1 */
> return err+1;
> return 0;
> }
> =========================== cut here ===========================
>
> sample output:
> # scsi-inquiry /dev/rdsk/c0t0d0s2
> /dev/rdsk/c0t0d0s2:
> Vendor ID: SEAGATE
> Product ID: ST31200N SUN1.05
> Revision: 8722
> Serial number: 00494102
>
>
> (that was on a SPARC 10, running Solaris 8; probably not an original drive)
>
> # scsi-inquiry /dev/rdsk/c0t1d0s2
> /dev/rdsk/c0t1d0s2:
> Vendor ID: LITEON
> Product ID: DVD-ROM LTD163
> Revision: GH4W
> Serial number:
>
> (that was on a Sun Blade 100 running Solaris 9, on which the original
> LITEON CD-ROM was replaced with a LITEON DVD-ROM drive; note: I may have
> reshuffled where the device was when I added an extra disk drive)
>
> # scsi-inquiry /dev/rdsk/c1t0d0s2
> /dev/rdsk/c1t0d0s2:
> Vendor ID: IOMEGA
> Product ID: CDRW960207DA1110
> Revision: 0Sab
> Serial number:
>
> (that was on the same Sun Blade 100, showing an attached Iomega Predator
> model CDRW9602EXT-B USB CDRW drive; for both the DVD-ROM and CDRW drives,
> volume management was turned off to make this simpler, although it also
> worked (but still only as root) with volume management on, as in
> # scsi-inquiry /vol/dev/rdsk/c0t1d0/sol_9_803_sparc/s0
> )
|
|
0
|
|
|
|
Reply
|
hamadani
|
10/2/2003 6:36:32 PM
|
|
In article <bb6f754a.0310021036.216acbc5@posting.google.com>,
hamadani@uclink.berkeley.edu (babak) writes:
> Hi Richard
> This is the result that I get:
>> scsi-inquiry-demo /dev/dsk/c0t6d0s0
> scsi-inquiry-demo: /dev/dsk/c0t6d0s0: open() failed: Device busy
> Exit 2
>
Probably vold is using it. Run
/usr/sbin/fuser /dev/rdsk/c0t6d0s*
Hopefully it will give you the PID of the process that's causing the
device to be busy. If appropriate, stop that process and try again.
--
mailto:rlhamil@mindwarp.smart.net http://www.smart.net/~rlhamil
|
|
0
|
|
|
|
Reply
|
Richard
|
10/2/2003 8:43:47 PM
|
|
|
5 Replies
837 Views
(page loaded in 0.082 seconds)
|