This is select.c in view mode; [Download] [Up]
/*
This program loads SCSI select page codes
*/
/*
USE AT YOUR OUR RISK.
I NOT NOT BE RESPONSIBLE FOR PROBLEM CAUSED BY THIS PROGRAM.
Note that I have only tested these programs on a small number of drives (see PARAMETERS directories). BE CAREFUL, if you do not know what you are doing, then I recommend that you not use it. But it is very useful for those people that do know.
*/
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <nextdev/scsireg.h>
static char *dev_name="/dev/sg0"; /* generic scsi interface */
#define MAX_inq_dat 64
#define MAX_mod_hdr 4
#define MAX_mod_bdf 16
#define MAX_mod_pag 64
#define MAX_mod_dat 64
#define MAX_mod_buf 256
int scsi_open(int target, int lun);
int gs_inquiry(int fd, int lun, int clen, u_char *data);
int gs_mode_select(int fd, int lun, int clen, u_char *data);
int gs_mode_sense(int fd, int lun, int ccode, int cfield, int clen, u_char *data);
int gs_request_sense(int fd, int lun);
struct MODBDF {
u_char data[MAX_mod_bdf];
u_char mask[MAX_mod_bdf];
};
struct MODPAG {
int flag;
u_char data[MAX_mod_dat];
u_char mask[MAX_mod_dat];
};
u_char inq_dat[MAX_inq_dat];
u_char mod_hdr[MAX_mod_hdr];
u_char mod_buf[MAX_mod_buf];
int mod_buf_len;
struct MODBDF mod_bdf;
struct MODPAG mod_pag[MAX_mod_pag];
main(int argc, char *argv[])
{
extern int optind;
extern char *optarg;
char c;
int mismatch;
FILE *infile;
int fd;
int target = -1;
int lun = -1;
infile = stdin;
while ((c = getopt(argc, argv, "t:l:f:")) != EOF) {
switch (c) {
case 't':
target = atoi(optarg);
break;
case 'l':
lun = atoi(optarg);
break;
case 'f':
if ( (infile=fopen(optarg, "r")) == NULL) {
fprintf(stdout,"Error opening input file");
exit(0);
}
break;
default:
fprintf(stderr,
"usage: %s -t<target> [-l<lun>] [-f inputfile]\n",
argv[0]);
exit(1);
}
}
if (target == -1) {
fprintf(stderr,
"usage: %s -t<target> [-l<lun>] [-f inputfile]\n",
argv[0]);
exit(1);
}
if (lun == -1) {
lun = 0;
}
get_input_data(infile);
if ((fd = scsi_open(target, lun)) < 0) {
fputs("error opening scsi device\n", stderr);
exit(1);
}
/*+start debug+/
fprintf(stdout,"Target %d, Handle %d, Lun %d\n",target,fd,lun);
/-end debug-*/
compare_inquire(fd, lun);
compare_mode_sense(fd, lun);
write_mode_select(fd, lun);
exit(0);
}
get_input_data(FILE *input_file)
{
char line[80];
int inq_len,mod_len;
int i,j,data,mask,page;
int done;
bzero(inq_dat,sizeof(inq_dat));
bzero(mod_hdr,sizeof(mod_hdr));
bzero(mod_bdf.data,sizeof(mod_bdf.data));
bzero(mod_bdf.mask,sizeof(mod_bdf.mask));
bzero(mod_pag,sizeof(mod_pag));
done = 1;
while (! feof(input_file) & done) {
fgets(line,sizeof(line),input_file);
line[sizeof(line)-1] = '\0';
if (!strncmp(line,"#",1)) {
continue;
} else if (!strncmp(line,"-ilen",5)) {
sscanf(&line[5],"%d",&inq_len);
if (inq_len > MAX_inq_dat) {
fprintf(stdout,"inq_len parameter %d greater than max %d\n"
,inq_len,MAX_inq_dat);
}
} else if (!strncmp(line,"-idat",5)) {
sscanf(&line[5],"%d %x",&i,&data);
if (i > MAX_inq_dat)
fprintf(stdout,"inq_dat parameter %d greater than max %d\n"
,i,MAX_inq_dat);
else inq_dat[i] = data & 0xff;
} else if (!strncmp(line,"-mlen",5)) {
sscanf(&line[3],"%d",&mod_len);
if (i > MAX_mod_dat)
fprintf(stdout,"mlen parameter %d greater than max %d\n"
,mod_len,MAX_mod_dat);
} else if (!strncmp(line,"-mhdr",5)) {
sscanf(&line[5],"%d %x %x",&i,&data,&mask);
if (i > MAX_mod_hdr)
fprintf(stdout,"mod_hdr parameter %d greater than max %d\n"
,i,MAX_mod_hdr);
else {
mod_hdr[i] = data & 0xff;
}
} else if (!strncmp(line,"-mbdf",5)) {
sscanf(&line[5],"%d %x %x",&i,&data,&mask);
if (i > MAX_mod_bdf)
fprintf(stdout,"mod_bdf parameter %d greater than max %d\n"
,i,MAX_mod_bdf);
else {
mod_bdf.data[i] = data & 0xff;
mod_bdf.mask[i] = mask & 0xff;
}
} else if (!strncmp(line,"-mp",3)) {
sscanf(&line[3],"%d %d %x %x",&page,&i,&data,&mask);
if (page > MAX_mod_pag)
fprintf(stdout,"page parameter %d greater than max %d\n"
,page,MAX_mod_pag);
else {
mod_pag[page].flag = 1;
if (i > MAX_mod_dat)
fprintf(stdout,"mod_pag.data parameter %d, for page %d greater than max %d\n"
,i,page,MAX_inq_dat);
else {
mod_pag[page].data[i] = data & 0xff;
mod_pag[page].mask[i] = mask & 0xff;
}
}
} else if (!strncmp(line,"end",3)) {
fprintf(stdout,"Encountered end statement\n");
done = 0;
} else {
fprintf(stdout,"Invalid input line\n");
fprintf(stdout,"%s",line);
}
}
fprintf(stdout,"Done reading input\n");
}
compare_inquire(int fd, int lun)
{
u_char new_dat[MAX_inq_dat];
char c;
int mismatch;
bzero(new_dat, sizeof(new_dat));
if(gs_inquiry(fd, lun, sizeof(new_dat), new_dat)) {
fputs("error in inquiry\n", stderr);
close(fd);
exit(1);
}
/*+start debug+/
for (mismatch=0; mismatch<inq_dat[4]+5; mismatch++)
fprintf(stdout," %2.2x",inq_dat[mismatch]);
fprintf(stdout,"\n");
for (mismatch=0; mismatch<new_dat[4]+5; mismatch++)
fprintf(stdout," %2.2x",new_dat[mismatch]);
fprintf(stdout,"\n");
/-end debug-*/
inq_dat[inq_dat[4]+5] = '\0';
new_dat[new_dat[4]+5] = '\0';
mismatch = 0;
if (new_dat[0] != inq_dat[0]) {
fprintf(stdout,"INQUIRY (byte 0)-Peripheral Device types not not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",inq_dat[0], new_dat[0]);
mismatch = 1;
}
if (new_dat[1] != inq_dat[1]) {
fprintf(stdout,"INQUIRY (byte 1)Device type qualifiers or RMB do not match \n");
fprintf(stdout," input=%2x, disk=%2x\n",inq_dat[1], new_dat[1]);
mismatch = 1;
}
if (new_dat[2] != inq_dat[2]) {
fprintf(stdout," INQUIRY (byte 2)-ANSI version's do not not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",inq_dat[2], new_dat[2]);
mismatch = 1;
}
if (new_dat[3] != inq_dat[3]) {
fprintf(stdout,"INQUIRY (byte 3)-Response Data Formats do not not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",inq_dat[3], new_dat[3]);
mismatch = 1;
}
if (new_dat[4] != inq_dat[4]) {
fprintf(stdout,"INQUIRY (byte 4)-Additional lengths do not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",inq_dat[4], new_dat[4]);
fprintf(stdout," (bytes 8-n)-Additional data\n");
fprintf(stdout," rest of input=\"%s\"\n",&inq_dat[8]);
fprintf(stdout," rest of disk =\"%s\"\n",&new_dat[8]);
mismatch = 1;
}
if (new_dat[5] != inq_dat[5]) {
fprintf(stdout,"INQUIRY (byte 5)-Request sense lengths do not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",inq_dat[5], new_dat[5]);
mismatch = 1;
}
if (strcmp(&new_dat[8],&inq_dat[8])) {
fprintf(stdout,"INQUIRY (bytes 8-n)-Additional data does not match\n");
fprintf(stdout," rest of input=\"%s\"\n",&inq_dat[8]);
fprintf(stdout," rest of disk =\"%s\"\n",&new_dat[8]);
mismatch = 1;
}
if (mismatch) {
if (feof(stdin))
c = 'n';
else {
fprintf(stdout,"Do you wish to continue? [y/n]: ");
gets(&c);
}
if (! (c == 'y' | c == 'Y')) {
fprintf(stdout,"exiting due to error in SCSI INQUIRY data\n");
exit(1);
} else
fprintf(stdout,"continuing to reselect drive\n");
}
}
compare_mode_sense(int fd, int lun)
{
struct MODPAG new_dat;
char c;
int mismatch,change,i,j,page,old,new;
u_char tmpmask;
/* compare header/bdf first, via SCSI MODE SENSE/PAGE 0 of current paramters (1)*/
bzero(new_dat.data, sizeof(new_dat.data));
bzero(new_dat.mask, sizeof(new_dat.mask));
bzero(mod_buf, sizeof(mod_buf));
mod_buf_len = 0;
mod_buf[0] = 0;
if(gs_mode_sense(fd, lun, 0, 1, sizeof(new_dat.mask), new_dat.mask)) {
fputs("error in MODE SENSE for header (page 0)\n", stderr);
close(fd);
exit(1);
}
if(gs_mode_sense(fd, lun, 0, 3, sizeof(new_dat.data), new_dat.data)) {
fputs("error in MODE SENSE for header (page 0)\n", stderr);
close(fd);
exit(1);
}
/*+start debug+/
for (mismatch=0; mismatch<new_dat.data[0]; mismatch++)
fprintf(stdout," %2.2x",new_dat.data[mismatch]);
fprintf(stdout,"\n");
for (mismatch=0; mismatch<new_dat.data[0]; mismatch++)
fprintf(stdout," %2.2x",new_dat.mask[mismatch]);
fprintf(stdout,"\n");
/-end debug-*/
mismatch = 0;
change = 0;
/*+start debug+*/
fprintf(stdout,"Compare header\n");
/*-end debug-*/
for (i = 1; i <= 3; i++) {
mod_buf_len++;
mod_buf[mod_buf_len] = mod_hdr[i];
}
if (new_dat.data[1] != mod_hdr[1]) {
fprintf(stdout,"MODE SENSE (header byte 1)-Medium type does not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",mod_hdr[1], new_dat.data[1]);
mismatch = 1;
}
if (new_dat.data[2] != mod_hdr[2]) {
fprintf(stdout,"MODE SENSE (header byte 2)-Write protect bit does not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",mod_hdr[2], new_dat.data[2]);
mismatch = 1;
}
if (new_dat.data[3] != mod_hdr[3]) {
fprintf(stdout,"MODE SENSE (header byte 3)-Block Descriptor Length does not match\n");
fprintf(stdout," input=%2x, disk=%2x\n",mod_hdr[3], new_dat.data[3]);
mismatch = 1;
} else for (i = 0; i < new_dat.data[3]; i++) {
mod_buf_len++;
tmpmask = mod_bdf.mask[i];
mod_buf[mod_buf_len] = (mod_bdf.data[i]&tmpmask) | (new_dat.data[i+4]&~tmpmask);
if ((new_dat.mask[i+4]|mod_bdf.mask[i]) != new_dat.mask[i+4]) {
fprintf(stdout,"MODE SENSE (BDF byte %4.4d)-input mask not subset of disk mask\n",i);
fprintf(stdout," input mask=%x, disk mask=%x\n",mod_bdf.mask[i],new_dat.mask[i+4]);
mismatch = 1;
}
if ((mod_bdf.data[i]&mod_bdf.mask[i]) != mod_bdf.data[i]) {
fprintf(stdout,"MODE SENSE (BDF byte %4.4d)-input value not subset of input mask\n",i);
fprintf(stdout," input value=%2.2x, input mask=%2.2x\n",mod_bdf.data[i],mod_bdf.mask[i]);
mismatch = 1;
}
if (mod_buf[mod_buf_len] != new_dat.data[i+4]) {
fprintf(stdout,"MODE SENSE (BDF byte %4.4d)-disk value will be changed\n",i);
fprintf(stdout," old value=%2.2x, new value=%2.2x\n",new_dat.data[i+4],mod_buf[mod_buf_len]);
change = 1;
}
}
/* compare page codes now, via SCSI MODE SENSE of current paramters (1)*/
for (page = 0; page < MAX_mod_pag; page++) {
if (mod_pag[page].flag != 0) {
/*+start debug+*/
fprintf(stdout,"Compare page %2.2d\n",page);
/*-end debug-*/
bzero(new_dat.data, sizeof(new_dat.data));
bzero(new_dat.mask, sizeof(new_dat.mask));
if(gs_mode_sense(fd, lun, page, 1, sizeof(new_dat.mask), new_dat.mask)) {
fprintf(stdout,"MODE SENSE error for page code %d reading masks\n",page);
mismatch = 1;
} else if(gs_mode_sense(fd, lun, page, 3, sizeof(new_dat.data), new_dat.data)) {
fprintf(stdout,"MODE SENSE error for page code %d reading data\n",page);
mismatch = 1;
} else {
i = new_dat.data[3]+4;
if (new_dat.data[0]+1 == i) {
fprintf(stdout,"MODE SENSE (Page %2.2d)-No such page code on disk\n",page);
mismatch = 1;
} else if ((new_dat.data[i]&63) != (mod_pag[page].data[0]&63)) {
fprintf(stdout,"MODE SENSE (Page %2.2d,byte-0)-Page code does not match\n",page);
fprintf(stdout
," input value=%2.2x, disk value=%2.2x\n"
,mod_pag[page].data[0],new_dat.data[i]);
mismatch = 1;
} else if ((new_dat.data[i]&128) != (mod_pag[page].data[0]&128)) {
fprintf(stdout,"MODE SENSE (Page %2.2d,byte-0)-PS bit does not match\n",page);
fprintf(stdout
," input value=%2.2x, disk value=%2.2x\n"
,mod_pag[page].data[0],new_dat.data[i]);
mismatch = 1;
} else if (new_dat.data[i+1] != mod_pag[page].data[1]) {
fprintf(stdout,"MODE SENSE (Page %2.2d,byte-1)-Page length does not match\n",page);
fprintf(stdout
," input value=%2.2x, disk value=%2.2x\n"
,mod_pag[page].data[1],new_dat.data[i+1]);
mismatch = 1;
} else for (j = 0; j < mod_pag[page].data[1]+2; j++) {
mod_buf_len++;
tmpmask = mod_pag[page].mask[j]&new_dat.mask[i+j];
if (j == 0) {
mod_buf[mod_buf_len] = mod_pag[page].data[0]&63;
new_dat.data[i] = new_dat.data[i]&63;
} else {
mod_buf[mod_buf_len] = (mod_pag[page].data[j]&tmpmask) | (new_dat.data[i+j]&~tmpmask);
}
if ((new_dat.mask[i+j]|mod_pag[page].mask[j]) != new_dat.mask[i+j]) {
fprintf(stdout
,"MODE SENSE (Page %2.2d byte %d)-input mask not subset of disk mask\n"
,page,j);
fprintf(stdout
," input mask=%2.2x, disk mask=%2.2x\n"
,mod_pag[page].mask[j],new_dat.mask[i+j]);
mismatch = 1;
} else if ((mod_pag[page].data[j]&mod_pag[page].mask[j]) != mod_pag[page].data[j]) {
fprintf(stdout,
"MODE SENSE (Page %2.2d byte %d)-input value not subset of input mask\n"
,page,j);
fprintf(stdout,
" input value=%2.2x, input mask=%2.2x\n"
,mod_pag[page].data[j],mod_pag[page].mask[j]);
mismatch = 1;
} else if (mod_buf[mod_buf_len] != new_dat.data[i+j]) {
fprintf(stdout,"MODE SENSE (Page %2.2d byte %d)-disk value will be changed\n",page,j);
fprintf(stdout," old value=%2.2x, new value=%2.2x\n",new_dat.data[i+j],mod_buf[mod_buf_len]);
change = 1;
}
}
}
}
}
if (mismatch) {
if (feof(stdin))
c = 'n';
else {
fprintf(stdout,"Do you wish to continue? [y/n]: ");
gets(&c);
}
if (! (c == 'y' | c == 'Y')) {
fprintf(stdout,"exiting due to error in SCSI SENSE MODE data\n");
exit(1);
} else
fprintf(stdout,"continuing to SELECT MODE drive\n");
}
}
write_mode_select(int fd, int lun)
{
char c;
int i;
mod_buf[0] = 0;
mod_buf_len++;
fprintf(stdout,"mod buffer output\n");
for (i = 0; i < mod_buf_len; i++) {
fprintf(stdout,"%2.2x %2.2x\n",i,mod_buf[i]);
}
if (feof(stdin))
c = 'n';
else {
fprintf(stdout,"Do you wish to continue with the scsi mode select of drive? [y/n]: ");
gets(&c);
}
if (! (c == 'y' | c == 'Y')) {
fprintf(stdout,"exiting without doing SCSI SELECT MODE\n");
exit(1);
} else {
fprintf(stdout,"continuing with doing SCSI SELECT MODE\n");
if(gs_mode_select(fd, lun, mod_buf_len, mod_buf)) {
fputs("error in mode select\n", stderr);
close(fd);
exit(1);
} else {
fputs("exiting SCSI SELECT MODE successfully completed\n",stderr);
}
}
}
int scsi_open(int target, int lun)
{
struct scsi_adr sa;
int fd;
if ((fd = open(dev_name, O_RDWR)) < 0) {
fprintf(stderr,"\nCould not open %s\n",dev_name);
return(-1);
}
sa.sa_target = target;
sa.sa_lun = lun;
if (ioctl(fd,SGIOCSTL,&sa) < 0) {
fprintf(stderr,"Error setting target %d lun %d\n",target,lun);
close(fd);
return(-1);
}
if(gs_request_sense(fd, lun)) { /* clear unit attention */
close(fd);
return(-1);
}
return(fd);
}
int gs_inquiry(int fd, int lun, int clen, u_char *data)
{
struct scsi_req sr;
struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
bzero((char *)&sr, sizeof(sr));
cdbp->c6_opcode = C6OP_INQUIRY;
cdbp->c6_lun = lun;
cdbp->c6_lba = 0;
cdbp->c6_len = clen;
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = (caddr_t)data;
sr.sr_dma_max = clen;
sr.sr_ioto = 10;
return(do_ioc(fd, &sr));
}
int gs_mode_select(int fd, int lun, int clen, u_char *ddat)
{
struct scsi_req sr;
struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
bzero((char *)&sr, sizeof(sr));
cdbp->c6_opcode = C6OP_MODESELECT;
cdbp->c6_lun = lun;
cdbp->c6_lba = 0x110000 ; /* use pf=1 & sp=1 to save parameters */
/* cdbp->c6_lba = (( (pf&1) << 21) | (sp&1) << 17);*/
cdbp->c6_len = clen;
sr.sr_dma_dir = SR_DMA_WR;
sr.sr_addr = (caddr_t)ddat;
sr.sr_dma_max = clen;
sr.sr_ioto = 10;
return(do_ioc(fd, &sr));
}
int gs_mode_sense(int fd, int lun, int ccode, int cfield, int clen, u_char *data)
{
struct scsi_req sr;
struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
bzero((char *)&sr, sizeof(sr));
cdbp->c6_opcode = C6OP_MODESENSE;
cdbp->c6_lun = lun;
cdbp->c6_lba = ((cfield << 14) & 0xc000) | ((ccode << 8) & 0x3f00);
cdbp->c6_len = clen;
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = (caddr_t)data;
sr.sr_dma_max = clen;
sr.sr_ioto = 10;
return(do_ioc(fd, &sr));
}
int do_ioc(int fd, struct scsi_req *sr)
{
if (ioctl(fd, SGIOCREQ, sr) < 0) {
perror("ioctl(SGIOCREQ)");
return(-1);
}
if(sr->sr_io_status) {
fprintf(stderr,"sr_io_status = 0x%02X\n",sr->sr_io_status);
if(sr->sr_io_status == SR_IOST_CHKSV) {
fprintf(stderr,
"sense key = 0x%02X, sense code = 0x%02X\n",
sr->sr_esense.er_sensekey,
sr->sr_esense.er_addsensecode);
}
fprintf(stderr,"SCSI status = 0x%02X\n", sr->sr_scsi_status);
return(-1);
}
return(0);
}
int gs_request_sense(int fd, int lun)
{
struct scsi_req sr;
struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
u_char sbuf[128];
bzero((char *)&sr, sizeof(sr));
cdbp->c6_opcode = C6OP_REQSENSE;
cdbp->c6_lun = lun;
cdbp->c6_len = 18;
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = (caddr_t)sbuf;
sr.sr_dma_max = 128;
sr.sr_ioto = 10;
return(do_ioc(fd, &sr));
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.