version 1.43, 1994/11/22 00:14:24 |
version 1.44, 1994/12/28 19:43:17 |
|
|
* and note how they are bad, so we can correct for them |
* and note how they are bad, so we can correct for them |
*/ |
*/ |
struct modes { |
struct modes { |
u_int blksiz; |
u_int quirks; /* same definitions as in quirkdata */ |
u_int quirks; /* same definitions as in rogues */ |
int blksize; |
char density; |
u_int8_t density; |
char spare[3]; |
|
}; |
}; |
|
|
struct rogues { |
struct quirkdata { |
char *manu; |
u_int quirks; |
char *model; |
#define ST_Q_FORCE_BLKSIZE 0x0001 |
char *version; |
#define ST_Q_SENSE_HELP 0x0002 /* must do READ for good MODE SENSE */ |
u_int quirks; /* valid for all modes */ |
#define ST_Q_IGNORE_LOADS 0x0004 |
|
#define ST_Q_BLKSIZE 0x0008 /* variable-block media_blksize > 0 */ |
u_int page_0_size; |
u_int page_0_size; |
#define MAX_PAGE_0_SIZE 64 |
#define MAX_PAGE_0_SIZE 64 |
struct modes modes[4]; |
struct modes modes[4]; |
}; |
}; |
|
|
/* define behaviour codes (quirks) */ |
struct st_quirk_inquiry_pattern { |
#define ST_Q_FORCE_FIXED_MODE 0x00002 |
struct scsi_inquiry_pattern pattern; |
#define ST_Q_FORCE_VAR_MODE 0x00004 |
struct quirkdata quirkdata; |
#define ST_Q_SENSE_HELP 0x00008 /* must do READ for good MODE SENSE */ |
}; |
#define ST_Q_IGNORE_LOADS 0x00010 |
|
#define ST_Q_BLKSIZ 0x00020 /* variable-block media_blksiz > 0 */ |
struct st_quirk_inquiry_pattern st_quirk_patterns[] = { |
|
{T_SEQUENTIAL, T_REMOV, |
static struct rogues gallery[] = /* ends with an all-null entry */ |
"unknown ", "unknown ", "????", 0, 0, { |
{ |
ST_Q_FORCE_BLKSIZE, 512, 0, /* minor 0-3 */ |
{"pre-scsi", " unknown model ", "????", |
ST_Q_FORCE_BLKSIZE, 512, QIC_24, /* minor 4-7 */ |
0, 0, |
ST_Q_FORCE_BLKSIZE, 0, HALFINCH_1600, /* minor 8-11 */ |
{ |
ST_Q_FORCE_BLKSIZE, 0, HALFINCH_6250 /* minor 12-15 */ |
{512, ST_Q_FORCE_FIXED_MODE, 0}, /* minor 0-3 */ |
}}, |
{512, ST_Q_FORCE_FIXED_MODE, QIC_24}, /* minor 4-7 */ |
{T_SEQUENTIAL, T_REMOV, |
{0, ST_Q_FORCE_VAR_MODE, HALFINCH_1600}, /* minor 8-11 */ |
"TANDBERG", " TDC 3600 ", "", 0, 12, { |
{0, ST_Q_FORCE_VAR_MODE, HALFINCH_6250} /* minor 12-15 */ |
0, 0, 0, /* minor 0-3 */ |
} |
ST_Q_FORCE_BLKSIZE, 0, QIC_525, /* minor 4-7 */ |
}, |
0, 0, QIC_150, /* minor 8-11 */ |
{"TANDBERG", " TDC 3600", "????", |
0, 0, QIC_120 /* minor 12-15 */ |
0, 12, |
}}, |
{ |
/* |
{0, 0, 0}, /* minor 0-3 */ |
* At least -005 and -007 need this. I'll assume they all do unless I |
{0, ST_Q_FORCE_VAR_MODE, QIC_525}, /* minor 4-7 */ |
* hear otherwise. - mycroft, 31MAR1994 |
{0, 0, QIC_150}, /* minor 8-11 */ |
*/ |
{0, 0, QIC_120} /* minor 12-15 */ |
{T_SEQUENTIAL, T_REMOV, |
} |
"ARCHIVE ", "VIPER 2525 25462", "", 0, 0, { |
}, |
ST_Q_SENSE_HELP, 0, 0, /* minor 0-3 */ |
/* |
ST_Q_SENSE_HELP, 0, QIC_525, /* minor 4-7 */ |
* At least -005 and -007 need this. I'll assume they all do unless I |
0, 0, QIC_150, /* minor 8-11 */ |
* hear otherwise. - mycroft, 31MAR1994 |
0, 0, QIC_120 /* minor 12-15 */ |
*/ |
}}, |
{"ARCHIVE ", "VIPER 2525 25462", "????", |
/* |
0, 0, |
* One user reports that this works for his tape drive. It probably |
{ |
* needs more work. - mycroft, 09APR1994 |
{0, ST_Q_SENSE_HELP, 0}, /* minor 0-3 */ |
*/ |
{0, ST_Q_SENSE_HELP, QIC_525}, /* minor 4-7 */ |
{T_SEQUENTIAL, T_REMOV, |
{0, 0, QIC_150}, /* minor 8-11 */ |
"SANKYO ", "CP525 ", "", 0, 0, { |
{0, 0, QIC_120} /* minor 12-15 */ |
ST_Q_FORCE_BLKSIZE, 512, 0, /* minor 0-3 */ |
} |
ST_Q_FORCE_BLKSIZE, 512, QIC_525, /* minor 4-7 */ |
}, |
0, 0, QIC_150, /* minor 8-11 */ |
/* |
0, 0, QIC_120 /* minor 12-15 */ |
* One user reports that this works for his tape drive. It probably |
}}, |
* needs more work. - mycroft, 09APR1994 |
{T_SEQUENTIAL, T_REMOV, |
*/ |
"ARCHIVE ", "VIPER 150 21247", "", 0, 12, { |
{"SANKYO ", "CP525", "????", |
0, 0, 0, /* minor 0-3 */ |
0, 0, |
0, 0, QIC_150, /* minor 4-7 */ |
{ |
0, 0, QIC_120, /* minor 8-11 */ |
{512, ST_Q_FORCE_FIXED_MODE, 0}, /* minor 0-3 */ |
0, 0, QIC_24 /* minor 12-15 */ |
{512, ST_Q_FORCE_FIXED_MODE, QIC_525}, /* minor 4-7 */ |
}}, |
{0, 0, QIC_150}, /* minor 8-11 */ |
{T_SEQUENTIAL, T_REMOV, |
{0, 0, QIC_120} /* minor 12-15 */ |
"WANGTEK ", "5525ES SCSI REV7", "", 0, 0, { |
} |
0, 0, 0, /* minor 0-3 */ |
}, |
ST_Q_BLKSIZE, 0, QIC_525, /* minor 4-7 */ |
{"ARCHIVE ", "VIPER 150", "????", |
0, 0, QIC_150, /* minor 8-11 */ |
0, 12, |
0, 0, QIC_120 /* minor 12-15 */ |
{ |
}}, |
{0, 0, 0}, /* minor 0-3 */ |
{T_SEQUENTIAL, T_REMOV, |
{0, 0, QIC_150}, /* minor 4-7 */ |
"WangDAT ", "Model 1300 ", "", 0, 0, { |
{0, 0, QIC_120}, /* minor 8-11 */ |
0, 0, 0, /* minor 0-3 */ |
{0, 0, QIC_24} /* minor 12-15 */ |
ST_Q_FORCE_BLKSIZE, 512, DDS, /* minor 4-7 */ |
} |
ST_Q_FORCE_BLKSIZE, 1024, DDS, /* minor 8-11 */ |
}, |
ST_Q_FORCE_BLKSIZE, 0, DDS /* minor 12-15 */ |
{"WANGTEK ", "5525ES SCSI REV7", "????", |
}}, |
0, 0, |
|
{ |
|
{0, 0, 0}, /* minor 0-3 */ |
|
{0, ST_Q_BLKSIZ, QIC_525}, /* minor 4-7 */ |
|
{0, 0, QIC_150}, /* minor 8-11 */ |
|
{0, 0, QIC_120} /* minor 12-15 */ |
|
} |
|
}, |
|
{"WangDAT ", "Model 1300", "????", |
|
0, 0, |
|
{ |
|
{0, 0, 0}, /* minor 0-3 */ |
|
{512, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 4-7 */ |
|
{1024, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 8-11 */ |
|
{0, ST_Q_FORCE_VAR_MODE, DDS} /* minor 12-15 */ |
|
} |
|
}, |
|
#if 0 |
#if 0 |
{"EXABYTE ", "EXB-8200", "????", |
{T_SEQUENTIAL, T_REMOV, |
0, 5, |
"EXABYTE ", "EXB-8200 ", "", 0, 12, { |
{ |
0, 0, 0, /* minor 0-3 */ |
{0, 0, 0}, /* minor 0-3 */ |
0, 0, 0, /* minor 4-7 */ |
{0, 0, 0}, /* minor 4-7 */ |
0, 0, 0, /* minor 8-11 */ |
{0, 0, 0}, /* minor 8-11 */ |
0, 0, 0 /* minor 12-15 */ |
{0, 0, 0} /* minor 12-15 */ |
}}, |
} |
|
}, |
|
#endif |
#endif |
{0} |
|
}; |
}; |
|
|
#define NOEJECT 0 |
#define NOEJECT 0 |
#define EJECT 1 |
#define EJECT 1 |
|
|
struct st_data { |
struct st_softc { |
struct device sc_dev; |
struct device sc_dev; |
/*--------------------present operating parameters, flags etc.----------------*/ |
/*--------------------present operating parameters, flags etc.----------------*/ |
int flags; /* see below */ |
int flags; /* see below */ |
u_int blksiz; /* blksiz we are using */ |
|
u_int density; /* present density */ |
|
u_int quirks; /* quirks for the open mode */ |
u_int quirks; /* quirks for the open mode */ |
|
int blksize; /* blksize we are using */ |
|
u_int8_t density; /* present density */ |
u_int page_0_size; /* size of page 0 data */ |
u_int page_0_size; /* size of page 0 data */ |
u_int last_dsty; /* last density openned */ |
u_int last_dsty; /* last density opened */ |
/*--------------------device/scsi parameters----------------------------------*/ |
/*--------------------device/scsi parameters----------------------------------*/ |
struct scsi_link *sc_link; /* our link to the adpter etc. */ |
struct scsi_link *sc_link; /* our link to the adpter etc. */ |
/*--------------------parameters reported by the device ----------------------*/ |
/*--------------------parameters reported by the device ----------------------*/ |
u_int blkmin; /* min blk size */ |
int blkmin; /* min blk size */ |
u_int blkmax; /* max blk size */ |
int blkmax; /* max blk size */ |
struct rogues *rogues; /* if we have a rogue entry */ |
struct quirkdata *quirkdata; /* if we have a rogue entry */ |
/*--------------------parameters reported by the device for this media--------*/ |
/*--------------------parameters reported by the device for this media--------*/ |
u_int numblks; /* nominal blocks capacity */ |
u_long numblks; /* nominal blocks capacity */ |
u_int media_blksiz; /* 0 if not ST_FIXEDBLOCKS */ |
int media_blksize; /* 0 if not ST_FIXEDBLOCKS */ |
u_int media_density; /* this is what it said when asked */ |
u_int8_t media_density; /* this is what it said when asked */ |
/*--------------------quirks for the whole drive------------------------------*/ |
/*--------------------quirks for the whole drive------------------------------*/ |
u_int drive_quirks; /* quirks of this drive */ |
u_int drive_quirks; /* quirks of this drive */ |
/*--------------------How we should set up when openning each minor device----*/ |
/*--------------------How we should set up when opening each minor device----*/ |
struct modes modes[4]; /* plus more for each mode */ |
struct modes modes[4]; /* plus more for each mode */ |
u_int8 modeflags[4]; /* flags for the modes */ |
u_int8_t modeflags[4]; /* flags for the modes */ |
#define DENSITY_SET_BY_USER 0x01 |
#define DENSITY_SET_BY_USER 0x01 |
#define DENSITY_SET_BY_QUIRK 0x02 |
#define DENSITY_SET_BY_QUIRK 0x02 |
#define BLKSIZE_SET_BY_USER 0x04 |
#define BLKSIZE_SET_BY_USER 0x04 |
Line 233 struct st_data { |
|
Line 213 struct st_data { |
|
* for mode sense/select. |
* for mode sense/select. |
*/ |
*/ |
struct buf buf_queue; /* the queue of pending IO operations */ |
struct buf buf_queue; /* the queue of pending IO operations */ |
struct scsi_xfer scsi_xfer; /* scsi xfer struct for this drive */ |
|
u_int xfer_block_wait; /* is a process waiting? */ |
|
}; |
}; |
|
|
|
int stmatch __P((struct device *, void *, void *)); |
void stattach __P((struct device *, struct device *, void *)); |
void stattach __P((struct device *, struct device *, void *)); |
|
|
struct cfdriver stcd = { |
struct cfdriver stcd = { |
NULL, "st", scsi_targmatch, stattach, DV_TAPE, sizeof(struct st_data) |
NULL, "st", stmatch, stattach, DV_TAPE, sizeof(struct st_softc) |
}; |
}; |
|
|
int st_space __P((struct st_data *, int number, u_int what, int flags)); |
int st_space __P((struct st_softc *, int number, u_int what, int flags)); |
int st_rewind __P((struct st_data *, u_int immediate, int flags)); |
int st_rewind __P((struct st_softc *, u_int immediate, int flags)); |
int st_mode_sense __P((struct st_data *, int flags)); |
int st_mode_sense __P((struct st_softc *, int flags)); |
int st_decide_mode __P((struct st_data *, boolean first_read)); |
int st_decide_mode __P((struct st_softc *, boolean first_read)); |
int st_read_block_limits __P((struct st_data *, int flags)); |
int st_read_block_limits __P((struct st_softc *, int flags)); |
int st_touch_tape __P((struct st_data *)); |
int st_touch_tape __P((struct st_softc *)); |
int st_write_filemarks __P((struct st_data *, int number, int flags)); |
int st_write_filemarks __P((struct st_softc *, int number, int flags)); |
int st_load __P((struct st_data *, u_int type, int flags)); |
int st_load __P((struct st_softc *, u_int type, int flags)); |
int st_mode_select __P((struct st_data *, int flags)); |
int st_mode_select __P((struct st_softc *, int flags)); |
void ststrategy(); |
void ststrategy(); |
void stminphys(); |
void stminphys(); |
int st_check_eod(); |
int st_check_eod(); |
Line 267 struct scsi_device st_switch = { |
|
Line 246 struct scsi_device st_switch = { |
|
ststart, |
ststart, |
NULL, |
NULL, |
NULL, |
NULL, |
"st", |
|
0 |
|
}; |
}; |
|
|
#define ST_INFO_VALID 0x0001 |
#define ST_INFO_VALID 0x0001 |
Line 290 struct scsi_device st_switch = { |
|
Line 267 struct scsi_device st_switch = { |
|
|
|
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ) |
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ) |
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \ |
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \ |
ST_FIXEDBLOCKS | ST_READONLY | \ |
ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \ |
ST_FM_WRITTEN | ST_2FM_AT_EOD | ST_PER_ACTION) |
ST_2FM_AT_EOD | ST_PER_ACTION) |
|
|
|
struct scsi_inquiry_pattern st_patterns[] = { |
|
{T_SEQUENTIAL, T_REMOV, |
|
"", "", ""}, |
|
}; |
|
|
|
int |
|
stmatch(parent, match, aux) |
|
struct device *parent; |
|
void *match, *aux; |
|
{ |
|
struct cfdata *cf = match; |
|
struct scsibus_attach_args *sa = aux; |
|
int priority; |
|
|
|
(void)scsi_inqmatch(sa->sa_inqbuf, |
|
(caddr_t)st_patterns, sizeof(st_patterns)/sizeof(st_patterns[0]), |
|
sizeof(st_patterns[0]), &priority); |
|
return (priority); |
|
} |
|
|
/* |
/* |
* The routine called by the low level scsi routine when it discovers |
* The routine called by the low level scsi routine when it discovers |
Line 302 stattach(parent, self, aux) |
|
Line 299 stattach(parent, self, aux) |
|
struct device *parent, *self; |
struct device *parent, *self; |
void *aux; |
void *aux; |
{ |
{ |
struct st_data *st = (void *)self; |
struct st_softc *st = (void *)self; |
struct scsi_link *sc_link = aux; |
struct scsibus_attach_args *sa = aux; |
|
struct scsi_link *sc_link = sa->sa_sc_link; |
|
|
SC_DEBUG(sc_link, SDEV_DB2, ("stattach: ")); |
SC_DEBUG(sc_link, SDEV_DB2, ("stattach: ")); |
|
|
sc_link->device = &st_switch; |
|
sc_link->device_softc = st; |
|
|
|
/* |
/* |
* Store information needed to contact our base driver |
* Store information needed to contact our base driver |
*/ |
*/ |
st->sc_link = sc_link; |
st->sc_link = sc_link; |
|
sc_link->device = &st_switch; |
|
sc_link->device_softc = st; |
|
sc_link->openings = 1; |
|
|
/* |
/* |
* Check if the drive is a known criminal and take |
* Check if the drive is a known criminal and take |
* Any steps needed to bring it into line |
* Any steps needed to bring it into line |
*/ |
*/ |
st_identify_drive(st); |
st_identify_drive(st, sa->sa_inqbuf); |
|
|
/* |
/* |
* Use the subdriver to request information regarding |
* Use the subdriver to request information regarding |
* the drive. We cannot use interrupts yet, so the |
* the drive. We cannot use interrupts yet, so the |
* request must specify this. |
* request must specify this. |
*/ |
*/ |
printf(": %s", st->rogues ? "rogue, " : ""); |
printf(": %s", st->quirkdata ? "rogue, " : ""); |
if (st_mode_sense(st, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) |
if (scsi_test_unit_ready(sc_link, |
printf("drive offline\n"); |
SCSI_AUTOCONF | SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE) || |
else if (scsi_test_unit_ready(sc_link, |
st_mode_sense(st, |
SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) |
SCSI_AUTOCONF | SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE)) |
printf("drive empty\n"); |
printf("drive empty\n"); |
else { |
else { |
printf("density code 0x%x, ", st->media_density); |
printf("density code 0x%x, ", st->media_density); |
if (st->media_blksiz) |
if (st->media_blksize > 0) |
printf("%d-byte", st->media_blksiz); |
printf("%d-byte", st->media_blksize); |
else |
else |
printf("variable"); |
printf("variable"); |
printf(" blocks, write-%s\n", |
printf(" blocks, write-%s\n", |
Line 355 stattach(parent, self, aux) |
|
Line 353 stattach(parent, self, aux) |
|
* Further tailor our behaviour. |
* Further tailor our behaviour. |
*/ |
*/ |
void |
void |
st_identify_drive(st) |
st_identify_drive(st, inqbuf) |
struct st_data *st; |
struct st_softc *st; |
{ |
struct scsi_inquiry_data *inqbuf; |
struct scsi_inquiry_data inqbuf; |
{ |
struct rogues *finger; |
struct st_quirk_inquiry_pattern *finger; |
char manu[32]; |
int priority; |
char model[32]; |
|
char model2[32]; |
finger = (struct st_quirk_inquiry_pattern *)scsi_inqmatch(inqbuf, |
char version[32]; |
(caddr_t)st_quirk_patterns, |
u_int model_len; |
sizeof(st_quirk_patterns)/sizeof(st_quirk_patterns[0]), |
|
sizeof(st_quirk_patterns[0]), &priority); |
/* |
if (priority != 0) { |
* Get the device type information |
st->quirkdata = &finger->quirkdata; |
*/ |
st->drive_quirks = finger->quirkdata.quirks; |
if (scsi_inquire(st->sc_link, &inqbuf, |
st->quirks = finger->quirkdata.quirks; /* start value */ |
SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT) != 0) { |
st->page_0_size = finger->quirkdata.page_0_size; |
printf("%s: couldn't get device type, using default\n", |
st_loadquirks(st); |
st->sc_dev.dv_xname); |
|
return; |
|
} |
|
if ((inqbuf.version & SID_ANSII) == 0) { |
|
/* |
|
* If not advanced enough, use default values |
|
*/ |
|
strncpy(manu, "pre-scsi", 8); |
|
manu[8] = 0; |
|
strncpy(model, " unknown model ", 16); |
|
model[16] = 0; |
|
strncpy(version, "????", 4); |
|
version[4] = 0; |
|
} else { |
|
strncpy(manu, inqbuf.vendor, 8); |
|
manu[8] = 0; |
|
strncpy(model, inqbuf.product, 16); |
|
model[16] = 0; |
|
strncpy(version, inqbuf.revision, 4); |
|
version[4] = 0; |
|
} |
|
|
|
/* |
|
* Load the parameters for this kind of device, so we |
|
* treat it as appropriate for each operating mode. |
|
* Only check the number of characters in the array's |
|
* model entry, not the entire model string returned. |
|
*/ |
|
finger = gallery; |
|
while (finger->manu) { |
|
model_len = 0; |
|
while (finger->model[model_len] && (model_len < 32)) { |
|
model2[model_len] = model[model_len]; |
|
model_len++; |
|
} |
|
model2[model_len] = 0; |
|
if ((strcmp(manu, finger->manu) == 0) && |
|
(strcmp(model2, finger->model) == 0 || |
|
strcmp("????????????????", finger->model) == 0) && |
|
(strcmp(version, finger->version) == 0 || |
|
strcmp("????", finger->version) == 0)) { |
|
st->rogues = finger; |
|
st->drive_quirks = finger->quirks; |
|
st->quirks = finger->quirks; /* start value */ |
|
st->page_0_size = finger->page_0_size; |
|
st_loadquirks(st); |
|
break; |
|
} else |
|
finger++; /* go to next suspect */ |
|
} |
} |
} |
} |
|
|
Line 431 st_identify_drive(st) |
|
Line 380 st_identify_drive(st) |
|
*/ |
*/ |
void |
void |
st_loadquirks(st) |
st_loadquirks(st) |
struct st_data *st; |
struct st_softc *st; |
{ |
{ |
int i; |
int i; |
struct modes *mode; |
struct modes *mode; |
struct modes *mode2; |
struct modes *mode2; |
|
|
if (!st->rogues) |
mode = st->quirkdata->modes; |
return; |
|
mode = st->rogues->modes; |
|
mode2 = st->modes; |
mode2 = st->modes; |
for (i = 0; i < 4; i++) { |
for (i = 0; i < 4; i++) { |
bzero(mode2, sizeof(struct modes)); |
bzero(mode2, sizeof(struct modes)); |
st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK | |
st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK | |
DENSITY_SET_BY_QUIRK | BLKSIZE_SET_BY_USER | |
DENSITY_SET_BY_QUIRK | BLKSIZE_SET_BY_USER | |
DENSITY_SET_BY_USER); |
DENSITY_SET_BY_USER); |
if (mode->blksiz && ((mode->quirks | st->drive_quirks) & |
if ((mode->quirks | st->drive_quirks) & ST_Q_FORCE_BLKSIZE) { |
ST_Q_FORCE_FIXED_MODE)) { |
mode2->blksize = mode->blksize; |
mode2->blksiz = mode->blksiz; |
|
st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK; |
|
} else if ((mode->quirks | st->drive_quirks) & |
|
ST_Q_FORCE_VAR_MODE) { |
|
mode2->blksiz = 0; |
|
st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK; |
st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK; |
} |
} |
if (mode->density) { |
if (mode->density) { |
Line 475 stopen(dev, flags) |
|
Line 417 stopen(dev, flags) |
|
int unit; |
int unit; |
u_int mode, dsty; |
u_int mode, dsty; |
int error = 0; |
int error = 0; |
struct st_data *st; |
struct st_softc *st; |
struct scsi_link *sc_link; |
struct scsi_link *sc_link; |
|
|
unit = STUNIT(dev); |
unit = STUNIT(dev); |
Line 503 stopen(dev, flags) |
|
Line 445 stopen(dev, flags) |
|
/* |
/* |
* Catch any unit attention errors. |
* Catch any unit attention errors. |
*/ |
*/ |
scsi_test_unit_ready(sc_link, SCSI_SILENT); |
if (error = scsi_test_unit_ready(sc_link, |
|
SCSI_IGNORE_MEDIA_CHANGE | (mode == CTLMODE ? SCSI_IGNORE_NOT_READY : 0))) |
|
goto bad; |
|
|
sc_link->flags |= SDEV_OPEN; /* unit attn are now errors */ |
sc_link->flags |= SDEV_OPEN; /* unit attn are now errors */ |
|
|
/* |
/* |
* If the mode is 3 (e.g. minor = 3,7,11,15) |
* If the mode is 3 (e.g. minor = 3,7,11,15) |
* then the device has been openned to set defaults |
* then the device has been opened to set defaults |
* This mode does NOT ALLOW I/O, only ioctls |
* This mode does NOT ALLOW I/O, only ioctls |
*/ |
*/ |
if (mode == CTLMODE) |
if (mode == CTLMODE) |
return 0; |
return 0; |
|
|
/* |
/* |
* Check that the device is ready to use (media loaded?) |
|
* This time take notice of the return result |
|
*/ |
|
if (scsi_test_unit_ready(sc_link, 0)) { |
|
SC_DEBUG(sc_link, SDEV_DB3, ("device not responding\n")); |
|
st_unmount(st, NOEJECT); |
|
error = EIO; |
|
goto bad; |
|
} |
|
|
|
/* |
|
* if it's a different mode, or if the media has been |
* if it's a different mode, or if the media has been |
* invalidated, unmount the tape from the previous |
* invalidated, unmount the tape from the previous |
* session but continue with open processing |
* session but continue with open processing |
Line 555 stopen(dev, flags) |
|
Line 488 stopen(dev, flags) |
|
return 0; |
return 0; |
|
|
bad: |
bad: |
|
st_unmount(st, NOEJECT); |
sc_link->flags &= ~SDEV_OPEN; |
sc_link->flags &= ~SDEV_OPEN; |
return error; |
return error; |
} |
} |
|
|
stclose(dev) |
stclose(dev) |
dev_t dev; |
dev_t dev; |
{ |
{ |
struct st_data *st = stcd.cd_devs[STUNIT(dev)]; |
struct st_softc *st = stcd.cd_devs[STUNIT(dev)]; |
|
|
SC_DEBUG(st->sc_link, SDEV_DB1, ("closing\n")); |
SC_DEBUG(st->sc_link, SDEV_DB1, ("closing\n")); |
if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN) |
if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN) |
Line 603 st_mount_tape(dev, flags) |
|
Line 537 st_mount_tape(dev, flags) |
|
{ |
{ |
int unit; |
int unit; |
u_int mode, dsty; |
u_int mode, dsty; |
struct st_data *st; |
struct st_softc *st; |
struct scsi_link *sc_link; |
struct scsi_link *sc_link; |
int error = 0; |
int error = 0; |
|
|
Line 631 st_mount_tape(dev, flags) |
|
Line 565 st_mount_tape(dev, flags) |
|
* these after doing a Load instruction. |
* these after doing a Load instruction. |
* (noteably some DAT drives) |
* (noteably some DAT drives) |
*/ |
*/ |
scsi_test_unit_ready(sc_link, SCSI_SILENT); |
scsi_test_unit_ready(sc_link, SCSI_SILENT); /* XXX */ |
|
|
/* |
/* |
* Some devices can't tell you much until they have been |
* Some devices can't tell you much until they have been |
Line 648 st_mount_tape(dev, flags) |
|
Line 582 st_mount_tape(dev, flags) |
|
return error; |
return error; |
/* |
/* |
* Load the media dependent parameters |
* Load the media dependent parameters |
* includes: media_blksiz,media_density,numblks |
* includes: media_blksize,media_density,numblks |
* As we have a tape in, it should be reflected here. |
* As we have a tape in, it should be reflected here. |
* If not you may need the "quirk" above. |
* If not you may need the "quirk" above. |
*/ |
*/ |
Line 670 st_mount_tape(dev, flags) |
|
Line 604 st_mount_tape(dev, flags) |
|
*/ |
*/ |
st->flags &= ~ST_FIXEDBLOCKS; |
st->flags &= ~ST_FIXEDBLOCKS; |
if (st->modeflags[dsty] & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) { |
if (st->modeflags[dsty] & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) { |
st->blksiz = st->modes[dsty].blksiz; |
st->blksize = st->modes[dsty].blksize; |
if (st->blksiz) |
if (st->blksize) |
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
} else { |
} else { |
if (error = st_decide_mode(st, FALSE)) |
if (error = st_decide_mode(st, FALSE)) |
Line 681 st_mount_tape(dev, flags) |
|
Line 615 st_mount_tape(dev, flags) |
|
printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname); |
printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname); |
return error; |
return error; |
} |
} |
scsi_prevent(sc_link, PR_PREVENT, 0); /* who cares if it fails? */ |
scsi_prevent(sc_link, PR_PREVENT, |
|
SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY); |
st->flags &= ~ST_NEW_MOUNT; |
st->flags &= ~ST_NEW_MOUNT; |
st->flags |= ST_MOUNTED; |
st->flags |= ST_MOUNTED; |
sc_link->flags |= SDEV_MEDIA_LOADED; /* move earlier? */ |
sc_link->flags |= SDEV_MEDIA_LOADED; /* move earlier? */ |
Line 697 st_mount_tape(dev, flags) |
|
Line 632 st_mount_tape(dev, flags) |
|
*/ |
*/ |
void |
void |
st_unmount(st, eject) |
st_unmount(st, eject) |
struct st_data *st; |
struct st_softc *st; |
boolean eject; |
boolean eject; |
{ |
{ |
struct scsi_link *sc_link = st->sc_link; |
struct scsi_link *sc_link = st->sc_link; |
Line 706 st_unmount(st, eject) |
|
Line 641 st_unmount(st, eject) |
|
if (!(st->flags & ST_MOUNTED)) |
if (!(st->flags & ST_MOUNTED)) |
return; |
return; |
SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n")); |
SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n")); |
st_check_eod(st, FALSE, &nmarks, SCSI_SILENT); |
st_check_eod(st, FALSE, &nmarks, SCSI_IGNORE_NOT_READY); |
st_rewind(st, 0, SCSI_SILENT); |
st_rewind(st, 0, SCSI_IGNORE_NOT_READY); |
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT); |
scsi_prevent(sc_link, PR_ALLOW, |
|
SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY); |
if (eject) |
if (eject) |
st_load(st, LD_UNLOAD, SCSI_SILENT); |
st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY); |
st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT); |
st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT); |
sc_link->flags &= ~SDEV_MEDIA_LOADED; |
sc_link->flags &= ~SDEV_MEDIA_LOADED; |
} |
} |
Line 722 st_unmount(st, eject) |
|
Line 658 st_unmount(st, eject) |
|
*/ |
*/ |
int |
int |
st_decide_mode(st, first_read) |
st_decide_mode(st, first_read) |
struct st_data *st; |
struct st_softc *st; |
boolean first_read; |
boolean first_read; |
{ |
{ |
#ifdef SCSIDEBUG |
#ifdef SCSIDEBUG |
Line 732 st_decide_mode(st, first_read) |
|
Line 668 st_decide_mode(st, first_read) |
|
SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n")); |
SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n")); |
|
|
/* |
/* |
* If the user hasn't already specified fixed or variable-length |
|
* blocks and the block size (zero if variable-length), we'll |
|
* have to try to figure them out ourselves. |
|
* |
|
* Our first shot at a method is, "The quirks made me do it!" |
|
*/ |
|
switch (st->quirks & (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE)) { |
|
case (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE): |
|
printf("%s: bad quirks\n", st->sc_dev.dv_xname); |
|
return EINVAL; |
|
case ST_Q_FORCE_FIXED_MODE: /*specified fixed, but not what size */ |
|
st->flags |= ST_FIXEDBLOCKS; |
|
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; |
|
SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force fixed mode(%d)\n", |
|
st->blksiz)); |
|
goto done; |
|
case ST_Q_FORCE_VAR_MODE: |
|
st->flags &= ~ST_FIXEDBLOCKS; |
|
st->blksiz = 0; |
|
SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force variable mode\n")); |
|
goto done; |
|
} |
|
|
|
/* |
|
* If the drive can only handle fixed-length blocks and only at |
* If the drive can only handle fixed-length blocks and only at |
* one size, perhaps we should just do that. |
* one size, perhaps we should just do that. |
*/ |
*/ |
if (st->blkmin && (st->blkmin == st->blkmax)) { |
if (st->blkmin && (st->blkmin == st->blkmax)) { |
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
st->blksiz = st->blkmin; |
st->blksize = st->blkmin; |
SC_DEBUG(sc_link, SDEV_DB3, |
SC_DEBUG(sc_link, SDEV_DB3, |
("blkmin == blkmax of %d\n", st->blkmin)); |
("blkmin == blkmax of %d\n", st->blkmin)); |
goto done; |
goto done; |
Line 781 st_decide_mode(st, first_read) |
|
Line 688 st_decide_mode(st, first_read) |
|
case HALFINCH_6250: |
case HALFINCH_6250: |
case DDS: |
case DDS: |
st->flags &= ~ST_FIXEDBLOCKS; |
st->flags &= ~ST_FIXEDBLOCKS; |
st->blksiz = 0; |
st->blksize = 0; |
SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n")); |
SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n")); |
goto done; |
goto done; |
case QIC_11: |
case QIC_11: |
Line 791 st_decide_mode(st, first_read) |
|
Line 698 st_decide_mode(st, first_read) |
|
case QIC_525: |
case QIC_525: |
case QIC_1320: |
case QIC_1320: |
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
if (st->media_blksiz > 0) |
if (st->media_blksize > 0) |
st->blksiz = st->media_blksiz; |
st->blksize = st->media_blksize; |
else |
else |
st->blksiz = DEF_FIXED_BSIZE; |
st->blksize = DEF_FIXED_BSIZE; |
SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n")); |
SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n")); |
goto done; |
goto done; |
} |
} |
Line 804 st_decide_mode(st, first_read) |
|
Line 711 st_decide_mode(st, first_read) |
|
* what the drive found on the tape. |
* what the drive found on the tape. |
*/ |
*/ |
if (first_read && |
if (first_read && |
(!(st->quirks & ST_Q_BLKSIZ) || (st->media_blksiz == 0) || |
(!(st->quirks & ST_Q_BLKSIZE) || (st->media_blksize == 0) || |
(st->media_blksiz == DEF_FIXED_BSIZE) || |
(st->media_blksize == DEF_FIXED_BSIZE) || |
(st->media_blksiz == 1024))) { |
(st->media_blksize == 1024))) { |
if (st->media_blksiz == 0) |
if (st->media_blksize > 0) |
st->flags &= ~ST_FIXEDBLOCKS; |
|
else |
|
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
st->blksiz = st->media_blksiz; |
else |
|
st->flags &= ~ST_FIXEDBLOCKS; |
|
st->blksize = st->media_blksize; |
SC_DEBUG(sc_link, SDEV_DB3, |
SC_DEBUG(sc_link, SDEV_DB3, |
("Used media_blksiz of %d\n", st->media_blksiz)); |
("Used media_blksize of %d\n", st->media_blksize)); |
goto done; |
goto done; |
} |
} |
/* |
/* |
Line 821 st_decide_mode(st, first_read) |
|
Line 728 st_decide_mode(st, first_read) |
|
* length blocks arbitrarily. |
* length blocks arbitrarily. |
*/ |
*/ |
st->flags &= ~ST_FIXEDBLOCKS; |
st->flags &= ~ST_FIXEDBLOCKS; |
st->blksiz = 0; |
st->blksize = 0; |
SC_DEBUG(sc_link, SDEV_DB3, |
SC_DEBUG(sc_link, SDEV_DB3, |
("Give up and default to variable mode\n")); |
("Give up and default to variable mode\n")); |
done: |
|
|
|
|
done: |
/* |
/* |
* Decide whether or not to write two file marks to signify end- |
* Decide whether or not to write two file marks to signify end- |
* of-data. Make the decision as a function of density. If |
* of-data. Make the decision as a function of density. If |
|
|
stminphys(bp) |
stminphys(bp) |
struct buf *bp; |
struct buf *bp; |
{ |
{ |
register struct st_data *st = stcd.cd_devs[STUNIT(bp->b_dev)]; |
register struct st_softc *st = stcd.cd_devs[STUNIT(bp->b_dev)]; |
|
|
(st->sc_link->adapter->scsi_minphys) (bp); |
(st->sc_link->adapter->scsi_minphys) (bp); |
} |
} |
|
|
ststrategy(bp) |
ststrategy(bp) |
struct buf *bp; |
struct buf *bp; |
{ |
{ |
struct st_data *st = stcd.cd_devs[STUNIT(bp->b_dev)]; |
struct st_softc *st = stcd.cd_devs[STUNIT(bp->b_dev)]; |
struct buf *dp; |
struct buf *dp; |
int opri; |
int opri; |
|
|
|
|
* Odd sized request on fixed drives are verboten |
* Odd sized request on fixed drives are verboten |
*/ |
*/ |
if (st->flags & ST_FIXEDBLOCKS) { |
if (st->flags & ST_FIXEDBLOCKS) { |
if (bp->b_bcount % st->blksiz) { |
if (bp->b_bcount % st->blksize) { |
printf("%s: bad request, must be multiple of %d\n", |
printf("%s: bad request, must be multiple of %d\n", |
st->sc_dev.dv_xname, st->blksiz); |
st->sc_dev.dv_xname, st->blksize); |
bp->b_error = EIO; |
bp->b_error = EIO; |
goto bad; |
goto bad; |
} |
} |
|
|
*/ |
*/ |
void |
void |
ststart(st) |
ststart(st) |
struct st_data *st; |
struct st_softc *st; |
{ |
{ |
struct scsi_link *sc_link = st->sc_link; |
struct scsi_link *sc_link = st->sc_link; |
register struct buf *bp, *dp; |
register struct buf *bp, *dp; |
|
|
* See if there is a buf to do and we are not already |
* See if there is a buf to do and we are not already |
* doing one |
* doing one |
*/ |
*/ |
while (sc_link->opennings) { |
while (sc_link->openings > 0) { |
/* if a special awaits, let it proceed first */ |
/* if a special awaits, let it proceed first */ |
if (sc_link->flags & SDEV_WAITING) { |
if (sc_link->flags & SDEV_WAITING) { |
sc_link->flags &= ~SDEV_WAITING; |
sc_link->flags &= ~SDEV_WAITING; |
|
|
*/ |
*/ |
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
if ((bp->b_flags & B_READ) == B_WRITE) { |
if ((bp->b_flags & B_READ) == B_WRITE) { |
cmd.op_code = WRITE; |
cmd.opcode = WRITE; |
st->flags &= ~ST_FM_WRITTEN; |
st->flags &= ~ST_FM_WRITTEN; |
st->flags |= ST_WRITTEN; |
st->flags |= ST_WRITTEN; |
flags = SCSI_DATA_OUT; |
flags = SCSI_DATA_OUT; |
} else { |
} else { |
cmd.op_code = READ; |
cmd.opcode = READ; |
flags = SCSI_DATA_IN; |
flags = SCSI_DATA_IN; |
} |
} |
|
|
|
|
*/ |
*/ |
if (st->flags & ST_FIXEDBLOCKS) { |
if (st->flags & ST_FIXEDBLOCKS) { |
cmd.byte2 |= SRW_FIXED; |
cmd.byte2 |= SRW_FIXED; |
lto3b(bp->b_bcount / st->blksiz, cmd.len); |
lto3b(bp->b_bcount / st->blksize, cmd.len); |
} else |
} else |
lto3b(bp->b_bcount, cmd.len); |
lto3b(bp->b_bcount, cmd.len); |
|
|
|
|
*/ |
*/ |
if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, |
if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd, |
sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 0, |
sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 0, |
100000, bp, flags | SCSI_NOSLEEP) != SUCCESSFULLY_QUEUED) |
100000, bp, flags | SCSI_NOSLEEP)) |
printf("%s: not queued\n", st->sc_dev.dv_xname); |
printf("%s: not queued\n", st->sc_dev.dv_xname); |
} /* go back and see if we can cram more work in.. */ |
} /* go back and see if we can cram more work in.. */ |
} |
} |
|
|
* knows about the internals of this device |
* knows about the internals of this device |
*/ |
*/ |
int |
int |
stioctl(dev, cmd, arg, flag) |
stioctl(dev, cmd, arg, flag, p) |
dev_t dev; |
dev_t dev; |
u_long cmd; |
u_long cmd; |
caddr_t arg; |
caddr_t arg; |
int flag; |
int flag; |
|
struct proc *p; |
{ |
{ |
int error = 0; |
int error = 0; |
int unit; |
int unit; |
int number, nmarks, dsty; |
int number, nmarks, dsty; |
int flags; |
int flags; |
struct st_data *st; |
struct st_softc *st; |
u_int hold_blksiz; |
int hold_blksize; |
u_int hold_density; |
u_int8_t hold_density; |
struct mtop *mt = (struct mtop *) arg; |
struct mtop *mt = (struct mtop *) arg; |
|
|
/* |
/* |
Line 1104 stioctl(dev, cmd, arg, flag) |
|
Line 1012 stioctl(dev, cmd, arg, flag) |
|
unit = STUNIT(dev); |
unit = STUNIT(dev); |
dsty = STDSTY(dev); |
dsty = STDSTY(dev); |
st = stcd.cd_devs[unit]; |
st = stcd.cd_devs[unit]; |
hold_blksiz = st->blksiz; |
hold_blksize = st->blksize; |
hold_density = st->density; |
hold_density = st->density; |
|
|
switch (cmd) { |
switch (cmd) { |
Line 1115 stioctl(dev, cmd, arg, flag) |
|
Line 1023 stioctl(dev, cmd, arg, flag) |
|
SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n")); |
SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n")); |
bzero(g, sizeof(struct mtget)); |
bzero(g, sizeof(struct mtget)); |
g->mt_type = 0x7; /* Ultrix compat *//*? */ |
g->mt_type = 0x7; /* Ultrix compat *//*? */ |
g->mt_blksiz = st->blksiz; |
g->mt_blksiz = st->blksize; |
g->mt_density = st->density; |
g->mt_density = st->density; |
g->mt_mblksiz[0] = st->modes[0].blksiz; |
g->mt_mblksiz[0] = st->modes[0].blksize; |
g->mt_mblksiz[1] = st->modes[1].blksiz; |
g->mt_mblksiz[1] = st->modes[1].blksize; |
g->mt_mblksiz[2] = st->modes[2].blksiz; |
g->mt_mblksiz[2] = st->modes[2].blksize; |
g->mt_mblksiz[3] = st->modes[3].blksiz; |
g->mt_mblksiz[3] = st->modes[3].blksize; |
g->mt_mdensity[0] = st->modes[0].density; |
g->mt_mdensity[0] = st->modes[0].density; |
g->mt_mdensity[1] = st->modes[1].density; |
g->mt_mdensity[1] = st->modes[1].density; |
g->mt_mdensity[2] = st->modes[2].density; |
g->mt_mdensity[2] = st->modes[2].density; |
Line 1193 stioctl(dev, cmd, arg, flag) |
|
Line 1101 stioctl(dev, cmd, arg, flag) |
|
} |
} |
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
} |
} |
st->blksiz = number; |
st->blksize = number; |
st->flags |= ST_BLOCK_SET; /*XXX */ |
st->flags |= ST_BLOCK_SET; /*XXX */ |
goto try_new_value; |
goto try_new_value; |
|
|
Line 1214 stioctl(dev, cmd, arg, flag) |
|
Line 1122 stioctl(dev, cmd, arg, flag) |
|
break; |
break; |
default: |
default: |
if (STMODE(dev) == CTLMODE) |
if (STMODE(dev) == CTLMODE) |
error = scsi_do_ioctl(st->sc_link, dev, cmd, arg, flag); |
error = scsi_do_ioctl(st->sc_link, dev, cmd, arg, flag, p); |
else |
else |
error = ENOTTY; |
error = ENOTTY; |
break; |
break; |
|
|
if (error = st_mode_select(st, 0)) { /* put it back as it was */ |
if (error = st_mode_select(st, 0)) { /* put it back as it was */ |
printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname); |
printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname); |
st->density = hold_density; |
st->density = hold_density; |
st->blksiz = hold_blksiz; |
st->blksize = hold_blksize; |
if (st->blksiz) |
if (st->blksize) |
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
else |
else |
st->flags &= ~ST_FIXEDBLOCKS; |
st->flags &= ~ST_FIXEDBLOCKS; |
|
|
/* XXX */ |
/* XXX */ |
switch ((short) (mt->mt_op)) { |
switch ((short) (mt->mt_op)) { |
case MTSETBSIZ: |
case MTSETBSIZ: |
st->modes[dsty].blksiz = st->blksiz; |
st->modes[dsty].blksize = st->blksize; |
st->modeflags[dsty] |= BLKSIZE_SET_BY_USER; |
st->modeflags[dsty] |= BLKSIZE_SET_BY_USER; |
break; |
break; |
case MTSETDNSTY: |
case MTSETDNSTY: |
|
|
*/ |
*/ |
int |
int |
st_read(st, buf, size, flags) |
st_read(st, buf, size, flags) |
struct st_data *st; |
struct st_softc *st; |
u_int size; |
int size; |
int flags; |
int flags; |
char *buf; |
char *buf; |
{ |
{ |
Line 1277 st_read(st, buf, size, flags) |
|
Line 1185 st_read(st, buf, size, flags) |
|
if (size == 0) |
if (size == 0) |
return 0; |
return 0; |
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = READ; |
cmd.opcode = READ; |
if (st->flags & ST_FIXEDBLOCKS) { |
if (st->flags & ST_FIXEDBLOCKS) { |
cmd.byte2 |= SRW_FIXED; |
cmd.byte2 |= SRW_FIXED; |
lto3b(size / (st->blksiz ? st->blksiz : DEF_FIXED_BSIZE), |
lto3b(size / (st->blksize ? st->blksize : DEF_FIXED_BSIZE), |
cmd.len); |
cmd.len); |
} else |
} else |
lto3b(size, cmd.len); |
lto3b(size, cmd.len); |
Line 1300 st_read(st, buf, size, flags) |
|
Line 1208 st_read(st, buf, size, flags) |
|
*/ |
*/ |
int |
int |
st_read_block_limits(st, flags) |
st_read_block_limits(st, flags) |
struct st_data *st; |
struct st_softc *st; |
int flags; |
int flags; |
{ |
{ |
struct scsi_block_limits cmd; |
struct scsi_block_limits cmd; |
Line 1318 st_read_block_limits(st, flags) |
|
Line 1226 st_read_block_limits(st, flags) |
|
* do a 'Read Block Limits' |
* do a 'Read Block Limits' |
*/ |
*/ |
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = READ_BLOCK_LIMITS; |
cmd.opcode = READ_BLOCK_LIMITS; |
|
|
/* |
/* |
* do the command, update the global values |
* do the command, update the global values |
Line 1332 st_read_block_limits(st, flags) |
|
Line 1240 st_read_block_limits(st, flags) |
|
st->blkmax = _3btol(&block_limits.max_length_2); |
st->blkmax = _3btol(&block_limits.max_length_2); |
|
|
SC_DEBUG(sc_link, SDEV_DB3, |
SC_DEBUG(sc_link, SDEV_DB3, |
("(%d <= blksiz <= %d)\n", st->blkmin, st->blkmax)); |
("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax)); |
return 0; |
return 0; |
} |
} |
|
|
Line 1348 st_read_block_limits(st, flags) |
|
Line 1256 st_read_block_limits(st, flags) |
|
*/ |
*/ |
int |
int |
st_mode_sense(st, flags) |
st_mode_sense(st, flags) |
struct st_data *st; |
struct st_softc *st; |
int flags; |
int flags; |
{ |
{ |
u_int scsi_sense_len; |
u_int scsi_sense_len; |
Line 1356 st_mode_sense(st, flags) |
|
Line 1264 st_mode_sense(st, flags) |
|
struct scsi_mode_sense cmd; |
struct scsi_mode_sense cmd; |
struct scsi_sense { |
struct scsi_sense { |
struct scsi_mode_header header; |
struct scsi_mode_header header; |
struct blk_desc blk_desc; |
struct scsi_blk_desc blk_desc; |
u_char sense_data[MAX_PAGE_0_SIZE]; |
u_char sense_data[MAX_PAGE_0_SIZE]; |
} scsi_sense; |
} scsi_sense; |
struct scsi_link *sc_link = st->sc_link; |
struct scsi_link *sc_link = st->sc_link; |
Line 1367 st_mode_sense(st, flags) |
|
Line 1275 st_mode_sense(st, flags) |
|
* Set up a mode sense |
* Set up a mode sense |
*/ |
*/ |
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = MODE_SENSE; |
cmd.opcode = MODE_SENSE; |
cmd.length = scsi_sense_len; |
cmd.length = scsi_sense_len; |
|
|
/* |
/* |
Line 1382 st_mode_sense(st, flags) |
|
Line 1290 st_mode_sense(st, flags) |
|
return error; |
return error; |
|
|
st->numblks = _3btol(scsi_sense.blk_desc.nblocks); |
st->numblks = _3btol(scsi_sense.blk_desc.nblocks); |
st->media_blksiz = _3btol(scsi_sense.blk_desc.blklen); |
st->media_blksize = _3btol(scsi_sense.blk_desc.blklen); |
st->media_density = scsi_sense.blk_desc.density; |
st->media_density = scsi_sense.blk_desc.density; |
if (scsi_sense.header.dev_spec & SMH_DSP_WRITE_PROT) |
if (scsi_sense.header.dev_spec & SMH_DSP_WRITE_PROT) |
st->flags |= ST_READONLY; |
st->flags |= ST_READONLY; |
SC_DEBUG(sc_link, SDEV_DB3, |
SC_DEBUG(sc_link, SDEV_DB3, |
("density code 0x%x, %d-byte blocks, write-%s, ", |
("density code 0x%x, %d-byte blocks, write-%s, ", |
st->media_density, st->media_blksiz, |
st->media_density, st->media_blksize, |
st->flags & ST_READONLY ? "protected" : "enabled")); |
st->flags & ST_READONLY ? "protected" : "enabled")); |
SC_DEBUG(sc_link, SDEV_DB3, |
SC_DEBUG(sc_link, SDEV_DB3, |
("%sbuffered\n", |
("%sbuffered\n", |
Line 1405 st_mode_sense(st, flags) |
|
Line 1313 st_mode_sense(st, flags) |
|
*/ |
*/ |
int |
int |
st_mode_select(st, flags) |
st_mode_select(st, flags) |
struct st_data *st; |
struct st_softc *st; |
int flags; |
int flags; |
{ |
{ |
u_int scsi_select_len; |
u_int scsi_select_len; |
Line 1413 st_mode_select(st, flags) |
|
Line 1321 st_mode_select(st, flags) |
|
struct scsi_mode_select cmd; |
struct scsi_mode_select cmd; |
struct scsi_select { |
struct scsi_select { |
struct scsi_mode_header header; |
struct scsi_mode_header header; |
struct blk_desc blk_desc; |
struct scsi_blk_desc blk_desc; |
u_char sense_data[MAX_PAGE_0_SIZE]; |
u_char sense_data[MAX_PAGE_0_SIZE]; |
} scsi_select; |
} scsi_select; |
struct scsi_link *sc_link = st->sc_link; |
struct scsi_link *sc_link = st->sc_link; |
Line 1424 st_mode_select(st, flags) |
|
Line 1332 st_mode_select(st, flags) |
|
* Set up for a mode select |
* Set up for a mode select |
*/ |
*/ |
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = MODE_SELECT; |
cmd.opcode = MODE_SELECT; |
cmd.length = scsi_select_len; |
cmd.length = scsi_select_len; |
|
|
bzero(&scsi_select, scsi_select_len); |
bzero(&scsi_select, scsi_select_len); |
scsi_select.header.blk_desc_len = sizeof(struct blk_desc); |
scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc); |
scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON; |
scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON; |
scsi_select.blk_desc.density = st->density; |
scsi_select.blk_desc.density = st->density; |
if (st->flags & ST_FIXEDBLOCKS) |
if (st->flags & ST_FIXEDBLOCKS) |
lto3b(st->blksiz, scsi_select.blk_desc.blklen); |
lto3b(st->blksize, scsi_select.blk_desc.blklen); |
if (st->page_0_size) |
if (st->page_0_size) |
bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size); |
bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size); |
|
|
Line 1449 st_mode_select(st, flags) |
|
Line 1357 st_mode_select(st, flags) |
|
*/ |
*/ |
int |
int |
st_space(st, number, what, flags) |
st_space(st, number, what, flags) |
struct st_data *st; |
struct st_softc *st; |
u_int what; |
u_int what; |
int flags; |
int flags; |
int number; |
int number; |
Line 1518 st_space(st, number, what, flags) |
|
Line 1426 st_space(st, number, what, flags) |
|
return 0; |
return 0; |
|
|
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = SPACE; |
cmd.opcode = SPACE; |
cmd.byte2 = what; |
cmd.byte2 = what; |
lto3b(number, cmd.number); |
lto3b(number, cmd.number); |
|
|
Line 1531 st_space(st, number, what, flags) |
|
Line 1439 st_space(st, number, what, flags) |
|
*/ |
*/ |
int |
int |
st_write_filemarks(st, number, flags) |
st_write_filemarks(st, number, flags) |
struct st_data *st; |
struct st_softc *st; |
int flags; |
int flags; |
int number; |
int number; |
{ |
{ |
Line 1558 st_write_filemarks(st, number, flags) |
|
Line 1466 st_write_filemarks(st, number, flags) |
|
} |
} |
|
|
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = WRITE_FILEMARKS; |
cmd.opcode = WRITE_FILEMARKS; |
lto3b(number, cmd.number); |
lto3b(number, cmd.number); |
|
|
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd, |
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd, |
Line 1575 st_write_filemarks(st, number, flags) |
|
Line 1483 st_write_filemarks(st, number, flags) |
|
*/ |
*/ |
int |
int |
st_check_eod(st, position, nmarks, flags) |
st_check_eod(st, position, nmarks, flags) |
struct st_data *st; |
struct st_softc *st; |
boolean position; |
boolean position; |
int *nmarks; |
int *nmarks; |
int flags; |
int flags; |
Line 1604 st_check_eod(st, position, nmarks, flags |
|
Line 1512 st_check_eod(st, position, nmarks, flags |
|
*/ |
*/ |
int |
int |
st_load(st, type, flags) |
st_load(st, type, flags) |
struct st_data *st; |
struct st_softc *st; |
u_int type; |
u_int type; |
int flags; |
int flags; |
{ |
{ |
Line 1622 st_load(st, type, flags) |
|
Line 1530 st_load(st, type, flags) |
|
return 0; |
return 0; |
|
|
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = LOAD; |
cmd.opcode = LOAD; |
cmd.how = type; |
cmd.how = type; |
|
|
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd, |
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd, |
Line 1634 st_load(st, type, flags) |
|
Line 1542 st_load(st, type, flags) |
|
*/ |
*/ |
int |
int |
st_rewind(st, immediate, flags) |
st_rewind(st, immediate, flags) |
struct st_data *st; |
struct st_softc *st; |
u_int immediate; |
u_int immediate; |
int flags; |
int flags; |
{ |
{ |
Line 1648 st_rewind(st, immediate, flags) |
|
Line 1556 st_rewind(st, immediate, flags) |
|
st->flags &= ~ST_PER_ACTION; |
st->flags &= ~ST_PER_ACTION; |
|
|
bzero(&cmd, sizeof(cmd)); |
bzero(&cmd, sizeof(cmd)); |
cmd.op_code = REWIND; |
cmd.opcode = REWIND; |
cmd.byte2 = immediate; |
cmd.byte2 = immediate; |
|
|
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd, |
return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd, |
Line 1667 st_interpret_sense(xs) |
|
Line 1575 st_interpret_sense(xs) |
|
{ |
{ |
struct scsi_link *sc_link = xs->sc_link; |
struct scsi_link *sc_link = xs->sc_link; |
struct scsi_sense_data *sense = &xs->sense; |
struct scsi_sense_data *sense = &xs->sense; |
boolean silent = xs->flags & SCSI_SILENT; |
|
struct buf *bp = xs->bp; |
struct buf *bp = xs->bp; |
struct st_data *st = sc_link->device_softc; |
struct st_softc *st = sc_link->device_softc; |
u_int key; |
u_int8_t key; |
int info; |
u_int32_t info; |
|
|
/* |
/* |
* Get the sense fields and work out what code |
* Get the sense fields and work out what code |
Line 1684 st_interpret_sense(xs) |
|
Line 1591 st_interpret_sense(xs) |
|
if ((sense->error_code & SSD_ERRCODE) != 0x70) |
if ((sense->error_code & SSD_ERRCODE) != 0x70) |
return -1; /* let the generic code handle it */ |
return -1; /* let the generic code handle it */ |
if (st->flags & ST_FIXEDBLOCKS) { |
if (st->flags & ST_FIXEDBLOCKS) { |
xs->resid = info * st->blksiz; |
xs->resid = info * st->blksize; |
if (sense->extended_flags & SSD_EOM) { |
if (sense->extended_flags & SSD_EOM) { |
st->flags |= ST_EIO_PENDING; |
st->flags |= ST_EIO_PENDING; |
if (bp) |
if (bp) |
Line 1699 st_interpret_sense(xs) |
|
Line 1606 st_interpret_sense(xs) |
|
st->flags |= ST_EIO_PENDING; |
st->flags |= ST_EIO_PENDING; |
if (bp) |
if (bp) |
bp->b_resid = xs->resid; |
bp->b_resid = xs->resid; |
if (sense->error_code & SSD_ERRCODE_VALID && !silent) |
if (sense->error_code & SSD_ERRCODE_VALID && |
|
(xs->flags & SCSI_SILENT) == 0) |
printf("%s: block wrong size, %d blocks residual\n", |
printf("%s: block wrong size, %d blocks residual\n", |
st->sc_dev.dv_xname, info); |
st->sc_dev.dv_xname, info); |
|
|
Line 1712 st_interpret_sense(xs) |
|
Line 1620 st_interpret_sense(xs) |
|
*/ |
*/ |
if ((st->quirks & ST_Q_SENSE_HELP) && |
if ((st->quirks & ST_Q_SENSE_HELP) && |
!(sc_link->flags & SDEV_MEDIA_LOADED)) |
!(sc_link->flags & SDEV_MEDIA_LOADED)) |
st->blksiz -= 512; |
st->blksize -= 512; |
} |
} |
/* |
/* |
* If no data was tranfered, do it immediatly |
* If no data was tranfered, do it immediatly |
Line 1740 st_interpret_sense(xs) |
|
Line 1648 st_interpret_sense(xs) |
|
/* |
/* |
* the record was bigger than the read |
* the record was bigger than the read |
*/ |
*/ |
if (!silent) |
if ((xs->flags & SCSI_SILENT) == 0) |
printf("%s: %d-byte record too big\n", |
printf("%s: %d-byte record too big\n", |
st->sc_dev.dv_xname, |
st->sc_dev.dv_xname, |
xs->datalen - info); |
xs->datalen - info); |
Line 1763 st_interpret_sense(xs) |
|
Line 1671 st_interpret_sense(xs) |
|
if ((st->quirks & ST_Q_SENSE_HELP) && |
if ((st->quirks & ST_Q_SENSE_HELP) && |
!(sc_link->flags & SDEV_MEDIA_LOADED)) { |
!(sc_link->flags & SDEV_MEDIA_LOADED)) { |
/* still starting */ |
/* still starting */ |
st->blksiz -= 512; |
st->blksize -= 512; |
} else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) { |
} else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) { |
st->flags |= ST_BLANK_READ; |
st->flags |= ST_BLANK_READ; |
xs->resid = xs->datalen; |
xs->resid = xs->datalen; |
Line 1795 st_interpret_sense(xs) |
|
Line 1703 st_interpret_sense(xs) |
|
*/ |
*/ |
int |
int |
st_touch_tape(st) |
st_touch_tape(st) |
struct st_data *st; |
struct st_softc *st; |
{ |
{ |
char *buf; |
char *buf; |
u_int readsiz; |
int readsize; |
int error; |
int error; |
|
|
buf = malloc(1024, M_TEMP, M_NOWAIT); |
buf = malloc(1024, M_TEMP, M_NOWAIT); |
Line 1807 st_touch_tape(st) |
|
Line 1715 st_touch_tape(st) |
|
|
|
if (error = st_mode_sense(st, 0)) |
if (error = st_mode_sense(st, 0)) |
goto bad; |
goto bad; |
st->blksiz = 1024; |
st->blksize = 1024; |
do { |
do { |
switch (st->blksiz) { |
switch (st->blksize) { |
case 512: |
case 512: |
case 1024: |
case 1024: |
readsiz = st->blksiz; |
readsize = st->blksize; |
st->flags |= ST_FIXEDBLOCKS; |
st->flags |= ST_FIXEDBLOCKS; |
break; |
break; |
default: |
default: |
readsiz = 1; |
readsize = 1; |
st->flags &= ~ST_FIXEDBLOCKS; |
st->flags &= ~ST_FIXEDBLOCKS; |
} |
} |
if (error = st_mode_select(st, 0)) |
if (error = st_mode_select(st, 0)) |
goto bad; |
goto bad; |
st_read(st, buf, readsiz, SCSI_SILENT); |
st_read(st, buf, readsize, SCSI_SILENT); /* XXX */ |
if (error = st_rewind(st, 0, 0)) { |
if (error = st_rewind(st, 0, 0)) { |
bad: free(buf, M_TEMP); |
bad: free(buf, M_TEMP); |
return error; |
return error; |
} |
} |
} while (readsiz != 1 && readsiz > st->blksiz); |
} while (readsize != 1 && readsize > st->blksize); |
|
|
free(buf, M_TEMP); |
free(buf, M_TEMP); |
return 0; |
return 0; |
} |
} |