From: phk@data.fls.dk (Poul-Henning Kamp)
Newsgroups: comp.sys.sun.admin
Subject: scsiping.c -- retreive SCSI-info from disk
Date: 13 Aug 92 10:51:09 GMT
Organization: FLS Data A/S, Valby, Copenhagen, Denmark.

Here is my scsiping program,
It runs on my sun's 4.1.2 It might work on yours too.
DO NOT trust the fields all too much, the "standards" are a bit thin yet...

enjoy...

Poul-Henning Kamp

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  scsiping.c
# Wrapped by phk@gimli on Thu Aug 13 12:49:00 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'scsiping.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scsiping.c'\"
else
echo shar: Extracting \"'scsiping.c'\" \(14506 characters\)
sed "s/^X//" >'scsiping.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <fcntl.h>
X#include <scsi/impl/types.h>
X#include <scsi/impl/uscsi.h>
X
X#define SUCCESS 0
X
Xunsigned char bdef[8000];
Xunsigned char bsav[8000];
Xunsigned char bcur[8000];
Xunsigned char bchg[8000];
Xint idef,isav,icur,ichg;
Xchar hostname[100];
X
Xmain(argc,argv)
X    int argc;
X    char **argv;
X    {
X    setbuf(stdout,0);
X    gethostname(hostname,100);
X    while(--argc)
X        Do(*++argv);
X    exit(0);
X    }
X
XHexDump(p,l,s)
X    unsigned char *p;
X    int l;
X    char *s;
X    {
X    int i;
X
X    while(l > 0)
X	{
X        printf("%s",s);
X	for(i=0;i<16;i++)
X	    {
X	    if(i<l)
X		printf("%02x ",p[i]);
X	    else
X		printf("   ");
X	    }
X	printf("   |");
X	for(i=0;i<16;i++)
X	    {
X	    if(i<l && p[i] >= ' ' && p[i] <= '~')
X		printf("%c",p[i]);
X	    else
X		printf(" ");
X	    }
X	printf("|\n");
X	l-=16;
X	p+=16;
X	}
X
X    }
X
XDo(arg)
X    char *arg;
X    {
X    int fd;
X    int i,j;
X    struct uscsi_cmd u,v,w;
X    unsigned char buf[8000],*p,*q,*r;
X    union scsi_cdb cdb;
X    char *s;
X    char f_ven[10];
X    char f_typ[30];
X    char f_rev[30];
X    int f_trks_zone=-1;
X    int f_asect=-1;
X    int f_atrks=-1;
X    int f_ncyl=-1;
X    int f_pcyl=-1;
X    int f_acyl=-1;
X    int f_nhead=-1;
X    int f_nsect=-1;
X    int f_rpm=-1;
X    int f_bpt=-1;
X    int f_mgmt=-1;
X    int f_capacity=-1;
X
X    if((fd=open(arg,O_RDONLY))<SUCCESS)
X	return;
X
X    i=strlen(arg)+strlen(hostname)+1;
X    while(i--)
X	putchar('=');
X    putchar('\n');
X    printf("%s %s\n",hostname,arg);
X    i=strlen(arg)+strlen(hostname)+1;
X    while(i--)
X	putchar('=');
X    putchar('\n');
X    
X    u.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
X    u.uscsi_bufaddr=(caddr_t)buf;
X    u.uscsi_buflen=8000;
X    memset(buf,0,8000);
X    cdb.scc_cmd = SCMD_READ_CAPACITY;
X    cdb.scc_lun = 0;
X    u.uscsi_cdb=(caddr_t)&cdb;
X    u.uscsi_cdblen=10;
X    i=ioctl(fd,USCSICMD,&u);
X    if(i != SUCCESS)
X	{
X	fprintf(stderr,"i=%d ",i);
X	perror("ioctl(READ_CAPACITY)");
X	}
X    printf("READ_CAPACITY:\n");
X    printf("    Capacity:               %d\n",
X        f_capacity=1+(buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]);
X
X    u.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
X    u.uscsi_bufaddr=(caddr_t)buf;
X    u.uscsi_buflen=8000;
X    memset(buf,0,8000);
X    cdb.scc_cmd = SCMD_INQUIRY;
X    cdb.scc_lun = 0;
X    cdb.g0_count0=200;
X    u.uscsi_cdb=(caddr_t)&cdb;
X    u.uscsi_cdblen=6;
X    i=ioctl(fd,USCSICMD,&u);
X    if(i != SUCCESS)
X	{
X	fprintf(stderr,"i=%d ",i);
X	perror("ioctl(SCSI_INQUIRY)");
X	}
X    printf("INQUIRY:\n");
X    printf("    Peripheral qualifier:   %d\n",(buf[0]>>5)&7);
X    printf("    Peripheral device-type: %d\n",buf[0]&0x1f);
X    printf("    Device-type modifier:   %d\n",buf[1]&0x7f);
X    printf("    Removable medium:       %d\n",(buf[1]>>7)&0x1);
X    printf("    ISO version:            %d\n",(buf[2]>>6)&0x3);
X    printf("    ECMA version:           %d\n",(buf[2]>>3)&0x7);
X    printf("    ANSI version:           %d\n",(buf[2]>>0)&0x7);
X    printf("    AENC:                   %d\n",(buf[3]>>7)&0x1);
X    printf("    TrmIOP:                 %d\n",(buf[3]>>6)&0x1);
X    printf("    Response data format:   %d\n",(buf[3]>>0)&0xf);
X    printf("    Relative addressing:    %d\n",(buf[7]>>7)&0x1);
X    printf("    Wide bus 32:            %d\n",(buf[7]>>6)&0x1);
X    printf("    Wide bus 16:            %d\n",(buf[7]>>5)&0x1);
X    printf("    Sync transfer:          %d\n",(buf[7]>>4)&0x1);
X    printf("    Linked commands:        %d\n",(buf[7]>>3)&0x1);
X    printf("    Command queing:         %d\n",(buf[7]>>1)&0x1);
X    printf("    Soft reset:             %d\n",(buf[7]>>0)&0x1);
X    printf("    Vendor:                 '%-8.8s'\n",buf+8);
X    printf("    Product:                '%-16.16s'\n",buf+16);
X    printf("    Revision:               '%-4.4s'\n",buf+32);
X    printf("    Comment1:               '%-20.20s'\n",buf+36);
X    printf("    Comment2:               '%-40.40s'\n",buf+56);
X    printf("    Comment3:               '%-40.40s'\n",buf+96);
X    strncpy(f_ven,buf+8,8);
X    for(s=f_ven+8-1;*s==' ';s--)
X        *s=0;
X    strncpy(f_typ,buf+16,16);
X    for(s=f_typ+16-1;*s==' ';s--)
X        *s=0;
X    strncpy(f_rev,buf+32,4);
X    for(s=f_rev+16-1;*s==' ';s--)
X        *s=0;
X
X    for(j=0;j<0x100;j+=0x40)
X	{
X	u.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
X	if(j==0x00) u.uscsi_bufaddr=(caddr_t)bcur;
X	if(j==0x40) u.uscsi_bufaddr=(caddr_t)bchg;
X	if(j==0x80) u.uscsi_bufaddr=(caddr_t)bdef;
X	if(j==0xc0) u.uscsi_bufaddr=(caddr_t)bsav;
X	u.uscsi_buflen=8000;
X	memset(u.uscsi_bufaddr,0,8000);
X	cdb.scc_cmd = SCMD_MODE_SENSE;
X	cdb.scc_lun = 0;
X	cdb.g0_addr1=0x3f | j;
X	cdb.g0_count0=255;
X	u.uscsi_cdb=(caddr_t)&cdb;
X	u.uscsi_cdblen=6;
X	i=ioctl(fd,USCSICMD,&u);
X	if(i != SUCCESS)
X	    {
X	    fprintf(stderr,"i=%d ",i);
X	    perror("ioctl(SCSI_MODE_SENSE)");
X	    }
X	}
X
X#define IFDIFF(idx,val)	if(bsav[idx] != val || bcur[idx] != val || bchg[idx] != val || bdef[idx] != val)
X#define IFUNEQ(idx)	if(bsav[idx] != bcur[idx] || bsav[idx] != bchg[idx] || bsav[idx] != bdef[idx])
X
X	isav=icur=ichg=idef=0;
X	IFUNEQ(0)
X	    { printf("unequal page length in MODE SENSE PAGE\n"); return; }
X        Pphead("*** Mode Sense:");
X	Pp1("Medium Type","%d",1);
X	Pp1("Device-specific","%d",2);
X	Pp1("Length of pages(@8)","%d",3);
X	isav=icur=ichg=idef=4;
X	IFDIFF(3,8)
X	    { printf("more than one page in MODE SENSE PAGE\n"); return; }
X	Pp1("Density code","%d",0);
X	Pp3("Number of blocks","%d",1);
X	Pp3("Block length","%d",5);
X	isav=icur=ichg=idef=12;
X	p=bdef+idef;
X	while(p < bdef+*bdef)
X	    {
X	    isav=icur=ichg=idef=p-bdef;
X	    sprintf(buf,"*** Page %02x:",*p&0x3f);
X	    Pphead(buf);
X	    IFUNEQ(isav+1)
X		{ printf("unequal page length in MODE SENSE PAGE\n"); return; }
X	    switch(*p & 0x3f)
X		{
X		case 0x03:
X		    Pp2("Tracks/zone","%d",2);
X		    Pp2("AltSect/zone","%d",4);
X		    Pp2("AltTrack/zone","%d",6);
X		    Pp2("AltTrack/LU","%d",8);
X		    Pp2("Sect/track","%d",10);
X		    Pp2("Byte/sect","%d",12);
X		    Pp2("InterLeave","%d",14);
X		    Pp2("Track skew","%d",16);
X		    Pp2("Cyl. skew","%d",18);
X		    break;
X		case 0x04:
X		    Pp3("Cylinders","%d",2);
X		    Pp1("Head","%d",5);
X		    Pp3("Precomp cyl","%d",6);
X		    Pp3("reduced cyl","%d",9);
X		    Pp2("Step rate","%d",12);
X		    Pp2("Landing zone","%d",14);
X		    Pp1("Rotation offset","%d",18);
X		    Pp2("RPM","%d",20);
X		    break;
X		}
X	    HexDump(bcur+icur,bcur[1+icur]+2,"    curr |");
X	    HexDump(bchg+ichg,bchg[1+ichg]+2,"    chg  |");
X	    HexDump(bdef+idef,bdef[1+idef]+2,"    def  |");
X	    HexDump(bsav+isav,bsav[1+isav]+2,"    save |");
X	    p+=p[1]+2;
X	    }
X	return;
X	}
X#if 0
X	{
X	{
X#define p2(x) ((p[x]<<8)+p[x+1])
X#define p3(x) ((p[x]<<16)+(p[x+1]<<8)+p[x+2])
X
X	while(p < buf+*buf)
X	    {
X	    printf("  Page %02x:\n",*p&0x3f);
X	    switch(*p & 0x3f)
X		{
X		case 0x01:
X		    printf("    AWRE:                   %d\n",p[2]&0x80?1:0);
X		    printf("    ARRE:                   %d\n",p[2]&0x40?1:0);
X		    printf("    TB:                     %d\n",p[2]&0x20?1:0);
X		    printf("    RC:                     %d\n",p[2]&0x10?1:0);
X		    printf("    ECC:                    %d\n",p[2]&0x08?1:0);
X		    printf("    PER:                    %d\n",p[2]&0x04?1:0);
X		    printf("    DTE:                    %d\n",p[2]&0x02?1:0);
X		    printf("    DCR:                    %d\n",p[2]&0x01?1:0);
X		    printf("    Read retry count:       %d\n",p[3]);
X		    printf("    Correction span:        %d\n",p[4]);
X		    printf("    Head offset count:      %d\n",p[5]);
X		    printf("    Data strobe off. cnt:   %d\n",p[6]);
X		    printf("    Write retry count:      %d\n",p[8]);
X		    printf("    Recovery time limit:    %d\n",p2(10));
X		    break;
X		case 0x02:
X		    printf("    Buffer full ratio:      %d\n",p[2]);
X		    printf("    Buffer empty ratio:     %d\n",p[3]);
X		    printf("    Bus inactivity limit:   %d\n",p2(4));
X		    printf("    Disc. time limit:       %d\n",p2(6));
X		    printf("    Conn. time limit:       %d\n",p2(8));
X		    printf("    Max burst size:         %d\n",p2(10));
X		    printf("    DTDC:                   %d\n",p[12]&3);
X		    break;
X		case 0x03:
X		    printf("    Tracks/zone:            %d\n",
X			f_trks_zone=(p[2]<<8)+p[3]);
X		    printf("    AltSect/zone:           %d\n",
X			f_asect=(p[4]<<8)+p[5]);
X		    printf("    AltTrack/zone:          %d\n",(p[6]<<8)+p[7]);
X		    printf("    AltTrack/LU:            %d\n",
X			f_atrks=(p[8]<<8)+p[9]);
X		    printf("    Sect/track:             %d\n",
X			f_nsect=(p[10]<<8)+p[11]);
X		    printf("    Byte/sect:              %d\n",(p[12]<<8)+p[13]);
X		    printf("    Interleave:             %d\n",(p[14]<<8)+p[15]);
X		    printf("    Track skew:             %d\n",(p[16]<<8)+p[17]);
X		    printf("    Cylinder skew:          %d\n",(p[18]<<8)+p[19]);
X		    printf("    SSEC:                   %d\n",p[20]&0x80?1:0);
X		    printf("    HSEC:                   %d\n",p[20]&0x40?1:0);
X		    printf("    RMB:                    %d\n",p[20]&0x20?1:0);
X		    printf("    SURF:                   %d\n",p[20]&0x10?1:0);
X		    break;
X		case 0x04:
X		    printf("    Cylinders:              %d\n",
X			f_pcyl=(p[2]<<16)+(p[3]<<8)+p[4]);
X		    printf("    Heads:                  %d\n",
X			f_nhead=p[5]);
X		    printf("    Write precomp start:    %d\n",p2(6));
X		    printf("    Write reduced start:    %d\n",p2(8));
X		    printf("    Drive step rate:        %d\n",p2(10));
X		    printf("    Landing zone:           %d\n",p2(12));
X		    printf("    Rotation pos. lock:     %d\n",(p[17]>>0) & 0x3);
X		    printf("    Rotation offset:        %d\n",p[18]);
X		    printf("    RPM:                    %d\n",f_rpm=p2(20));
X		    break;
X		case 0x07:
X		    printf("    ERR:                    %d\n",(p[2]>>3) & 0x1);
X		    printf("    PER:                    %d\n",(p[2]>>2) & 0x1);
X		    printf("    DTE:                    %d\n",(p[2]>>1) & 0x1);
X		    printf("    DCR:                    %d\n",(p[2]>>0) & 0x1);
X		    printf("    Verify retry count:     %d\n",p[3]);
X		    printf("    Verify retry span:      %d\n",p[4]);
X		    printf("    Recovery time limit:    %d\n",p2(10));
X		    break;
X		case 0x08:
X		    printf("    Write cache enable:     %d\n",(p[2]>>2) & 0x1);
X		    printf("    Multiplication factor:  %d\n",(p[2]>>1) & 0x1);
X		    printf("    Read cache disable:     %d\n",(p[2]>>0) & 0x1);
X		    printf("    Demand rd reten. pri:   %d\n",(p[3]>>4)&0x0f);
X		    printf("    Write reten. pri:       %d\n",(p[3]>>0)&0x0f);
X		    printf("    Dis. pre-fetch xfer-len:%d\n",p2(4));
X		    printf("    Minimum pre-fetch:      %d\n",p2(6));
X		    printf("    Maximum pre-fetch:      %d\n",p2(8));
X		    printf("    Max pre-fetch-ceil:     %d\n",p2(10));
X		    break;
X		case 0x09:
X		    printf("    Interface Identifier:   %d\n",p2(2));
X		    break;
X		case 0x0a:
X		    printf("    RLEC:                   %d\n",p[2] & 0x1);
X		    printf("    Queue Alg. modifier:    %d\n",(p[3]>>4) & 0xf);
X		    printf("    Queue Err. mgmt:        %d\n",(p[3]>>1) & 0x1);
X		    printf("    Disable queing:         %d\n",(p[3]>>0) & 0x1);
X		    printf("    EECA:                   %d\n",(p[4]>>7) & 0x1);
X		    printf("    RAENP:                  %d\n",(p[4]>>2) & 0x1);
X		    printf("    UAAENP:                 %d\n",(p[4]>>1) & 0x1);
X		    printf("    EAENP:                  %d\n",(p[4]>>0) & 0x1);
X		    printf("    EAN Holdoff:            %d\n",(p[6]<<8)+p[7]);
X		    break;
X		case 0x0b:
X		    printf("    Medium type 1:          %d\n",p[4]);
X		    printf("    Medium type 2:          %d\n",p[5]);
X		    printf("    Medium type 3:          %d\n",p[6]);
X		    printf("    Medium type 4:          %d\n",p[7]);
X		    break;
X		case 0x0c:
X		    printf("    Notched drive:          %d\n",(p[2]>>7) & 0x1);
X		    printf("    Log/Phys notch:         %d\n",(p[2]>>6) & 0x1);
X		    printf("    Max notches:            %d\n",p2(4));
X		    printf("    Active notch:           %d\n",p2(6));
X		    printf("    Start boundary:         %d\n",p2(8));
X		    printf("    End boundary:           %d\n",p2(10));
X		    printf("    Pages notched:          0x%04x\n",p2(12));
X		    break;
X		default:
X		    HexDump(p,p[1]+2);
X		    break;
X		}
X	    p+=p[1]+2;
X	    }
X	}
X    if(f_capacity != -1)
X	{
X	f_ncyl=f_capacity/(f_trks_zone*f_nsect-f_asect);
X	}
X    else
X	{
X	f_ncyl=f_pcyl-f_mgmt-f_atrks/f_nhead;
X	}
X    printf("\014");
X    printf("# Vendor   '%s'\n",f_ven);
X    printf("# Type     '%s'\n",f_typ);
X    printf("# Revision '%s'\n",f_rev);
X    printf("disk_type = \"%s %s (%s)\" \\\n",f_ven,f_typ,f_rev);
X    printf("\t: ctlr = MD21 \\\n");
X    printf("\t: pcyl = %d \\\n",f_pcyl);
X    printf("\t: ncyl = %d \\\n",f_ncyl);
X    printf("\t: nhead = %d \\\n",f_nhead);
X    printf("\t: nsect = %d \\\n",f_nsect);
X    printf("\t: atrks = %d \\\n",f_atrks);
X    printf("\t: asect = %d \\\n",f_asect);
X    printf("\t: trks_zone = %d \\\n",f_trks_zone);
X    printf("\t: rpm = %d \\\n",3600);
X    printf("\t: bpt = %d \n",36000);
X    printf("\n");
X    printf("# One zone = %d cyl\n",f_trks_zone/f_nhead);
X    printf("# One zone = %d blocks\n",(f_trks_zone*f_nsect-f_asect));
X    printf("# One zone = %d kB\n",(f_trks_zone*f_nsect-f_asect)/2);
X    printf("partition = \"%s %s (%s)\" \\\n",f_ven,f_typ,f_rev);
X    printf("\t: disk = \"%s %s (%s)\" \\\n",f_ven,f_typ,f_rev);
X    printf("\t: ctlr = MD21 \\\n");
X    printf("\t: c = 0, %d\n",
X        (f_ncyl*f_nhead)*(f_trks_zone*f_nsect-f_asect)/f_trks_zone);
X    }
X#endif
X
X#define q2(p,x) ((p[x]<<8)+p[x+1])
X#define q3(p,x) ((p[x]<<16)+(p[x+1]<<8)+p[x+2])
XPphead(s)
X    char *s;
X    {
X    printf("\n%-20s",s);
X    printf("%15s","curr");
X    printf("%15s","chg");
X    printf("%15s","def");
X    printf("%15s\n","save");
X    }
X
XPp1(ldr,fmt,idx)
X    char *ldr,*fmt;
X    int idx;
X    {
X    char s[20];
X    printf("%-20s",ldr);
X    sprintf(s,fmt,bcur[idx+icur]); printf("%15s",s);
X    sprintf(s,fmt,bchg[idx+ichg]); printf("%15s",s);
X    sprintf(s,fmt,bdef[idx+idef]); printf("%15s",s);
X    sprintf(s,fmt,bsav[idx+isav]); printf("%15s\n",s);
X    }
X
XPp2(ldr,fmt,idx)
X    char *ldr,*fmt;
X    int idx;
X    {
X    char s[20];
X    printf("%-20s",ldr);
X    sprintf(s,fmt,q2(bcur,idx+icur)); printf("%15s",s);
X    sprintf(s,fmt,q2(bchg,idx+ichg)); printf("%15s",s);
X    sprintf(s,fmt,q2(bdef,idx+idef)); printf("%15s",s);
X    sprintf(s,fmt,q2(bsav,idx+isav)); printf("%15s\n",s);
X    }
X
XPp3(ldr,fmt,idx)
X    char *ldr,*fmt;
X    int idx;
X    {
X    char s[20];
X    printf("%-20s",ldr);
X    sprintf(s,fmt,q3(bcur,idx+icur)); printf("%15s",s);
X    sprintf(s,fmt,q3(bchg,idx+ichg)); printf("%15s",s);
X    sprintf(s,fmt,q3(bdef,idx+idef)); printf("%15s",s);
X    sprintf(s,fmt,q3(bsav,idx+isav)); printf("%15s\n",s);
X    }
X
END_OF_FILE
if test 14506 -ne `wc -c <'scsiping.c'`; then
    echo shar: \"'scsiping.c'\" unpacked with wrong size!
fi
# end of 'scsiping.c'
fi
echo shar: End of shell archive.
exit 0
-- 
phk@data.fls.dk		  || If you can't join 'em -- beat 'em !
Poul-Henning Kamp	  ||			the Danish foreign minister
FLS DATA A/S		  ||
Phone: (+45) 36 18 12 35  ||
Newsgroups: comp.sys.sun.admin,alt.sys.sun,comp.sys.sun.misc,comp.sys.next.sysadmin