scsi_sa.c revision 68114
193139Sru/* 2146515Sru * $FreeBSD: head/sys/cam/scsi/scsi_sa.c 68114 2000-10-31 22:34:51Z mjacob $ 356160Sru * 4146515Sru * Implementation of SCSI Sequential Access Peripheral driver for CAM. 5116525Sru * 656160Sru * Copyright (c) 1999, 2000 Matthew Jacob 756160Sru * All rights reserved. 856160Sru * 956160Sru * Redistribution and use in source and binary forms, with or without 1056160Sru * modification, are permitted provided that the following conditions 1156160Sru * are met: 1256160Sru * 1. Redistributions of source code must retain the above copyright 1356160Sru * notice, this list of conditions, and the following disclaimer, 1456160Sru * without modification, immediately at the beginning of the file. 1556160Sru * 2. The name of the author may not be used to endorse or promote products 1656160Sru * derived from this software without specific prior written permission. 1756160Sru * 1856160Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1956160Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2056160Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2156160Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2256160Sru * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23146515Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24146515Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2556160Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2656160Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27146515Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2856160Sru * SUCH DAMAGE. 2956160Sru * 3056160Sru */ 3156160Sru 3256160Sru#include <sys/param.h> 3356160Sru#include <sys/queue.h> 3456160Sru#ifdef _KERNEL 3556160Sru#include <sys/systm.h> 3656160Sru#include <sys/kernel.h> 3756160Sru#endif 3856160Sru#include <sys/types.h> 3956160Sru#include <sys/bio.h> 4056160Sru#include <sys/malloc.h> 41146515Sru#include <sys/mtio.h> 4256160Sru#ifdef _KERNEL 4356160Sru#include <sys/conf.h> 4456160Sru#endif 4556160Sru#include <sys/devicestat.h> 4656160Sru#include <machine/limits.h> 4756160Sru 4856160Sru#ifndef _KERNEL 4956160Sru#include <stdio.h> 5056160Sru#include <string.h> 5156160Sru#endif 5256160Sru 5356160Sru#include <cam/cam.h> 5456160Sru#include <cam/cam_ccb.h> 5556160Sru#include <cam/cam_extend.h> 5656160Sru#include <cam/cam_periph.h> 5756160Sru#include <cam/cam_xpt_periph.h> 5856160Sru#include <cam/cam_debug.h> 5956160Sru 6056160Sru#include <cam/scsi/scsi_all.h> 6156160Sru#include <cam/scsi/scsi_message.h> 6256160Sru#include <cam/scsi/scsi_sa.h> 6356160Sru 6456160Sru#ifdef _KERNEL 6556160Sru 6656160Sru#include <opt_sa.h> 6756160Sru 6856160Sru#ifndef SA_SPACE_TIMEOUT 6956160Sru#define SA_SPACE_TIMEOUT 1 * 60 7056160Sru#endif 7156160Sru#ifndef SA_REWIND_TIMEOUT 7256160Sru#define SA_REWIND_TIMEOUT 2 * 60 7356160Sru#endif 7456160Sru#ifndef SA_ERASE_TIMEOUT 7556160Sru#define SA_ERASE_TIMEOUT 4 * 60 7656160Sru#endif 7756160Sru 7856160Sru#define REWIND_TIMEOUT (SA_REWIND_TIMEOUT * 60 * 1000) 7956160Sru#define ERASE_TIMEOUT (SA_ERASE_TIMEOUT * 60 * 1000) 8056160Sru#define SPACE_TIMEOUT (SA_SPACE_TIMEOUT * 60 * 1000) 8156160Sru 8256160Sru/* 8356160Sru * Additional options that can be set for config: SA_1FM_AT_EOT 8456160Sru */ 8556160Sru 86116525Sru#ifndef UNUSED_PARAMETER 87146515Sru#define UNUSED_PARAMETER(x) x = x 8856160Sru#endif 8956160Sru 9056160Sru#define QFRLS(ccb) \ 9156160Sru if (((ccb)->ccb_h.status & CAM_DEV_QFRZN) != 0) \ 9256160Sru cam_release_devq((ccb)->ccb_h.path, 0, 0, 0, FALSE) 9356160Sru 9456160Sru/* 9556160Sru * Driver states 9656160Sru */ 9756160Sru 9856160Sru 9956160Srutypedef enum { 10056160Sru SA_STATE_NORMAL, SA_STATE_ABNORMAL 10156160Sru} sa_state; 10256160Sru 10356160Srutypedef enum { 10456160Sru SA_CCB_BUFFER_IO, 10556160Sru SA_CCB_WAITING 10656160Sru} sa_ccb_types; 10756160Sru 10856160Sru#define ccb_type ppriv_field0 10956160Sru#define ccb_bp ppriv_ptr1 11056160Sru 11156160Srutypedef enum { 11256160Sru SA_FLAG_OPEN = 0x0001, 11356160Sru SA_FLAG_FIXED = 0x0002, 11456160Sru SA_FLAG_TAPE_LOCKED = 0x0004, 11556160Sru SA_FLAG_TAPE_MOUNTED = 0x0008, 11656160Sru SA_FLAG_TAPE_WP = 0x0010, 11756160Sru SA_FLAG_TAPE_WRITTEN = 0x0020, 11856160Sru SA_FLAG_EOM_PENDING = 0x0040, 11956160Sru SA_FLAG_EIO_PENDING = 0x0080, 12056160Sru SA_FLAG_EOF_PENDING = 0x0100, 12156160Sru SA_FLAG_ERR_PENDING = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING| 12256160Sru SA_FLAG_EOF_PENDING), 12356160Sru SA_FLAG_INVALID = 0x0200, 12456160Sru SA_FLAG_COMP_ENABLED = 0x0400, 12556160Sru SA_FLAG_COMP_SUPP = 0x0800, 12656160Sru SA_FLAG_COMP_UNSUPP = 0x1000, 12756160Sru SA_FLAG_TAPE_FROZEN = 0x2000 12856160Sru} sa_flags; 12956160Sru 130146515Srutypedef enum { 131146515Sru SA_MODE_REWIND = 0x00, 132146515Sru SA_MODE_NOREWIND = 0x01, 133146515Sru SA_MODE_OFFLINE = 0x02 134146515Sru} sa_mode; 135146515Sru 136146515Srutypedef enum { 137146515Sru SA_PARAM_NONE = 0x00, 138146515Sru SA_PARAM_BLOCKSIZE = 0x01, 139146515Sru SA_PARAM_DENSITY = 0x02, 140146515Sru SA_PARAM_COMPRESSION = 0x04, 141146515Sru SA_PARAM_BUFF_MODE = 0x08, 142146515Sru SA_PARAM_NUMBLOCKS = 0x10, 143146515Sru SA_PARAM_WP = 0x20, 144146515Sru SA_PARAM_SPEED = 0x40, 145146515Sru SA_PARAM_ALL = 0x7f 146146515Sru} sa_params; 147146515Sru 148146515Srutypedef enum { 149146515Sru SA_QUIRK_NONE = 0x00, 150146515Sru SA_QUIRK_NOCOMP = 0x01, /* Can't deal with compression at all */ 151146515Sru SA_QUIRK_FIXED = 0x02, /* Force fixed mode */ 152146515Sru SA_QUIRK_VARIABLE = 0x04, /* Force variable mode */ 153146515Sru SA_QUIRK_2FM = 0x08, /* Needs Two File Marks at EOD */ 154146515Sru SA_QUIRK_1FM = 0x10, /* No more than 1 File Mark at EOD */ 155146515Sru SA_QUIRK_NODREAD = 0x20, /* Don't try and dummy read density */ 156146515Sru SA_QUIRK_NO_MODESEL = 0x40 /* Don't do mode select at all */ 157146515Sru} sa_quirks; 158146515Sru 159146515Sru/* units are bits 4-7, 16-21 (1024 units) */ 160146515Sru#define SAUNIT(DEV) \ 161146515Sru (((minor(DEV) & 0xF0) >> 4) | ((minor(DEV) & 0x3f0000) >> 16)) 162146515Sru 163146515Sru#define SAMODE(z) ((minor(z) & 0x3)) 164146515Sru#define SADENSITY(z) (((minor(z) >> 2) & 0x3)) 165146515Sru#define SA_IS_CTRL(z) (minor(z) & (1 << 29)) 166146515Sru 167146515Sru#define SA_NOT_CTLDEV 0 168146515Sru#define SA_CTLDEV 1 169146515Sru 170146515Sru#define SA_ATYPE_R 0 171146515Sru#define SA_ATYPE_NR 1 172146515Sru#define SA_ATYPE_ER 2 173146515Sru 174146515Sru#define SAMINOR(ctl, unit, mode, access) \ 175146515Sru ((ctl << 29) | ((unit & 0x3f0) << 16) | ((unit & 0xf) << 4) | \ 176146515Sru (mode << 0x2) | (access & 0x3)) 177146515Sru 178146515Sru#define SA_NUM_MODES 4 179146515Srustruct sa_devs { 180146515Sru dev_t ctl_dev; 181146515Sru struct sa_mode_devs { 182146515Sru dev_t r_dev; 183146515Sru dev_t nr_dev; 18456160Sru dev_t er_dev; 18556160Sru } mode_devs[SA_NUM_MODES]; 186146515Sru}; 187146515Sru 188146515Srustruct sa_softc { 189146515Sru sa_state state; 19056160Sru sa_flags flags; 191146515Sru sa_quirks quirks; 19256160Sru struct bio_queue_head bio_queue; 19356160Sru int queue_count; 19456160Sru struct devstat device_stats; 19556160Sru struct sa_devs devs; 19656160Sru int blk_gran; 19793139Sru int blk_mask; 19856160Sru int blk_shift; 19956160Sru u_int32_t max_blk; 20056160Sru u_int32_t min_blk; 201146515Sru u_int32_t comp_algorithm; 202146515Sru u_int32_t saved_comp_algorithm; 203146515Sru u_int32_t media_blksize; 20456160Sru u_int32_t last_media_blksize; 20556160Sru u_int32_t media_numblks; 20656160Sru u_int8_t media_density; 20756160Sru u_int8_t speed; 20856160Sru u_int8_t scsi_rev; 20956160Sru u_int8_t dsreg; /* mtio mt_dsreg, redux */ 21056160Sru int buffer_mode; 21156160Sru int filemarks; 21256160Sru union ccb saved_ccb; 21356160Sru 21456160Sru /* 21556160Sru * Relative to BOT Location. 21656160Sru */ 21756160Sru daddr_t fileno; 21856160Sru daddr_t blkno; 21956160Sru 22056160Sru /* 22193139Sru * Latched Error Info 22293139Sru */ 22393139Sru struct { 22493139Sru struct scsi_sense_data _last_io_sense; 22593139Sru u_int32_t _last_io_resid; 22693139Sru u_int8_t _last_io_cdb[CAM_MAX_CDBLEN]; 22793139Sru struct scsi_sense_data _last_ctl_sense; 22893139Sru u_int32_t _last_ctl_resid; 22956160Sru u_int8_t _last_ctl_cdb[CAM_MAX_CDBLEN]; 23056160Sru#define last_io_sense errinfo._last_io_sense 23156160Sru#define last_io_resid errinfo._last_io_resid 23293139Sru#define last_io_cdb errinfo._last_io_cdb 23356160Sru#define last_ctl_sense errinfo._last_ctl_sense 23456160Sru#define last_ctl_resid errinfo._last_ctl_resid 23556160Sru#define last_ctl_cdb errinfo._last_ctl_cdb 23656160Sru } errinfo; 23756160Sru /* 23856160Sru * Misc other flags/state 23956160Sru */ 24056160Sru u_int32_t 24156160Sru : 31, 24256160Sru ctrl_mode : 1; /* control device open */ 24356160Sru}; 24456160Sru 24556160Srustruct sa_quirk_entry { 24656160Sru struct scsi_inquiry_pattern inq_pat; /* matching pattern */ 24756160Sru sa_quirks quirks; /* specific quirk type */ 24856160Sru u_int32_t prefblk; /* preferred blocksize when in fixed mode */ 24956160Sru}; 25056160Sru 25156160Srustatic struct sa_quirk_entry sa_quirk_table[] = 25256160Sru{ 25356160Sru { 25456160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "OnStream", 25556160Sru "ADR*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_NODREAD | 25656160Sru SA_QUIRK_1FM|SA_QUIRK_NO_MODESEL, 32768 25756160Sru }, 25856160Sru { 25956160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 26056160Sru "Python 25601*", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_NODREAD, 0 26156160Sru }, 26256160Sru { 26356160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 264146515Sru "Python*", "*"}, SA_QUIRK_NODREAD, 0 265146515Sru }, 26656160Sru { 26756160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 26856160Sru "VIPER 150*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 26956160Sru }, 27056160Sru { 27156160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE", 27256160Sru "VIPER 2525*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024 27356160Sru }, 27456160Sru { 275146515Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP", 276146515Sru "T20*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 27756160Sru }, 27856160Sru { 27956160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP", 28056160Sru "T4000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 28156160Sru }, 28256160Sru { 283146515Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP", 28456160Sru "HP-88780*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0 28556160Sru }, 28656160Sru { 28756160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY", 28856160Sru "*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0 28956160Sru }, 29056160Sru { 29156160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "M4 DATA", 29256160Sru "123107 SCSI*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0 29356160Sru }, 29456160Sru { /* jreynold@primenet.com */ 29556160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate", 29656160Sru "STT8000N*", "*"}, SA_QUIRK_1FM, 0 29756160Sru }, 29856160Sru { /* mike@sentex.net */ 299146515Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate", 30056160Sru "STT20000*", "*"}, SA_QUIRK_1FM, 0 30156160Sru }, 30256160Sru { 30356160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 30456160Sru " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 30556160Sru }, 30656160Sru { 30756160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 30856160Sru " TDC 3800", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 30956160Sru }, 31056160Sru { 31156160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 31256160Sru " TDC 4100", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 31356160Sru }, 31456160Sru { 31556160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 31656160Sru " TDC 4200", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512 31756160Sru }, 31856160Sru { 31956160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG", 32056160Sru " SLR*", "*"}, SA_QUIRK_1FM, 0 32156160Sru }, 32256160Sru { 32356160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK", 32456160Sru "5525ES*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512 32556160Sru }, 32656160Sru { 32756160Sru { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK", 32856160Sru "51000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024 32956160Sru } 33056160Sru}; 33156160Sru 33256160Srustatic d_open_t saopen; 333146515Srustatic d_close_t saclose; 33456160Srustatic d_strategy_t sastrategy; 33556160Srustatic d_ioctl_t saioctl; 33656160Srustatic periph_init_t sainit; 33756160Srustatic periph_ctor_t saregister; 33856160Srustatic periph_oninv_t saoninvalidate; 33956160Srustatic periph_dtor_t sacleanup; 34056160Srustatic periph_start_t sastart; 34156160Srustatic void saasync(void *callback_arg, u_int32_t code, 34256160Sru struct cam_path *path, void *arg); 34356160Srustatic void sadone(struct cam_periph *periph, 34456160Sru union ccb *start_ccb); 34556160Srustatic int saerror(union ccb *ccb, u_int32_t cam_flags, 34656160Sru u_int32_t sense_flags); 34756160Srustatic int samarkswanted(struct cam_periph *); 348146515Srustatic int sacheckeod(struct cam_periph *periph); 34956160Srustatic int sagetparams(struct cam_periph *periph, 35056160Sru sa_params params_to_get, 35156160Sru u_int32_t *blocksize, u_int8_t *density, 35256160Sru u_int32_t *numblocks, int *buff_mode, 35356160Sru u_int8_t *write_protect, u_int8_t *speed, 35456160Sru int *comp_supported, int *comp_enabled, 35556160Sru u_int32_t *comp_algorithm, 35656160Sru sa_comp_t *comp_page); 35756160Srustatic int sasetparams(struct cam_periph *periph, 35856160Sru sa_params params_to_set, 35956160Sru u_int32_t blocksize, u_int8_t density, 36056160Sru u_int32_t comp_algorithm, 36156160Sru u_int32_t sense_flags); 362146515Srustatic void saprevent(struct cam_periph *periph, int action); 363146515Srustatic int sarewind(struct cam_periph *periph); 36456160Srustatic int saspace(struct cam_periph *periph, int count, 36556160Sru scsi_space_code code); 36656160Srustatic int samount(struct cam_periph *, int, dev_t); 36756160Srustatic int saretension(struct cam_periph *periph); 36856160Srustatic int sareservereleaseunit(struct cam_periph *periph, 36956160Sru int reserve); 37056160Srustatic int saloadunload(struct cam_periph *periph, int load); 37156160Srustatic int saerase(struct cam_periph *periph, int longerase); 372146515Srustatic int sawritefilemarks(struct cam_periph *periph, 37356160Sru int nmarks, int setmarks); 37456160Srustatic int sardpos(struct cam_periph *periph, int, u_int32_t *); 37556160Srustatic int sasetpos(struct cam_periph *periph, int, u_int32_t *); 37656160Sru 37756160Sru 37856160Srustatic struct periph_driver sadriver = 379116525Sru{ 38056160Sru sainit, "sa", 38156160Sru TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0 38256160Sru}; 38356160Sru 38456160SruDATA_SET(periphdriver_set, sadriver); 38556160Sru 38656160Sru/* For 2.2-stable support */ 38756160Sru#ifndef D_TAPE 38856160Sru#define D_TAPE 0 389146515Sru#endif 39056160Sru 39156160Sru#define SA_CDEV_MAJOR 14 39256160Sru 39356160Srustatic struct cdevsw sa_cdevsw = { 39456160Sru /* open */ saopen, 39556160Sru /* close */ saclose, 39656160Sru /* read */ physread, 39756160Sru /* write */ physwrite, 39856160Sru /* ioctl */ saioctl, 39956160Sru /* poll */ nopoll, 40056160Sru /* mmap */ nommap, 40156160Sru /* strategy */ sastrategy, 40256160Sru /* name */ "sa", 40356160Sru /* maj */ SA_CDEV_MAJOR, 40456160Sru /* dump */ nodump, 40556160Sru /* psize */ nopsize, 40656160Sru /* flags */ D_TAPE, 40756160Sru /* bmaj */ -1 408146515Sru}; 409146515Sru 41056160Srustatic struct extend_array *saperiphs; 41156160Sru 41256160Srustatic int 41356160Srusaopen(dev_t dev, int flags, int fmt, struct proc *p) 41456160Sru{ 41556160Sru struct cam_periph *periph; 41656160Sru struct sa_softc *softc; 41756160Sru int unit; 41856160Sru int mode; 41956160Sru int density; 42056160Sru int error; 42156160Sru int s; 42256160Sru 42356160Sru unit = SAUNIT(dev); 42456160Sru mode = SAMODE(dev); 42556160Sru density = SADENSITY(dev); 42656160Sru 42756160Sru s = splsoftcam(); 42856160Sru periph = cam_extend_get(saperiphs, unit); 42956160Sru if (periph == NULL) { 43056160Sru (void) splx(s); 43156160Sru return (ENXIO); 43256160Sru } 43356160Sru softc = (struct sa_softc *)periph->softc; 43456160Sru if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) { 43556160Sru splx(s); 43656160Sru return (error); 43756160Sru } 43856160Sru splx(s); 43956160Sru 44056160Sru CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO, 44156160Sru ("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags)); 44256160Sru 44356160Sru if (cam_periph_acquire(periph) != CAM_REQ_CMP) { 44456160Sru cam_periph_unlock(periph); 44556160Sru return (ENXIO); 44656160Sru } 44756160Sru if (SA_IS_CTRL(dev)) { 44856160Sru softc->ctrl_mode = 1; 44956160Sru cam_periph_unlock(periph); 45056160Sru return (0); 45156160Sru } 45256160Sru 45356160Sru 45456160Sru if (softc->flags & SA_FLAG_OPEN) { 45556160Sru error = EBUSY; 45656160Sru } else if (softc->flags & SA_FLAG_INVALID) { 45756160Sru error = ENXIO; 45856160Sru } else { 45956160Sru /* 46056160Sru * The function samount ensures media is loaded and ready. 46156160Sru * It also does a device RESERVE if the tape isn't yet mounted. 46256160Sru */ 46356160Sru error = samount(periph, flags, dev); 46456160Sru } 46556160Sru 46656160Sru if (error) { 46756160Sru cam_periph_release(periph); 46856160Sru } else { 46956160Sru saprevent(periph, PR_PREVENT); 47056160Sru softc->flags |= SA_FLAG_OPEN; 47156160Sru } 47256160Sru cam_periph_unlock(periph); 47356160Sru return (error); 47456160Sru} 47556160Sru 47656160Srustatic int 47756160Srusaclose(dev_t dev, int flag, int fmt, struct proc *p) 47856160Sru{ 47956160Sru struct cam_periph *periph; 48056160Sru struct sa_softc *softc; 48156160Sru int unit, mode, error, writing, tmp; 48256160Sru int closedbits = SA_FLAG_OPEN; 48356160Sru 48456160Sru unit = SAUNIT(dev); 48556160Sru mode = SAMODE(dev); 48656160Sru periph = cam_extend_get(saperiphs, unit); 48756160Sru if (periph == NULL) 48856160Sru return (ENXIO); 48956160Sru 49056160Sru softc = (struct sa_softc *)periph->softc; 49156160Sru 49256160Sru CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO, 49356160Sru ("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags)); 49456160Sru 49556160Sru 49656160Sru if ((error = cam_periph_lock(periph, PRIBIO)) != 0) { 49756160Sru return (error); 49856160Sru } 499146515Sru 50056160Sru if (SA_IS_CTRL(dev)) { 501146515Sru softc->ctrl_mode = 0; 50256160Sru cam_periph_release(periph); 503146515Sru cam_periph_unlock(periph); 504146515Sru return (0); 505146515Sru } 506146515Sru 507146515Sru /* 508146515Sru * Were we writing the tape? 509146515Sru */ 510146515Sru writing = (softc->flags & SA_FLAG_TAPE_WRITTEN) != 0; 511146515Sru 512146515Sru /* 513146515Sru * See whether or not we need to write filemarks. If this 514146515Sru * fails, we probably have to assume we've lost tape 515146515Sru * position. 516146515Sru */ 517146515Sru error = sacheckeod(periph); 518146515Sru if (error) { 519146515Sru xpt_print_path(periph->path); 520146515Sru printf("failed to write terminating filemark(s)\n"); 521146515Sru softc->flags |= SA_FLAG_TAPE_FROZEN; 522146515Sru } 523146515Sru 524146515Sru /* 525146515Sru * Whatever we end up doing, allow users to eject tapes from here on. 526146515Sru */ 527146515Sru saprevent(periph, PR_ALLOW); 528146515Sru 529146515Sru /* 530146515Sru * Decide how to end... 531146515Sru */ 532146515Sru if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) { 533146515Sru closedbits |= SA_FLAG_TAPE_FROZEN; 534146515Sru } else switch (mode) { 535146515Sru case SA_MODE_OFFLINE: 536146515Sru /* 537146515Sru * An 'offline' close is an unconditional release of 538146515Sru * frozen && mount conditions, irrespective of whether 539146515Sru * these operations succeeded. The reason for this is 540146515Sru * to allow at least some kind of programmatic way 541146515Sru * around our state getting all fouled up. If somebody 542146515Sru * issues an 'offline' command, that will be allowed 543146515Sru * to clear state. 544146515Sru */ 545146515Sru (void) sarewind(periph); 546146515Sru (void) saloadunload(periph, FALSE); 547146515Sru closedbits |= SA_FLAG_TAPE_MOUNTED|SA_FLAG_TAPE_FROZEN; 548146515Sru break; 549146515Sru case SA_MODE_REWIND: 550146515Sru /* 551146515Sru * If the rewind fails, return an error- if anyone cares, 552146515Sru * but not overwriting any previous error. 553146515Sru * 554146515Sru * We don't clear the notion of mounted here, but we do 555146515Sru * clear the notion of frozen if we successfully rewound. 556146515Sru */ 557146515Sru tmp = sarewind(periph); 558146515Sru if (tmp) { 559146515Sru if (error != 0) 560146515Sru error = tmp; 561146515Sru } else { 56256160Sru closedbits |= SA_FLAG_TAPE_FROZEN; 56356160Sru } 56493139Sru break; 56593139Sru case SA_MODE_NOREWIND: 56693139Sru /* 56793139Sru * If we're not rewinding/unloading the tape, find out 56893139Sru * whether we need to back up over one of two filemarks 56993139Sru * we wrote (if we wrote two filemarks) so that appends 57093139Sru * from this point on will be sane. 57193139Sru */ 572146515Sru if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) { 57393139Sru tmp = saspace(periph, -1, SS_FILEMARKS); 57493139Sru if (tmp) { 57593139Sru xpt_print_path(periph->path); 57693139Sru printf("unable to backspace over one of double" 57793139Sru " filemarks at end of tape\n"); 57893139Sru xpt_print_path(periph->path); 57993139Sru printf("it is possible that this device" 58093139Sru " needs a SA_QUIRK_1FM quirk set for it\n"); 58193139Sru softc->flags |= SA_FLAG_TAPE_FROZEN; 58293139Sru } 58393139Sru } 58493139Sru break; 58593139Sru default: 58693139Sru xpt_print_path(periph->path); 58793139Sru panic("unknown mode 0x%x in saclose\n", mode); 58893139Sru /* NOTREACHED */ 58993139Sru break; 59093139Sru } 59193139Sru 59293139Sru /* 59393139Sru * We wish to note here that there are no more filemarks to be written. 59493139Sru */ 59593139Sru softc->filemarks = 0; 59693139Sru softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 59793139Sru 59893139Sru /* 59993139Sru * And we are no longer open for business. 60093139Sru */ 60193139Sru softc->flags &= ~closedbits; 60293139Sru 60393139Sru /* 60493139Sru * Inform users if tape state if frozen.... 60593139Sru */ 60693139Sru if (softc->flags & SA_FLAG_TAPE_FROZEN) { 60793139Sru xpt_print_path(periph->path); 60893139Sru printf("tape is now frozen- use an OFFLINE, REWIND or MTEOM " 60993139Sru "command to clear this state.\n"); 61093139Sru } 61193139Sru 61293139Sru /* release the device if it is no longer mounted */ 61393139Sru if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) 61493139Sru sareservereleaseunit(periph, FALSE); 61593139Sru 61693139Sru cam_periph_unlock(periph); 61793139Sru cam_periph_release(periph); 61893139Sru 61993139Sru return (error); 62093139Sru} 62193139Sru 622146515Sru/* 623146515Sru * Actually translate the requested transfer into one the physical driver 624146515Sru * can understand. The transfer is described by a buf and will include 625146515Sru * only one physical transfer. 626146515Sru */ 627146515Srustatic void 628146515Srusastrategy(struct bio *bp) 629146515Sru{ 630146515Sru struct cam_periph *periph; 631146515Sru struct sa_softc *softc; 632146515Sru u_int unit; 633146515Sru int s; 634146515Sru 635146515Sru if (SA_IS_CTRL(bp->bio_dev)) { 636146515Sru bp->bio_error = EINVAL; 637146515Sru goto bad; 638146515Sru } 639146515Sru unit = SAUNIT(bp->bio_dev); 640146515Sru periph = cam_extend_get(saperiphs, unit); 641146515Sru if (periph == NULL) { 642146515Sru bp->bio_error = ENXIO; 643146515Sru goto bad; 644146515Sru } 645146515Sru softc = (struct sa_softc *)periph->softc; 646146515Sru 647146515Sru s = splsoftcam(); 648146515Sru 649146515Sru if (softc->flags & SA_FLAG_INVALID) { 650146515Sru splx(s); 651146515Sru bp->bio_error = ENXIO; 652146515Sru goto bad; 653146515Sru } 654146515Sru 655146515Sru if (softc->flags & SA_FLAG_TAPE_FROZEN) { 656146515Sru splx(s); 657146515Sru bp->bio_error = EPERM; 658146515Sru goto bad; 659146515Sru } 660146515Sru 661146515Sru splx(s); 662146515Sru 663146515Sru /* 664146515Sru * If it's a null transfer, return immediatly 665146515Sru */ 666146515Sru if (bp->bio_bcount == 0) 667146515Sru goto done; 668146515Sru 669146515Sru /* valid request? */ 670146515Sru if (softc->flags & SA_FLAG_FIXED) { 671146515Sru /* 672146515Sru * Fixed block device. The byte count must 673146515Sru * be a multiple of our block size. 674146515Sru */ 675146515Sru if (((softc->blk_mask != ~0) && 676146515Sru ((bp->bio_bcount & softc->blk_mask) != 0)) || 677146515Sru ((softc->blk_mask == ~0) && 678146515Sru ((bp->bio_bcount % softc->min_blk) != 0))) { 679146515Sru xpt_print_path(periph->path); 680146515Sru printf("Invalid request. Fixed block device " 681146515Sru "requests must be a multiple " 682146515Sru "of %d bytes\n", softc->min_blk); 683146515Sru bp->bio_error = EINVAL; 684146515Sru goto bad; 685146515Sru } 686146515Sru } else if ((bp->bio_bcount > softc->max_blk) || 687146515Sru (bp->bio_bcount < softc->min_blk) || 688146515Sru (bp->bio_bcount & softc->blk_mask) != 0) { 689146515Sru 690146515Sru xpt_print_path(periph->path); 691146515Sru printf("Invalid request. Variable block device " 692146515Sru "requests must be "); 693146515Sru if (softc->blk_mask != 0) { 694146515Sru printf("a multiple of %d ", (0x1 << softc->blk_gran)); 695146515Sru } 696146515Sru printf("between %d and %d bytes\n", softc->min_blk, 697146515Sru softc->max_blk); 698146515Sru bp->bio_error = EINVAL; 699146515Sru goto bad; 700146515Sru } 701146515Sru 702146515Sru /* 703146515Sru * Mask interrupts so that the device cannot be invalidated until 704146515Sru * after we are in the queue. Otherwise, we might not properly 705146515Sru * clean up one of the buffers. 706146515Sru */ 707146515Sru s = splbio(); 708146515Sru 709146515Sru /* 710146515Sru * Place it at the end of the queue. 711146515Sru */ 712146515Sru bioq_insert_tail(&softc->bio_queue, bp); 713146515Sru 714146515Sru softc->queue_count++; 715146515Sru CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("sastrategy: enqueuing a %d " 716146515Sru "%s byte %s queue count now %d\n", (int) bp->bio_bcount, 717146515Sru (softc->flags & SA_FLAG_FIXED)? "fixed" : "variable", 718146515Sru (bp->bio_cmd == BIO_READ)? "read" : "write", softc->queue_count)); 719146515Sru 720146515Sru splx(s); 721146515Sru 722146515Sru /* 723146515Sru * Schedule ourselves for performing the work. 724146515Sru */ 725146515Sru xpt_schedule(periph, 1); 726146515Sru 727146515Sru return; 728146515Srubad: 729146515Sru bp->bio_flags |= BIO_ERROR; 730146515Srudone: 731146515Sru 732146515Sru /* 733146515Sru * Correctly set the buf to indicate a completed xfer 734146515Sru */ 735146515Sru bp->bio_resid = bp->bio_bcount; 736146515Sru biodone(bp); 737146515Sru} 738146515Sru 739146515Srustatic int 740146515Srusaioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 741146515Sru{ 742146515Sru struct cam_periph *periph; 743146515Sru struct sa_softc *softc; 744146515Sru scsi_space_code spaceop; 745146515Sru int didlockperiph = 0; 746146515Sru int s; 747146515Sru int unit; 748146515Sru int mode; 749146515Sru int density; 750146515Sru int error = 0; 751146515Sru 752146515Sru unit = SAUNIT(dev); 753146515Sru mode = SAMODE(dev); 754146515Sru density = SADENSITY(dev); 755146515Sru error = 0; /* shut up gcc */ 756146515Sru spaceop = 0; /* shut up gcc */ 757146515Sru 758146515Sru periph = cam_extend_get(saperiphs, unit); 759146515Sru if (periph == NULL) 760146515Sru return (ENXIO); 761146515Sru 762146515Sru softc = (struct sa_softc *)periph->softc; 763146515Sru 764146515Sru /* 765146515Sru * Check for control mode accesses. We allow MTIOCGET and 766146515Sru * MTIOCERRSTAT (but need to be the only one open in order 767146515Sru * to clear latched status), and MTSETBSIZE, MTSETDNSTY 768146515Sru * and MTCOMP (but need to be the only one accessing this 769146515Sru * device to run those). 770146515Sru */ 771146515Sru 772146515Sru if (SA_IS_CTRL(dev)) { 773146515Sru switch (cmd) { 774146515Sru case MTIOCGETEOTMODEL: 775146515Sru case MTIOCGET: 776146515Sru break; 777146515Sru case MTIOCERRSTAT: 778146515Sru /* 779146515Sru * If the periph isn't already locked, lock it 780146515Sru * so our MTIOCERRSTAT can reset latched error stats. 781146515Sru * 782146515Sru * If the periph is already locked, skip it because 783146515Sru * we're just getting status and it'll be up to the 784146515Sru * other thread that has this device open to do 785 * an MTIOCERRSTAT that would clear latched status. 786 */ 787 s = splsoftcam(); 788 if ((periph->flags & CAM_PERIPH_LOCKED) == 0) { 789 error = cam_periph_lock(periph, PRIBIO|PCATCH); 790 if (error != 0) { 791 splx(s); 792 return (error); 793 } 794 didlockperiph = 1; 795 } 796 break; 797 798 case MTIOCSETEOTMODEL: 799 case MTSETBSIZ: 800 case MTSETDNSTY: 801 case MTCOMP: 802 /* 803 * We need to acquire the peripheral here rather 804 * than at open time because we are sharing writable 805 * access to data structures. 806 */ 807 s = splsoftcam(); 808 error = cam_periph_lock(periph, PRIBIO|PCATCH); 809 if (error != 0) { 810 splx(s); 811 return (error); 812 } 813 didlockperiph = 1; 814 break; 815 816 default: 817 return (EINVAL); 818 } 819 } 820 821 /* 822 * Find the device that the user is talking about 823 */ 824 switch (cmd) { 825 case MTIOCGET: 826 { 827 struct mtget *g = (struct mtget *)arg; 828 829 /* 830 * If this isn't the control mode device, actually go out 831 * and ask the drive again what it's set to. 832 */ 833 if (!SA_IS_CTRL(dev)) { 834 u_int8_t write_protect; 835 int comp_enabled, comp_supported; 836 error = sagetparams(periph, SA_PARAM_ALL, 837 &softc->media_blksize, &softc->media_density, 838 &softc->media_numblks, &softc->buffer_mode, 839 &write_protect, &softc->speed, &comp_supported, 840 &comp_enabled, &softc->comp_algorithm, NULL); 841 if (error) 842 break; 843 if (write_protect) 844 softc->flags |= SA_FLAG_TAPE_WP; 845 else 846 softc->flags &= ~SA_FLAG_TAPE_WP; 847 softc->flags &= ~(SA_FLAG_COMP_SUPP| 848 SA_FLAG_COMP_ENABLED|SA_FLAG_COMP_UNSUPP); 849 if (comp_supported) { 850 if (softc->saved_comp_algorithm == 0) 851 softc->saved_comp_algorithm = 852 softc->comp_algorithm; 853 softc->flags |= SA_FLAG_COMP_SUPP; 854 if (comp_enabled) 855 softc->flags |= SA_FLAG_COMP_ENABLED; 856 } else 857 softc->flags |= SA_FLAG_COMP_UNSUPP; 858 } 859 bzero(g, sizeof(struct mtget)); 860 g->mt_type = MT_ISAR; 861 if (softc->flags & SA_FLAG_COMP_UNSUPP) { 862 g->mt_comp = MT_COMP_UNSUPP; 863 g->mt_comp0 = MT_COMP_UNSUPP; 864 g->mt_comp1 = MT_COMP_UNSUPP; 865 g->mt_comp2 = MT_COMP_UNSUPP; 866 g->mt_comp3 = MT_COMP_UNSUPP; 867 } else { 868 if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) { 869 g->mt_comp = MT_COMP_DISABLED; 870 } else { 871 g->mt_comp = softc->comp_algorithm; 872 } 873 g->mt_comp0 = softc->comp_algorithm; 874 g->mt_comp1 = softc->comp_algorithm; 875 g->mt_comp2 = softc->comp_algorithm; 876 g->mt_comp3 = softc->comp_algorithm; 877 } 878 g->mt_density = softc->media_density; 879 g->mt_density0 = softc->media_density; 880 g->mt_density1 = softc->media_density; 881 g->mt_density2 = softc->media_density; 882 g->mt_density3 = softc->media_density; 883 g->mt_blksiz = softc->media_blksize; 884 g->mt_blksiz0 = softc->media_blksize; 885 g->mt_blksiz1 = softc->media_blksize; 886 g->mt_blksiz2 = softc->media_blksize; 887 g->mt_blksiz3 = softc->media_blksize; 888 g->mt_fileno = softc->fileno; 889 g->mt_blkno = softc->blkno; 890 g->mt_dsreg = (short) softc->dsreg; 891 error = 0; 892 break; 893 } 894 case MTIOCERRSTAT: 895 { 896 struct scsi_tape_errors *sep = 897 &((union mterrstat *)arg)->scsi_errstat; 898 899 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 900 ("saioctl: MTIOCERRSTAT\n")); 901 902 bzero(sep, sizeof(*sep)); 903 sep->io_resid = softc->last_io_resid; 904 bcopy((caddr_t) &softc->last_io_sense, sep->io_sense, 905 sizeof (sep->io_sense)); 906 bcopy((caddr_t) &softc->last_io_cdb, sep->io_cdb, 907 sizeof (sep->io_cdb)); 908 sep->ctl_resid = softc->last_ctl_resid; 909 bcopy((caddr_t) &softc->last_ctl_sense, sep->ctl_sense, 910 sizeof (sep->ctl_sense)); 911 bcopy((caddr_t) &softc->last_ctl_cdb, sep->ctl_cdb, 912 sizeof (sep->ctl_cdb)); 913 914 if (SA_IS_CTRL(dev) == 0 || didlockperiph) 915 bzero((caddr_t) &softc->errinfo, 916 sizeof (softc->errinfo)); 917 error = 0; 918 break; 919 } 920 case MTIOCTOP: 921 { 922 struct mtop *mt; 923 int count; 924 925 mt = (struct mtop *)arg; 926 927 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 928 ("saioctl: op=0x%x count=0x%x\n", 929 mt->mt_op, mt->mt_count)); 930 931 count = mt->mt_count; 932 switch (mt->mt_op) { 933 case MTWEOF: /* write an end-of-file marker */ 934 /* 935 * We don't need to clear the SA_FLAG_TAPE_WRITTEN 936 * flag because by keeping track of filemarks 937 * we have last written we know ehether or not 938 * we need to write more when we close the device. 939 */ 940 error = sawritefilemarks(periph, count, FALSE); 941 break; 942 case MTWSS: /* write a setmark */ 943 error = sawritefilemarks(periph, count, TRUE); 944 break; 945 case MTBSR: /* backward space record */ 946 case MTFSR: /* forward space record */ 947 case MTBSF: /* backward space file */ 948 case MTFSF: /* forward space file */ 949 case MTBSS: /* backward space setmark */ 950 case MTFSS: /* forward space setmark */ 951 case MTEOD: /* space to end of recorded medium */ 952 { 953 int nmarks; 954 955 spaceop = SS_FILEMARKS; 956 nmarks = softc->filemarks; 957 error = sacheckeod(periph); 958 if (error) { 959 xpt_print_path(periph->path); 960 printf("EOD check prior to spacing failed\n"); 961 softc->flags |= SA_FLAG_EIO_PENDING; 962 break; 963 } 964 nmarks -= softc->filemarks; 965 switch(mt->mt_op) { 966 case MTBSR: 967 count = -count; 968 /* FALLTHROUGH */ 969 case MTFSR: 970 spaceop = SS_BLOCKS; 971 break; 972 case MTBSF: 973 count = -count; 974 /* FALLTHROUGH */ 975 case MTFSF: 976 break; 977 case MTBSS: 978 count = -count; 979 /* FALLTHROUGH */ 980 case MTFSS: 981 spaceop = SS_SETMARKS; 982 break; 983 case MTEOD: 984 spaceop = SS_EOD; 985 count = 0; 986 nmarks = 0; 987 break; 988 default: 989 error = EINVAL; 990 break; 991 } 992 if (error) 993 break; 994 995 nmarks = softc->filemarks; 996 /* 997 * XXX: Why are we checking again? 998 */ 999 error = sacheckeod(periph); 1000 if (error) 1001 break; 1002 nmarks -= softc->filemarks; 1003 error = saspace(periph, count - nmarks, spaceop); 1004 /* 1005 * At this point, clear that we've written the tape 1006 * and that we've written any filemarks. We really 1007 * don't know what the applications wishes to do next- 1008 * the sacheckeod's will make sure we terminated the 1009 * tape correctly if we'd been writing, but the next 1010 * action the user application takes will set again 1011 * whether we need to write filemarks. 1012 */ 1013 softc->flags &= 1014 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 1015 softc->filemarks = 0; 1016 break; 1017 } 1018 case MTREW: /* rewind */ 1019 (void) sacheckeod(periph); 1020 error = sarewind(periph); 1021 /* see above */ 1022 softc->flags &= 1023 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 1024 softc->filemarks = 0; 1025 break; 1026 case MTERASE: /* erase */ 1027 error = saerase(periph, count); 1028 softc->flags &= 1029 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 1030 break; 1031 case MTRETENS: /* re-tension tape */ 1032 error = saretension(periph); 1033 softc->flags &= 1034 ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN); 1035 break; 1036 case MTOFFL: /* rewind and put the drive offline */ 1037 1038 (void) sacheckeod(periph); 1039 /* see above */ 1040 softc->flags &= ~SA_FLAG_TAPE_WRITTEN; 1041 softc->filemarks = 0; 1042 1043 error = sarewind(periph); 1044 /* clear the frozen flag anyway */ 1045 softc->flags &= ~SA_FLAG_TAPE_FROZEN; 1046 1047 /* 1048 * Be sure to allow media removal before ejecting. 1049 */ 1050 1051 saprevent(periph, PR_ALLOW); 1052 if (error == 0) { 1053 error = saloadunload(periph, FALSE); 1054 if (error == 0) { 1055 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1056 } 1057 } 1058 break; 1059 1060 case MTNOP: /* no operation, sets status only */ 1061 case MTCACHE: /* enable controller cache */ 1062 case MTNOCACHE: /* disable controller cache */ 1063 error = 0; 1064 break; 1065 1066 case MTSETBSIZ: /* Set block size for device */ 1067 1068 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count, 1069 0, 0, 0); 1070 if (error == 0) { 1071 softc->last_media_blksize = 1072 softc->media_blksize; 1073 softc->media_blksize = count; 1074 if (count) { 1075 softc->flags |= SA_FLAG_FIXED; 1076 if (powerof2(count)) { 1077 softc->blk_shift = 1078 ffs(count) - 1; 1079 softc->blk_mask = count - 1; 1080 } else { 1081 softc->blk_mask = ~0; 1082 softc->blk_shift = 0; 1083 } 1084 /* 1085 * Make the user's desire 'persistent'. 1086 */ 1087 softc->quirks &= ~SA_QUIRK_VARIABLE; 1088 softc->quirks |= SA_QUIRK_FIXED; 1089 } else { 1090 softc->flags &= ~SA_FLAG_FIXED; 1091 if (softc->max_blk == 0) { 1092 softc->max_blk = ~0; 1093 } 1094 softc->blk_shift = 0; 1095 if (softc->blk_gran != 0) { 1096 softc->blk_mask = 1097 softc->blk_gran - 1; 1098 } else { 1099 softc->blk_mask = 0; 1100 } 1101 /* 1102 * Make the user's desire 'persistent'. 1103 */ 1104 softc->quirks |= SA_QUIRK_VARIABLE; 1105 softc->quirks &= ~SA_QUIRK_FIXED; 1106 } 1107 } 1108 break; 1109 case MTSETDNSTY: /* Set density for device and mode */ 1110 if (count > UCHAR_MAX) { 1111 error = EINVAL; 1112 break; 1113 } else { 1114 error = sasetparams(periph, SA_PARAM_DENSITY, 1115 0, count, 0, 0); 1116 } 1117 break; 1118 case MTCOMP: /* enable compression */ 1119 /* 1120 * Some devices don't support compression, and 1121 * don't like it if you ask them for the 1122 * compression page. 1123 */ 1124 if ((softc->quirks & SA_QUIRK_NOCOMP) || 1125 (softc->flags & SA_FLAG_COMP_UNSUPP)) { 1126 error = ENODEV; 1127 break; 1128 } 1129 error = sasetparams(periph, SA_PARAM_COMPRESSION, 1130 0, 0, count, SF_NO_PRINT); 1131 break; 1132 default: 1133 error = EINVAL; 1134 } 1135 break; 1136 } 1137 case MTIOCIEOT: 1138 case MTIOCEEOT: 1139 error = 0; 1140 break; 1141 case MTIOCRDSPOS: 1142 error = sardpos(periph, 0, (u_int32_t *) arg); 1143 break; 1144 case MTIOCRDHPOS: 1145 error = sardpos(periph, 1, (u_int32_t *) arg); 1146 break; 1147 case MTIOCSLOCATE: 1148 error = sasetpos(periph, 0, (u_int32_t *) arg); 1149 break; 1150 case MTIOCHLOCATE: 1151 error = sasetpos(periph, 1, (u_int32_t *) arg); 1152 break; 1153 case MTIOCGETEOTMODEL: 1154 error = 0; 1155 if (softc->quirks & SA_QUIRK_1FM) 1156 mode = 1; 1157 else 1158 mode = 2; 1159 *((u_int32_t *) arg) = mode; 1160 break; 1161 case MTIOCSETEOTMODEL: 1162 error = 0; 1163 switch (*((u_int32_t *) arg)) { 1164 case 1: 1165 softc->quirks &= ~SA_QUIRK_2FM; 1166 softc->quirks |= SA_QUIRK_1FM; 1167 break; 1168 case 2: 1169 softc->quirks &= ~SA_QUIRK_1FM; 1170 softc->quirks |= SA_QUIRK_2FM; 1171 break; 1172 default: 1173 error = EINVAL; 1174 break; 1175 } 1176 break; 1177 default: 1178 error = cam_periph_ioctl(periph, cmd, arg, saerror); 1179 break; 1180 } 1181 if (didlockperiph) { 1182 cam_periph_unlock(periph); 1183 } 1184 return (error); 1185} 1186 1187static void 1188sainit(void) 1189{ 1190 cam_status status; 1191 struct cam_path *path; 1192 1193 /* 1194 * Create our extend array for storing the devices we attach to. 1195 */ 1196 saperiphs = cam_extend_new(); 1197 if (saperiphs == NULL) { 1198 printf("sa: Failed to alloc extend array!\n"); 1199 return; 1200 } 1201 1202 /* 1203 * Install a global async callback. 1204 */ 1205 status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID, 1206 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 1207 1208 if (status == CAM_REQ_CMP) { 1209 /* Register the async callbacks of interrest */ 1210 struct ccb_setasync csa; /* 1211 * This is an immediate CCB, 1212 * so using the stack is OK 1213 */ 1214 xpt_setup_ccb(&csa.ccb_h, path, 5); 1215 csa.ccb_h.func_code = XPT_SASYNC_CB; 1216 csa.event_enable = AC_FOUND_DEVICE; 1217 csa.callback = saasync; 1218 csa.callback_arg = NULL; 1219 xpt_action((union ccb *)&csa); 1220 status = csa.ccb_h.status; 1221 xpt_free_path(path); 1222 } 1223 1224 if (status != CAM_REQ_CMP) { 1225 printf("sa: Failed to attach master async callback " 1226 "due to status 0x%x!\n", status); 1227 } 1228} 1229 1230static void 1231saoninvalidate(struct cam_periph *periph) 1232{ 1233 struct sa_softc *softc; 1234 struct bio *q_bp; 1235 struct ccb_setasync csa; 1236 int s; 1237 1238 softc = (struct sa_softc *)periph->softc; 1239 1240 /* 1241 * De-register any async callbacks. 1242 */ 1243 xpt_setup_ccb(&csa.ccb_h, periph->path, 1244 /* priority */ 5); 1245 csa.ccb_h.func_code = XPT_SASYNC_CB; 1246 csa.event_enable = 0; 1247 csa.callback = saasync; 1248 csa.callback_arg = periph; 1249 xpt_action((union ccb *)&csa); 1250 1251 softc->flags |= SA_FLAG_INVALID; 1252 1253 /* 1254 * Although the oninvalidate() routines are always called at 1255 * splsoftcam, we need to be at splbio() here to keep the buffer 1256 * queue from being modified while we traverse it. 1257 */ 1258 s = splbio(); 1259 1260 /* 1261 * Return all queued I/O with ENXIO. 1262 * XXX Handle any transactions queued to the card 1263 * with XPT_ABORT_CCB. 1264 */ 1265 while ((q_bp = bioq_first(&softc->bio_queue)) != NULL){ 1266 bioq_remove(&softc->bio_queue, q_bp); 1267 q_bp->bio_resid = q_bp->bio_bcount; 1268 q_bp->bio_error = ENXIO; 1269 q_bp->bio_flags |= BIO_ERROR; 1270 biodone(q_bp); 1271 } 1272 softc->queue_count = 0; 1273 splx(s); 1274 1275 xpt_print_path(periph->path); 1276 printf("lost device\n"); 1277 1278} 1279 1280static void 1281sacleanup(struct cam_periph *periph) 1282{ 1283 struct sa_softc *softc; 1284 int i; 1285 1286 softc = (struct sa_softc *)periph->softc; 1287 1288 devstat_remove_entry(&softc->device_stats); 1289 1290 destroy_dev(softc->devs.ctl_dev); 1291 1292 for (i = 0; i < SA_NUM_MODES; i++) { 1293 destroy_dev(softc->devs.mode_devs[i].r_dev); 1294 destroy_dev(softc->devs.mode_devs[i].nr_dev); 1295 destroy_dev(softc->devs.mode_devs[i].er_dev); 1296 } 1297 1298 cam_extend_release(saperiphs, periph->unit_number); 1299 xpt_print_path(periph->path); 1300 printf("removing device entry\n"); 1301 free(softc, M_DEVBUF); 1302} 1303 1304static void 1305saasync(void *callback_arg, u_int32_t code, 1306 struct cam_path *path, void *arg) 1307{ 1308 struct cam_periph *periph; 1309 1310 periph = (struct cam_periph *)callback_arg; 1311 switch (code) { 1312 case AC_FOUND_DEVICE: 1313 { 1314 struct ccb_getdev *cgd; 1315 cam_status status; 1316 1317 cgd = (struct ccb_getdev *)arg; 1318 1319 if (SID_TYPE(&cgd->inq_data) != T_SEQUENTIAL) 1320 break; 1321 1322 /* 1323 * Allocate a peripheral instance for 1324 * this device and start the probe 1325 * process. 1326 */ 1327 status = cam_periph_alloc(saregister, saoninvalidate, 1328 sacleanup, sastart, 1329 "sa", CAM_PERIPH_BIO, cgd->ccb_h.path, 1330 saasync, AC_FOUND_DEVICE, cgd); 1331 1332 if (status != CAM_REQ_CMP 1333 && status != CAM_REQ_INPROG) 1334 printf("saasync: Unable to probe new device " 1335 "due to status 0x%x\n", status); 1336 break; 1337 } 1338 default: 1339 cam_periph_async(periph, code, path, arg); 1340 break; 1341 } 1342} 1343 1344static cam_status 1345saregister(struct cam_periph *periph, void *arg) 1346{ 1347 struct sa_softc *softc; 1348 struct ccb_setasync csa; 1349 struct ccb_getdev *cgd; 1350 caddr_t match; 1351 int i; 1352 1353 cgd = (struct ccb_getdev *)arg; 1354 if (periph == NULL) { 1355 printf("saregister: periph was NULL!!\n"); 1356 return (CAM_REQ_CMP_ERR); 1357 } 1358 1359 if (cgd == NULL) { 1360 printf("saregister: no getdev CCB, can't register device\n"); 1361 return (CAM_REQ_CMP_ERR); 1362 } 1363 1364 softc = (struct sa_softc *) 1365 malloc(sizeof (*softc), M_DEVBUF, M_NOWAIT | M_ZERO); 1366 if (softc == NULL) { 1367 printf("saregister: Unable to probe new device. " 1368 "Unable to allocate softc\n"); 1369 return (CAM_REQ_CMP_ERR); 1370 } 1371 softc->scsi_rev = SID_ANSI_REV(&cgd->inq_data); 1372 softc->state = SA_STATE_NORMAL; 1373 softc->fileno = (daddr_t) -1; 1374 softc->blkno = (daddr_t) -1; 1375 1376 bioq_init(&softc->bio_queue); 1377 periph->softc = softc; 1378 cam_extend_set(saperiphs, periph->unit_number, periph); 1379 1380 /* 1381 * See if this device has any quirks. 1382 */ 1383 match = cam_quirkmatch((caddr_t)&cgd->inq_data, 1384 (caddr_t)sa_quirk_table, 1385 sizeof(sa_quirk_table)/sizeof(*sa_quirk_table), 1386 sizeof(*sa_quirk_table), scsi_inquiry_match); 1387 1388 if (match != NULL) { 1389 softc->quirks = ((struct sa_quirk_entry *)match)->quirks; 1390 softc->last_media_blksize = 1391 ((struct sa_quirk_entry *)match)->prefblk; 1392#ifdef CAMDEBUG 1393 xpt_print_path(periph->path); 1394 printf("found quirk entry %d\n", (int) 1395 (((struct sa_quirk_entry *) match) - sa_quirk_table)); 1396#endif 1397 } else 1398 softc->quirks = SA_QUIRK_NONE; 1399 1400 /* 1401 * The SA driver supports a blocksize, but we don't know the 1402 * blocksize until we media is inserted. So, set a flag to 1403 * indicate that the blocksize is unavailable right now. 1404 */ 1405 devstat_add_entry(&softc->device_stats, "sa", periph->unit_number, 0, 1406 DEVSTAT_BS_UNAVAILABLE, SID_TYPE(&cgd->inq_data) | 1407 DEVSTAT_TYPE_IF_SCSI, DEVSTAT_PRIORITY_TAPE); 1408 1409 softc->devs.ctl_dev = make_dev(&sa_cdevsw, SAMINOR(SA_CTLDEV, 1410 periph->unit_number, 0, SA_ATYPE_R), UID_ROOT, GID_OPERATOR, 1411 0660, "r%s%d.ctl", periph->periph_name, periph->unit_number); 1412 1413 for (i = 0; i < SA_NUM_MODES; i++) { 1414 1415 softc->devs.mode_devs[i].r_dev = make_dev(&sa_cdevsw, 1416 SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_R), 1417 UID_ROOT, GID_OPERATOR, 0660, "r%s%d.%d", 1418 periph->periph_name, periph->unit_number, i); 1419 1420 softc->devs.mode_devs[i].nr_dev = make_dev(&sa_cdevsw, 1421 SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_NR), 1422 UID_ROOT, GID_OPERATOR, 0660, "nr%s%d.%d", 1423 periph->periph_name, periph->unit_number, i); 1424 1425 1426 softc->devs.mode_devs[i].er_dev = make_dev(&sa_cdevsw, 1427 SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_ER), 1428 UID_ROOT, GID_OPERATOR, 0660, "er%s%d.%d", 1429 periph->periph_name, periph->unit_number, i); 1430 1431 /* 1432 * Make the (well known) aliases for the first mode. 1433 */ 1434 if (i == 0) { 1435 make_dev_alias(softc->devs.mode_devs[i].r_dev, 1436 "r%s%d", periph->periph_name, periph->unit_number); 1437 make_dev_alias(softc->devs.mode_devs[i].nr_dev, 1438 "nr%s%d", periph->periph_name, periph->unit_number); 1439 make_dev_alias(softc->devs.mode_devs[i].er_dev, 1440 "er%s%d", periph->periph_name, periph->unit_number); 1441 } 1442 } 1443 1444 /* 1445 * Add an async callback so that we get 1446 * notified if this device goes away. 1447 */ 1448 xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); 1449 csa.ccb_h.func_code = XPT_SASYNC_CB; 1450 csa.event_enable = AC_LOST_DEVICE; 1451 csa.callback = saasync; 1452 csa.callback_arg = periph; 1453 xpt_action((union ccb *)&csa); 1454 1455 xpt_announce_periph(periph, NULL); 1456 1457 return (CAM_REQ_CMP); 1458} 1459 1460static void 1461sastart(struct cam_periph *periph, union ccb *start_ccb) 1462{ 1463 struct sa_softc *softc; 1464 1465 softc = (struct sa_softc *)periph->softc; 1466 1467 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("sastart")); 1468 1469 switch (softc->state) { 1470 case SA_STATE_NORMAL: 1471 { 1472 /* Pull a buffer from the queue and get going on it */ 1473 struct bio *bp; 1474 int s; 1475 1476 /* 1477 * See if there is a buf with work for us to do.. 1478 */ 1479 s = splbio(); 1480 bp = bioq_first(&softc->bio_queue); 1481 if (periph->immediate_priority <= periph->pinfo.priority) { 1482 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE, 1483 ("queuing for immediate ccb\n")); 1484 start_ccb->ccb_h.ccb_type = SA_CCB_WAITING; 1485 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, 1486 periph_links.sle); 1487 periph->immediate_priority = CAM_PRIORITY_NONE; 1488 splx(s); 1489 wakeup(&periph->ccb_list); 1490 } else if (bp == NULL) { 1491 splx(s); 1492 xpt_release_ccb(start_ccb); 1493 } else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) { 1494 struct bio *done_bp; 1495 softc->queue_count--; 1496 bioq_remove(&softc->bio_queue, bp); 1497 bp->bio_resid = bp->bio_bcount; 1498 bp->bio_flags |= BIO_ERROR; 1499 if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) { 1500 if (bp->bio_cmd == BIO_WRITE) 1501 bp->bio_error = ENOSPC; 1502 else 1503 bp->bio_error = EIO; 1504 } 1505 if ((softc->flags & SA_FLAG_EOF_PENDING) != 0) { 1506 bp->bio_error = EIO; 1507 } 1508 if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) { 1509 bp->bio_error = EIO; 1510 } 1511 done_bp = bp; 1512 bp = bioq_first(&softc->bio_queue); 1513 /* 1514 * Only if we have no other buffers queued up 1515 * do we clear the pending error flag. 1516 */ 1517 if (bp == NULL) 1518 softc->flags &= ~SA_FLAG_ERR_PENDING; 1519 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1520 ("sastart- ERR_PENDING now 0x%x, bp is %sNULL, " 1521 "%d more buffers queued up\n", 1522 (softc->flags & SA_FLAG_ERR_PENDING), 1523 (bp != NULL)? "not " : " ", softc->queue_count)); 1524 splx(s); 1525 xpt_release_ccb(start_ccb); 1526 biodone(done_bp); 1527 } else { 1528 u_int32_t length; 1529 1530 bioq_remove(&softc->bio_queue, bp); 1531 softc->queue_count--; 1532 1533 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1534 if (softc->blk_shift != 0) { 1535 length = 1536 bp->bio_bcount >> softc->blk_shift; 1537 } else if (softc->media_blksize != 0) { 1538 length = 1539 bp->bio_bcount / softc->media_blksize; 1540 } else { 1541 bp->bio_error = EIO; 1542 xpt_print_path(periph->path); 1543 printf("zero blocksize for " 1544 "FIXED length writes?\n"); 1545 splx(s); 1546 biodone(bp); 1547 break; 1548 } 1549 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1550 ("Fixed Record Count is %d\n", length)); 1551 } else { 1552 length = bp->bio_bcount; 1553 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO, 1554 ("Variable Record Count is %d\n", length)); 1555 } 1556 devstat_start_transaction(&softc->device_stats); 1557 /* 1558 * Some people have theorized that we should 1559 * suppress illegal length indication if we are 1560 * running in variable block mode so that we don't 1561 * have to request sense every time our requested 1562 * block size is larger than the written block. 1563 * The residual information from the ccb allows 1564 * us to identify this situation anyway. The only 1565 * problem with this is that we will not get 1566 * information about blocks that are larger than 1567 * our read buffer unless we set the block size 1568 * in the mode page to something other than 0. 1569 * 1570 * I believe that this is a non-issue. If user apps 1571 * don't adjust their read size to match our record 1572 * size, that's just life. Anyway, the typical usage 1573 * would be to issue, e.g., 64KB reads and occasionally 1574 * have to do deal with 512 byte or 1KB intermediate 1575 * records. 1576 */ 1577 softc->dsreg = (bp->bio_cmd == BIO_READ)? 1578 MTIO_DSREG_RD : MTIO_DSREG_WR; 1579 scsi_sa_read_write(&start_ccb->csio, 0, sadone, 1580 MSG_SIMPLE_Q_TAG, (bp->bio_cmd == BIO_READ), 1581 FALSE, (softc->flags & SA_FLAG_FIXED) != 0, 1582 length, bp->bio_data, bp->bio_bcount, SSD_FULL_SIZE, 1583 120 * 60 * 1000); 1584 start_ccb->ccb_h.ccb_type = SA_CCB_BUFFER_IO; 1585 start_ccb->ccb_h.ccb_bp = bp; 1586 bp = bioq_first(&softc->bio_queue); 1587 splx(s); 1588 xpt_action(start_ccb); 1589 } 1590 1591 if (bp != NULL) { 1592 /* Have more work to do, so ensure we stay scheduled */ 1593 xpt_schedule(periph, 1); 1594 } 1595 break; 1596 } 1597 case SA_STATE_ABNORMAL: 1598 default: 1599 panic("state 0x%x in sastart", softc->state); 1600 break; 1601 } 1602} 1603 1604 1605static void 1606sadone(struct cam_periph *periph, union ccb *done_ccb) 1607{ 1608 struct sa_softc *softc; 1609 struct ccb_scsiio *csio; 1610 1611 softc = (struct sa_softc *)periph->softc; 1612 csio = &done_ccb->csio; 1613 switch (csio->ccb_h.ccb_type) { 1614 case SA_CCB_BUFFER_IO: 1615 { 1616 struct bio *bp; 1617 int error; 1618 1619 softc->dsreg = MTIO_DSREG_REST; 1620 bp = (struct bio *)done_ccb->ccb_h.ccb_bp; 1621 error = 0; 1622 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 1623 if ((error = saerror(done_ccb, 0, 0)) == ERESTART) { 1624 /* 1625 * A retry was scheduled, so just return. 1626 */ 1627 return; 1628 } 1629 } 1630 1631 if (error == EIO) { 1632 int s; 1633 struct bio *q_bp; 1634 1635 /* 1636 * Catastrophic error. Mark the tape as frozen 1637 * (we no longer know tape position). 1638 * 1639 * Return all queued I/O with EIO, and unfreeze 1640 * our queue so that future transactions that 1641 * attempt to fix this problem can get to the 1642 * device. 1643 * 1644 */ 1645 1646 s = splbio(); 1647 softc->flags |= SA_FLAG_TAPE_FROZEN; 1648 while ((q_bp = bioq_first(&softc->bio_queue)) != NULL) { 1649 bioq_remove(&softc->bio_queue, q_bp); 1650 q_bp->bio_resid = q_bp->bio_bcount; 1651 q_bp->bio_error = EIO; 1652 q_bp->bio_flags |= BIO_ERROR; 1653 biodone(q_bp); 1654 } 1655 splx(s); 1656 } 1657 if (error != 0) { 1658 bp->bio_resid = bp->bio_bcount; 1659 bp->bio_error = error; 1660 bp->bio_flags |= BIO_ERROR; 1661 /* 1662 * In the error case, position is updated in saerror. 1663 */ 1664 } else { 1665 bp->bio_resid = csio->resid; 1666 bp->bio_error = 0; 1667 if (csio->resid != 0) { 1668 bp->bio_flags |= BIO_ERROR; 1669 } 1670 if (bp->bio_cmd == BIO_WRITE) { 1671 softc->flags |= SA_FLAG_TAPE_WRITTEN; 1672 softc->filemarks = 0; 1673 } 1674 if (softc->blkno != (daddr_t) -1) { 1675 if ((softc->flags & SA_FLAG_FIXED) != 0) { 1676 u_int32_t l; 1677 if (softc->blk_shift != 0) { 1678 l = bp->bio_bcount >> 1679 softc->blk_shift; 1680 } else { 1681 l = bp->bio_bcount / 1682 softc->media_blksize; 1683 } 1684 softc->blkno += (daddr_t) l; 1685 } else { 1686 softc->blkno++; 1687 } 1688 } 1689 } 1690 /* 1691 * If we had an error (immediate or pending), 1692 * release the device queue now. 1693 */ 1694 if (error || (softc->flags & SA_FLAG_ERR_PENDING)) 1695 cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0); 1696#ifdef CAMDEBUG 1697 if (error || bp->bio_resid) { 1698 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, 1699 ("error %d resid %ld count %ld\n", error, 1700 bp->bio_resid, bp->bio_bcount)); 1701 } 1702#endif 1703 devstat_end_transaction_bio(&softc->device_stats, bp); 1704 biodone(bp); 1705 break; 1706 } 1707 case SA_CCB_WAITING: 1708 { 1709 /* Caller will release the CCB */ 1710 wakeup(&done_ccb->ccb_h.cbfcnp); 1711 return; 1712 } 1713 } 1714 xpt_release_ccb(done_ccb); 1715} 1716 1717/* 1718 * Mount the tape (make sure it's ready for I/O). 1719 */ 1720static int 1721samount(struct cam_periph *periph, int oflags, dev_t dev) 1722{ 1723 struct sa_softc *softc; 1724 union ccb *ccb; 1725 int error; 1726 1727 /* 1728 * oflags can be checked for 'kind' of open (read-only check) - later 1729 * dev can be checked for a control-mode or compression open - later 1730 */ 1731 UNUSED_PARAMETER(oflags); 1732 UNUSED_PARAMETER(dev); 1733 1734 1735 softc = (struct sa_softc *)periph->softc; 1736 1737 /* 1738 * This should determine if something has happend since the last 1739 * open/mount that would invalidate the mount. We do *not* want 1740 * to retry this command- we just want the status. But we only 1741 * do this if we're mounted already- if we're not mounted, 1742 * we don't care about the unit read state and can instead use 1743 * this opportunity to attempt to reserve the tape unit. 1744 */ 1745 1746 if (softc->flags & SA_FLAG_TAPE_MOUNTED) { 1747 ccb = cam_periph_getccb(periph, 1); 1748 scsi_test_unit_ready(&ccb->csio, 0, sadone, 1749 MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000); 1750 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 1751 &softc->device_stats); 1752 QFRLS(ccb); 1753 if (error == ENXIO) { 1754 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1755 scsi_test_unit_ready(&ccb->csio, 0, sadone, 1756 MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000); 1757 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 1758 &softc->device_stats); 1759 QFRLS(ccb); 1760 } else if (error) { 1761 /* 1762 * We don't need to freeze the tape because we 1763 * will now attempt to rewind/load it. 1764 */ 1765 softc->flags &= ~SA_FLAG_TAPE_MOUNTED; 1766 if (CAM_DEBUGGED(ccb->ccb_h.path, CAM_DEBUG_INFO)) { 1767 xpt_print_path(ccb->ccb_h.path); 1768 printf("error %d on TUR in samount\n", error); 1769 } 1770 } 1771 } else { 1772 error = sareservereleaseunit(periph, TRUE); 1773 if (error) { 1774 return (error); 1775 } 1776 ccb = cam_periph_getccb(periph, 1); 1777 scsi_test_unit_ready(&ccb->csio, 0, sadone, 1778 MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5 * 60 * 1000); 1779 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 1780 &softc->device_stats); 1781 QFRLS(ccb); 1782 } 1783 1784 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) { 1785 struct scsi_read_block_limits_data *rblim = NULL; 1786 int comp_enabled, comp_supported; 1787 u_int8_t write_protect, guessing = 0; 1788 1789 /* 1790 * Clear out old state. 1791 */ 1792 softc->flags &= ~(SA_FLAG_TAPE_WP|SA_FLAG_TAPE_WRITTEN| 1793 SA_FLAG_ERR_PENDING|SA_FLAG_COMP_ENABLED| 1794 SA_FLAG_COMP_SUPP|SA_FLAG_COMP_UNSUPP); 1795 softc->filemarks = 0; 1796 1797 /* 1798 * *Very* first off, make sure we're loaded to BOT. 1799 */ 1800 scsi_load_unload(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE, 1801 FALSE, FALSE, 1, SSD_FULL_SIZE, REWIND_TIMEOUT); 1802 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 1803 &softc->device_stats); 1804 QFRLS(ccb); 1805 1806 /* 1807 * In case this doesn't work, do a REWIND instead 1808 */ 1809 if (error) { 1810 scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, 1811 FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT); 1812 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 1813 &softc->device_stats); 1814 QFRLS(ccb); 1815 } 1816 if (error) { 1817 xpt_release_ccb(ccb); 1818 goto exit; 1819 } 1820 1821 /* 1822 * Do a dummy test read to force access to the 1823 * media so that the drive will really know what's 1824 * there. We actually don't really care what the 1825 * blocksize on tape is and don't expect to really 1826 * read a full record. 1827 */ 1828 rblim = (struct scsi_read_block_limits_data *) 1829 malloc(8192, M_TEMP, M_WAITOK); 1830 if (rblim == NULL) { 1831 xpt_print_path(ccb->ccb_h.path); 1832 printf("no memory for test read\n"); 1833 xpt_release_ccb(ccb); 1834 error = ENOMEM; 1835 goto exit; 1836 } 1837 1838 if ((softc->quirks & SA_QUIRK_NODREAD) == 0) { 1839 scsi_sa_read_write(&ccb->csio, 0, sadone, 1840 MSG_SIMPLE_Q_TAG, 1, FALSE, 0, 8192, 1841 (void *) rblim, 8192, SSD_FULL_SIZE, 1842 120 * 60 * 1000); 1843 (void) cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 1844 &softc->device_stats); 1845 QFRLS(ccb); 1846 scsi_rewind(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 1847 FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT); 1848 error = cam_periph_runccb(ccb, saerror, 0, 1849 SF_NO_PRINT | SF_RETRY_SELTO | SF_RETRY_UA, 1850 &softc->device_stats); 1851 QFRLS(ccb); 1852 if (error) { 1853 xpt_print_path(ccb->ccb_h.path); 1854 printf("unable to rewind after test read\n"); 1855 xpt_release_ccb(ccb); 1856 goto exit; 1857 } 1858 } 1859 1860 /* 1861 * Next off, determine block limits. 1862 */ 1863 scsi_read_block_limits(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, 1864 rblim, SSD_FULL_SIZE, 5000); 1865 1866 error = cam_periph_runccb(ccb, saerror, 0, 1867 SF_NO_PRINT | SF_RETRY_UA | SF_RETRY_SELTO, 1868 &softc->device_stats); 1869 QFRLS(ccb); 1870 xpt_release_ccb(ccb); 1871 1872 if (error != 0) { 1873 /* 1874 * If it's less than SCSI-2, READ BLOCK LIMITS is not 1875 * a MANDATORY command. Anyway- it doesn't matter- 1876 * we can proceed anyway. 1877 */ 1878 softc->blk_gran = 0; 1879 softc->max_blk = ~0; 1880 softc->min_blk = 0; 1881 } else { 1882 if (softc->scsi_rev >= SCSI_REV_3) { 1883 softc->blk_gran = RBL_GRAN(rblim); 1884 } else { 1885 softc->blk_gran = 0; 1886 } 1887 /* 1888 * We take max_blk == min_blk to mean a default to 1889 * fixed mode- but note that whatever we get out of 1890 * sagetparams below will actually determine whether 1891 * we are actually *in* fixed mode. 1892 */ 1893 softc->max_blk = scsi_3btoul(rblim->maximum); 1894 softc->min_blk = scsi_2btoul(rblim->minimum); 1895 1896 1897 } 1898 /* 1899 * Next, perform a mode sense to determine 1900 * current density, blocksize, compression etc. 1901 */ 1902 error = sagetparams(periph, SA_PARAM_ALL, 1903 &softc->media_blksize, 1904 &softc->media_density, 1905 &softc->media_numblks, 1906 &softc->buffer_mode, &write_protect, 1907 &softc->speed, &comp_supported, 1908 &comp_enabled, &softc->comp_algorithm, 1909 NULL); 1910 1911 if (error != 0) { 1912 /* 1913 * We could work a little harder here. We could 1914 * adjust our attempts to get information. It 1915 * might be an ancient tape drive. If someone 1916 * nudges us, we'll do that. 1917 */ 1918 goto exit; 1919 } 1920 1921 /* 1922 * If no quirk has determined that this is a device that is 1923 * preferred to be in fixed or variable mode, now is the time 1924 * to find out. 1925 */ 1926 if ((softc->quirks & (SA_QUIRK_FIXED|SA_QUIRK_VARIABLE)) == 0) { 1927 guessing = 1; 1928 /* 1929 * This could be expensive to find out. Luckily we 1930 * only need to do this once. If we start out in 1931 * 'default' mode, try and set ourselves to one 1932 * of the densities that would determine a wad 1933 * of other stuff. Go from highest to lowest. 1934 */ 1935 if (softc->media_density == SCSI_DEFAULT_DENSITY) { 1936 int i; 1937 static u_int8_t ctry[] = { 1938 SCSI_DENSITY_HALFINCH_PE, 1939 SCSI_DENSITY_HALFINCH_6250C, 1940 SCSI_DENSITY_HALFINCH_6250, 1941 SCSI_DENSITY_HALFINCH_1600, 1942 SCSI_DENSITY_HALFINCH_800, 1943 SCSI_DENSITY_QIC_4GB, 1944 SCSI_DENSITY_QIC_2GB, 1945 SCSI_DENSITY_QIC_525_320, 1946 SCSI_DENSITY_QIC_150, 1947 SCSI_DENSITY_QIC_120, 1948 SCSI_DENSITY_QIC_24, 1949 SCSI_DENSITY_QIC_11_9TRK, 1950 SCSI_DENSITY_QIC_11_4TRK, 1951 SCSI_DENSITY_QIC_1320, 1952 SCSI_DENSITY_QIC_3080, 1953 0 1954 }; 1955 for (i = 0; ctry[i]; i++) { 1956 error = sasetparams(periph, 1957 SA_PARAM_DENSITY, 0, ctry[i], 1958 0, SF_NO_PRINT); 1959 if (error == 0) { 1960 softc->media_density = ctry[i]; 1961 break; 1962 } 1963 } 1964 } 1965 switch (softc->media_density) { 1966 case SCSI_DENSITY_QIC_11_4TRK: 1967 case SCSI_DENSITY_QIC_11_9TRK: 1968 case SCSI_DENSITY_QIC_24: 1969 case SCSI_DENSITY_QIC_120: 1970 case SCSI_DENSITY_QIC_150: 1971 case SCSI_DENSITY_QIC_525_320: 1972 case SCSI_DENSITY_QIC_1320: 1973 case SCSI_DENSITY_QIC_3080: 1974 softc->quirks &= ~SA_QUIRK_2FM; 1975 softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM; 1976 softc->last_media_blksize = 512; 1977 break; 1978 case SCSI_DENSITY_QIC_4GB: 1979 case SCSI_DENSITY_QIC_2GB: 1980 softc->quirks &= ~SA_QUIRK_2FM; 1981 softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM; 1982 softc->last_media_blksize = 1024; 1983 break; 1984 default: 1985 softc->last_media_blksize = 1986 softc->media_blksize; 1987 softc->quirks |= SA_QUIRK_VARIABLE; 1988 break; 1989 } 1990 } 1991 1992 /* 1993 * If no quirk has determined that this is a device that needs 1994 * to have 2 Filemarks at EOD, now is the time to find out. 1995 */ 1996 1997 if ((softc->quirks & SA_QUIRK_2FM) == 0) { 1998 switch (softc->media_density) { 1999 case SCSI_DENSITY_HALFINCH_800: 2000 case SCSI_DENSITY_HALFINCH_1600: 2001 case SCSI_DENSITY_HALFINCH_6250: 2002 case SCSI_DENSITY_HALFINCH_6250C: 2003 case SCSI_DENSITY_HALFINCH_PE: 2004 softc->quirks &= ~SA_QUIRK_1FM; 2005 softc->quirks |= SA_QUIRK_2FM; 2006 break; 2007 default: 2008 break; 2009 } 2010 } 2011 2012 /* 2013 * Now validate that some info we got makes sense. 2014 */ 2015 if ((softc->max_blk < softc->media_blksize) || 2016 (softc->min_blk > softc->media_blksize && 2017 softc->media_blksize)) { 2018 xpt_print_path(ccb->ccb_h.path); 2019 printf("BLOCK LIMITS (%d..%d) could not match current " 2020 "block settings (%d)- adjusting\n", softc->min_blk, 2021 softc->max_blk, softc->media_blksize); 2022 softc->max_blk = softc->min_blk = 2023 softc->media_blksize; 2024 } 2025 2026 /* 2027 * Now put ourselves into the right frame of mind based 2028 * upon quirks... 2029 */ 2030tryagain: 2031 /* 2032 * If we want to be in FIXED mode and our current blocksize 2033 * is not equal to our last blocksize (if nonzero), try and 2034 * set ourselves to this last blocksize (as the 'preferred' 2035 * block size). The initial quirkmatch at registry sets the 2036 * initial 'last' blocksize. If, for whatever reason, this 2037 * 'last' blocksize is zero, set the blocksize to 512, 2038 * or min_blk if that's larger. 2039 */ 2040 if ((softc->quirks & SA_QUIRK_FIXED) && 2041 (softc->quirks & SA_QUIRK_NO_MODESEL) == 0 && 2042 (softc->media_blksize != softc->last_media_blksize)) { 2043 softc->media_blksize = softc->last_media_blksize; 2044 if (softc->media_blksize == 0) { 2045 softc->media_blksize = 512; 2046 if (softc->media_blksize < softc->min_blk) { 2047 softc->media_blksize = softc->min_blk; 2048 } 2049 } 2050 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, 2051 softc->media_blksize, 0, 0, SF_NO_PRINT); 2052 if (error) { 2053 xpt_print_path(ccb->ccb_h.path); 2054 printf("unable to set fixed blocksize to %d\n", 2055 softc->media_blksize); 2056 goto exit; 2057 } 2058 } 2059 2060 if ((softc->quirks & SA_QUIRK_VARIABLE) && 2061 (softc->media_blksize != 0)) { 2062 softc->last_media_blksize = softc->media_blksize; 2063 softc->media_blksize = 0; 2064 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, 2065 0, 0, 0, SF_NO_PRINT); 2066 if (error) { 2067 /* 2068 * If this fails and we were guessing, just 2069 * assume that we got it wrong and go try 2070 * fixed block mode. Don't even check against 2071 * density code at this point. 2072 */ 2073 if (guessing) { 2074 softc->quirks &= ~SA_QUIRK_VARIABLE; 2075 softc->quirks |= SA_QUIRK_FIXED; 2076 if (softc->last_media_blksize == 0) 2077 softc->last_media_blksize = 512; 2078 goto tryagain; 2079 } 2080 xpt_print_path(ccb->ccb_h.path); 2081 printf("unable to set variable blocksize\n"); 2082 goto exit; 2083 } 2084 } 2085 2086 /* 2087 * Now that we have the current block size, 2088 * set up some parameters for sastart's usage. 2089 */ 2090 if (softc->media_blksize) { 2091 softc->flags |= SA_FLAG_FIXED; 2092 if (powerof2(softc->media_blksize)) { 2093 softc->blk_shift = 2094 ffs(softc->media_blksize) - 1; 2095 softc->blk_mask = softc->media_blksize - 1; 2096 } else { 2097 softc->blk_mask = ~0; 2098 softc->blk_shift = 0; 2099 } 2100 } else { 2101 /* 2102 * The SCSI-3 spec allows 0 to mean "unspecified". 2103 * The SCSI-1 spec allows 0 to mean 'infinite'. 2104 * 2105 * Either works here. 2106 */ 2107 if (softc->max_blk == 0) { 2108 softc->max_blk = ~0; 2109 } 2110 softc->blk_shift = 0; 2111 if (softc->blk_gran != 0) { 2112 softc->blk_mask = softc->blk_gran - 1; 2113 } else { 2114 softc->blk_mask = 0; 2115 } 2116 } 2117 2118 if (write_protect) 2119 softc->flags |= SA_FLAG_TAPE_WP; 2120 2121 if (comp_supported) { 2122 if (softc->saved_comp_algorithm == 0) 2123 softc->saved_comp_algorithm = 2124 softc->comp_algorithm; 2125 softc->flags |= SA_FLAG_COMP_SUPP; 2126 if (comp_enabled) 2127 softc->flags |= SA_FLAG_COMP_ENABLED; 2128 } else 2129 softc->flags |= SA_FLAG_COMP_UNSUPP; 2130 2131 if ((softc->buffer_mode == SMH_SA_BUF_MODE_NOBUF) && 2132 (softc->quirks & SA_QUIRK_NO_MODESEL) == 0) { 2133 error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0, 2134 0, 0, SF_NO_PRINT); 2135 if (error == 0) 2136 softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF; 2137 xpt_print_path(ccb->ccb_h.path); 2138 printf("unable to set buffered mode\n"); 2139 error = 0; /* not an error */ 2140 } 2141 2142 2143 if (error == 0) { 2144 softc->flags |= SA_FLAG_TAPE_MOUNTED; 2145 } 2146exit: 2147 if (rblim != NULL) 2148 free(rblim, M_TEMP); 2149 2150 if (error != 0) { 2151 softc->dsreg = MTIO_DSREG_NIL; 2152 } else { 2153 softc->fileno = softc->blkno = 0; 2154 softc->dsreg = MTIO_DSREG_REST; 2155 } 2156#ifdef SA_1FM_AT_EOD 2157 if ((softc->quirks & SA_QUIRK_2FM) == 0) 2158 softc->quirks |= SA_QUIRK_1FM; 2159#else 2160 if ((softc->quirks & SA_QUIRK_1FM) == 0) 2161 softc->quirks |= SA_QUIRK_2FM; 2162#endif 2163 } else 2164 xpt_release_ccb(ccb); 2165 2166 /* 2167 * If we return an error, we're not mounted any more, 2168 * so release any device reservation. 2169 */ 2170 if (error != 0) { 2171 (void) sareservereleaseunit(periph, FALSE); 2172 } 2173 return (error); 2174} 2175 2176/* 2177 * How many filemarks do we need to write if we were to terminate the 2178 * tape session right now? Note that this can be a negative number 2179 */ 2180 2181static int 2182samarkswanted(struct cam_periph *periph) 2183{ 2184 int markswanted; 2185 struct sa_softc *softc; 2186 2187 softc = (struct sa_softc *)periph->softc; 2188 markswanted = 0; 2189 if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) { 2190 markswanted++; 2191 if (softc->quirks & SA_QUIRK_2FM) 2192 markswanted++; 2193 } 2194 markswanted -= softc->filemarks; 2195 return (markswanted); 2196} 2197 2198static int 2199sacheckeod(struct cam_periph *periph) 2200{ 2201 int error; 2202 int markswanted; 2203 struct sa_softc *softc; 2204 2205 softc = (struct sa_softc *)periph->softc; 2206 markswanted = samarkswanted(periph); 2207 2208 if (markswanted > 0) { 2209 error = sawritefilemarks(periph, markswanted, FALSE); 2210 } else { 2211 error = 0; 2212 } 2213 return (error); 2214} 2215 2216static int 2217saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs) 2218{ 2219 static const char *toobig = 2220 "%d-byte tape record bigger than suplied buffer\n"; 2221 struct cam_periph *periph; 2222 struct sa_softc *softc; 2223 struct ccb_scsiio *csio; 2224 struct scsi_sense_data *sense; 2225 u_int32_t resid = 0; 2226 int32_t info = 0; 2227 int error_code, sense_key, asc, ascq; 2228 int error, defer_action; 2229 2230 periph = xpt_path_periph(ccb->ccb_h.path); 2231 softc = (struct sa_softc *)periph->softc; 2232 csio = &ccb->csio; 2233 sense = &csio->sense_data; 2234 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); 2235 error = 0; 2236 2237 /* 2238 * Calculate/latch up, any residuals... 2239 */ 2240 if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR) { 2241 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) { 2242 info = (int32_t) scsi_4btoul(sense->info); 2243 resid = info; 2244 if ((softc->flags & SA_FLAG_FIXED) != 0) 2245 resid *= softc->media_blksize; 2246 } else { 2247 resid = csio->dxfer_len; 2248 info = resid; 2249 if ((softc->flags & SA_FLAG_FIXED) != 0) { 2250 if (softc->media_blksize) 2251 info /= softc->media_blksize; 2252 } 2253 } 2254 if (csio->ccb_h.ccb_type == SA_CCB_BUFFER_IO) { 2255 bcopy((caddr_t) sense, (caddr_t) &softc->last_io_sense, 2256 sizeof (struct scsi_sense_data)); 2257 bcopy(csio->cdb_io.cdb_bytes, softc->last_io_cdb, 2258 (int) csio->cdb_len); 2259 softc->last_io_resid = resid; 2260 } else { 2261 bcopy((caddr_t) sense, (caddr_t) &softc->last_ctl_sense, 2262 sizeof (struct scsi_sense_data)); 2263 bcopy(csio->cdb_io.cdb_bytes, softc->last_ctl_cdb, 2264 (int) csio->cdb_len); 2265 softc->last_ctl_resid = resid; 2266 } 2267 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Key 0x%x ASC/ASCQ 2268 0x%x 0x%x flags 0x%x resid %d dxfer_len %d\n", sense_key, 2269 asc, ascq, sense->flags & ~SSD_KEY_RESERVED, resid, 2270 csio->dxfer_len)); 2271 } else { 2272 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Cam Status 0x%x\n", 2273 csio->ccb_h.status & CAM_STATUS_MASK)); 2274 } 2275 2276 /* 2277 * If it's neither a SCSI Check Condition Error nor a non-read/write 2278 * command, let the common code deal with it the error setting. 2279 */ 2280 if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR || 2281 (csio->ccb_h.ccb_type == SA_CCB_WAITING)) { 2282 return (cam_periph_error(ccb, cflgs, sflgs, &softc->saved_ccb)); 2283 } 2284 2285 /* 2286 * Calculate whether we'll defer action. 2287 */ 2288 2289 if (resid > 0 && resid < csio->dxfer_len && 2290 (softc->flags & SA_FLAG_FIXED) != 0) { 2291 defer_action = TRUE; 2292 } else { 2293 defer_action = FALSE; 2294 } 2295 2296 /* 2297 * Handle filemark, end of tape, mismatched record sizes.... 2298 * From this point out, we're only handling read/write cases. 2299 * Handle writes && reads differently. 2300 */ 2301 2302 if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) { 2303 if (sense->flags & SSD_FILEMARK) { 2304 xpt_print_path(csio->ccb_h.path); 2305 printf("filemark detected on write?\n"); 2306 if (softc->fileno != (daddr_t) -1) { 2307 softc->fileno++; 2308 softc->blkno = 0; 2309 } 2310 } 2311 if (sense->flags & SSD_EOM) { 2312 csio->resid = resid; 2313 if (defer_action) { 2314 error = -1; 2315 softc->flags |= SA_FLAG_EOM_PENDING; 2316 } else { 2317 error = ENOSPC; 2318 } 2319 } 2320 } else { 2321 if (sense_key == SSD_KEY_BLANK_CHECK) { 2322 csio->resid = resid; 2323 if (defer_action) { 2324 error = -1; 2325 softc->flags |= SA_FLAG_EOM_PENDING; 2326 } else { 2327 error = EIO; 2328 } 2329 } 2330 if (sense->flags & SSD_FILEMARK) { 2331 csio->resid = resid; 2332 if (defer_action) { 2333 error = -1; 2334 softc->flags |= SA_FLAG_EOF_PENDING; 2335 } 2336 /* 2337 * Unconditionally, if we detected a filemark on a read, 2338 * mark that we've run moved a file ahead. 2339 */ 2340 if (softc->fileno != (daddr_t) -1) { 2341 softc->fileno++; 2342 softc->blkno = 0; 2343 } 2344 } 2345 } 2346 /* 2347 * Incorrect Length usually applies to read, but can apply to writes. 2348 */ 2349 if (error == 0 && (sense->flags & SSD_ILI)) { 2350 if (info < 0) { 2351 xpt_print_path(csio->ccb_h.path); 2352 printf(toobig, csio->dxfer_len - info); 2353 csio->resid = csio->dxfer_len; 2354 error = EIO; 2355 } else { 2356 csio->resid = resid; 2357 if ((softc->flags & SA_FLAG_FIXED) != 0) { 2358 if (defer_action) 2359 softc->flags |= SA_FLAG_EIO_PENDING; 2360 else 2361 error = EIO; 2362 } 2363 /* 2364 * Bump the block number if we hadn't seen a filemark. 2365 * Do this independent of errors (we've moved anyway). 2366 */ 2367 if ((sense->flags & SSD_FILEMARK) == 0) { 2368 if (softc->blkno != (daddr_t) -1) { 2369 softc->blkno++; 2370 } 2371 } 2372 } 2373 } 2374 if (error == 0) 2375 return (cam_periph_error(ccb, cflgs, sflgs, &softc->saved_ccb)); 2376 2377 if (error == -1) 2378 return (0); 2379 else 2380 return (error); 2381} 2382 2383static int 2384sagetparams(struct cam_periph *periph, sa_params params_to_get, 2385 u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks, 2386 int *buff_mode, u_int8_t *write_protect, u_int8_t *speed, 2387 int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm, 2388 sa_comp_t *tcs) 2389{ 2390 union ccb *ccb; 2391 void *mode_buffer; 2392 struct scsi_mode_header_6 *mode_hdr; 2393 struct scsi_mode_blk_desc *mode_blk; 2394 int mode_buffer_len; 2395 struct sa_softc *softc; 2396 u_int8_t cpage; 2397 int error; 2398 cam_status status; 2399 2400 softc = (struct sa_softc *)periph->softc; 2401 ccb = cam_periph_getccb(periph, 1); 2402 cpage = SA_DATA_COMPRESSION_PAGE; 2403 2404retry: 2405 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 2406 2407 if (params_to_get & SA_PARAM_COMPRESSION) { 2408 if (softc->quirks & SA_QUIRK_NOCOMP) { 2409 *comp_supported = FALSE; 2410 params_to_get &= ~SA_PARAM_COMPRESSION; 2411 } else 2412 mode_buffer_len += sizeof (sa_comp_t); 2413 } 2414 2415 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK | M_ZERO); 2416 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 2417 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 2418 2419 /* it is safe to retry this */ 2420 scsi_mode_sense(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2421 SMS_PAGE_CTRL_CURRENT, (params_to_get & SA_PARAM_COMPRESSION) ? 2422 cpage : SMS_VENDOR_SPECIFIC_PAGE, mode_buffer, mode_buffer_len, 2423 SSD_FULL_SIZE, 5000); 2424 2425 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 2426 &softc->device_stats); 2427 QFRLS(ccb); 2428 2429 status = ccb->ccb_h.status & CAM_STATUS_MASK; 2430 2431 if (error == EINVAL && (params_to_get & SA_PARAM_COMPRESSION) != 0) { 2432 /* 2433 * Hmm. Let's see if we can try another page... 2434 * If we've already done that, give up on compression 2435 * for this device and remember this for the future 2436 * and attempt the request without asking for compression 2437 * info. 2438 */ 2439 if (cpage == SA_DATA_COMPRESSION_PAGE) { 2440 cpage = SA_DEVICE_CONFIGURATION_PAGE; 2441 goto retry; 2442 } 2443 softc->quirks |= SA_QUIRK_NOCOMP; 2444 free(mode_buffer, M_TEMP); 2445 goto retry; 2446 } else if (status == CAM_SCSI_STATUS_ERROR) { 2447 /* Tell the user about the fatal error. */ 2448 scsi_sense_print(&ccb->csio); 2449 goto sagetparamsexit; 2450 } 2451 2452 /* 2453 * If the user only wants the compression information, and 2454 * the device doesn't send back the block descriptor, it's 2455 * no big deal. If the user wants more than just 2456 * compression, though, and the device doesn't pass back the 2457 * block descriptor, we need to send another mode sense to 2458 * get the block descriptor. 2459 */ 2460 if ((mode_hdr->blk_desc_len == 0) && 2461 (params_to_get & SA_PARAM_COMPRESSION) && 2462 (params_to_get & ~(SA_PARAM_COMPRESSION))) { 2463 2464 /* 2465 * Decrease the mode buffer length by the size of 2466 * the compression page, to make sure the data 2467 * there doesn't get overwritten. 2468 */ 2469 mode_buffer_len -= sizeof (sa_comp_t); 2470 2471 /* 2472 * Now move the compression page that we presumably 2473 * got back down the memory chunk a little bit so 2474 * it doesn't get spammed. 2475 */ 2476 bcopy(&mode_hdr[0], &mode_hdr[1], sizeof (sa_comp_t)); 2477 bzero(&mode_hdr[0], sizeof (mode_hdr[0])); 2478 2479 /* 2480 * Now, we issue another mode sense and just ask 2481 * for the block descriptor, etc. 2482 */ 2483 2484 scsi_mode_sense(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2485 SMS_PAGE_CTRL_CURRENT, SMS_VENDOR_SPECIFIC_PAGE, 2486 mode_buffer, mode_buffer_len, SSD_FULL_SIZE, 5000); 2487 2488 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT, 2489 &softc->device_stats); 2490 QFRLS(ccb); 2491 2492 if (error != 0) 2493 goto sagetparamsexit; 2494 } 2495 2496 if (params_to_get & SA_PARAM_BLOCKSIZE) 2497 *blocksize = scsi_3btoul(mode_blk->blklen); 2498 2499 if (params_to_get & SA_PARAM_NUMBLOCKS) 2500 *numblocks = scsi_3btoul(mode_blk->nblocks); 2501 2502 if (params_to_get & SA_PARAM_BUFF_MODE) 2503 *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK; 2504 2505 if (params_to_get & SA_PARAM_DENSITY) 2506 *density = mode_blk->density; 2507 2508 if (params_to_get & SA_PARAM_WP) 2509 *write_protect = (mode_hdr->dev_spec & SMH_SA_WP)? TRUE : FALSE; 2510 2511 if (params_to_get & SA_PARAM_SPEED) 2512 *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK; 2513 2514 if (params_to_get & SA_PARAM_COMPRESSION) { 2515 sa_comp_t *ntcs = (sa_comp_t *) &mode_blk[1]; 2516 if (cpage == SA_DATA_COMPRESSION_PAGE) { 2517 struct scsi_data_compression_page *cp = &ntcs->dcomp; 2518 *comp_supported = 2519 (cp->dce_and_dcc & SA_DCP_DCC)? TRUE : FALSE; 2520 *comp_enabled = 2521 (cp->dce_and_dcc & SA_DCP_DCE)? TRUE : FALSE; 2522 *comp_algorithm = scsi_4btoul(cp->comp_algorithm); 2523 } else { 2524 struct scsi_dev_conf_page *cp = &ntcs->dconf; 2525 /* 2526 * We don't really know whether this device supports 2527 * Data Compression if the the algorithm field is 2528 * zero. Just say we do. 2529 */ 2530 *comp_supported = TRUE; 2531 *comp_enabled = 2532 (cp->sel_comp_alg != SA_COMP_NONE)? TRUE : FALSE; 2533 *comp_algorithm = cp->sel_comp_alg; 2534 } 2535 if (tcs != NULL) 2536 bcopy(ntcs, tcs, sizeof (sa_comp_t)); 2537 } 2538 2539 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 2540 int idx; 2541 char *xyz = mode_buffer; 2542 xpt_print_path(periph->path); 2543 printf("Mode Sense Data="); 2544 for (idx = 0; idx < mode_buffer_len; idx++) 2545 printf(" 0x%02x", xyz[idx] & 0xff); 2546 printf("\n"); 2547 } 2548 2549sagetparamsexit: 2550 2551 xpt_release_ccb(ccb); 2552 free(mode_buffer, M_TEMP); 2553 return (error); 2554} 2555 2556/* 2557 * The purpose of this function is to set one of four different parameters 2558 * for a tape drive: 2559 * - blocksize 2560 * - density 2561 * - compression / compression algorithm 2562 * - buffering mode 2563 * 2564 * The assumption is that this will be called from saioctl(), and therefore 2565 * from a process context. Thus the waiting malloc calls below. If that 2566 * assumption ever changes, the malloc calls should be changed to be 2567 * NOWAIT mallocs. 2568 * 2569 * Any or all of the four parameters may be set when this function is 2570 * called. It should handle setting more than one parameter at once. 2571 */ 2572static int 2573sasetparams(struct cam_periph *periph, sa_params params_to_set, 2574 u_int32_t blocksize, u_int8_t density, u_int32_t calg, 2575 u_int32_t sense_flags) 2576{ 2577 struct sa_softc *softc; 2578 u_int32_t current_blocksize; 2579 u_int32_t current_calg; 2580 u_int8_t current_density; 2581 u_int8_t current_speed; 2582 int comp_enabled, comp_supported; 2583 void *mode_buffer; 2584 int mode_buffer_len; 2585 struct scsi_mode_header_6 *mode_hdr; 2586 struct scsi_mode_blk_desc *mode_blk; 2587 sa_comp_t *ccomp, *cpage; 2588 int buff_mode; 2589 union ccb *ccb = NULL; 2590 int error; 2591 2592 softc = (struct sa_softc *)periph->softc; 2593 2594 ccomp = malloc(sizeof (sa_comp_t), M_TEMP, M_WAITOK); 2595 2596 /* 2597 * Since it doesn't make sense to set the number of blocks, or 2598 * write protection, we won't try to get the current value. We 2599 * always want to get the blocksize, so we can set it back to the 2600 * proper value. 2601 */ 2602 error = sagetparams(periph, 2603 params_to_set | SA_PARAM_BLOCKSIZE | SA_PARAM_SPEED, 2604 ¤t_blocksize, ¤t_density, NULL, &buff_mode, NULL, 2605 ¤t_speed, &comp_supported, &comp_enabled, 2606 ¤t_calg, ccomp); 2607 2608 if (error != 0) { 2609 free(ccomp, M_TEMP); 2610 return (error); 2611 } 2612 2613 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk); 2614 if (params_to_set & SA_PARAM_COMPRESSION) 2615 mode_buffer_len += sizeof (sa_comp_t); 2616 2617 mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK | M_ZERO); 2618 2619 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer; 2620 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 2621 2622 ccb = cam_periph_getccb(periph, 1); 2623 2624retry: 2625 2626 if (params_to_set & SA_PARAM_COMPRESSION) { 2627 if (mode_blk) { 2628 cpage = (sa_comp_t *)&mode_blk[1]; 2629 } else { 2630 cpage = (sa_comp_t *)&mode_hdr[1]; 2631 } 2632 bcopy(ccomp, cpage, sizeof (sa_comp_t)); 2633 cpage->hdr.pagecode &= ~0x80; 2634 } else 2635 cpage = NULL; 2636 2637 /* 2638 * If the caller wants us to set the blocksize, use the one they 2639 * pass in. Otherwise, use the blocksize we got back from the 2640 * mode select above. 2641 */ 2642 if (mode_blk) { 2643 if (params_to_set & SA_PARAM_BLOCKSIZE) 2644 scsi_ulto3b(blocksize, mode_blk->blklen); 2645 else 2646 scsi_ulto3b(current_blocksize, mode_blk->blklen); 2647 2648 /* 2649 * Set density if requested, else preserve old density. 2650 * SCSI_SAME_DENSITY only applies to SCSI-2 or better 2651 * devices, else density we've latched up in our softc. 2652 */ 2653 if (params_to_set & SA_PARAM_DENSITY) { 2654 mode_blk->density = density; 2655 } else if (softc->scsi_rev > SCSI_REV_CCS) { 2656 mode_blk->density = SCSI_SAME_DENSITY; 2657 } else { 2658 mode_blk->density = softc->media_density; 2659 } 2660 } 2661 2662 /* 2663 * For mode selects, these two fields must be zero. 2664 */ 2665 mode_hdr->data_length = 0; 2666 mode_hdr->medium_type = 0; 2667 2668 /* set the speed to the current value */ 2669 mode_hdr->dev_spec = current_speed; 2670 2671 /* set single-initiator buffering mode */ 2672 mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF; 2673 2674 if (mode_blk) 2675 mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc); 2676 else 2677 mode_hdr->blk_desc_len = 0; 2678 2679 /* 2680 * First, if the user wants us to set the compression algorithm or 2681 * just turn compression on, check to make sure that this drive 2682 * supports compression. 2683 */ 2684 if (params_to_set & SA_PARAM_COMPRESSION) { 2685 /* 2686 * If the compression algorithm is 0, disable compression. 2687 * If the compression algorithm is non-zero, enable 2688 * compression and set the compression type to the 2689 * specified compression algorithm, unless the algorithm is 2690 * MT_COMP_ENABLE. In that case, we look at the 2691 * compression algorithm that is currently set and if it is 2692 * non-zero, we leave it as-is. If it is zero, and we have 2693 * saved a compression algorithm from a time when 2694 * compression was enabled before, set the compression to 2695 * the saved value. 2696 */ 2697 switch (ccomp->hdr.pagecode & ~0x80) { 2698 case SA_DATA_COMPRESSION_PAGE: 2699 if (ccomp->dcomp.dce_and_dcc & SA_DCP_DCC) { 2700 struct scsi_data_compression_page *dcp = &cpage->dcomp; 2701 if (calg == 0) { 2702 /* 2703 * Disable compression, but leave the 2704 * decompression and the capability bit 2705 * alone. 2706 */ 2707 dcp->dce_and_dcc = SA_DCP_DCC; 2708 dcp->dde_and_red |= SA_DCP_DDE; 2709 break; 2710 } 2711 /* enable compression && decompression */ 2712 dcp->dce_and_dcc = SA_DCP_DCE | SA_DCP_DCC; 2713 dcp->dde_and_red |= SA_DCP_DDE; 2714 /* 2715 * If there, use compression algorithm from caller. 2716 * Otherwise, if there's a saved compression algorithm 2717 * and there is no current algorithm, use the saved 2718 * algorithm. Else parrot back what we got and hope 2719 * for the best. 2720 */ 2721 if (calg != MT_COMP_ENABLE) { 2722 scsi_ulto4b(calg, dcp->comp_algorithm); 2723 scsi_ulto4b(calg, dcp->decomp_algorithm); 2724 } else if (scsi_4btoul(dcp->comp_algorithm) == 0 && 2725 softc->saved_comp_algorithm != 0) { 2726 scsi_ulto4b(softc->saved_comp_algorithm, 2727 dcp->comp_algorithm); 2728 scsi_ulto4b(softc->saved_comp_algorithm, 2729 dcp->decomp_algorithm); 2730 } 2731 break; 2732 } 2733 case SA_DEVICE_CONFIGURATION_PAGE: 2734 { 2735 struct scsi_dev_conf_page *dcp = &cpage->dconf; 2736 if (calg == 0) { 2737 dcp->sel_comp_alg = SA_COMP_NONE; 2738 break; 2739 } 2740 if (calg != MT_COMP_ENABLE) { 2741 dcp->sel_comp_alg = calg; 2742 } else if (dcp->sel_comp_alg == SA_COMP_NONE && 2743 softc->saved_comp_algorithm != 0) { 2744 dcp->sel_comp_alg = softc->saved_comp_algorithm; 2745 } 2746 break; 2747 } 2748 default: 2749 /* 2750 * The drive doesn't seem to support compression, 2751 * so turn off the set compression bit. 2752 */ 2753 params_to_set &= ~SA_PARAM_COMPRESSION; 2754 xpt_print_path(periph->path); 2755 printf("device does not seem to support compression\n"); 2756 2757 /* 2758 * If that was the only thing the user wanted us to set, 2759 * clean up allocated resources and return with 2760 * 'operation not supported'. 2761 */ 2762 if (params_to_set == SA_PARAM_NONE) { 2763 free(mode_buffer, M_TEMP); 2764 xpt_release_ccb(ccb); 2765 return (ENODEV); 2766 } 2767 2768 /* 2769 * That wasn't the only thing the user wanted us to set. 2770 * So, decrease the stated mode buffer length by the 2771 * size of the compression mode page. 2772 */ 2773 mode_buffer_len -= sizeof(sa_comp_t); 2774 } 2775 } 2776 2777 /* It is safe to retry this operation */ 2778 scsi_mode_select(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, 2779 (params_to_set & SA_PARAM_COMPRESSION)? TRUE : FALSE, 2780 FALSE, mode_buffer, mode_buffer_len, SSD_FULL_SIZE, 5000); 2781 2782 error = cam_periph_runccb(ccb, saerror, 0, 2783 sense_flags, &softc->device_stats); 2784 QFRLS(ccb); 2785 2786 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 2787 int idx; 2788 char *xyz = mode_buffer; 2789 xpt_print_path(periph->path); 2790 printf("Err%d, Mode Select Data=", error); 2791 for (idx = 0; idx < mode_buffer_len; idx++) 2792 printf(" 0x%02x", xyz[idx] & 0xff); 2793 printf("\n"); 2794 } 2795 2796 2797 if (error) { 2798 /* 2799 * If we can, try without setting density/blocksize. 2800 */ 2801 if (mode_blk) { 2802 if ((params_to_set & 2803 (SA_PARAM_DENSITY|SA_PARAM_BLOCKSIZE)) == 0) { 2804 mode_blk = NULL; 2805 goto retry; 2806 } 2807 } else { 2808 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1]; 2809 cpage = (sa_comp_t *)&mode_blk[1]; 2810 } 2811 2812 /* 2813 * If we were setting the blocksize, and that failed, we 2814 * want to set it to its original value. If we weren't 2815 * setting the blocksize, we don't want to change it. 2816 */ 2817 scsi_ulto3b(current_blocksize, mode_blk->blklen); 2818 2819 /* 2820 * Set density if requested, else preserve old density. 2821 * SCSI_SAME_DENSITY only applies to SCSI-2 or better 2822 * devices, else density we've latched up in our softc. 2823 */ 2824 if (params_to_set & SA_PARAM_DENSITY) { 2825 mode_blk->density = current_density; 2826 } else if (softc->scsi_rev > SCSI_REV_CCS) { 2827 mode_blk->density = SCSI_SAME_DENSITY; 2828 } else { 2829 mode_blk->density = softc->media_density; 2830 } 2831 2832 if (params_to_set & SA_PARAM_COMPRESSION) 2833 bcopy(ccomp, cpage, sizeof (sa_comp_t)); 2834 2835 /* 2836 * The retry count is the only CCB field that might have been 2837 * changed that we care about, so reset it back to 1. 2838 */ 2839 ccb->ccb_h.retry_count = 1; 2840 cam_periph_runccb(ccb, saerror, 0, sense_flags, 2841 &softc->device_stats); 2842 QFRLS(ccb); 2843 } 2844 2845 xpt_release_ccb(ccb); 2846 2847 if (ccomp != NULL) 2848 free(ccomp, M_TEMP); 2849 2850 if (params_to_set & SA_PARAM_COMPRESSION) { 2851 if (error) { 2852 softc->flags &= ~SA_FLAG_COMP_ENABLED; 2853 /* 2854 * Even if we get an error setting compression, 2855 * do not say that we don't support it. We could 2856 * have been wrong, or it may be media specific. 2857 * softc->flags &= ~SA_FLAG_COMP_SUPP; 2858 */ 2859 softc->saved_comp_algorithm = softc->comp_algorithm; 2860 softc->comp_algorithm = 0; 2861 } else { 2862 softc->flags |= SA_FLAG_COMP_ENABLED; 2863 softc->comp_algorithm = calg; 2864 } 2865 } 2866 2867 free(mode_buffer, M_TEMP); 2868 return (error); 2869} 2870 2871static void 2872saprevent(struct cam_periph *periph, int action) 2873{ 2874 struct sa_softc *softc; 2875 union ccb *ccb; 2876 int error, sf; 2877 2878 softc = (struct sa_softc *)periph->softc; 2879 2880 if ((action == PR_ALLOW) && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0) 2881 return; 2882 if ((action == PR_PREVENT) && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0) 2883 return; 2884 2885 /* 2886 * We can be quiet about illegal requests. 2887 */ 2888 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) { 2889 sf = 0; 2890 } else 2891 sf = SF_QUIET_IR; 2892 2893 ccb = cam_periph_getccb(periph, 1); 2894 2895 /* It is safe to retry this operation */ 2896 scsi_prevent(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, action, 2897 SSD_FULL_SIZE, 100000); 2898 2899 error = cam_periph_runccb(ccb, saerror, 0, sf, &softc->device_stats); 2900 QFRLS(ccb); 2901 if (error == 0) { 2902 if (action == PR_ALLOW) 2903 softc->flags &= ~SA_FLAG_TAPE_LOCKED; 2904 else 2905 softc->flags |= SA_FLAG_TAPE_LOCKED; 2906 } 2907 2908 xpt_release_ccb(ccb); 2909} 2910 2911static int 2912sarewind(struct cam_periph *periph) 2913{ 2914 union ccb *ccb; 2915 struct sa_softc *softc; 2916 int error; 2917 2918 softc = (struct sa_softc *)periph->softc; 2919 2920 ccb = cam_periph_getccb(periph, 1); 2921 2922 /* It is safe to retry this operation */ 2923 scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE, 2924 SSD_FULL_SIZE, REWIND_TIMEOUT); 2925 2926 softc->dsreg = MTIO_DSREG_REW; 2927 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2928 softc->dsreg = MTIO_DSREG_REST; 2929 2930 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2931 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2932 2933 xpt_release_ccb(ccb); 2934 if (error == 0) 2935 softc->fileno = softc->blkno = (daddr_t) 0; 2936 else 2937 softc->fileno = softc->blkno = (daddr_t) -1; 2938 return (error); 2939} 2940 2941static int 2942saspace(struct cam_periph *periph, int count, scsi_space_code code) 2943{ 2944 union ccb *ccb; 2945 struct sa_softc *softc; 2946 int error; 2947 2948 softc = (struct sa_softc *)periph->softc; 2949 2950 ccb = cam_periph_getccb(periph, 1); 2951 2952 /* This cannot be retried */ 2953 2954 scsi_space(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, code, count, 2955 SSD_FULL_SIZE, SPACE_TIMEOUT); 2956 2957 softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD; 2958 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 2959 softc->dsreg = MTIO_DSREG_REST; 2960 2961 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 2962 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 2963 2964 xpt_release_ccb(ccb); 2965 2966 /* 2967 * If a spacing operation has failed, we need to invalidate 2968 * this mount. 2969 * 2970 * If the spacing operation was setmarks or to end of recorded data, 2971 * we no longer know our relative position. 2972 * 2973 * We are not managing residuals here (really). 2974 */ 2975 if (error) { 2976 softc->fileno = softc->blkno = (daddr_t) -1; 2977 } else if (code == SS_SETMARKS || code == SS_EOD) { 2978 softc->fileno = softc->blkno = (daddr_t) -1; 2979 } else if (code == SS_FILEMARKS && softc->fileno != (daddr_t) -1) { 2980 softc->fileno += count; 2981 softc->blkno = 0; 2982 } else if (code == SS_BLOCKS && softc->blkno != (daddr_t) -1) { 2983 softc->blkno += count; 2984 } 2985 return (error); 2986} 2987 2988static int 2989sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks) 2990{ 2991 union ccb *ccb; 2992 struct sa_softc *softc; 2993 int error; 2994 2995 softc = (struct sa_softc *)periph->softc; 2996 2997 ccb = cam_periph_getccb(periph, 1); 2998 2999 softc->dsreg = MTIO_DSREG_FMK; 3000 /* this *must* not be retried */ 3001 scsi_write_filemarks(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, 3002 FALSE, setmarks, nmarks, SSD_FULL_SIZE, 60000); 3003 softc->dsreg = MTIO_DSREG_REST; 3004 3005 3006 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3007 3008 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3009 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 3010 3011 /* 3012 * XXXX: Get back the actual number of filemarks written 3013 * XXXX: (there can be a residual). 3014 */ 3015 if (error == 0 && nmarks) { 3016 struct sa_softc *softc = (struct sa_softc *)periph->softc; 3017 softc->filemarks += nmarks; 3018 } 3019 xpt_release_ccb(ccb); 3020 3021 /* 3022 * Update relative positions (if we're doing that). 3023 */ 3024 if (error) { 3025 softc->fileno = softc->blkno = (daddr_t) -1; 3026 } else if (softc->fileno != (daddr_t) -1) { 3027 softc->fileno += nmarks; 3028 softc->blkno = 0; 3029 } 3030 return (error); 3031} 3032 3033static int 3034sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) 3035{ 3036 struct scsi_tape_position_data loc; 3037 union ccb *ccb; 3038 struct sa_softc *softc = (struct sa_softc *)periph->softc; 3039 int error; 3040 3041 /* 3042 * We have to try and flush any buffered writes here if we were writing. 3043 * 3044 * The SCSI specification is vague enough about situations like 3045 * different sized blocks in a tape drive buffer as to make one 3046 * wary about trying to figure out the actual block location value 3047 * if data is in the tape drive buffer. 3048 */ 3049 3050 if (softc->flags & SA_FLAG_TAPE_WRITTEN) { 3051 error = sawritefilemarks(periph, 0, 0); 3052 if (error && error != EACCES) 3053 return (error); 3054 } 3055 3056 ccb = cam_periph_getccb(periph, 1); 3057 scsi_read_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 3058 hard, &loc, SSD_FULL_SIZE, 5000); 3059 softc->dsreg = MTIO_DSREG_RBSY; 3060 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3061 softc->dsreg = MTIO_DSREG_REST; 3062 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3063 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 3064 3065 if (error == 0) { 3066 if (loc.flags & SA_RPOS_UNCERTAIN) { 3067 error = EINVAL; /* nothing is certain */ 3068 } else { 3069#if 0 3070 u_int32_t firstblk, lastblk, nbufblk, nbufbyte; 3071 3072 firstblk = scsi_4btoul(loc.firstblk); 3073 lastblk = scsi_4btoul(loc.lastblk); 3074 nbufblk = scsi_4btoul(loc.nbufblk); 3075 nbufbyte = scsi_4btoul(loc.nbufbyte); 3076 if (lastblk || nbufblk || nbufbyte) { 3077 xpt_print_path(periph->path); 3078 printf("rdpos firstblk 0x%x lastblk 0x%x bufblk" 3079 " 0x%x bufbyte 0x%x\n", firstblk, lastblk, 3080 nbufblk, nbufbyte); 3081 } 3082 *blkptr = firstblk; 3083#else 3084 *blkptr = scsi_4btoul(loc.firstblk); 3085#endif 3086 } 3087 } 3088 3089 xpt_release_ccb(ccb); 3090 return (error); 3091} 3092 3093static int 3094sasetpos(struct cam_periph *periph, int hard, u_int32_t *blkptr) 3095{ 3096 union ccb *ccb; 3097 struct sa_softc *softc; 3098 int error; 3099 3100 /* 3101 * We used to try and flush any buffered writes here. 3102 * Now we push this onto user applications to either 3103 * flush the pending writes themselves (via a zero count 3104 * WRITE FILEMARKS command) or they can trust their tape 3105 * drive to do this correctly for them. 3106 */ 3107 3108 softc = (struct sa_softc *)periph->softc; 3109 ccb = cam_periph_getccb(periph, 1); 3110 3111 3112 scsi_set_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, 3113 hard, *blkptr, SSD_FULL_SIZE, 60 * 60 * 1000); 3114 3115 softc->dsreg = MTIO_DSREG_POS; 3116 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3117 softc->dsreg = MTIO_DSREG_REST; 3118 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3119 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0); 3120 xpt_release_ccb(ccb); 3121 /* 3122 * Note relative file && block number position as now unknown. 3123 */ 3124 softc->fileno = softc->blkno = (daddr_t) -1; 3125 return (error); 3126} 3127 3128static int 3129saretension(struct cam_periph *periph) 3130{ 3131 union ccb *ccb; 3132 struct sa_softc *softc; 3133 int error; 3134 3135 softc = (struct sa_softc *)periph->softc; 3136 3137 ccb = cam_periph_getccb(periph, 1); 3138 3139 /* It is safe to retry this operation */ 3140 scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE, 3141 FALSE, TRUE, TRUE, SSD_FULL_SIZE, ERASE_TIMEOUT); 3142 3143 softc->dsreg = MTIO_DSREG_TEN; 3144 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3145 softc->dsreg = MTIO_DSREG_REST; 3146 3147 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3148 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 3149 xpt_release_ccb(ccb); 3150 if (error == 0) 3151 softc->fileno = softc->blkno = (daddr_t) 0; 3152 else 3153 softc->fileno = softc->blkno = (daddr_t) -1; 3154 return (error); 3155} 3156 3157static int 3158sareservereleaseunit(struct cam_periph *periph, int reserve) 3159{ 3160 union ccb *ccb; 3161 struct sa_softc *softc; 3162 int error; 3163 3164 softc = (struct sa_softc *)periph->softc; 3165 ccb = cam_periph_getccb(periph, 1); 3166 3167 /* It is safe to retry this operation */ 3168 scsi_reserve_release_unit(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, 3169 FALSE, 0, SSD_FULL_SIZE, 5000, reserve); 3170 softc->dsreg = MTIO_DSREG_RBSY; 3171 error = cam_periph_runccb(ccb, saerror, 0, 3172 SF_RETRY_UA | SF_NO_PRINT, &softc->device_stats); 3173 softc->dsreg = MTIO_DSREG_REST; 3174 QFRLS(ccb); 3175 xpt_release_ccb(ccb); 3176 3177 /* 3178 * If the error was Illegal Request, then the device doesn't support 3179 * RESERVE/RELEASE. This is not an error. 3180 */ 3181 if (error == EINVAL) { 3182 error = 0; 3183 } 3184 3185 return (error); 3186} 3187 3188static int 3189saloadunload(struct cam_periph *periph, int load) 3190{ 3191 union ccb *ccb; 3192 struct sa_softc *softc; 3193 int error; 3194 3195 softc = (struct sa_softc *)periph->softc; 3196 3197 ccb = cam_periph_getccb(periph, 1); 3198 3199 /* It is safe to retry this operation */ 3200 scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE, 3201 FALSE, FALSE, load, SSD_FULL_SIZE, REWIND_TIMEOUT); 3202 3203 softc->dsreg = (load)? MTIO_DSREG_LD : MTIO_DSREG_UNL; 3204 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3205 softc->dsreg = MTIO_DSREG_REST; 3206 QFRLS(ccb); 3207 xpt_release_ccb(ccb); 3208 3209 if (error || load == 0) 3210 softc->fileno = softc->blkno = (daddr_t) -1; 3211 else if (error == 0) 3212 softc->fileno = softc->blkno = (daddr_t) 0; 3213 return (error); 3214} 3215 3216static int 3217saerase(struct cam_periph *periph, int longerase) 3218{ 3219 3220 union ccb *ccb; 3221 struct sa_softc *softc; 3222 int error; 3223 3224 softc = (struct sa_softc *)periph->softc; 3225 3226 ccb = cam_periph_getccb(periph, 1); 3227 3228 scsi_erase(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, FALSE, longerase, 3229 SSD_FULL_SIZE, ERASE_TIMEOUT); 3230 3231 softc->dsreg = MTIO_DSREG_ZER; 3232 error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats); 3233 softc->dsreg = MTIO_DSREG_REST; 3234 3235 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) 3236 cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); 3237 xpt_release_ccb(ccb); 3238 return (error); 3239} 3240 3241#endif /* _KERNEL */ 3242 3243/* 3244 * Read tape block limits command. 3245 */ 3246void 3247scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries, 3248 void (*cbfcnp)(struct cam_periph *, union ccb *), 3249 u_int8_t tag_action, 3250 struct scsi_read_block_limits_data *rlimit_buf, 3251 u_int8_t sense_len, u_int32_t timeout) 3252{ 3253 struct scsi_read_block_limits *scsi_cmd; 3254 3255 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action, 3256 (u_int8_t *)rlimit_buf, sizeof(*rlimit_buf), sense_len, 3257 sizeof(*scsi_cmd), timeout); 3258 3259 scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes; 3260 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3261 scsi_cmd->opcode = READ_BLOCK_LIMITS; 3262} 3263 3264void 3265scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries, 3266 void (*cbfcnp)(struct cam_periph *, union ccb *), 3267 u_int8_t tag_action, int readop, int sli, 3268 int fixed, u_int32_t length, u_int8_t *data_ptr, 3269 u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout) 3270{ 3271 struct scsi_sa_rw *scsi_cmd; 3272 3273 scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes; 3274 scsi_cmd->opcode = readop ? SA_READ : SA_WRITE; 3275 scsi_cmd->sli_fixed = 0; 3276 if (sli && readop) 3277 scsi_cmd->sli_fixed |= SAR_SLI; 3278 if (fixed) 3279 scsi_cmd->sli_fixed |= SARW_FIXED; 3280 scsi_ulto3b(length, scsi_cmd->length); 3281 scsi_cmd->control = 0; 3282 3283 cam_fill_csio(csio, retries, cbfcnp, readop ? CAM_DIR_IN : CAM_DIR_OUT, 3284 tag_action, data_ptr, dxfer_len, sense_len, 3285 sizeof(*scsi_cmd), timeout); 3286} 3287 3288void 3289scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries, 3290 void (*cbfcnp)(struct cam_periph *, union ccb *), 3291 u_int8_t tag_action, int immediate, int eot, 3292 int reten, int load, u_int8_t sense_len, 3293 u_int32_t timeout) 3294{ 3295 struct scsi_load_unload *scsi_cmd; 3296 3297 scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes; 3298 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3299 scsi_cmd->opcode = LOAD_UNLOAD; 3300 if (immediate) 3301 scsi_cmd->immediate = SLU_IMMED; 3302 if (eot) 3303 scsi_cmd->eot_reten_load |= SLU_EOT; 3304 if (reten) 3305 scsi_cmd->eot_reten_load |= SLU_RETEN; 3306 if (load) 3307 scsi_cmd->eot_reten_load |= SLU_LOAD; 3308 3309 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, 3310 NULL, 0, sense_len, sizeof(*scsi_cmd), timeout); 3311} 3312 3313void 3314scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries, 3315 void (*cbfcnp)(struct cam_periph *, union ccb *), 3316 u_int8_t tag_action, int immediate, u_int8_t sense_len, 3317 u_int32_t timeout) 3318{ 3319 struct scsi_rewind *scsi_cmd; 3320 3321 scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes; 3322 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3323 scsi_cmd->opcode = REWIND; 3324 if (immediate) 3325 scsi_cmd->immediate = SREW_IMMED; 3326 3327 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3328 0, sense_len, sizeof(*scsi_cmd), timeout); 3329} 3330 3331void 3332scsi_space(struct ccb_scsiio *csio, u_int32_t retries, 3333 void (*cbfcnp)(struct cam_periph *, union ccb *), 3334 u_int8_t tag_action, scsi_space_code code, 3335 u_int32_t count, u_int8_t sense_len, u_int32_t timeout) 3336{ 3337 struct scsi_space *scsi_cmd; 3338 3339 scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes; 3340 scsi_cmd->opcode = SPACE; 3341 scsi_cmd->code = code; 3342 scsi_ulto3b(count, scsi_cmd->count); 3343 scsi_cmd->control = 0; 3344 3345 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3346 0, sense_len, sizeof(*scsi_cmd), timeout); 3347} 3348 3349void 3350scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries, 3351 void (*cbfcnp)(struct cam_periph *, union ccb *), 3352 u_int8_t tag_action, int immediate, int setmark, 3353 u_int32_t num_marks, u_int8_t sense_len, 3354 u_int32_t timeout) 3355{ 3356 struct scsi_write_filemarks *scsi_cmd; 3357 3358 scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes; 3359 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3360 scsi_cmd->opcode = WRITE_FILEMARKS; 3361 if (immediate) 3362 scsi_cmd->byte2 |= SWFMRK_IMMED; 3363 if (setmark) 3364 scsi_cmd->byte2 |= SWFMRK_WSMK; 3365 3366 scsi_ulto3b(num_marks, scsi_cmd->num_marks); 3367 3368 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3369 0, sense_len, sizeof(*scsi_cmd), timeout); 3370} 3371 3372/* 3373 * The reserve and release unit commands differ only by their opcodes. 3374 */ 3375void 3376scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries, 3377 void (*cbfcnp)(struct cam_periph *, union ccb *), 3378 u_int8_t tag_action, int third_party, 3379 int third_party_id, u_int8_t sense_len, 3380 u_int32_t timeout, int reserve) 3381{ 3382 struct scsi_reserve_release_unit *scsi_cmd; 3383 3384 scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes; 3385 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3386 3387 if (reserve) 3388 scsi_cmd->opcode = RESERVE_UNIT; 3389 else 3390 scsi_cmd->opcode = RELEASE_UNIT; 3391 3392 if (third_party) { 3393 scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY; 3394 scsi_cmd->lun_thirdparty |= 3395 ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK); 3396 } 3397 3398 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3399 0, sense_len, sizeof(*scsi_cmd), timeout); 3400} 3401 3402void 3403scsi_erase(struct ccb_scsiio *csio, u_int32_t retries, 3404 void (*cbfcnp)(struct cam_periph *, union ccb *), 3405 u_int8_t tag_action, int immediate, int long_erase, 3406 u_int8_t sense_len, u_int32_t timeout) 3407{ 3408 struct scsi_erase *scsi_cmd; 3409 3410 scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes; 3411 bzero(scsi_cmd, sizeof(*scsi_cmd)); 3412 3413 scsi_cmd->opcode = ERASE; 3414 3415 if (immediate) 3416 scsi_cmd->lun_imm_long |= SE_IMMED; 3417 3418 if (long_erase) 3419 scsi_cmd->lun_imm_long |= SE_LONG; 3420 3421 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL, 3422 0, sense_len, sizeof(*scsi_cmd), timeout); 3423} 3424 3425/* 3426 * Read Tape Position command. 3427 */ 3428void 3429scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries, 3430 void (*cbfcnp)(struct cam_periph *, union ccb *), 3431 u_int8_t tag_action, int hardsoft, 3432 struct scsi_tape_position_data *sbp, 3433 u_int8_t sense_len, u_int32_t timeout) 3434{ 3435 struct scsi_tape_read_position *scmd; 3436 3437 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action, 3438 (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout); 3439 scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes; 3440 bzero(scmd, sizeof(*scmd)); 3441 scmd->opcode = READ_POSITION; 3442 scmd->byte1 = hardsoft; 3443} 3444 3445/* 3446 * Set Tape Position command. 3447 */ 3448void 3449scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries, 3450 void (*cbfcnp)(struct cam_periph *, union ccb *), 3451 u_int8_t tag_action, int hardsoft, u_int32_t blkno, 3452 u_int8_t sense_len, u_int32_t timeout) 3453{ 3454 struct scsi_tape_locate *scmd; 3455 3456 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, 3457 (u_int8_t *)NULL, 0, sense_len, sizeof(*scmd), timeout); 3458 scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes; 3459 bzero(scmd, sizeof(*scmd)); 3460 scmd->opcode = LOCATE; 3461 if (hardsoft) 3462 scmd->byte1 |= SA_SPOS_BT; 3463 scsi_ulto4b(blkno, scmd->blkaddr); 3464} 3465