From ab9d3f8d54b803090dc9d293f37dce65152dac8c Mon Sep 17 00:00:00 2001 From: rgrimes Date: Sun, 5 Sep 1993 15:42:22 +0000 Subject: SCSI code update from Julian --- sys/scsi/scsi_tape.h | 4 +- sys/scsi/st.c | 456 ++++++++++++++++++++------------------------------- 2 files changed, 180 insertions(+), 280 deletions(-) (limited to 'sys') diff --git a/sys/scsi/scsi_tape.h b/sys/scsi/scsi_tape.h index 74e656c..eb46092 100644 --- a/sys/scsi/scsi_tape.h +++ b/sys/scsi/scsi_tape.h @@ -21,7 +21,7 @@ /* * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * - * $Id: scsi_tape.h,v 1.7 93/08/26 21:09:32 julian Exp Locker: julian $ + * $Id: scsi_tape.h,v 1.8 93/08/31 21:40:16 julian Exp Locker: julian $ */ @@ -196,5 +196,7 @@ struct blk_desc_cipher #define QIC_320 0x11 #define QIC_525 0x11 #define QIC_1320 0x12 +#define DDS 0x13 +#define DAT-1 0x13 diff --git a/sys/scsi/st.c b/sys/scsi/st.c index 75f994b..d0df2e8 100644 --- a/sys/scsi/st.c +++ b/sys/scsi/st.c @@ -21,13 +21,13 @@ * 16 Feb 93 Julian Elischer ADDED for SCSI system * 1.15 is the last verion to support MACH and OSF/1 */ -/* $Revision: 1.23 $ */ +/* $Revision: 1.25 $ */ /* * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993 * - * $Id: st.c,v 1.23 93/08/26 21:09:51 julian Exp Locker: julian $ + * $Id: st.c,v 1.25 93/08/31 21:29:41 julian Exp Locker: julian $ */ @@ -72,9 +72,9 @@ long int ststrats,stqueues; #define DSTY(z) ( ((minor(z) >> 2) & 0x03) ) #define UNIT(z) ( (minor(z) >> 4) ) -#define LOW_DSTY 3 -#define MED_DSTY 2 -#define HIGH_DSTY 1 +#define DSTY3 3 +#define DSTY2 2 +#define DSTY1 1 #define SCSI_2_MAX_DENSITY_CODE 0x17 /* maximum density code specified in SCSI II spec. */ @@ -103,6 +103,7 @@ struct rogues #define ST_Q_FORCE_FIXED_MODE 0x00002 #define ST_Q_FORCE_VAR_MODE 0x00004 #define ST_Q_SNS_HLP 0x00008 +#define ST_Q_IGNORE_LOADS 0x00010 static struct rogues gallery[] = /* ends with an all null entry */ { @@ -138,14 +139,6 @@ static struct rogues gallery[] = /* ends with an all null entry */ {0,QIC_24} /* minor 12,13,14,15*/ } }, - { "Wangdat Dat (1.3GB)", "WangDAT ", "Model 1300","????", - 0, - { {ST_Q_FORCE_VAR_MODE,0}, /* minor 0,1,2,3*/ - {ST_Q_SNS_HLP,0}, /* minor 4,5,6,7*/ - {ST_Q_FORCE_FIXED_MODE,0}, /* minor 8,9,10,11*/ - {ST_Q_FORCE_VAR_MODE,0} /* minor 12,13,14,15*/ - } - }, {(char *)0} }; @@ -257,9 +250,9 @@ struct scsi_switch *scsi_switch; /*******************************************************\ * Store information about default densities * \*******************************************************/ - st->modes[HIGH_DSTY].density = QIC_525; - st->modes[MED_DSTY].density = QIC_150; - st->modes[LOW_DSTY].density = QIC_120; + st->modes[DSTY1].density = QIC_525; + st->modes[DSTY2].density = QIC_150; + st->modes[DSTY3].density = QIC_120; /*******************************************************\ * Check if the drive is a known criminal and take * @@ -430,7 +423,7 @@ stopen(dev) * errors (the error handling will invalidate all our * * device info if we get one, but otherwise, ignore it * \*******************************************************/ - st_test_ready(unit, 0); + st_test_ready(unit, SCSI_SILENT); /***************************************************************\ * Check that the device is ready to use (media loaded?) * @@ -478,13 +471,13 @@ stopen(dev) * value to st_mode_sense incorrectly until the * * tape has actually passed by the head. * * * - * The method is to set the drive to fixed-block * - * state (user-specified density and 512-byte * - * blocks), then read and rewind to get it to * - * sense the tape. If the sense interpretation * - * code determines that the tape contains * - * variable-length blocks, set to variable-block * - * state and try again. The result will be the * + * The method is to set the drive to large * + * fixed-block state (user-specified density and * + * 1024-byte blocks), then read and rewind to * + * get it to sense the tape. If that doesn't * + * work, try 512-byte fixed blocks. If that * + * doesn't work, as a last resort, try variable- * + * length blocks. The result will be the * * ability to do an accurate st_mode_sense. * * * * We pretend not to be at beginning of medium * @@ -494,54 +487,49 @@ stopen(dev) * did a load, which implies rewind. Rewind * * seems preferable to space backward if we have * * a virgin tape. * - * * - * This is really a check fr 512 byte records * - * Needs more thought * + * * + * The rest of the code for this quirk is in ILI * + * processing and BLANK CHECK error processing, * + * both part of st_interpret_sense. * \***********************************************/ char *buf; + int readsiz; - buf = malloc(DEF_FIXED_BSIZE,M_TEMP,M_NOWAIT); + buf = malloc(1024,M_TEMP,M_NOWAIT); if(!buf) return(ENOMEM); if (errno = st_mode_sense(unit, 0)) { - free(buf,M_TEMP); - return(errno); - } - st->blksiz = DEF_FIXED_BSIZE; - st->flags = ~ST_AT_BOM & st->flags | ST_FIXEDBLOCKS; - if (errno = st_mode_select(unit, 0)) - { - free(buf,M_TEMP); - return(errno); + goto bad; } - st_read(unit, buf, DEF_FIXED_BSIZE, 0); - if (errno = st_rewind(unit, FALSE, 0)) - { - free(buf,M_TEMP); - return(errno); - } - if (st->blksiz == 0) /* set it back the way it was */ - { - st->flags &= ~(ST_FIXEDBLOCKS | ST_AT_BOM); + st->blksiz = 1024; + do { + switch (st->blksiz) + { + case 512: + case 1024: + readsiz = st->blksiz; + st->flags |= ST_FIXEDBLOCKS; + break; + default: + readsiz = 1; + st->flags &= ~ST_FIXEDBLOCKS; + } if (errno = st_mode_select(unit, 0)) { - free(buf,M_TEMP); - return(errno); + goto bad; } - st_read(unit, buf, 1, 0); + st->flags &= ~ST_AT_BOM; + st_read(unit, buf, readsiz, SCSI_SILENT); if (errno = st_rewind(unit, FALSE, 0)) { - free(buf,M_TEMP); +bad: free(buf,M_TEMP); return(errno); } - } + } while (readsiz != 1 && readsiz > st->blksiz); free(buf,M_TEMP); } } -#ifdef removing_this -#endif removing_this - /*******************************************************\ * Load the physical device parameters * @@ -561,6 +549,33 @@ stopen(dev) return(errno); } + if (!(st->flags & ST_INFO_VALID) && dsty == 0) + { + /*******************************************************\ + * If the user defaulted the density, use the drive's * + * opinion of it. * + \*******************************************************/ + st->quirks = st->drive_quirks; + st->density = st->media_density; + do { + if (st->density == st->modes[dsty].density) + { + st->quirks |= st->modes[dsty].quirks; +#ifdef STDEBUG + if(st_debug) printf("selected density %d\n", dsty); +#endif /*STDEBUG*/ + break; /* only out of the loop*/ + } + } while (++dsty < 4); + /*******************************************************\ + * If dsty got to 4, the drive must have reported a * + * density which isn't in our density list (e.g. QIC-24 * + * for a default drive). We can handle that, except * + * there'd better be no density-specific quirks in the * + * drive's behavior. * + \*******************************************************/ + } + st->flags |= ST_INFO_VALID; st_prevent(unit,PR_PREVENT,0); /* who cares if it fails? */ @@ -653,54 +668,14 @@ int unit, first_read; #endif /*STDEBUG*/ /***************************************************************\ - * Second, set the density, and set the quirk flags as a * - * function of the density. * - \***************************************************************/ - st->quirks = st->drive_quirks; - dsty = st->last_dsty; /* set in the open call */ - if (dsty > 0) - { - /*******************************************************\ - * If the user specified the density, believe him. * - \*******************************************************/ - st->density = st->modes[dsty].density; - st->quirks |= st->modes[dsty].quirks; - } - else - { - /*******************************************************\ - * If the user defaulted the density, use the drive's * - * opinion of it. * - \*******************************************************/ - st->density = st->media_density; - do { - if (st->density == st->modes[dsty].density) - { - st->quirks |= st->modes[dsty].quirks; -#ifdef STDEBUG - if(st_debug) printf("selected density %d\n",dsty); -#endif /*STDEBUG*/ - break; /* only out of the loop*/ - } - } while (++dsty < 4); - /*******************************************************\ - * If dsty got to 4, the drive must have reported a * - * density which isn't in our density list (e.g. QIC-24 * - * for a default drive). We can handle that, except * - * there'd better be no density-specific quirks in the * - * drive's behavior. * - \*******************************************************/ - } - - /***************************************************************\ * If the user has already specified fixed or variable-length * * blocks using an ioctl, just believe him. OVERRIDE ALL * \***************************************************************/ if (st->flags & ST_BLOCK_SET) { #ifdef STDEBUG - if(st_debug) printf("user has specified %s\n", - st->flags & ST_FIXEDBLOCKS ? "variable mode" : "fixed mode"); + if(st_debug) printf("user has specified %s mode\n", + st->flags & ST_FIXEDBLOCKS ? "fixed" : "variable"); #endif /*STDEBUG*/ goto done; } @@ -719,21 +694,21 @@ int unit, first_read; return (EINVAL); case ST_Q_FORCE_FIXED_MODE: st->flags |= ST_FIXEDBLOCKS; - if (st->blkmin && st->blkmin == st->blkmax) + if (st->blkmin && (st->blkmin == st->blkmax)) st->blksiz = st->blkmin; else if(st->media_blksiz > 0) st->blksiz = st->media_blksiz; else st->blksiz = DEF_FIXED_BSIZE; #ifdef STDEBUG - if(st_debug) printf("Quirks force fixed mode\n"); + if(st_debug) printf("Quirks force fixed mode\n"); #endif /*STDEBUG*/ goto done; case ST_Q_FORCE_VAR_MODE: st->flags &= ~ST_FIXEDBLOCKS; st->blksiz = 0; #ifdef STDEBUG - if(st_debug) printf("Quirks force variable mode\n"); + if(st_debug) printf("Quirks force variable mode\n"); #endif /*STDEBUG*/ goto done; } @@ -747,7 +722,7 @@ int unit, first_read; st->flags |= ST_FIXEDBLOCKS; st->blksiz = st->blkmin; #ifdef STDEBUG - if(st_debug) printf("blkmin == blkmax of %d\n",st->blkmin); + if(st_debug) printf("blkmin == blkmax of %d\n",st->blkmin); #endif /*STDEBUG*/ goto done; } @@ -761,6 +736,7 @@ int unit, first_read; case HALFINCH_800: case HALFINCH_1600: case HALFINCH_6250: + case DDS: st->flags &= ~ST_FIXEDBLOCKS; st->blksiz = 0; #ifdef STDEBUG @@ -786,7 +762,6 @@ int unit, first_read; * If we're about to read the tape, perhaps we should choose * * fixed or variable-length blocks and block size according to * * what the drive found on the tape. * - * ****though it probably hasn't looked yet!**** * \***************************************************************/ if (first_read) { @@ -796,33 +771,19 @@ int unit, first_read; st->flags |= ST_FIXEDBLOCKS; st->blksiz = st->media_blksiz; #ifdef STDEBUG - if(st_debug) printf("Used media_blksiz of %d\n",st->media_blksiz); -#endif /*STDEBUG*/ - goto done; - } - - /***************************************************************\ - * If the drive says it can handle variable size blocks * - * and nothing has been specified until now, hey let's do it * - \***************************************************************/ - if (st->blkmin != st->blkmax) - { - st->flags &= ~ST_FIXEDBLOCKS; - st->blksiz = 0; -#ifdef STDEBUG - if(st_debug) printf("blkmin != blkmax\n, select variable\n"); + if(st_debug) printf("Used media_blksiz of %d\n",st->media_blksiz); #endif /*STDEBUG*/ goto done; } /***************************************************************\ - * We're getting no hints from any direction. Choose fixed- * + * We're getting no hints from any direction. Choose variable- * * length blocks arbitrarily. * \***************************************************************/ - st->flags |= ST_FIXEDBLOCKS; - st->blksiz = DEF_FIXED_BSIZE; + st->flags &= ~ST_FIXEDBLOCKS; + st->blksiz = 0; #ifdef STDEBUG - if(st_debug) printf("Give up and default to fixed mode\n"); + if(st_debug) printf("Give up and default to variable mode\n"); #endif /*STDEBUG*/ done: st->flags &= ~ST_AT_BOM; @@ -955,14 +916,16 @@ caddr_t arg; unsigned int opri; int errcode = 0; unsigned char unit; - int number,flags; + int number,flags,dsty; struct st_data *st; + /*******************************************************\ * Find the device that the user is talking about * \*******************************************************/ flags = 0; /* give error messages, act on errors etc. */ unit = UNIT(dev); + dsty = DSTY(dev); st = st_data[unit]; switch(cmd) @@ -979,9 +942,10 @@ caddr_t arg; } else { g->mt_bsiz = 0; } - g->mt_dns_high = st->modes[HIGH_DSTY].density; - g->mt_dns_medium = st->modes[MED_DSTY].density; - g->mt_dns_low = st->modes[LOW_DSTY].density; + g->mt_dns_dflt = st->modes[0].density; + g->mt_dns_dsty1 = st->modes[DSTY1].density; + g->mt_dns_dsty2 = st->modes[DSTY2].density; + g->mt_dns_dsty3 = st->modes[DSTY3].density; break; } @@ -1037,21 +1001,26 @@ caddr_t arg; case MTNOCACHE: /* disable controller cache */ break; case MTSETBSIZ: /* Set block size for device */ - if (st->blkmin && st->blkmin == st->blkmax || - st->quirks & ST_Q_FORCE_FIXED_MODE) - /* Per definition in mtio.h, this is a */ - /* no-op for a real fixed block device */ - break; - if (!(st->flags & ST_AT_BOM) || number < 0 || number > 0 - && (number < st->blkmin || number > st->blkmax)) + if (!(st->flags & ST_AT_BOM)) { - errcode = EINVAL; + errcode = EINVAL; break; } if (number == 0) + { st->flags &= ~ST_FIXEDBLOCKS; + } else + { + if ((st->blkmin || st->blkmax) /* they exist */ + && ((number < st->blkmin + || number > st->blkmax))) + { + errcode = EINVAL; + break; + } st->flags |= ST_FIXEDBLOCKS; + } st->blksiz = number; st->flags |= ST_BLOCK_SET; break; @@ -1059,39 +1028,17 @@ caddr_t arg; /* How do we check that the drive can handle the requested density ? */ - case MTSETHDNSTY: /* Set high density defaults for device */ + case MTSETDNSTY: /* Set density for device and mode */ if (number < 0 || number > SCSI_2_MAX_DENSITY_CODE) { errcode = EINVAL; } else { - st->modes[HIGH_DSTY].density = number; - } - break; - - case MTSETMDNSTY: /* Set medium density defaults for device */ - if (number < 0 || number > SCSI_2_MAX_DENSITY_CODE) - { - errcode = EINVAL; - } - else - { - st->modes[MED_DSTY].density = number; + st->modes[dsty].density = number; } break; - case MTSETLDNSTY: /* Set low density defaults for device */ - if (number < 0 || number > SCSI_2_MAX_DENSITY_CODE) - { - errcode = EINVAL; - } - else - { - st->modes[LOW_DSTY].density = number; - } - break; - default: errcode = EINVAL; } @@ -1486,6 +1433,7 @@ int unit,type,flags; struct st_data *st = st_data[unit]; st->flags &= ~ST_PER_ACTION; + if(st->quirks & ST_Q_IGNORE_LOADS) return(0); bzero(&scsi_cmd, sizeof(scsi_cmd)); scsi_cmd.op_code = LOAD_UNLOAD; scsi_cmd.how=type; @@ -1822,7 +1770,7 @@ struct scsi_xfer *xs; break; case XS_TIMEOUT: - printf("st%d timeout\n",unit); + printf("st%d: timeout\n",unit); case XS_BUSY: /* should retry */ /* how? */ /************************************************/ @@ -2025,7 +1973,15 @@ struct scsi_xfer *xs; int silent = xs->flags & SCSI_SILENT; struct st_data *st = st_data[unit]; int info; - int errno = 0;/* default error */ + static char *error_mes[] = { "soft error (corrected)", + "not ready", "medium error", + "non-media hardware failure", "illegal request", + "unit attention", "tape is write-protected", + "no data found", "vendor unique", + "copy aborted", "command aborted", + "search returned equal", "volume overflow", + "verify miscompare", "unknown error key" + }; /***************************************************************\ * If errors are ok, report a success * @@ -2079,7 +2035,6 @@ struct scsi_xfer *xs; * If it's code 70, use the extended stuff and interpret the key * \***************************************************************/ case 0x70: - { if(st->flags & ST_FIXEDBLOCKS) { xs->resid = info * st->blksiz; @@ -2094,32 +2049,24 @@ struct scsi_xfer *xs; if(sense->ext.extended.flags & SSD_ILI) { st->flags |= ST_EIO_PENDING; - /*******************************************************\ - * The following quirk code deals with the fact that the * - * value of media_blksiz returned by the drive in * - * response to an st_mode_sense call doesn't reflect the * - * tape's format. * - * * - * The method is to try a fixed-length block read and * - * let this code determine whether the tape has fixed or * - * variable-length blocks, by seeing if we get an ILI * - * * - * Since the quirk code is the only place that calls the * - * board without the INFO_VALID set, catch that case * - * and handle it here (no other way of catching it * - * because resid info can't get passed without a buf) * - \*******************************************************/ - if ((st->quirks & ST_Q_SNS_HLP) - && !(st->flags & ST_INFO_VALID)) + /***************************************\ + * This quirk code helps the drive read * + * the first tape block, regardless of * + * format. That is required for these * + * drives to return proper MODE SENSE * + * information. * + \***************************************/ + if ((st->quirks & ST_Q_SNS_HLP) && + !(st->flags & ST_INFO_VALID)) { - st->blksiz = 0; + st->blksiz -= 512; } } /***********************************************\ * If no data was tranfered, do it immediatly * \***********************************************/ - if(xs->resid == xs->datalen) + if(xs->resid >= xs->datalen) { if(st->flags & ST_EIO_PENDING) { @@ -2149,8 +2096,10 @@ struct scsi_xfer *xs; * the record was bigger than the read * \***************************************/ { - printf("st%d: record of %d bytes too big\n", - unit, xs->datalen - info); + if (!silent) + printf("st%d: %d-byte record " + "too big\n", unit, + xs->datalen - info); return(EIO); } xs->resid = info; @@ -2158,133 +2107,82 @@ struct scsi_xfer *xs; }/* there may be some other error. check the rest */ key=sense->ext.extended.flags & SSD_KEY; - switch(key) + + if (!silent && key > 0) { - case 0x0: - if(xs->resid == xs->datalen) xs->resid = 0; - return(ESUCCESS); - case 0x1: - if(xs->resid == xs->datalen) xs->resid = 0; - if(!silent) + printf("st%d: %s", unit, error_mes[key - 1]); + if(sense->error_code & SSD_ERRCODE_VALID) { - printf("st%d: soft error(corrected)", unit); - if(sense->error_code & SSD_ERRCODE_VALID) + switch (key) { - printf("info = %d (decimal)", - info); + case 0x2: /* NOT READY */ + case 0x5: /* ILLEGAL REQUEST */ + case 0x6: /* UNIT ATTENTION */ + case 0x7: /* DATA PROTECT */ + break; + case 0x8: /* BLANK CHECK */ + printf(", requested size: %d (decimal)", + info); + break; + default: + printf(", info = %d (decimal)", info); } - printf("\n"); } + printf("\n"); + } + + switch (key) + { + case 0x0: /* NO SENSE */ + case 0x1: /* RECOVERED ERROR */ + if(xs->resid == xs->datalen) xs->resid = 0; + case 0xc: /* EQUAL */ return(ESUCCESS); - case 0x2: - if(!silent) printf("st%d: not ready\n", unit); + case 0x2: /* NOT READY */ return(ENODEV); - case 0x3: - if(!silent) - { - printf("st%d: medium error", unit); - if(sense->error_code & SSD_ERRCODE_VALID) - { - printf(" block no. %d (decimal)", - info); - } - printf("\n"); - } - return(EIO); - case 0x4: - if(!silent) printf("st%d: non-media hardware failure\n", - unit); - return(EIO); - case 0x5: - if(!silent) printf("st%d: illegal request\n", unit); + case 0x5: /* ILLEGAL REQUEST */ return(EINVAL); - case 0x6: - if(!silent) printf("st%d: Unit attention\n", unit); + case 0x6: /* UNIT ATTENTION */ st->flags &= ~ST_PER_MEDIA; if (st->flags & ST_OPEN) /* TEMP!!!! */ return(EIO); else return(ESUCCESS); - case 0x7: - if(!silent) - printf("st%d: tape is write protected\n", unit); + case 0x7: /* DATA PROTECT */ return(EACCES); - case 0x8: - if(!silent) - { - printf("st%d: no data found", unit); - if(sense->error_code & SSD_ERRCODE_VALID) - printf(": requested size: %d (decimal)", - info); - printf("\n"); - } - return(EIO); - case 0x9: - if(!silent) printf("st%d: vendor unique\n", - unit); - return(EIO); - case 0xa: - if(!silent) printf("st%d: copy aborted\n", - unit); - return(EIO); - case 0xb: - if(!silent) printf("st%d: command aborted\n", - unit); - return(EIO); - case 0xc: - if(!silent) - { - printf("st%d: search returned", unit); - if(sense->error_code & SSD_ERRCODE_VALID) - { - printf(" block no. %d (decimal)", - info); - } - printf("\n"); - } - return(ESUCCESS); - case 0xd: - if(!silent) printf("st%d: volume overflow\n", - unit); + case 0xd: /* VOLUME OVERFLOW */ return(ENOSPC); - case 0xe: - if(!silent) + case 0x8: /* BLANK CHECK */ + /***********************************************\ + * This quirk code helps the drive read the * + * first tape block, regardless of format. That * + * is required for these drives to return proper * + * MODE SENSE information. * + \***********************************************/ + if ((st->quirks & ST_Q_SNS_HLP) && + !(st->flags & ST_INFO_VALID)) { - printf("st%d: verify miscompare", unit); - if(sense->error_code & SSD_ERRCODE_VALID) - { - printf(" block no. %d (decimal)", - info); - } - printf("\n"); + st->blksiz -= 512; } - return(EIO); - case 0xf: - if(!silent) printf("st%d: unknown error key\n", - unit); + default: return(EIO); } - break; - } /***************************************************************\ * If it's NOT code 70, just report it. * \***************************************************************/ default: + if (!silent) { - if(!silent) printf("st%d: error code %d", - unit, + printf("st%d: error code %d", unit, sense->error_code & SSD_ERRCODE); if(sense->error_code & SSD_ERRCODE_VALID) { - if(!silent) - { - printf(" block no. %d (decimal)", - (sense->ext.unextended.blockhi <<16), - + (sense->ext.unextended.blockmed <<8), - + (sense->ext.unextended.blocklow )); - } - printf("\n"); + printf(" at block no. %d (decimal)", + (sense->ext.unextended.blockhi << 16) + + (sense->ext.unextended.blockmed << 8) + + sense->ext.unextended.blocklow); } + printf("\n"); } return(EIO); } -- cgit v1.1