Honor cache request and implement erase command, and add the SCSI tape
device configuration page. Fixes PRs 807, 1201, and 1705. From John Kohl <jtk@kolvir.blrc.ma.us>.
This commit is contained in:
parent
94bb8db5ad
commit
5b51ec5cc8
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: scsi_tape.h,v 1.6 1994/12/28 19:43:08 mycroft Exp $ */
|
||||
/* $NetBSD: scsi_tape.h,v 1.7 1996/01/11 03:36:34 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
@ -110,6 +110,16 @@ struct scsi_load {
|
||||
u_char control;
|
||||
};
|
||||
|
||||
#define ERASE 0x19
|
||||
struct scsi_erase {
|
||||
u_char opcode;
|
||||
u_char byte2;
|
||||
#define SE_LONG 0x01
|
||||
#define SE_IMMED 0x02
|
||||
u_char unused[3];
|
||||
u_char control;
|
||||
};
|
||||
|
||||
#define READ_BLOCK_LIMITS 0x05
|
||||
struct scsi_block_limits {
|
||||
u_char opcode;
|
||||
@ -127,6 +137,41 @@ struct scsi_block_limits_data {
|
||||
u_char min_length_0; /* Least significant */
|
||||
};
|
||||
|
||||
/* See SCSI-II spec 9.3.3.1 */
|
||||
struct scsi_tape_dev_conf_page {
|
||||
u_char pagecode; /* 0x10 */
|
||||
u_char pagelength; /* 0x0e */
|
||||
u_char byte2;
|
||||
#define SMT_CAP 0x40 /* change active partition */
|
||||
#define SMT_CAF 0x20 /* change active format */
|
||||
#define SMT_AFMASK 0x1f /* active format mask */
|
||||
u_char active_partition;
|
||||
u_char wb_full_ratio;
|
||||
u_char rb_empty_ratio;
|
||||
u_char wrdelay_time_1; /* MSB */
|
||||
u_char wrdelay_time_0; /* LSB */
|
||||
u_char byte8;
|
||||
#define SMT_DBR 0x80 /* data buffer recovery */
|
||||
#define SMT_BIS 0x40 /* block identifiers supported */
|
||||
#define SMT_RSMK 0x20 /* report setmarks */
|
||||
#define SMT_AVC 0x10 /* automatic velocity control */
|
||||
#define SMT_SOCF_MASK 0xc0 /* stop on consecutive formats */
|
||||
#define SMT_RBO 0x20 /* recover buffer order */
|
||||
#define SMT_REW 0x10 /* report early warning */
|
||||
u_char gap_size;
|
||||
u_char byte10;
|
||||
#define SMT_EODDEFINED 0xe0 /* EOD defined */
|
||||
#define SMT_EEG 0x10 /* enable EOD generation */
|
||||
#define SMT_SEW 0x80 /* synchronize at early warning */
|
||||
u_char ew_bufsize_2; /* MSB */
|
||||
u_char ew_bufsize_1; /* ... */
|
||||
u_char ew_bufsize_0; /* LSB */
|
||||
u_char sel_comp_alg;
|
||||
#define SMT_COMP_NONE 0x00
|
||||
#define SMT_COMP_DEFAULT 0x01
|
||||
u_char reserved;
|
||||
};
|
||||
|
||||
/* defines for the device specific byte in the mode select/sense header */
|
||||
#define SMH_DSP_SPEED 0x0F
|
||||
#define SMH_DSP_BUFF_MODE 0x70
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: st.c,v 1.56 1996/01/05 16:03:35 pk Exp $ */
|
||||
/* $NetBSD: st.c,v 1.57 1996/01/11 03:36:38 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
@ -266,14 +266,14 @@ int st_touch_tape __P((struct st_softc *));
|
||||
int st_write_filemarks __P((struct st_softc *, int number, int flags));
|
||||
int st_load __P((struct st_softc *, u_int type, int flags));
|
||||
int st_mode_select __P((struct st_softc *, int flags));
|
||||
void ststrategy();
|
||||
int st_check_eod();
|
||||
void ststart();
|
||||
void st_unmount();
|
||||
int st_mount_tape();
|
||||
void st_loadquirks();
|
||||
void st_identify_drive();
|
||||
int st_interpret_sense();
|
||||
void ststrategy __P((struct buf *));
|
||||
int st_check_eod __P((struct st_softc *, boolean, int *, int));
|
||||
void ststart __P((struct st_softc *));
|
||||
void st_unmount __P((struct st_softc *, boolean));
|
||||
int st_mount_tape __P((dev_t, int));
|
||||
void st_loadquirks __P((struct st_softc *));
|
||||
void st_identify_drive __P((struct st_softc *, struct scsi_inquiry_data *));
|
||||
int st_interpret_sense __P((struct scsi_xfer *));
|
||||
|
||||
struct scsi_device st_switch = {
|
||||
st_interpret_sense,
|
||||
@ -298,6 +298,7 @@ struct scsi_device st_switch = {
|
||||
#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_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
|
||||
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
|
||||
@ -1121,7 +1122,13 @@ stioctl(dev, cmd, arg, flag, p)
|
||||
error = st_space(st, 1, SP_EOM, flags);
|
||||
break;
|
||||
case MTCACHE: /* enable controller cache */
|
||||
st->flags &= ~ST_DONTBUFFER;
|
||||
goto try_new_value;
|
||||
case MTNOCACHE: /* disable controller cache */
|
||||
st->flags |= ST_DONTBUFFER;
|
||||
goto try_new_value;
|
||||
case MTERASE: /* erase volume */
|
||||
error = st_erase(st, number, flags);
|
||||
break;
|
||||
case MTSETBSIZ: /* Set block size for device */
|
||||
#ifdef NOTYET
|
||||
@ -1147,9 +1154,10 @@ stioctl(dev, cmd, arg, flag, p)
|
||||
goto try_new_value;
|
||||
|
||||
case MTSETDNSTY: /* Set density for device and mode */
|
||||
if (number > SCSI_2_MAX_DENSITY_CODE)
|
||||
if (number > SCSI_2_MAX_DENSITY_CODE) {
|
||||
error = EINVAL;
|
||||
else
|
||||
break;
|
||||
} else
|
||||
st->density = number;
|
||||
goto try_new_value;
|
||||
|
||||
@ -1378,8 +1386,12 @@ st_mode_select(st, flags)
|
||||
|
||||
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_ON;
|
||||
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)
|
||||
@ -1393,6 +1405,36 @@ st_mode_select(st, flags)
|
||||
ST_RETRIES, 5000, NULL, flags | SCSI_DATA_OUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* issue an erase command
|
||||
*/
|
||||
int
|
||||
st_erase(st, full, flags)
|
||||
struct st_softc *st;
|
||||
int full, flags;
|
||||
{
|
||||
struct scsi_erase cmd;
|
||||
|
||||
/*
|
||||
* Full erase means set LONG bit in erase command, which asks
|
||||
* the drive to erase the entire unit. Without this bit, we're
|
||||
* asking the drive to write an erase gap.
|
||||
*/
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.opcode = ERASE;
|
||||
if (full)
|
||||
cmd.byte2 = SE_IMMED|SE_LONG;
|
||||
else
|
||||
cmd.byte2 = SE_IMMED;
|
||||
|
||||
/*
|
||||
* XXX We always do this asynchronously, for now. How long should
|
||||
* we wait if we want to (eventually) to it synchronously?
|
||||
*/
|
||||
return (scsi_scsi_cmd(st->sc_link, (struct scsi_generic *)&cmd,
|
||||
sizeof(cmd), 0, 0, ST_RETRIES, 5000, NULL, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* skip N blocks/filemarks/seq filemarks/eom
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: scsi_tape.h,v 1.6 1994/12/28 19:43:08 mycroft Exp $ */
|
||||
/* $NetBSD: scsi_tape.h,v 1.7 1996/01/11 03:36:34 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
@ -110,6 +110,16 @@ struct scsi_load {
|
||||
u_char control;
|
||||
};
|
||||
|
||||
#define ERASE 0x19
|
||||
struct scsi_erase {
|
||||
u_char opcode;
|
||||
u_char byte2;
|
||||
#define SE_LONG 0x01
|
||||
#define SE_IMMED 0x02
|
||||
u_char unused[3];
|
||||
u_char control;
|
||||
};
|
||||
|
||||
#define READ_BLOCK_LIMITS 0x05
|
||||
struct scsi_block_limits {
|
||||
u_char opcode;
|
||||
@ -127,6 +137,41 @@ struct scsi_block_limits_data {
|
||||
u_char min_length_0; /* Least significant */
|
||||
};
|
||||
|
||||
/* See SCSI-II spec 9.3.3.1 */
|
||||
struct scsi_tape_dev_conf_page {
|
||||
u_char pagecode; /* 0x10 */
|
||||
u_char pagelength; /* 0x0e */
|
||||
u_char byte2;
|
||||
#define SMT_CAP 0x40 /* change active partition */
|
||||
#define SMT_CAF 0x20 /* change active format */
|
||||
#define SMT_AFMASK 0x1f /* active format mask */
|
||||
u_char active_partition;
|
||||
u_char wb_full_ratio;
|
||||
u_char rb_empty_ratio;
|
||||
u_char wrdelay_time_1; /* MSB */
|
||||
u_char wrdelay_time_0; /* LSB */
|
||||
u_char byte8;
|
||||
#define SMT_DBR 0x80 /* data buffer recovery */
|
||||
#define SMT_BIS 0x40 /* block identifiers supported */
|
||||
#define SMT_RSMK 0x20 /* report setmarks */
|
||||
#define SMT_AVC 0x10 /* automatic velocity control */
|
||||
#define SMT_SOCF_MASK 0xc0 /* stop on consecutive formats */
|
||||
#define SMT_RBO 0x20 /* recover buffer order */
|
||||
#define SMT_REW 0x10 /* report early warning */
|
||||
u_char gap_size;
|
||||
u_char byte10;
|
||||
#define SMT_EODDEFINED 0xe0 /* EOD defined */
|
||||
#define SMT_EEG 0x10 /* enable EOD generation */
|
||||
#define SMT_SEW 0x80 /* synchronize at early warning */
|
||||
u_char ew_bufsize_2; /* MSB */
|
||||
u_char ew_bufsize_1; /* ... */
|
||||
u_char ew_bufsize_0; /* LSB */
|
||||
u_char sel_comp_alg;
|
||||
#define SMT_COMP_NONE 0x00
|
||||
#define SMT_COMP_DEFAULT 0x01
|
||||
u_char reserved;
|
||||
};
|
||||
|
||||
/* defines for the device specific byte in the mode select/sense header */
|
||||
#define SMH_DSP_SPEED 0x0F
|
||||
#define SMH_DSP_BUFF_MODE 0x70
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: st.c,v 1.56 1996/01/05 16:03:35 pk Exp $ */
|
||||
/* $NetBSD: st.c,v 1.57 1996/01/11 03:36:38 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
@ -266,14 +266,14 @@ int st_touch_tape __P((struct st_softc *));
|
||||
int st_write_filemarks __P((struct st_softc *, int number, int flags));
|
||||
int st_load __P((struct st_softc *, u_int type, int flags));
|
||||
int st_mode_select __P((struct st_softc *, int flags));
|
||||
void ststrategy();
|
||||
int st_check_eod();
|
||||
void ststart();
|
||||
void st_unmount();
|
||||
int st_mount_tape();
|
||||
void st_loadquirks();
|
||||
void st_identify_drive();
|
||||
int st_interpret_sense();
|
||||
void ststrategy __P((struct buf *));
|
||||
int st_check_eod __P((struct st_softc *, boolean, int *, int));
|
||||
void ststart __P((struct st_softc *));
|
||||
void st_unmount __P((struct st_softc *, boolean));
|
||||
int st_mount_tape __P((dev_t, int));
|
||||
void st_loadquirks __P((struct st_softc *));
|
||||
void st_identify_drive __P((struct st_softc *, struct scsi_inquiry_data *));
|
||||
int st_interpret_sense __P((struct scsi_xfer *));
|
||||
|
||||
struct scsi_device st_switch = {
|
||||
st_interpret_sense,
|
||||
@ -298,6 +298,7 @@ struct scsi_device st_switch = {
|
||||
#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_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
|
||||
#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
|
||||
@ -1121,7 +1122,13 @@ stioctl(dev, cmd, arg, flag, p)
|
||||
error = st_space(st, 1, SP_EOM, flags);
|
||||
break;
|
||||
case MTCACHE: /* enable controller cache */
|
||||
st->flags &= ~ST_DONTBUFFER;
|
||||
goto try_new_value;
|
||||
case MTNOCACHE: /* disable controller cache */
|
||||
st->flags |= ST_DONTBUFFER;
|
||||
goto try_new_value;
|
||||
case MTERASE: /* erase volume */
|
||||
error = st_erase(st, number, flags);
|
||||
break;
|
||||
case MTSETBSIZ: /* Set block size for device */
|
||||
#ifdef NOTYET
|
||||
@ -1147,9 +1154,10 @@ stioctl(dev, cmd, arg, flag, p)
|
||||
goto try_new_value;
|
||||
|
||||
case MTSETDNSTY: /* Set density for device and mode */
|
||||
if (number > SCSI_2_MAX_DENSITY_CODE)
|
||||
if (number > SCSI_2_MAX_DENSITY_CODE) {
|
||||
error = EINVAL;
|
||||
else
|
||||
break;
|
||||
} else
|
||||
st->density = number;
|
||||
goto try_new_value;
|
||||
|
||||
@ -1378,8 +1386,12 @@ st_mode_select(st, flags)
|
||||
|
||||
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_ON;
|
||||
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)
|
||||
@ -1393,6 +1405,36 @@ st_mode_select(st, flags)
|
||||
ST_RETRIES, 5000, NULL, flags | SCSI_DATA_OUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* issue an erase command
|
||||
*/
|
||||
int
|
||||
st_erase(st, full, flags)
|
||||
struct st_softc *st;
|
||||
int full, flags;
|
||||
{
|
||||
struct scsi_erase cmd;
|
||||
|
||||
/*
|
||||
* Full erase means set LONG bit in erase command, which asks
|
||||
* the drive to erase the entire unit. Without this bit, we're
|
||||
* asking the drive to write an erase gap.
|
||||
*/
|
||||
bzero(&cmd, sizeof(cmd));
|
||||
cmd.opcode = ERASE;
|
||||
if (full)
|
||||
cmd.byte2 = SE_IMMED|SE_LONG;
|
||||
else
|
||||
cmd.byte2 = SE_IMMED;
|
||||
|
||||
/*
|
||||
* XXX We always do this asynchronously, for now. How long should
|
||||
* we wait if we want to (eventually) to it synchronously?
|
||||
*/
|
||||
return (scsi_scsi_cmd(st->sc_link, (struct scsi_generic *)&cmd,
|
||||
sizeof(cmd), 0, 0, ST_RETRIES, 5000, NULL, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* skip N blocks/filemarks/seq filemarks/eom
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user