1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

Fix for 11815 (at mount time do a throwaway read of the front of the

tape to force the drive to do a media access so it knows what media
may be inserted).

Also Ken's make_dev patches- relatively untested.
This commit is contained in:
Matt Jacob 1999-11-17 06:05:09 +00:00
parent 273a1a3da7
commit 387c08f0e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=53259

View File

@ -78,13 +78,28 @@
#ifndef SA_ERASE_TIMEOUT
#define SA_ERASE_TIMEOUT 4 * 60
#endif
#define REWIND_TIMEOUT (SA_REWIND_TIMEOUT * 60 * 10000)
#define ERASE_TIMEOUT (SA_ERASE_TIMEOUT * 60 * 10000)
#define SPACE_TIMEOUT (SA_SPACE_TIMEOUT * 60 * 10000)
/*
* Additional options that can be set for config: SA_1FM_AT_EOT
*/
#ifndef UNUSED_PARAMETER
#define UNUSED_PARAMETER(x) x = x
#endif
#define QFRLS(ccb) \
if (((ccb)->ccb_h.status & CAM_DEV_QFRZN) != 0) \
cam_release_devq((ccb)->ccb_h.path, 0, 0, 0, FALSE)
/*
* Driver states
*/
typedef enum {
SA_STATE_NORMAL, SA_STATE_ABNORMAL
} sa_state;
@ -143,6 +158,30 @@ typedef enum {
SA_QUIRK_1FM = 0x10 /* No more than 1 File Mark at EOD */
} sa_quirks;
#define SA_NOT_CTLDEV 0
#define SA_CTLDEV 1
#define SA_ATYPE_R 0
#define SA_ATYPE_NR 1
#define SA_ATYPE_ER 2
#define SAMINOR(ctl, unit, mode, access) \
((ctl << 29) | ((unit & 0x3f0) << 16) | (unit & 0xf) | \
(mode << 2) | access)
#define SA_NUM_MODES 4
struct sa_devs {
dev_t ctl_dev;
struct sa_mode_devs {
dev_t r_dev;
dev_t nr_dev;
dev_t er_dev;
} mode_devs[SA_NUM_MODES];
dev_t r_dev;
dev_t nr_dev;
dev_t er_dev;
};
struct sa_softc {
sa_state state;
sa_flags flags;
@ -150,6 +189,7 @@ struct sa_softc {
struct buf_queue_head buf_queue;
int queue_count;
struct devstat device_stats;
struct sa_devs devs;
int blk_gran;
int blk_mask;
int blk_shift;
@ -379,61 +419,51 @@ saopen(dev_t dev, int flags, int fmt, struct proc *p)
mode = SAMODE(dev);
density = SADENSITY(dev);
s = splsoftcam();
periph = cam_extend_get(saperiphs, unit);
if (periph == NULL)
if (periph == NULL) {
(void) splx(s);
return (ENXIO);
}
softc = (struct sa_softc *)periph->softc;
if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
splx(s);
return (error);
}
splx(s);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
s = splsoftcam();
if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
cam_periph_unlock(periph);
return(ENXIO);
}
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 1;
(void) splx(s);
cam_periph_unlock(periph);
return (0);
}
if (softc->flags & SA_FLAG_INVALID) {
splx(s);
return(ENXIO);
if (softc->flags & SA_FLAG_OPEN) {
error = EBUSY;
} else if (softc->flags & SA_FLAG_INVALID) {
error = ENXIO;
} else {
/*
* The function samount ensures media is loaded and ready.
* It also does a device RESERVE if the tape isn't yet mounted.
*/
error = samount(periph, flags, dev);
}
if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
splx(s);
return (error); /* error code from tsleep */
}
splx(s);
if ((softc->flags & SA_FLAG_OPEN) == 0) {
if (cam_periph_acquire(periph) != CAM_REQ_CMP)
return(ENXIO);
if ((error = sareservereleaseunit(periph, TRUE)) != 0) {
cam_periph_unlock(periph);
cam_periph_release(periph);
return(error);
}
}
if (error == 0) {
if ((softc->flags & SA_FLAG_OPEN) != 0) {
error = EBUSY;
}
if (error == 0)
error = samount(periph, flags, dev);
/* Perform other checking... */
}
if (error == 0) {
if (error) {
cam_periph_release(periph);
} else {
saprevent(periph, PR_PREVENT);
softc->flags |= SA_FLAG_OPEN;
}
cam_periph_unlock(periph);
return (error);
}
@ -458,15 +488,17 @@ saclose(dev_t dev, int flag, int fmt, struct proc *p)
("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 0;
return (0);
}
if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
return (error);
}
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 0;
cam_periph_release(periph);
cam_periph_unlock(periph);
return (0);
}
/*
* Were we writing the tape?
*/
@ -570,8 +602,9 @@ saclose(dev_t dev, int flag, int fmt, struct proc *p)
"command to clear this state.\n");
}
/* release the device */
sareservereleaseunit(periph, FALSE);
/* release the device if it is no longer mounted */
if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
sareservereleaseunit(periph, FALSE);
cam_periph_unlock(periph);
cam_periph_release(periph);
@ -707,7 +740,7 @@ saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
int unit;
int mode;
int density;
int error;
int error = 0;
unit = SAUNIT(dev);
mode = SAMODE(dev);
@ -786,6 +819,36 @@ saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
{
struct mtget *g = (struct mtget *)arg;
/*
* If this isn't the control mode device, actually go out
* and ask the drive again what it's set to.
*/
if (!SA_IS_CTRL(dev)) {
u_int8_t write_protect;
int comp_enabled, comp_supported;
error = sagetparams(periph, SA_PARAM_ALL,
&softc->media_blksize, &softc->media_density,
&softc->media_numblks, &softc->buffer_mode,
&write_protect, &softc->speed, &comp_supported,
&comp_enabled, &softc->comp_algorithm, NULL);
if (error)
break;
if (write_protect)
softc->flags |= SA_FLAG_TAPE_WP;
else
softc->flags &= ~SA_FLAG_TAPE_WP;
softc->flags &= ~(SA_FLAG_COMP_SUPP|
SA_FLAG_COMP_ENABLED|SA_FLAG_COMP_UNSUPP);
if (comp_supported) {
if (softc->saved_comp_algorithm == 0)
softc->saved_comp_algorithm =
softc->comp_algorithm;
softc->flags |= SA_FLAG_COMP_SUPP;
if (comp_enabled)
softc->flags |= SA_FLAG_COMP_ENABLED;
} else
softc->flags |= SA_FLAG_COMP_UNSUPP;
}
bzero(g, sizeof(struct mtget));
g->mt_type = MT_ISAR;
if (softc->flags & SA_FLAG_COMP_UNSUPP) {
@ -969,17 +1032,15 @@ saioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
/*
* Be sure to allow media removal before
* attempting the eject.
* attempting the eject. And clear flags
* anyway.
*/
softc->flags &= ~(SA_FLAG_TAPE_LOCKED|
SA_FLAG_TAPE_FROZEN|SA_FLAG_TAPE_MOUNTED);
saprevent(periph, PR_ALLOW);
if (error == 0)
error = saloadunload(periph, FALSE);
else
break;
softc->flags &= ~(SA_FLAG_TAPE_LOCKED|
SA_FLAG_TAPE_WRITTEN| SA_FLAG_TAPE_WRITTEN|
SA_FLAG_TAPE_FROZEN);
break;
case MTNOP: /* no operation, sets status only */
@ -1149,9 +1210,6 @@ sainit(void)
if (status != CAM_REQ_CMP) {
printf("sa: Failed to attach master async callback "
"due to status 0x%x!\n", status);
} else {
/* If we were successfull, register our devsw */
cdevsw_add(&sa_cdevsw);
}
}
@ -1209,10 +1267,23 @@ static void
sacleanup(struct cam_periph *periph)
{
struct sa_softc *softc;
int i;
softc = (struct sa_softc *)periph->softc;
devstat_remove_entry(&softc->device_stats);
destroy_dev(softc->devs.ctl_dev);
destroy_dev(softc->devs.r_dev);
destroy_dev(softc->devs.nr_dev);
destroy_dev(softc->devs.er_dev);
for (i = 0; i < SA_NUM_MODES; i++) {
destroy_dev(softc->devs.mode_devs[i].r_dev);
destroy_dev(softc->devs.mode_devs[i].nr_dev);
destroy_dev(softc->devs.mode_devs[i].er_dev);
}
cam_extend_release(saperiphs, periph->unit_number);
xpt_print_path(periph->path);
printf("removing device entry\n");
@ -1266,6 +1337,7 @@ saregister(struct cam_periph *periph, void *arg)
struct ccb_setasync csa;
struct ccb_getdev *cgd;
caddr_t match;
int i;
cgd = (struct ccb_getdev *)arg;
if (periph == NULL) {
@ -1321,12 +1393,42 @@ saregister(struct cam_periph *periph, void *arg)
* blocksize until we media is inserted. So, set a flag to
* indicate that the blocksize is unavailable right now.
*/
devstat_add_entry(&softc->device_stats, "sa",
periph->unit_number, 0,
DEVSTAT_BS_UNAVAILABLE,
cgd->pd_type | DEVSTAT_TYPE_IF_SCSI,
DEVSTAT_PRIORITY_SA);
devstat_add_entry(&softc->device_stats, "sa", periph->unit_number, 0,
DEVSTAT_BS_UNAVAILABLE, cgd->pd_type | DEVSTAT_TYPE_IF_SCSI,
DEVSTAT_PRIORITY_SA);
softc->devs.ctl_dev = make_dev(&sa_cdevsw, SAMINOR(SA_CTLDEV,
periph->unit_number, 0, SA_ATYPE_R), UID_ROOT, GID_OPERATOR,
0660, "r%s%d.ctl", periph->periph_name, periph->unit_number);
softc->devs.r_dev = make_dev(&sa_cdevsw, SAMINOR(SA_NOT_CTLDEV,
periph->unit_number, 0, SA_ATYPE_R), UID_ROOT, GID_OPERATOR,
0660, "r%s%d", periph->periph_name, periph->unit_number);
softc->devs.nr_dev = make_dev(&sa_cdevsw, SAMINOR(SA_NOT_CTLDEV,
periph->unit_number, 0, SA_ATYPE_NR), UID_ROOT, GID_OPERATOR,
0660, "nr%s%d", periph->periph_name, periph->unit_number);
softc->devs.er_dev = make_dev(&sa_cdevsw, SAMINOR(SA_NOT_CTLDEV,
periph->unit_number, 0, SA_ATYPE_ER), UID_ROOT, GID_OPERATOR,
0660, "er%s%d", periph->periph_name, periph->unit_number);
for (i = 0; i < SA_NUM_MODES; i++) {
softc->devs.mode_devs[i].r_dev = make_dev(&sa_cdevsw,
SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_R),
UID_ROOT, GID_OPERATOR, 0660, "r%s%d.%d",
periph->periph_name, periph->unit_number, i);
softc->devs.mode_devs[i].nr_dev = make_dev(&sa_cdevsw,
SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_NR),
UID_ROOT, GID_OPERATOR, 0660, "nr%s%d.%d",
periph->periph_name, periph->unit_number, i);
softc->devs.mode_devs[i].nr_dev = make_dev(&sa_cdevsw,
SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_ER),
UID_ROOT, GID_OPERATOR, 0660, "er%s%d.%d",
periph->periph_name, periph->unit_number, i);
}
/*
* Add an async callback so that we get
* notified if this device goes away.
@ -1606,7 +1708,6 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
{
struct sa_softc *softc;
union ccb *ccb;
struct ccb_scsiio *csio;
int error;
/*
@ -1618,30 +1719,47 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
softc = (struct sa_softc *)periph->softc;
ccb = cam_periph_getccb(periph, 1);
csio = &ccb->csio;
error = 0;
/*
* This *should* determine if something has happend since the last
* open/mount that would invalidate the mount, but is currently
* broken.
*
* This will also eat any pending UAs.
* This should determine if something has happend since the last
* open/mount that would invalidate the mount. We do *not* want
* to retry this command- we just want the status. But we only
* do this if we're mounted already- if we're not mounted,
* we don't care about the unit read state and can instead use
* this opportunity to attempt to reserve the tape unit.
*/
scsi_test_unit_ready(csio, 1, sadone,
MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000);
/*
* Because we're not supplying a error routine, cam_periph_runccb
* will unfreeze the queue if there was an error.
*/
cam_periph_runccb(ccb, NULL, 0, 0, &softc->device_stats);
if (softc->flags & SA_FLAG_TAPE_MOUNTED) {
ccb = cam_periph_getccb(periph, 1);
scsi_test_unit_ready(&ccb->csio, 0, sadone,
MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000);
error = cam_periph_runccb(ccb, saerror, 0, 0,
&softc->device_stats);
QFRLS(ccb);
if (error == ENXIO) {
softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
scsi_test_unit_ready(&ccb->csio, 0, sadone,
MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000);
error = cam_periph_runccb(ccb, saerror, 0, 0,
&softc->device_stats);
QFRLS(ccb);
} else if (error) {
/* XXX: Should we freeze the tape? */
softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
xpt_print_path(ccb->ccb_h.path);
printf("error %d on TUR in samount\n", error);
}
} else {
error = sareservereleaseunit(periph, TRUE);
if (error) {
return (error);
}
ccb = cam_periph_getccb(periph, 1);
}
if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
struct scsi_read_block_limits_data *rblim = NULL;
int comp_enabled, comp_supported;
struct scsi_read_block_limits_data *rblim = NULL;
int comp_enabled, comp_supported;
u_int8_t write_protect, guessing = 0;
/*
@ -1659,17 +1777,17 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
FALSE, FALSE, 1, SSD_FULL_SIZE, 60000);
error = cam_periph_runccb(ccb, saerror, 0, SF_QUIET_IR,
&softc->device_stats);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
QFRLS(ccb);
/*
* In case this doesn't work, do a REWIND instead
*/
if (error) {
scsi_rewind(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG,
FALSE, SSD_FULL_SIZE,
(SA_REWIND_TIMEOUT) * 60 * 1000);
scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG,
FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT);
error = cam_periph_runccb(ccb, saerror, 0, 0,
&softc->device_stats);
QFRLS(ccb);
}
if (error) {
xpt_release_ccb(ccb);
@ -1677,18 +1795,47 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
}
/*
* Next off, determine block limits.
* Do a dummy test read to force access to the
* media so that the drive will really know what's
* there.
*/
rblim = (struct scsi_read_block_limits_data *)
malloc(sizeof(*rblim), M_TEMP, M_WAITOK);
malloc(MAXPHYS, M_TEMP, M_WAITOK);
if (rblim == NULL) {
xpt_print_path(ccb->ccb_h.path);
printf("no memory for test read\n");
xpt_release_ccb(ccb);
error = ENOMEM;
goto exit;
}
scsi_sa_read_write(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, 1,
FALSE, 0, MAXPHYS, (void *) rblim, MAXPHYS, SSD_FULL_SIZE,
120 * 60 * 1000);
(void) cam_periph_runccb(ccb, saerror, 0, SF_QUIET_IR,
&softc->device_stats);
QFRLS(ccb);
scsi_rewind(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG,
FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT);
error = cam_periph_runccb(ccb, saerror, 0, 0,
&softc->device_stats);
QFRLS(ccb);
if (error) {
xpt_print_path(ccb->ccb_h.path);
printf("unable to rewind after test read\n");
xpt_release_ccb(ccb);
goto exit;
}
/* it is safe to retry this */
scsi_read_block_limits(csio, 5, sadone, MSG_SIMPLE_Q_TAG,
/*
* Next off, determine block limits.
*/
scsi_read_block_limits(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG,
rblim, SSD_FULL_SIZE, 5000);
error = cam_periph_runccb(ccb, saerror, 0,
SF_RETRY_UA | SF_RETRY_SELTO, &softc->device_stats);
QFRLS(ccb);
xpt_release_ccb(ccb);
if (error != 0) {
@ -1965,7 +2112,6 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
free(rblim, M_TEMP);
if (error != 0) {
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
softc->dsreg = MTIO_DSREG_NIL;
} else {
softc->fileno = softc->blkno = 0;
@ -1981,7 +2127,14 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
} else
xpt_release_ccb(ccb);
return (error);
/*
* If we return an error, we're not mounted any more,
* so release any device reservation.
*/
if (error != 0) {
(void) sareservereleaseunit(periph, FALSE);
}
return(error);
}
static int
@ -2018,8 +2171,8 @@ saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
struct sa_softc *softc;
struct ccb_scsiio *csio;
struct scsi_sense_data *sense;
u_int32_t resid;
int32_t info;
u_int32_t resid = 0;
int32_t info = 0;
int error_code, sense_key, asc, ascq;
int error, defer_action;
@ -2060,6 +2213,13 @@ saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
(int) csio->cdb_len);
softc->last_ctl_resid = resid;
}
CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Key 0x%x ASC/ASCQ
0x%x 0x%x flags 0x%x resid %d dxfer_len %d\n", sense_key,
asc, ascq, sense->flags & ~SSD_KEY_RESERVED, resid,
csio->dxfer_len));
} else {
CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Cam Status 0x%x\n",
csio->ccb_h.status & CAM_STATUS_MASK));
}
/*
@ -2088,10 +2248,6 @@ saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
* Handle writes && reads differently.
*/
CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Key 0x%x ASC/ASCQ 0x%x "
"0x%x flags 0x%x resid %d dxfer_len %d\n", sense_key, asc, ascq,
sense->flags & ~SSD_KEY_RESERVED, resid, csio->dxfer_len));
if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
if (sense->flags & SSD_FILEMARK) {
xpt_print_path(csio->ccb_h.path);
@ -2430,8 +2586,16 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
ccb = cam_periph_getccb(periph, 1);
retry:
if (params_to_set & SA_PARAM_COMPRESSION) {
cpage = (sa_comp_t *)&mode_blk[1];
if (mode_blk) {
cpage = (sa_comp_t *)&mode_blk[1];
} else {
cpage = (sa_comp_t *)&mode_hdr[1];
}
bcopy(ccomp, cpage, sizeof (sa_comp_t));
} else
cpage = NULL;
@ -2441,22 +2605,24 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
* pass in. Otherwise, use the blocksize we got back from the
* mode select above.
*/
if (params_to_set & SA_PARAM_BLOCKSIZE)
scsi_ulto3b(blocksize, mode_blk->blklen);
else
scsi_ulto3b(current_blocksize, mode_blk->blklen);
if (mode_blk) {
if (params_to_set & SA_PARAM_BLOCKSIZE)
scsi_ulto3b(blocksize, mode_blk->blklen);
else
scsi_ulto3b(current_blocksize, mode_blk->blklen);
/*
* Set density if requested, else preserve old density.
* SCSI_SAME_DENSITY only applies to SCSI-2 or better
* devices, else density we've latched up in our softc.
*/
if (params_to_set & SA_PARAM_DENSITY) {
mode_blk->density = density;
} else if (softc->scsi_rev > SCSI_REV_CCS) {
mode_blk->density = SCSI_SAME_DENSITY;
} else {
mode_blk->density = softc->media_density;
/*
* Set density if requested, else preserve old density.
* SCSI_SAME_DENSITY only applies to SCSI-2 or better
* devices, else density we've latched up in our softc.
*/
if (params_to_set & SA_PARAM_DENSITY) {
mode_blk->density = density;
} else if (softc->scsi_rev > SCSI_REV_CCS) {
mode_blk->density = SCSI_SAME_DENSITY;
} else {
mode_blk->density = softc->media_density;
}
}
/*
@ -2471,7 +2637,10 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
/* set single-initiator buffering mode */
mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF;
mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc);
if (mode_blk)
mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc);
else
mode_hdr->blk_desc_len = 0;
/*
* First, if the user wants us to set the compression algorithm or
@ -2496,24 +2665,34 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
if (ccomp->dcomp.dce_and_dcc & SA_DCP_DCC) {
struct scsi_data_compression_page *dcp = &cpage->dcomp;
if (calg == 0) {
/* disable compression */
dcp->dce_and_dcc &= ~SA_DCP_DCE;
/* disable compression && decompression */
dcp->dce_and_dcc = 0;
dcp->dde_and_red = 0;
break;
}
/* enable compression */
dcp->dce_and_dcc |= SA_DCP_DCE;
/* enable decompression */
dcp->dde_and_red |= SA_DCP_DDE;
/* enable compression && decompression */
dcp->dce_and_dcc = SA_DCP_DCE;
dcp->dde_and_red = SA_DCP_DDE;
/*
* If there, use compression algorithm from caller.
* Otherwise, if there's a saved compression algorithm
* and there is no current algorithm, use the saved
* algorithm. Else parrot back what we got and hope
* for the best.
*/
if (calg != MT_COMP_ENABLE) {
scsi_ulto4b(calg, dcp->comp_algorithm);
scsi_ulto4b(calg, dcp->decomp_algorithm);
} else if (scsi_4btoul(dcp->comp_algorithm) == 0 &&
softc->saved_comp_algorithm != 0) {
scsi_ulto4b(softc->saved_comp_algorithm,
dcp->comp_algorithm);
scsi_ulto4b(softc->saved_comp_algorithm,
dcp->decomp_algorithm);
}
break;
}
case SA_DEVICE_CONFIGURATION_PAGE: /* NOT YET */
case SA_DEVICE_CONFIGURATION_PAGE:
{
struct scsi_dev_conf_page *dcp = &cpage->dconf;
if (calg == 0) {
@ -2555,8 +2734,6 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
}
}
ccb = cam_periph_getccb(periph, 1);
/* It is safe to retry this operation */
scsi_mode_select(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG,
(params_to_set & SA_PARAM_COMPRESSION)? TRUE : FALSE,
@ -2576,12 +2753,24 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
}
if (error == 0) {
xpt_release_ccb(ccb);
} else {
if (error) {
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
/*
* If we can, try without setting density/blocksize.
*/
if (mode_blk) {
if ((params_to_set &
(SA_PARAM_DENSITY|SA_PARAM_BLOCKSIZE)) == 0) {
mode_blk = NULL;
goto retry;
}
} else {
mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
cpage = (sa_comp_t *)&mode_blk[1];
}
/*
* If we were setting the blocksize, and that failed, we
* want to set it to its original value. If we weren't
@ -2615,9 +2804,10 @@ sasetparams(struct cam_periph *periph, sa_params params_to_set,
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
xpt_release_ccb(ccb);
}
xpt_release_ccb(ccb);
if (ccomp != NULL)
free(ccomp, M_TEMP);
@ -2665,7 +2855,7 @@ saprevent(struct cam_periph *periph, int action)
/* It is safe to retry this operation */
scsi_prevent(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, action,
SSD_FULL_SIZE, 60000);
SSD_FULL_SIZE, 100000);
/*
* We can be quiet about illegal requests.
@ -2698,7 +2888,7 @@ sarewind(struct cam_periph *periph)
/* It is safe to retry this operation */
scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE,
SSD_FULL_SIZE, (SA_REWIND_TIMEOUT) * 60 * 1000);
SSD_FULL_SIZE, REWIND_TIMEOUT);
softc->dsreg = MTIO_DSREG_REW;
error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
@ -2729,7 +2919,7 @@ saspace(struct cam_periph *periph, int count, scsi_space_code code)
/* This cannot be retried */
scsi_space(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, code, count,
SSD_FULL_SIZE, (SA_SPACE_TIMEOUT) * 60 * 1000);
SSD_FULL_SIZE, SPACE_TIMEOUT);
softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD;
error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
@ -2915,7 +3105,7 @@ saretension(struct cam_periph *periph)
/* It is safe to retry this operation */
scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE,
FALSE, TRUE, TRUE, SSD_FULL_SIZE, (SA_ERASE_TIMEOUT) * 60 * 1000);
FALSE, TRUE, TRUE, SSD_FULL_SIZE, ERASE_TIMEOUT);
softc->dsreg = MTIO_DSREG_TEN;
error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
@ -3021,7 +3211,7 @@ saerase(struct cam_periph *periph, int longerase)
ccb = cam_periph_getccb(periph, 1);
scsi_erase(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, FALSE, longerase,
SSD_FULL_SIZE, (SA_ERASE_TIMEOUT) * 60 * 1000);
SSD_FULL_SIZE, ERASE_TIMEOUT);
softc->dsreg = MTIO_DSREG_ZER;
error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);