Snapshot of ATAPI tapes support. Known to be able to read/write to tape with:
st0 at atapibus0 drive 1: <Seagate STT8000A, , 5.51> type 1 sequential removable Major changes may still happen in order to properly support other ATAPI tape drives.
This commit is contained in:
parent
d135da5614
commit
0a63f01fef
|
@ -0,0 +1,122 @@
|
|||
/* $NetBSD: atapi_tape.h,v 1.1 2001/06/18 09:05:05 bouyer Exp $ */
|
||||
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998,1999,2000,2001 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/dev/ata/atapi-tape.h,v 1.15 2001/03/14 12:05:44 sos Exp $
|
||||
*/
|
||||
|
||||
/* defines for the device specific byte in the mode select/sense header */
|
||||
#define SMH_DSP_BUFF_MODE 0x70
|
||||
#define SMH_DSP_BUFF_MODE_OFF 0x00
|
||||
#define SMH_DSP_BUFF_MODE_ON 0x10
|
||||
#define SMH_DSP_BUFF_MODE_MLTI 0x20
|
||||
#define SMH_DSP_WRITE_PROT 0x80
|
||||
|
||||
/* ATAPI tape drive Capabilities and Mechanical Status Page */
|
||||
struct atapi_cappage {
|
||||
/* mode page data header */
|
||||
struct scsipi_mode_header header;
|
||||
/* capabilities page */
|
||||
u_int8_t page_code;
|
||||
#define ATAPI_TAPE_CAP_PAGE 0x2a
|
||||
u_int8_t page_length; /* page Length == 0x12 */
|
||||
u_int8_t reserved2;
|
||||
u_int8_t reserved3;
|
||||
u_int8_t cap1;
|
||||
#define ATAPI_TAPE_CAP_PAGE_RO 0x01; /* read Only Mode */
|
||||
#define ATAPI_TAPE_CAP_PAGE_REV 0x20; /* supports reverse direction */
|
||||
#define ATAPI_TAPE_CAP_PAGE_
|
||||
u_int8_t cap2;
|
||||
#define ATAPI_TAPE_CAP_PAGE_EF 0x08; /* supports ERASE formatting */
|
||||
#define ATAPI_TAPE_CAP_PAGE_QFA 0x20 /* supports QFA formats */
|
||||
u_int8_t cap3;
|
||||
#define ATAPI_TAPE_CAP_PAGE_LCK 0x01 /* supports locking media */
|
||||
#define ATAPI_TAPE_CAP_PAGE_LCKED 0x02 /* the media is locked */
|
||||
#define ATAPI_TAPE_CAP_PAGE_PRV 0x04 /* defaults to prevent state */
|
||||
#define ATAPI_TAPE_CAP_PAGE_EJ 0x08 /* supports eject */
|
||||
#define ATAPI_TAPE_CAP_PAGE_DIS 0x10 /* can break request > ctl */
|
||||
#define ATAPI_TAPE_CAP_PAGE_ECC 0x40 /* supports error correction */
|
||||
#define ATAPI_TAPE_CAP_PAGE_CMP 0x80 /* supports data compression */
|
||||
u_int8_t cap4;
|
||||
#define ATAPI_TAPE_CAP_PAGE_BLK512 0x02 /* supports 512b block size */
|
||||
#define ATAPI_TAPE_CAP_PAGE_BLK1K 0x04 /* supports 1024b block size */
|
||||
#define ATAPI_TAPE_CAP_PAGE_BLK32K 0x80 /* supports 32kb block size */
|
||||
u_int16_t max_speed; /* supported speed in KBps */
|
||||
u_int16_t max_defects; /* max stored defect entries */
|
||||
u_int16_t ctl; /* continuous transfer limit */
|
||||
u_int16_t speed; /* current Speed, in KBps */
|
||||
u_int16_t buffer_size; /* buffer Size, in 512 bytes */
|
||||
u_int8_t reserved18;
|
||||
u_int8_t reserved19;
|
||||
};
|
||||
|
||||
/* ATAPI OnStream ADR data transfer mode page (ADR unique) */
|
||||
struct ast_transferpage {
|
||||
/* mode page data header */
|
||||
u_int8_t data_length; /* total length of data */
|
||||
u_int8_t medium_type; /* medium type (if any) */
|
||||
u_int8_t dsp; /* device specific parameter */
|
||||
u_int8_t blk_desc_len; /* block Descriptor Length */
|
||||
|
||||
/* data transfer page */
|
||||
u_int8_t page_code :6;
|
||||
#define ATAPI_TAPE_TRANSFER_PAGE 0x30
|
||||
|
||||
u_int8_t reserved0_6 :1;
|
||||
u_int8_t ps :1; /* parameters saveable */
|
||||
u_int8_t page_length; /* page Length == 0x02 */
|
||||
u_int8_t reserved2;
|
||||
u_int8_t read32k :1; /* 32k blk size (data only) */
|
||||
u_int8_t read32k5 :1; /* 32.5k blk size (data&AUX) */
|
||||
u_int8_t reserved3_23 :2;
|
||||
u_int8_t write32k :1; /* 32k blk size (data only) */
|
||||
u_int8_t write32k5 :1; /* 32.5k blk size (data&AUX) */
|
||||
u_int8_t reserved3_6 :1;
|
||||
u_int8_t streaming :1; /* streaming mode enable */
|
||||
};
|
||||
|
||||
/* ATAPI OnStream ADR vendor identification mode page (ADR unique) */
|
||||
struct ast_identifypage {
|
||||
/* mode page data header */
|
||||
u_int8_t data_length; /* total length of data */
|
||||
u_int8_t medium_type; /* medium type (if any) */
|
||||
u_int8_t dsp; /* device specific parameter */
|
||||
u_int8_t blk_desc_len; /* block Descriptor Length */
|
||||
|
||||
/* data transfer page */
|
||||
u_int8_t page_code :6;
|
||||
#define ATAPI_TAPE_IDENTIFY_PAGE 0x36
|
||||
|
||||
u_int8_t reserved0_6 :1;
|
||||
u_int8_t ps :1; /* parameters saveable */
|
||||
u_int8_t page_length; /* page Length == 0x06 */
|
||||
u_int8_t ident[4]; /* host id string */
|
||||
u_int8_t reserved6;
|
||||
u_int8_t reserved7;
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: st.c,v 1.140 2001/05/30 20:28:17 bouyer Exp $ */
|
||||
/* $NetBSD: st.c,v 1.141 2001/06/18 09:05:05 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -79,7 +79,6 @@
|
|||
|
||||
/* Defines for device specific stuff */
|
||||
#define DEF_FIXED_BSIZE 512
|
||||
#define ST_RETRIES 4 /* only on non IO commands */
|
||||
|
||||
#define STMODE(z) ( minor(z) & 0x03)
|
||||
#define STDSTY(z) ((minor(z) >> 2) & 0x03)
|
||||
|
@ -93,10 +92,6 @@
|
|||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define ST_IO_TIME (3 * 60 * 1000) /* 3 minutes */
|
||||
#define ST_CTL_TIME (30 * 1000) /* 30 seconds */
|
||||
#define ST_SPC_TIME (4 * 60 * 60 * 1000) /* 4 hours */
|
||||
|
||||
#ifndef ST_MOUNT_DELAY
|
||||
#define ST_MOUNT_DELAY 0
|
||||
#endif
|
||||
|
@ -279,6 +274,13 @@ const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
|
|||
{0, 0, 0}, /* minor 8-11 */
|
||||
{0, 0, 0} /* minor 12-15 */
|
||||
}}},
|
||||
{{T_SEQUENTIAL, T_REMOV,
|
||||
"OnStream DI-30", "", "1.0"}, {ST_Q_IGNORE_LOADS, 0, {
|
||||
{0, 0, 0}, /* minor 0-3 */
|
||||
{0, 0, 0}, /* minor 4-7 */
|
||||
{0, 0, 0}, /* minor 8-11 */
|
||||
{0, 0, 0} /* minor 12-15 */
|
||||
}}},
|
||||
};
|
||||
|
||||
#define NOEJECT 0
|
||||
|
@ -293,10 +295,6 @@ int st_decide_mode __P((struct st_softc *, boolean));
|
|||
void ststart __P((struct scsipi_periph *));
|
||||
void stdone __P((struct scsipi_xfer *));
|
||||
int st_read __P((struct st_softc *, char *, int, int));
|
||||
int st_read_block_limits __P((struct st_softc *, int));
|
||||
int st_mode_sense __P((struct st_softc *, int));
|
||||
int st_mode_select __P((struct st_softc *, int));
|
||||
int st_cmprss __P((struct st_softc *, int));
|
||||
int st_space __P((struct st_softc *, int, u_int, int));
|
||||
int st_write_filemarks __P((struct st_softc *, int, int));
|
||||
int st_check_eod __P((struct st_softc *, boolean, int *, int));
|
||||
|
@ -315,32 +313,6 @@ const struct scsipi_periphsw st_switch = {
|
|||
stdone
|
||||
};
|
||||
|
||||
#define ST_INFO_VALID 0x0001
|
||||
#define ST_BLOCK_SET 0x0002 /* block size, mode set by ioctl */
|
||||
#define ST_WRITTEN 0x0004 /* data has been written, EOD needed */
|
||||
#define ST_FIXEDBLOCKS 0x0008
|
||||
#define ST_AT_FILEMARK 0x0010
|
||||
#define ST_EIO_PENDING 0x0020 /* error reporting deferred until next op */
|
||||
#define ST_NEW_MOUNT 0x0040 /* still need to decide mode */
|
||||
#define ST_READONLY 0x0080 /* st_mode_sense says write protected */
|
||||
#define ST_FM_WRITTEN 0x0100 /*
|
||||
* EOF file mark written -- used with
|
||||
* ~ST_WRITTEN to indicate that multiple file
|
||||
* marks have been written
|
||||
*/
|
||||
#define ST_BLANK_READ 0x0200 /* BLANK CHECK encountered already */
|
||||
#define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */
|
||||
#define ST_MOUNTED 0x0800 /* Device is presently mounted */
|
||||
#define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
|
||||
#define ST_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */
|
||||
#define ST_EOM_PENDING 0x4000 /* EOM reporting deferred until next op */
|
||||
|
||||
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_EOM_PENDING | \
|
||||
ST_BLANK_READ)
|
||||
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
|
||||
ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
|
||||
ST_2FM_AT_EOD | ST_PER_ACTION)
|
||||
|
||||
#if defined(ST_ENABLE_EARLYWARN)
|
||||
#define ST_INIT_FLAGS ST_EARLYWARN
|
||||
#else
|
||||
|
@ -352,11 +324,11 @@ const struct scsipi_periphsw st_switch = {
|
|||
* A device suitable for this driver
|
||||
*/
|
||||
void
|
||||
stattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
stattach(parent, st, aux)
|
||||
struct device *parent;
|
||||
struct st_softc *st;
|
||||
void *aux;
|
||||
{
|
||||
struct st_softc *st = (void *)self;
|
||||
struct scsipibus_attach_args *sa = aux;
|
||||
struct scsipi_periph *periph = sa->sa_periph;
|
||||
|
||||
|
@ -387,7 +359,7 @@ stattach(parent, self, aux)
|
|||
printf("%s: %s", st->sc_dev.dv_xname, st->quirkdata ? "rogue, " : "");
|
||||
if (scsipi_test_unit_ready(periph,
|
||||
XS_CTL_DISCOVERY | XS_CTL_SILENT | XS_CTL_IGNORE_MEDIA_CHANGE) ||
|
||||
st_mode_sense(st,
|
||||
st->ops(st, ST_OPS_MODESENSE,
|
||||
XS_CTL_DISCOVERY | XS_CTL_SILENT | XS_CTL_IGNORE_MEDIA_CHANGE))
|
||||
printf("drive empty\n");
|
||||
else {
|
||||
|
@ -800,7 +772,7 @@ st_mount_tape(dev, flags)
|
|||
* Load the physical device parameters
|
||||
* loads: blkmin, blkmax
|
||||
*/
|
||||
if ((error = st_read_block_limits(st, 0)) != 0)
|
||||
if ((error = st->ops(st, ST_OPS_RBL, 0)) != 0)
|
||||
return (error);
|
||||
/*
|
||||
* Load the media dependent parameters
|
||||
|
@ -808,7 +780,7 @@ st_mount_tape(dev, flags)
|
|||
* As we have a tape in, it should be reflected here.
|
||||
* If not you may need the "quirk" above.
|
||||
*/
|
||||
if ((error = st_mode_sense(st, 0)) != 0)
|
||||
if ((error = st->ops(st, ST_OPS_MODESENSE, 0)) != 0)
|
||||
return (error);
|
||||
/*
|
||||
* If we have gained a permanent density from somewhere,
|
||||
|
@ -834,9 +806,13 @@ st_mount_tape(dev, flags)
|
|||
if ((error = st_decide_mode(st, FALSE)) != 0)
|
||||
return (error);
|
||||
}
|
||||
if ((error = st_mode_select(st, 0)) != 0) {
|
||||
printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
|
||||
return (error);
|
||||
if ((error = st->ops(st, ST_OPS_MODESELECT, 0)) != 0) {
|
||||
/* ATAPI will return ENODEV for this, and this may be OK */
|
||||
if (error != ENODEV) {
|
||||
printf("%s: cannot set selected mode\n",
|
||||
st->sc_dev.dv_xname);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
if (!(st->quirks & ST_Q_NOPREVENT)) {
|
||||
scsipi_prevent(periph, PR_PREVENT,
|
||||
|
@ -880,7 +856,7 @@ st_unmount(st, eject)
|
|||
* in st_touch_tape().
|
||||
*/
|
||||
st->density = 0;
|
||||
if (st_mode_select(st, 0) != 0) {
|
||||
if (st->ops(st, ST_OPS_MODESELECT, 0) != 0) {
|
||||
printf("%s: WARNING: cannot revert to default density\n",
|
||||
st->sc_dev.dv_xname);
|
||||
}
|
||||
|
@ -1298,7 +1274,7 @@ stioctl(dev, cmd, arg, flag, p)
|
|||
/*
|
||||
* (to get the current state of READONLY)
|
||||
*/
|
||||
error = st_mode_sense(st, XS_CTL_SILENT);
|
||||
error = st->ops(st, ST_OPS_MODESENSE, XS_CTL_SILENT);
|
||||
if (error) {
|
||||
/*
|
||||
* Ignore the error if in control mode;
|
||||
|
@ -1426,7 +1402,9 @@ stioctl(dev, cmd, arg, flag, p)
|
|||
goto try_new_value;
|
||||
|
||||
case MTCMPRESS:
|
||||
error = st_cmprss(st, number);
|
||||
error = st->ops(st, (number == 0) ?
|
||||
ST_OPS_CMPRSS_OFF : ST_OPS_CMPRSS_ON,
|
||||
XS_CTL_SILENT);
|
||||
break;
|
||||
|
||||
case MTEWARN:
|
||||
|
@ -1478,7 +1456,7 @@ try_new_value:
|
|||
* even if no medium is loaded (see st(4)).
|
||||
*/
|
||||
if ((STMODE(dev) != CTRL_MODE || (st->flags & ST_MOUNTED) != 0) &&
|
||||
(error = st_mode_select(st, 0)) != 0) {
|
||||
(error = st->ops(st, ST_OPS_MODESELECT, 0)) != 0) {
|
||||
/* put it back as it was */
|
||||
printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
|
||||
st->density = hold_density;
|
||||
|
@ -1542,282 +1520,6 @@ st_read(st, buf, size, flags)
|
|||
(u_char *)buf, size, 0, ST_IO_TIME, NULL, flags | XS_CTL_DATA_IN));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask the drive what it's min and max blk sizes are.
|
||||
*/
|
||||
int
|
||||
st_read_block_limits(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
struct scsi_block_limits cmd;
|
||||
struct scsi_block_limits_data block_limits;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* do a 'Read Block Limits'
|
||||
*/
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.opcode = READ_BLOCK_LIMITS;
|
||||
|
||||
/*
|
||||
* do the command, update the global values
|
||||
*/
|
||||
error = scsipi_command(periph, (struct scsipi_generic *)&cmd,
|
||||
sizeof(cmd), (u_char *)&block_limits, sizeof(block_limits),
|
||||
ST_RETRIES, ST_CTL_TIME, NULL,
|
||||
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
st->blkmin = _2btol(block_limits.min_length);
|
||||
st->blkmax = _3btol(block_limits.max_length);
|
||||
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the scsi driver to send a full inquiry to the
|
||||
* device and use the results to fill out the global
|
||||
* parameter structure.
|
||||
*
|
||||
* called from:
|
||||
* attach
|
||||
* open
|
||||
* ioctl (to reset original blksize)
|
||||
*/
|
||||
int
|
||||
st_mode_sense(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
u_int scsipi_sense_len;
|
||||
int error;
|
||||
struct scsipi_sense {
|
||||
struct scsipi_mode_header header;
|
||||
struct scsi_blk_desc blk_desc;
|
||||
u_char sense_data[MAX_PAGE_0_SIZE];
|
||||
} scsipi_sense;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
scsipi_sense_len = 12 + st->page_0_size;
|
||||
|
||||
/*
|
||||
* Set up a mode sense
|
||||
* We don't need the results. Just print them for our interest's sake,
|
||||
* if asked, or if we need it as a template for the mode select store
|
||||
* it away.
|
||||
*/
|
||||
error = scsipi_mode_sense(st->sc_periph, 0, SMS_PAGE_CTRL_CURRENT,
|
||||
&scsipi_sense.header, scsipi_sense_len, flags | XS_CTL_DATA_ONSTACK,
|
||||
ST_RETRIES, ST_CTL_TIME);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
st->numblks = _3btol(scsipi_sense.blk_desc.nblocks);
|
||||
st->media_blksize = _3btol(scsipi_sense.blk_desc.blklen);
|
||||
st->media_density = scsipi_sense.blk_desc.density;
|
||||
if (scsipi_sense.header.dev_spec & SMH_DSP_WRITE_PROT)
|
||||
st->flags |= ST_READONLY;
|
||||
else
|
||||
st->flags &= ~ST_READONLY;
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("density code %d, %d-byte blocks, write-%s, ",
|
||||
st->media_density, st->media_blksize,
|
||||
st->flags & ST_READONLY ? "protected" : "enabled"));
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("%sbuffered\n",
|
||||
scsipi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
|
||||
if (st->page_0_size)
|
||||
bcopy(scsipi_sense.sense_data, st->sense_data,
|
||||
st->page_0_size);
|
||||
periph->periph_flags |= PERIPH_MEDIA_LOADED;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a filled out parameter structure to the drive to
|
||||
* set it into the desire modes etc.
|
||||
*/
|
||||
int
|
||||
st_mode_select(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
u_int scsi_select_len;
|
||||
struct scsi_select {
|
||||
struct scsipi_mode_header header;
|
||||
struct scsi_blk_desc blk_desc;
|
||||
u_char sense_data[MAX_PAGE_0_SIZE];
|
||||
} scsi_select;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
scsi_select_len = 12 + st->page_0_size;
|
||||
|
||||
/*
|
||||
* This quirk deals with drives that have only one valid mode
|
||||
* and think this gives them license to reject all mode selects,
|
||||
* even if the selected mode is the one that is supported.
|
||||
*/
|
||||
if (st->quirks & ST_Q_UNIMODAL) {
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("not setting density 0x%x blksize 0x%x\n",
|
||||
st->density, st->blksize));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up for a mode select
|
||||
*/
|
||||
bzero(&scsi_select, scsi_select_len);
|
||||
scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc);
|
||||
scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
|
||||
scsi_select.blk_desc.density = st->density;
|
||||
if (st->flags & ST_DONTBUFFER)
|
||||
scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
|
||||
else
|
||||
scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
|
||||
if (st->flags & ST_FIXEDBLOCKS)
|
||||
_lto3b(st->blksize, scsi_select.blk_desc.blklen);
|
||||
if (st->page_0_size)
|
||||
bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size);
|
||||
|
||||
/*
|
||||
* do the command
|
||||
*/
|
||||
return scsipi_mode_select(periph, 0, &scsi_select.header,
|
||||
scsi_select_len, flags | XS_CTL_DATA_ONSTACK,
|
||||
ST_RETRIES, ST_CTL_TIME);
|
||||
}
|
||||
|
||||
int
|
||||
st_cmprss(st, onoff)
|
||||
struct st_softc *st;
|
||||
int onoff;
|
||||
{
|
||||
u_int scsi_dlen;
|
||||
int byte2, page;
|
||||
struct scsi_select {
|
||||
struct scsipi_mode_header header;
|
||||
struct scsi_blk_desc blk_desc;
|
||||
u_char pdata[MAX(sizeof(struct scsi_tape_dev_conf_page),
|
||||
sizeof(struct scsi_tape_dev_compression_page))];
|
||||
} scsi_pdata;
|
||||
struct scsi_tape_dev_conf_page *ptr;
|
||||
struct scsi_tape_dev_compression_page *cptr;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
int error, ison, flags = 0;
|
||||
|
||||
scsi_dlen = sizeof(scsi_pdata);
|
||||
|
||||
/*
|
||||
* Do DATA COMPRESSION page first.
|
||||
*/
|
||||
page = SMS_PAGE_CTRL_CURRENT | 0xf;
|
||||
byte2 = 0;
|
||||
|
||||
/*
|
||||
* Do the MODE SENSE command...
|
||||
*/
|
||||
again:
|
||||
bzero(&scsi_pdata, scsi_dlen);
|
||||
error = scsipi_mode_sense(periph, byte2, page,
|
||||
&scsi_pdata.header, scsi_dlen, flags | XS_CTL_DATA_ONSTACK,
|
||||
ST_RETRIES, ST_CTL_TIME);
|
||||
|
||||
if (error) {
|
||||
if (byte2 != SMS_DBD) {
|
||||
byte2 = SMS_DBD;
|
||||
goto again;
|
||||
}
|
||||
/*
|
||||
* Try a different page?
|
||||
*/
|
||||
if (page == (SMS_PAGE_CTRL_CURRENT | 0xf)) {
|
||||
page = SMS_PAGE_CTRL_CURRENT | 0x10;
|
||||
byte2 = 0;
|
||||
goto again;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (scsi_pdata.header.blk_desc_len)
|
||||
ptr = (struct scsi_tape_dev_conf_page *) scsi_pdata.pdata;
|
||||
else
|
||||
ptr = (struct scsi_tape_dev_conf_page *) &scsi_pdata.blk_desc;
|
||||
|
||||
if ((page & SMS_PAGE_CODE) == 0xf) {
|
||||
cptr = (struct scsi_tape_dev_compression_page *) ptr;
|
||||
ison = (cptr->dce_dcc & DCP_DCE) != 0;
|
||||
if (onoff)
|
||||
cptr->dce_dcc |= DCP_DCE;
|
||||
else
|
||||
cptr->dce_dcc &= ~DCP_DCE;
|
||||
cptr->pagecode &= ~0x80;
|
||||
} else {
|
||||
ison = (ptr->sel_comp_alg != 0);
|
||||
if (onoff)
|
||||
ptr->sel_comp_alg = 1;
|
||||
else
|
||||
ptr->sel_comp_alg = 0;
|
||||
ptr->pagecode &= ~0x80;
|
||||
ptr->byte2 = 0;
|
||||
ptr->active_partition = 0;
|
||||
ptr->wb_full_ratio = 0;
|
||||
ptr->rb_empty_ratio = 0;
|
||||
ptr->byte8 &= ~0x30;
|
||||
ptr->gap_size = 0;
|
||||
ptr->byte10 &= ~0xe7;
|
||||
ptr->ew_bufsize[0] = 0;
|
||||
ptr->ew_bufsize[1] = 0;
|
||||
ptr->ew_bufsize[2] = 0;
|
||||
ptr->reserved = 0;
|
||||
}
|
||||
onoff = onoff ? 1 : 0;
|
||||
/*
|
||||
* There might be a virtue in actually doing the MODE SELECTS,
|
||||
* but let's not clog the bus over it.
|
||||
*/
|
||||
if (onoff == ison)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Set up for a mode select
|
||||
*/
|
||||
|
||||
scsi_pdata.header.data_length = 0;
|
||||
scsi_pdata.header.medium_type = 0;
|
||||
if ((st->flags & ST_DONTBUFFER) == 0)
|
||||
scsi_pdata.header.dev_spec = SMH_DSP_BUFF_MODE_ON;
|
||||
else
|
||||
scsi_pdata.header.dev_spec = 0;
|
||||
|
||||
if (scsi_pdata.header.blk_desc_len) {
|
||||
scsi_pdata.blk_desc.density = 0;
|
||||
scsi_pdata.blk_desc.nblocks[0] = 0;
|
||||
scsi_pdata.blk_desc.nblocks[1] = 0;
|
||||
scsi_pdata.blk_desc.nblocks[2] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the command
|
||||
*/
|
||||
error = scsipi_mode_select(periph, SMS_PF, &scsi_pdata.header,
|
||||
scsi_dlen, flags | XS_CTL_DATA_ONSTACK, ST_RETRIES, ST_CTL_TIME);
|
||||
|
||||
if (error && (page & SMS_PAGE_CODE) == 0xf) {
|
||||
/*
|
||||
* Try DEVICE CONFIGURATION page.
|
||||
*/
|
||||
page = SMS_PAGE_CTRL_CURRENT | 0x10;
|
||||
goto again;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
/*
|
||||
* issue an erase command
|
||||
*/
|
||||
|
@ -2085,6 +1787,12 @@ st_rewind(st, immediate, flags)
|
|||
}
|
||||
st->flags &= ~ST_PER_ACTION;
|
||||
|
||||
/*
|
||||
* ATAPI tapes always need foo to be set
|
||||
*/
|
||||
if (scsipi_periph_bustype(st->sc_periph) == SCSIPI_BUSTYPE_ATAPI)
|
||||
immediate = SR_IMMED;
|
||||
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.opcode = REWIND;
|
||||
cmd.byte2 = immediate;
|
||||
|
@ -2426,7 +2134,7 @@ st_touch_tape(st)
|
|||
if (buf == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
if ((error = st_mode_sense(st, 0)) != 0)
|
||||
if ((error = st->ops(st, ST_OPS_MODESENSE, 0)) != 0)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
|
@ -2449,7 +2157,8 @@ st_touch_tape(st)
|
|||
readsize = 1;
|
||||
st->flags &= ~ST_FIXEDBLOCKS;
|
||||
}
|
||||
if ((error = st_mode_select(st, XS_CTL_SILENT)) != 0) {
|
||||
if ((error = st->ops(st, ST_OPS_MODESELECT, XS_CTL_SILENT))
|
||||
!= 0) {
|
||||
/*
|
||||
* The device did not agree with the proposed
|
||||
* block size. If we exhausted our options,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: st_atapi.c,v 1.1 2001/05/04 07:48:57 bouyer Exp $ */
|
||||
/* $NetBSD: st_atapi.c,v 1.2 2001/06/18 09:05:05 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -17,8 +17,8 @@
|
|||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
|
@ -65,18 +65,25 @@
|
|||
#include <sys/buf.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/scsipi/stvar.h>
|
||||
#include <dev/scsipi/atapi_tape.h>
|
||||
|
||||
int st_atapibus_match __P((struct device *, struct cfdata *, void *));
|
||||
void st_atapibus_attach __P((struct device *, struct device *, void *));
|
||||
int st_atapibus_ops __P((struct st_softc *, int, int));
|
||||
int st_atapibus_mode_sense __P((struct st_softc *, int));
|
||||
int st_atapibus_mode_select __P((struct st_softc *, int));
|
||||
int st_atapibus_do_ms __P((struct st_softc *, int, void *, int, int));
|
||||
|
||||
struct cfattach st_atapibus_ca = {
|
||||
sizeof(struct st_softc), st_atapibus_match, stattach
|
||||
sizeof(struct st_softc), st_atapibus_match, st_atapibus_attach
|
||||
};
|
||||
|
||||
const struct scsipi_inquiry_pattern st_atapibus_patterns[] = {
|
||||
{T_SEQUENTIAL, T_REMOV,
|
||||
"", "", ""},
|
||||
"", "", ""},
|
||||
};
|
||||
|
||||
int
|
||||
|
@ -88,9 +95,101 @@ st_atapibus_match(parent, match, aux)
|
|||
struct scsipibus_attach_args *sa = aux;
|
||||
int priority;
|
||||
|
||||
if (scsipi_periph_bustype(sa->sa_periph) != SCSIPI_BUSTYPE_ATAPI)
|
||||
return (0);
|
||||
|
||||
(void)scsipi_inqmatch(&sa->sa_inqbuf,
|
||||
(caddr_t)st_atapibus_patterns,
|
||||
sizeof(st_atapibus_patterns)/sizeof(st_atapibus_patterns[0]),
|
||||
sizeof(st_atapibus_patterns[0]), &priority);
|
||||
return (priority);
|
||||
}
|
||||
|
||||
void
|
||||
st_atapibus_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct st_softc *st = (void *)self;
|
||||
|
||||
st->ops = st_atapibus_ops;
|
||||
stattach(parent, st, aux);
|
||||
}
|
||||
|
||||
int
|
||||
st_atapibus_ops(st, op, flags)
|
||||
struct st_softc *st;
|
||||
int op;
|
||||
int flags;
|
||||
{
|
||||
switch(op) {
|
||||
case ST_OPS_RBL:
|
||||
/* done in mode_sense */
|
||||
return 0;
|
||||
case ST_OPS_MODESENSE:
|
||||
return st_atapibus_mode_sense(st, flags);
|
||||
case ST_OPS_MODESELECT:
|
||||
return st_atapibus_mode_select(st, flags);
|
||||
case ST_OPS_CMPRSS_ON:
|
||||
case ST_OPS_CMPRSS_OFF:
|
||||
return ENODEV;
|
||||
default:
|
||||
panic("st_scsibus_ops: invalid op");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
st_atapibus_mode_sense(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
int count, error;
|
||||
struct atapi_cappage cappage;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
/* get drive capabilities, some drives needs this repeated */
|
||||
for (count = 0 ; count < 5 ; count++) {
|
||||
error = scsipi_mode_sense(periph, SMS_DBD,
|
||||
ATAPI_TAPE_CAP_PAGE, &cappage.header, sizeof(cappage),
|
||||
flags | XS_CTL_DATA_ONSTACK, ST_RETRIES, ST_CTL_TIME);
|
||||
if (error == 0) {
|
||||
st->numblks = 0; /* unused anyway */
|
||||
if (cappage.cap4 & ATAPI_TAPE_CAP_PAGE_BLK32K)
|
||||
st->media_blksize = 32768;
|
||||
else if (cappage.cap4 & ATAPI_TAPE_CAP_PAGE_BLK1K)
|
||||
st->media_blksize = 1024;
|
||||
else if (cappage.cap4 & ATAPI_TAPE_CAP_PAGE_BLK512)
|
||||
st->media_blksize = 512;
|
||||
else {
|
||||
error = ENODEV;
|
||||
continue;
|
||||
}
|
||||
st->blkmin = st->blkmax = st->media_blksize;
|
||||
st->media_density = 0;
|
||||
if (cappage.header.dev_spec & SMH_DSP_WRITE_PROT)
|
||||
st->flags |= ST_READONLY;
|
||||
else
|
||||
st->flags &= ~ST_READONLY;
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("density code %d, %d-byte blocks, write-%s, ",
|
||||
st->media_density, st->media_blksize,
|
||||
st->flags & ST_READONLY ? "protected" : "enabled"));
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("%sbuffered\n",
|
||||
cappage.header.dev_spec & SMH_DSP_BUFF_MODE ?
|
||||
"" : "un"));
|
||||
periph->periph_flags |= PERIPH_MEDIA_LOADED;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
st_atapibus_mode_select(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
return ENODEV; /* for now ... */
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: st_scsi.c,v 1.1 2001/05/04 07:48:57 bouyer Exp $ */
|
||||
/* $NetBSD: st_scsi.c,v 1.2 2001/06/18 09:05:05 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -65,13 +65,22 @@
|
|||
#include <sys/buf.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/scsipi/stvar.h>
|
||||
#include <dev/scsipi/scsi_tape.h>
|
||||
#include <dev/scsipi/scsi_all.h>
|
||||
|
||||
int st_scsibus_match __P((struct device *, struct cfdata *, void *));
|
||||
void st_scsibus_attach __P((struct device *, struct device *, void *));
|
||||
int st_scsibus_ops __P((struct st_softc *, int, int));
|
||||
int st_scsibus_read_block_limits __P((struct st_softc *, int));
|
||||
int st_scsibus_mode_sense __P((struct st_softc *, int));
|
||||
int st_scsibus_mode_select __P((struct st_softc *, int));
|
||||
int st_scsibus_cmprss __P((struct st_softc *, int, int));
|
||||
|
||||
struct cfattach st_scsibus_ca = {
|
||||
sizeof(struct st_softc), st_scsibus_match, stattach
|
||||
sizeof(struct st_softc), st_scsibus_match, st_scsibus_attach
|
||||
};
|
||||
|
||||
const struct scsipi_inquiry_pattern st_scsibus_patterns[] = {
|
||||
|
@ -88,9 +97,322 @@ st_scsibus_match(parent, match, aux)
|
|||
struct scsipibus_attach_args *sa = aux;
|
||||
int priority;
|
||||
|
||||
if (scsipi_periph_bustype(sa->sa_periph) != SCSIPI_BUSTYPE_SCSI)
|
||||
return (0);
|
||||
|
||||
(void)scsipi_inqmatch(&sa->sa_inqbuf,
|
||||
(caddr_t)st_scsibus_patterns,
|
||||
sizeof(st_scsibus_patterns)/sizeof(st_scsibus_patterns[0]),
|
||||
sizeof(st_scsibus_patterns[0]), &priority);
|
||||
return (priority);
|
||||
}
|
||||
|
||||
void
|
||||
st_scsibus_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct st_softc *st = (void *)self;
|
||||
|
||||
st->ops = st_scsibus_ops;
|
||||
stattach(parent, st, aux);
|
||||
}
|
||||
|
||||
int
|
||||
st_scsibus_ops(st, op, flags)
|
||||
struct st_softc *st;
|
||||
int op;
|
||||
int flags;
|
||||
{
|
||||
switch(op) {
|
||||
case ST_OPS_RBL:
|
||||
return st_scsibus_read_block_limits(st, flags);
|
||||
case ST_OPS_MODESENSE:
|
||||
return st_scsibus_mode_sense(st, flags);
|
||||
case ST_OPS_MODESELECT:
|
||||
return st_scsibus_mode_select(st, flags);
|
||||
case ST_OPS_CMPRSS_ON:
|
||||
case ST_OPS_CMPRSS_OFF:
|
||||
return st_scsibus_cmprss(st, flags,
|
||||
(op == ST_OPS_CMPRSS_ON) ? 1 : 0);
|
||||
default:
|
||||
panic("st_scsibus_ops: invalid op");
|
||||
return 0; /* XXX to appease gcc */
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask the drive what it's min and max blk sizes are.
|
||||
*/
|
||||
int
|
||||
st_scsibus_read_block_limits(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
struct scsi_block_limits cmd;
|
||||
struct scsi_block_limits_data block_limits;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* do a 'Read Block Limits'
|
||||
*/
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.opcode = READ_BLOCK_LIMITS;
|
||||
|
||||
/*
|
||||
* do the command, update the global values
|
||||
*/
|
||||
error = scsipi_command(periph, (struct scsipi_generic *)&cmd,
|
||||
sizeof(cmd), (u_char *)&block_limits, sizeof(block_limits),
|
||||
ST_RETRIES, ST_CTL_TIME, NULL,
|
||||
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
st->blkmin = _2btol(block_limits.min_length);
|
||||
st->blkmax = _3btol(block_limits.max_length);
|
||||
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the scsi driver to send a full inquiry to the
|
||||
* device and use the results to fill out the global
|
||||
* parameter structure.
|
||||
*
|
||||
* called from:
|
||||
* attach
|
||||
* open
|
||||
* ioctl (to reset original blksize)
|
||||
*/
|
||||
int
|
||||
st_scsibus_mode_sense(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
u_int scsipi_sense_len;
|
||||
int error;
|
||||
struct scsipi_sense {
|
||||
struct scsipi_mode_header header;
|
||||
struct scsi_blk_desc blk_desc;
|
||||
u_char sense_data[MAX_PAGE_0_SIZE];
|
||||
} scsipi_sense;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
scsipi_sense_len = 12 + st->page_0_size;
|
||||
|
||||
/*
|
||||
* Set up a mode sense
|
||||
* We don't need the results. Just print them for our interest's sake,
|
||||
* if asked, or if we need it as a template for the mode select store
|
||||
* it away.
|
||||
*/
|
||||
error = scsipi_mode_sense(st->sc_periph, 0, SMS_PAGE_CTRL_CURRENT,
|
||||
&scsipi_sense.header, scsipi_sense_len, flags | XS_CTL_DATA_ONSTACK,
|
||||
ST_RETRIES, ST_CTL_TIME);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
st->numblks = _3btol(scsipi_sense.blk_desc.nblocks);
|
||||
st->media_blksize = _3btol(scsipi_sense.blk_desc.blklen);
|
||||
st->media_density = scsipi_sense.blk_desc.density;
|
||||
if (scsipi_sense.header.dev_spec & SMH_DSP_WRITE_PROT)
|
||||
st->flags |= ST_READONLY;
|
||||
else
|
||||
st->flags &= ~ST_READONLY;
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("density code %d, %d-byte blocks, write-%s, ",
|
||||
st->media_density, st->media_blksize,
|
||||
st->flags & ST_READONLY ? "protected" : "enabled"));
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("%sbuffered\n",
|
||||
scsipi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
|
||||
if (st->page_0_size)
|
||||
bcopy(scsipi_sense.sense_data, st->sense_data,
|
||||
st->page_0_size);
|
||||
periph->periph_flags |= PERIPH_MEDIA_LOADED;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a filled out parameter structure to the drive to
|
||||
* set it into the desire modes etc.
|
||||
*/
|
||||
int
|
||||
st_scsibus_mode_select(st, flags)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
{
|
||||
u_int scsi_select_len;
|
||||
struct scsi_select {
|
||||
struct scsipi_mode_header header;
|
||||
struct scsi_blk_desc blk_desc;
|
||||
u_char sense_data[MAX_PAGE_0_SIZE];
|
||||
} scsi_select;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
scsi_select_len = 12 + st->page_0_size;
|
||||
|
||||
/*
|
||||
* This quirk deals with drives that have only one valid mode
|
||||
* and think this gives them license to reject all mode selects,
|
||||
* even if the selected mode is the one that is supported.
|
||||
*/
|
||||
if (st->quirks & ST_Q_UNIMODAL) {
|
||||
SC_DEBUG(periph, SCSIPI_DB3,
|
||||
("not setting density 0x%x blksize 0x%x\n",
|
||||
st->density, st->blksize));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up for a mode select
|
||||
*/
|
||||
bzero(&scsi_select, scsi_select_len);
|
||||
scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc);
|
||||
scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
|
||||
scsi_select.blk_desc.density = st->density;
|
||||
if (st->flags & ST_DONTBUFFER)
|
||||
scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
|
||||
else
|
||||
scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
|
||||
if (st->flags & ST_FIXEDBLOCKS)
|
||||
_lto3b(st->blksize, scsi_select.blk_desc.blklen);
|
||||
if (st->page_0_size)
|
||||
bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size);
|
||||
|
||||
/*
|
||||
* do the command
|
||||
*/
|
||||
return scsipi_mode_select(periph, 0, &scsi_select.header,
|
||||
scsi_select_len, flags | XS_CTL_DATA_ONSTACK,
|
||||
ST_RETRIES, ST_CTL_TIME);
|
||||
}
|
||||
|
||||
int
|
||||
st_scsibus_cmprss(st, flags, onoff)
|
||||
struct st_softc *st;
|
||||
int flags;
|
||||
int onoff;
|
||||
{
|
||||
u_int scsi_dlen;
|
||||
int byte2, page;
|
||||
struct scsi_select {
|
||||
struct scsipi_mode_header header;
|
||||
struct scsi_blk_desc blk_desc;
|
||||
u_char pdata[MAX(sizeof(struct scsi_tape_dev_conf_page),
|
||||
sizeof(struct scsi_tape_dev_compression_page))];
|
||||
} scsi_pdata;
|
||||
struct scsi_tape_dev_conf_page *ptr;
|
||||
struct scsi_tape_dev_compression_page *cptr;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
int error, ison;
|
||||
|
||||
scsi_dlen = sizeof(scsi_pdata);
|
||||
/*
|
||||
* Do DATA COMPRESSION page first.
|
||||
*/
|
||||
page = SMS_PAGE_CTRL_CURRENT | 0xf;
|
||||
byte2 = 0;
|
||||
|
||||
/*
|
||||
* Do the MODE SENSE command...
|
||||
*/
|
||||
again:
|
||||
bzero(&scsi_pdata, scsi_dlen);
|
||||
error = scsipi_mode_sense(periph, byte2, page,
|
||||
&scsi_pdata.header, scsi_dlen, flags | XS_CTL_DATA_ONSTACK,
|
||||
ST_RETRIES, ST_CTL_TIME);
|
||||
|
||||
if (error) {
|
||||
if (byte2 != SMS_DBD) {
|
||||
byte2 = SMS_DBD;
|
||||
goto again;
|
||||
}
|
||||
/*
|
||||
* Try a different page?
|
||||
*/
|
||||
if (page == (SMS_PAGE_CTRL_CURRENT | 0xf)) {
|
||||
page = SMS_PAGE_CTRL_CURRENT | 0x10;
|
||||
byte2 = 0;
|
||||
goto again;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (scsi_pdata.header.blk_desc_len)
|
||||
ptr = (struct scsi_tape_dev_conf_page *) scsi_pdata.pdata;
|
||||
else
|
||||
ptr = (struct scsi_tape_dev_conf_page *) &scsi_pdata.blk_desc;
|
||||
|
||||
if ((page & SMS_PAGE_CODE) == 0xf) {
|
||||
cptr = (struct scsi_tape_dev_compression_page *) ptr;
|
||||
ison = (cptr->dce_dcc & DCP_DCE) != 0;
|
||||
if (onoff)
|
||||
cptr->dce_dcc |= DCP_DCE;
|
||||
else
|
||||
cptr->dce_dcc &= ~DCP_DCE;
|
||||
cptr->pagecode &= ~0x80;
|
||||
} else {
|
||||
ison = (ptr->sel_comp_alg != 0);
|
||||
if (onoff)
|
||||
ptr->sel_comp_alg = 1;
|
||||
else
|
||||
ptr->sel_comp_alg = 0;
|
||||
ptr->pagecode &= ~0x80;
|
||||
ptr->byte2 = 0;
|
||||
ptr->active_partition = 0;
|
||||
ptr->wb_full_ratio = 0;
|
||||
ptr->rb_empty_ratio = 0;
|
||||
ptr->byte8 &= ~0x30;
|
||||
ptr->gap_size = 0;
|
||||
ptr->byte10 &= ~0xe7;
|
||||
ptr->ew_bufsize[0] = 0;
|
||||
ptr->ew_bufsize[1] = 0;
|
||||
ptr->ew_bufsize[2] = 0;
|
||||
ptr->reserved = 0;
|
||||
}
|
||||
/*
|
||||
* There might be a virtue in actually doing the MODE SELECTS,
|
||||
* but let's not clog the bus over it.
|
||||
*/
|
||||
if (onoff == ison)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Set up for a mode select
|
||||
*/
|
||||
|
||||
scsi_pdata.header.data_length = 0;
|
||||
scsi_pdata.header.medium_type = 0;
|
||||
if ((st->flags & ST_DONTBUFFER) == 0)
|
||||
scsi_pdata.header.dev_spec = SMH_DSP_BUFF_MODE_ON;
|
||||
else
|
||||
scsi_pdata.header.dev_spec = 0;
|
||||
|
||||
if (scsi_pdata.header.blk_desc_len) {
|
||||
scsi_pdata.blk_desc.density = 0;
|
||||
scsi_pdata.blk_desc.nblocks[0] = 0;
|
||||
scsi_pdata.blk_desc.nblocks[1] = 0;
|
||||
scsi_pdata.blk_desc.nblocks[2] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the command
|
||||
*/
|
||||
error = scsipi_mode_select(periph, SMS_PF, &scsi_pdata.header,
|
||||
scsi_dlen, flags | XS_CTL_DATA_ONSTACK, ST_RETRIES, ST_CTL_TIME);
|
||||
|
||||
if (error && (page & SMS_PAGE_CODE) == 0xf) {
|
||||
/*
|
||||
* Try DEVICE CONFIGURATION page.
|
||||
*/
|
||||
page = SMS_PAGE_CTRL_CURRENT | 0x10;
|
||||
goto again;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: stvar.h,v 1.1 2001/05/04 07:48:57 bouyer Exp $ */
|
||||
/* $NetBSD: stvar.h,v 1.2 2001/06/18 09:05:05 bouyer Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -64,6 +64,12 @@
|
|||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsiconf.h>
|
||||
|
||||
#define ST_IO_TIME (3 * 60 * 1000) /* 3 minutes */
|
||||
#define ST_CTL_TIME (30 * 1000) /* 30 seconds */
|
||||
#define ST_SPC_TIME (4 * 60 * 60 * 1000) /* 4 hours */
|
||||
|
||||
#define ST_RETRIES 4 /* only on non IO commands */
|
||||
|
||||
struct modes {
|
||||
u_int quirks; /* same definitions as in quirkdata */
|
||||
int blksize;
|
||||
|
@ -91,6 +97,13 @@ struct st_quirk_inquiry_pattern {
|
|||
|
||||
struct st_softc {
|
||||
struct device sc_dev;
|
||||
/*--------------------callback to bus-specific code--------------------------*/
|
||||
int (*ops) __P((struct st_softc *, int, int));
|
||||
#define ST_OPS_RBL 0x00 /* read block limit */
|
||||
#define ST_OPS_MODESENSE 0x01 /* mode sense */
|
||||
#define ST_OPS_MODESELECT 0x02 /* mode select */
|
||||
#define ST_OPS_CMPRSS_ON 0x03 /* turn on compression */
|
||||
#define ST_OPS_CMPRSS_OFF 0x04 /* turn off compression */
|
||||
/*--------------------present operating parameters, flags etc.---------------*/
|
||||
int flags; /* see below */
|
||||
u_int quirks; /* quirks for the open mode */
|
||||
|
@ -134,7 +147,32 @@ struct st_softc {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define ST_INFO_VALID 0x0001
|
||||
#define ST_BLOCK_SET 0x0002 /* block size, mode set by ioctl */
|
||||
#define ST_WRITTEN 0x0004 /* data has been written, EOD needed */
|
||||
#define ST_FIXEDBLOCKS 0x0008
|
||||
#define ST_AT_FILEMARK 0x0010
|
||||
#define ST_EIO_PENDING 0x0020 /* error reporting deferred until next op */
|
||||
#define ST_NEW_MOUNT 0x0040 /* still need to decide mode */
|
||||
#define ST_READONLY 0x0080 /* st_mode_sense says write protected */
|
||||
#define ST_FM_WRITTEN 0x0100 /*
|
||||
* EOF file mark written -- used with
|
||||
* ~ST_WRITTEN to indicate that multiple file
|
||||
* marks have been written
|
||||
*/
|
||||
#define ST_BLANK_READ 0x0200 /* BLANK CHECK encountered already */
|
||||
#define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */
|
||||
#define ST_MOUNTED 0x0800 /* Device is presently mounted */
|
||||
#define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
|
||||
#define ST_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */
|
||||
#define ST_EOM_PENDING 0x4000 /* EOM reporting deferred until next op */
|
||||
|
||||
void stattach __P((struct device *, struct device *, void *));
|
||||
#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_EOM_PENDING | \
|
||||
ST_BLANK_READ)
|
||||
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
|
||||
ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
|
||||
ST_2FM_AT_EOD | ST_PER_ACTION)
|
||||
|
||||
void stattach __P((struct device *, struct st_softc *, void *));
|
||||
|
||||
extern struct cfdriver st_cd;
|
||||
|
|
Loading…
Reference in New Issue