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] & new_dat.mask[i+4]; 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; } else 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; } else 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] = mod_buf_len; 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.