1. Move the mode_select functionality into common code (in st.c) and
invoke the common routine for both scsi and atapi tapes. 2. Replace a numeric constant with some sizeof's when calculating the size of the mode_select command buffer, clear the entire buffer, and KASSERT to ensure the page_0_size loaded from quirk table is valid. 3. Add a quirk for my Seagate Travan-40 tape drive. As discussed on tech-kern@ Addresses my PR kern/34832
This commit is contained in:
parent
89669ce394
commit
345b8f1066
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: st.c,v 1.211 2009/05/12 14:44:31 cegger Exp $ */
|
||||
/* $NetBSD: st.c,v 1.212 2009/08/15 12:44:55 pgoyette Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
|
||||
@ -50,7 +50,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.211 2009/05/12 14:44:31 cegger Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.212 2009/08/15 12:44:55 pgoyette Exp $");
|
||||
|
||||
#include "opt_scsi.h"
|
||||
|
||||
@ -306,6 +306,13 @@ static 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,
|
||||
"Seagate STT3401A", "hp0atxa", ""}, {0, 0, {
|
||||
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
|
||||
{ST_Q_FORCE_BLKSIZE, 1024, 0}, /* minor 4-7 */
|
||||
{ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 8-11 */
|
||||
{ST_Q_FORCE_BLKSIZE, 512, 0} /* minor 12-15 */
|
||||
}}},
|
||||
};
|
||||
|
||||
#define NOEJECT 0
|
||||
@ -488,6 +495,7 @@ st_identify_drive(struct st_softc *st, struct scsipi_inquiry_pattern *inqbuf)
|
||||
st->drive_quirks = finger->quirkdata.quirks;
|
||||
st->quirks = finger->quirkdata.quirks; /* start value */
|
||||
st->page_0_size = finger->quirkdata.page_0_size;
|
||||
KASSERT(st->page_0_size <= MAX_PAGE_0_SIZE);
|
||||
st_loadquirks(st);
|
||||
}
|
||||
}
|
||||
@ -2401,3 +2409,57 @@ stdump(dev_t dev, daddr_t blkno, void *va,
|
||||
/* Not implemented. */
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a filled out parameter structure to the drive to
|
||||
* set it into the desire modes etc.
|
||||
*/
|
||||
int
|
||||
st_mode_select(struct st_softc *st, int flags)
|
||||
{
|
||||
u_int select_len;
|
||||
struct select {
|
||||
struct scsi_mode_parameter_header_6 header;
|
||||
struct scsi_general_block_descriptor blk_desc;
|
||||
u_char sense_data[MAX_PAGE_0_SIZE];
|
||||
} select;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
select_len = sizeof(select.header) + sizeof(select.blk_desc) +
|
||||
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
|
||||
*/
|
||||
memset(&select, 0, sizeof(select));
|
||||
select.header.blk_desc_len = sizeof(struct scsi_general_block_descriptor);
|
||||
select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
|
||||
select.blk_desc.density = st->density;
|
||||
if (st->flags & ST_DONTBUFFER)
|
||||
select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
|
||||
else
|
||||
select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
|
||||
if (st->flags & ST_FIXEDBLOCKS)
|
||||
_lto3b(st->blksize, select.blk_desc.blklen);
|
||||
if (st->page_0_size)
|
||||
memcpy(select.sense_data, st->sense_data, st->page_0_size);
|
||||
|
||||
/*
|
||||
* do the command
|
||||
*/
|
||||
return scsipi_mode_select(periph, 0, &select.header, select_len,
|
||||
flags | XS_CTL_DATA_ONSTACK, ST_RETRIES,
|
||||
ST_CTL_TIME);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: st_atapi.c,v 1.22 2009/05/12 14:44:31 cegger Exp $ */
|
||||
/* $NetBSD: st_atapi.c,v 1.23 2009/08/15 12:44:55 pgoyette Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Manuel Bouyer.
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: st_atapi.c,v 1.22 2009/05/12 14:44:31 cegger Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: st_atapi.c,v 1.23 2009/08/15 12:44:55 pgoyette Exp $");
|
||||
|
||||
#include "opt_scsi.h"
|
||||
#include "rnd.h"
|
||||
@ -51,7 +51,6 @@ static int st_atapibus_match(device_t, cfdata_t, void *);
|
||||
static void st_atapibus_attach(device_t, device_t, void *);
|
||||
static int st_atapibus_ops(struct st_softc *, int, int);
|
||||
static int st_atapibus_mode_sense(struct st_softc *, int);
|
||||
static int st_atapibus_mode_select(struct st_softc *, int);
|
||||
|
||||
CFATTACH_DECL(st_atapibus, sizeof(struct st_softc),
|
||||
st_atapibus_match, st_atapibus_attach, stdetach, stactivate);
|
||||
@ -122,7 +121,7 @@ st_atapibus_ops(struct st_softc *st, int op, int flags)
|
||||
case ST_OPS_MODESENSE:
|
||||
return st_atapibus_mode_sense(st, flags);
|
||||
case ST_OPS_MODESELECT:
|
||||
return st_atapibus_mode_select(st, flags);
|
||||
return st_mode_select(st, flags);
|
||||
case ST_OPS_CMPRSS_ON:
|
||||
case ST_OPS_CMPRSS_OFF:
|
||||
return ENODEV;
|
||||
@ -176,9 +175,3 @@ st_atapibus_mode_sense(struct st_softc *st, int flags)
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
st_atapibus_mode_select(struct st_softc *st, int flags)
|
||||
{
|
||||
return ENODEV; /* for now ... */
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: st_scsi.c,v 1.29 2009/05/12 14:44:31 cegger Exp $ */
|
||||
/* $NetBSD: st_scsi.c,v 1.30 2009/08/15 12:44:55 pgoyette Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
|
||||
@ -50,7 +50,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: st_scsi.c,v 1.29 2009/05/12 14:44:31 cegger Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: st_scsi.c,v 1.30 2009/08/15 12:44:55 pgoyette Exp $");
|
||||
|
||||
#include "opt_scsi.h"
|
||||
#include "rnd.h"
|
||||
@ -72,7 +72,6 @@ static void st_scsibus_attach(device_t, device_t, void *);
|
||||
static int st_scsibus_ops(struct st_softc *, int, int);
|
||||
static int st_scsibus_read_block_limits(struct st_softc *, int);
|
||||
static int st_scsibus_mode_sense(struct st_softc *, int);
|
||||
static int st_scsibus_mode_select(struct st_softc *, int);
|
||||
static int st_scsibus_cmprss(struct st_softc *, int, int);
|
||||
|
||||
CFATTACH_DECL(st_scsibus, sizeof(struct st_softc),
|
||||
@ -118,7 +117,7 @@ st_scsibus_ops(struct st_softc *st, int op, int flags)
|
||||
case ST_OPS_MODESENSE:
|
||||
return st_scsibus_mode_sense(st, flags);
|
||||
case ST_OPS_MODESELECT:
|
||||
return st_scsibus_mode_select(st, flags);
|
||||
return st_mode_select(st, flags);
|
||||
case ST_OPS_CMPRSS_ON:
|
||||
case ST_OPS_CMPRSS_OFF:
|
||||
return st_scsibus_cmprss(st, flags,
|
||||
@ -187,7 +186,9 @@ st_scsibus_mode_sense(struct st_softc *st, int flags)
|
||||
} scsipi_sense;
|
||||
struct scsipi_periph *periph = st->sc_periph;
|
||||
|
||||
scsipi_sense_len = 12 + st->page_0_size;
|
||||
scsipi_sense_len = sizeof(scsipi_sense.header) +
|
||||
sizeof(scsipi_sense.blk_desc) +
|
||||
st->page_0_size;
|
||||
|
||||
/*
|
||||
* Set up a mode sense
|
||||
@ -222,59 +223,6 @@ st_scsibus_mode_sense(struct st_softc *st, int flags)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a filled out parameter structure to the drive to
|
||||
* set it into the desire modes etc.
|
||||
*/
|
||||
static int
|
||||
st_scsibus_mode_select(struct st_softc *st, int flags)
|
||||
{
|
||||
u_int scsi_select_len;
|
||||
struct scsi_select {
|
||||
struct scsi_mode_parameter_header_6 header;
|
||||
struct scsi_general_block_descriptor 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
|
||||
*/
|
||||
memset(&scsi_select, 0, scsi_select_len);
|
||||
scsi_select.header.blk_desc_len = sizeof(struct scsi_general_block_descriptor);
|
||||
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)
|
||||
memcpy(scsi_select.sense_data, st->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);
|
||||
}
|
||||
|
||||
static int
|
||||
st_scsibus_cmprss(struct st_softc *st, int flags, int onoff)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: stvar.h,v 1.19 2009/05/12 14:44:31 cegger Exp $ */
|
||||
/* $NetBSD: stvar.h,v 1.20 2009/08/15 12:44:55 pgoyette Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -181,5 +181,6 @@ struct st_softc {
|
||||
void stattach(device_t, struct st_softc *, void *);
|
||||
int stactivate(device_t, enum devact);
|
||||
int stdetach(device_t, int);
|
||||
int st_mode_select(struct st_softc *, int);
|
||||
|
||||
extern struct cfdriver st_cd;
|
||||
|
Loading…
Reference in New Issue
Block a user