linux/drivers/scsi/st.c

// SPDX-License-Identifier: GPL-2.0-only
/*
   SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
   file Documentation/scsi/st.rst for more information.

   History:
   Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
   Contribution and ideas from several people including (in alphabetical
   order) Klaus Ehrenfried, Eugene Exarevsky, Eric Lee Green, Wolfgang Denk,
   Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
   Michael Schaefer, J"org Weule, and Eric Youngdale.

   Copyright 1992 - 2016 Kai Makisara
   email [email protected]

   Some small formal changes - aeb, 950809

   Last modified: 18-JAN-1998 Richard Gooch <[email protected]> Devfs support
 */

static const char *verstr =;

#include <linux/module.h>

#include <linux/compat.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/mtio.h>
#include <linux/major.h>
#include <linux/cdrom.h>
#include <linux/ioctl.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/moduleparam.h>
#include <linux/cdev.h>
#include <linux/idr.h>
#include <linux/delay.h>
#include <linux/mutex.h>

#include <linux/uaccess.h>
#include <asm/dma.h>
#include <asm/unaligned.h>

#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_driver.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>


/* The driver prints some debugging information on the console if DEBUG
   is defined and non-zero. */
#define DEBUG
#define NO_DEBUG

#define ST_DEB_MSG
#if DEBUG
/* The message level for the debug messages is currently set to KERN_NOTICE
   so that people can easily see the messages. Later when the debugging messages
   in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
#define DEB(a)
#define DEBC(a)
#else
#define DEB
#define DEBC
#endif

#define ST_KILOBYTE

#include "st_options.h"
#include "st.h"

static int buffer_kbs;
static int max_sg_segs;
static int try_direct_io =;
static int try_rdio =;
static int try_wdio =;
static int debug_flag;

static const struct class st_sysfs_class;
static const struct attribute_group *st_dev_groups[];
static const struct attribute_group *st_drv_groups[];

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS_CHARDEV_MAJOR();
MODULE_ALIAS_SCSI_DEVICE();

/* Set 'perm' (4th argument) to 0 to disable module_param's definition
 * of sysfs parameters (which module_param doesn't yet support).
 * Sysfs parameters defined explicitly later.
 */
module_param_named(buffer_kbs, buffer_kbs, int, 0);
MODULE_PARM_DESC();
module_param_named(max_sg_segs, max_sg_segs, int, 0);
MODULE_PARM_DESC();
module_param_named(try_direct_io, try_direct_io, int, 0);
MODULE_PARM_DESC();
module_param_named(debug_flag, debug_flag, int, 0);
MODULE_PARM_DESC();


/* Extra parameters for testing */
module_param_named(try_rdio, try_rdio, int, 0);
MODULE_PARM_DESC();
module_param_named(try_wdio, try_wdio, int, 0);
MODULE_PARM_DESC();

#ifndef MODULE
static int write_threshold_kbs;  /* retained for compatibility */
static struct st_dev_parm {} parms[] __initdata =;
#endif

/* Restrict the number of modes so that names for all are assigned */
#if ST_NBR_MODES > 16
#error "Maximum number of modes is 16"
#endif
/* Bit reversed order to get same names for same minors with all
   mode counts */
static const char *st_formats[] =; 

/* The default definitions have been moved to st_options.h */

#define ST_FIXED_BUFFER_SIZE

/* The buffer size should fit into the 24 bits for length in the
   6-byte SCSI read and write commands. */
#if ST_FIXED_BUFFER_SIZE >= (2 << 24 - 1)
#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
#endif

static int debugging =;

#define MAX_RETRIES
#define MAX_WRITE_RETRIES
#define MAX_READY_RETRIES
#define NO_TAPE

#define ST_TIMEOUT
#define ST_LONG_TIMEOUT

/* Remove mode bits and auto-rewind bit (7) */
#define TAPE_NR(x)
#define TAPE_MODE(x)

/* Construct the minor number from the device (d), mode (m), and non-rewind (n) data */
#define TAPE_MINOR(d, m, n)

/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
   24 bits) */
#define SET_DENS_AND_BLK

static int st_fixed_buffer_size =;
static int st_max_sg_segs =;

static int modes_defined;

static int enlarge_buffer(struct st_buffer *, int);
static void clear_buffer(struct st_buffer *);
static void normalize_buffer(struct st_buffer *);
static int append_to_buffer(const char __user *, struct st_buffer *, int);
static int from_buffer(struct st_buffer *, char __user *, int);
static void move_buffer_data(struct st_buffer *, int);

static int sgl_map_user_pages(struct st_buffer *, const unsigned int,
			      unsigned long, size_t, int);
static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int);

static int st_probe(struct device *);
static int st_remove(struct device *);

static struct scsi_driver st_template =;

static int st_compression(struct scsi_tape *, int);

static int find_partition(struct scsi_tape *);
static int switch_partition(struct scsi_tape *);

static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);

static void scsi_tape_release(struct kref *);

#define to_scsi_tape(obj)

static DEFINE_MUTEX(st_ref_mutex);
static DEFINE_SPINLOCK(st_index_lock);
static DEFINE_SPINLOCK(st_use_lock);
static DEFINE_IDR(st_index_idr);



#ifndef SIGS_FROM_OSST
#define SIGS_FROM_OSST
#endif

static struct scsi_tape *scsi_tape_get(int dev)
{}

static void scsi_tape_put(struct scsi_tape *STp)
{}

struct st_reject_data {};

static struct st_reject_data reject_list[] =;

/* If the device signature is on the list of incompatible drives, the
   function returns a pointer to the name of the correct driver (if known) */
static char * st_incompatible(struct scsi_device* SDp)
{}


#define st_printk(prefix, t, fmt, a...)
#ifdef DEBUG
#define DEBC_printk(t, fmt, a...)
#else
#define DEBC_printk
#endif

static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
{}


/* Convert the result to success code */
static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
{}

static struct st_request *st_allocate_request(struct scsi_tape *stp)
{}

static void st_release_request(struct st_request *streq)
{}

static void st_do_stats(struct scsi_tape *STp, struct request *req)
{}

static enum rq_end_io_ret st_scsi_execute_end(struct request *req,
					      blk_status_t status)
{}

static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
			   int data_direction, void *buffer, unsigned bufflen,
			   int timeout, int retries)
{}

/* Do the scsi command. Waits until command performed if do_wait is true.
   Otherwise write_behind_check() is used to check that the command
   has finished. */
static struct st_request *
st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
	   int bytes, int direction, int timeout, int retries, int do_wait)
{}


/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
   write has been correct but EOM early warning reached, -EIO if write ended in
   error or zero if write successful. Asynchronous writes are used only in
   variable block mode. */
static int write_behind_check(struct scsi_tape * STp)
{}


/* Step over EOF if it has been inadvertently crossed (ioctl not used because
   it messes up the block number). */
static int cross_eof(struct scsi_tape * STp, int forward)
{}


/* Flush the write buffer (never need to write if variable blocksize). */
static int st_flush_write_buffer(struct scsi_tape * STp)
{}


/* Flush the tape buffer. The tape will be positioned correctly unless
   seek_next is true. */
static int flush_buffer(struct scsi_tape *STp, int seek_next)
{}

/* Set the mode parameters */
static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
{}


/* Lock or unlock the drive door. Don't use when st_request allocated. */
static int do_door_lock(struct scsi_tape * STp, int do_lock)
{}


/* Set the internal state after reset */
static void reset_state(struct scsi_tape *STp)
{}

/* Test if the drive is ready. Returns either one of the codes below or a negative system
   error code. */
#define CHKRES_READY
#define CHKRES_NEW_SESSION
#define CHKRES_NOT_READY
#define CHKRES_NO_TAPE

#define MAX_ATTENTIONS

static int test_ready(struct scsi_tape *STp, int do_wait)
{}


/* See if the drive is ready and gather information about the tape. Return values:
   < 0   negative error code from errno.h
   0     drive ready
   1     drive not ready (possibly no tape)
*/
static int check_tape(struct scsi_tape *STp, struct file *filp)
{}


/* Open the device. Needs to take the BKL only because of incrementing the SCSI host
   module count. */
static int st_open(struct inode *inode, struct file *filp)
{}


/* Flush the tape buffer before close */
static int st_flush(struct file *filp, fl_owner_t id)
{}


/* Close the device and release it. BKL is not needed: this is the only thread
   accessing this tape. */
static int st_release(struct inode *inode, struct file *filp)
{}

/* The checks common to both reading and writing */
static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count)
{}


static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
			   size_t count, int is_read)
{}


/* Can be called more than once after each setup_buffer() */
static void release_buffering(struct scsi_tape *STp, int is_read)
{}


/* Write command */
static ssize_t
st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
{}

/* Read data from the tape. Returns zero in the normal case, one if the
   eof status has changed, and the negative error code in case of a
   fatal error. Otherwise updates the buffer and the eof state.

   Does release user buffer mapping if it is set.
*/
static long read_tape(struct scsi_tape *STp, long count,
		      struct st_request ** aSRpnt)
{}


/* Read command */
static ssize_t
st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
{}



DEB()


static int st_set_options(struct scsi_tape *STp, long options)
{}

#define MODE_HEADER_LENGTH

/* Mode header and page byte offsets */
#define MH_OFF_DATA_LENGTH
#define MH_OFF_MEDIUM_TYPE
#define MH_OFF_DEV_SPECIFIC
#define MH_OFF_BDESCS_LENGTH
#define MP_OFF_PAGE_NBR
#define MP_OFF_PAGE_LENGTH

/* Mode header and page bit masks */
#define MH_BIT_WP
#define MP_MSK_PAGE_NBR

/* Don't return block descriptors */
#define MODE_SENSE_OMIT_BDESCS

#define MODE_SELECT_PAGE_FORMAT

/* Read a mode page into the tape buffer. The block descriptors are included
   if incl_block_descs is true. The page control is ored to the page number
   parameter, if necessary. */
static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
{}


/* Send the mode page in the tape buffer to the drive. Assumes that the mode data
   in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */
static int write_mode_page(struct scsi_tape *STp, int page, int slow)
{}


#define COMPRESSION_PAGE
#define COMPRESSION_PAGE_LENGTH

#define CP_OFF_DCE_DCC
#define CP_OFF_C_ALGO

#define DCE_MASK
#define DCC_MASK
#define RED_MASK


/* Control the compression with mode page 15. Algorithm not changed if zero.

   The block descriptors are read and written because Sony SDT-7000 does not
   work without this (suggestion from Michael Schaefer <[email protected]>).
   Including block descriptors should not cause any harm to other drives. */

static int st_compression(struct scsi_tape * STp, int state)
{}


/* Process the load and unload commands (does unload if the load code is zero) */
static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code)
{}

#if DEBUG
#define ST_DEB_FORWARD
#define ST_DEB_BACKWARD
static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd)
{}
#else
#define ST_DEB_FORWARD
#define ST_DEB_BACKWARD
static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) {}
#endif


/* Internal ioctl function */
static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned long arg)
{}


/* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
   structure. */

static int get_location(struct scsi_tape *STp, unsigned int *block, int *partition,
			int logical)
{}


/* Set the tape block and partition. Negative partition means that only the
   block should be set in vendor specific way. */
static int set_location(struct scsi_tape *STp, unsigned int block, int partition,
			int logical)
{}


/* Find the current partition number for the drive status. Called from open and
   returns either partition number of negative error code. */
static int find_partition(struct scsi_tape *STp)
{}


/* Change the partition if necessary */
static int switch_partition(struct scsi_tape *STp)
{}

/* Functions for reading and writing the medium partition mode page. */

#define PART_PAGE
#define PART_PAGE_FIXED_LENGTH

#define PP_OFF_MAX_ADD_PARTS
#define PP_OFF_NBR_ADD_PARTS
#define PP_OFF_FLAGS
#define PP_OFF_PART_UNITS
#define PP_OFF_RESERVED

#define PP_BIT_IDP
#define PP_BIT_FDP
#define PP_MSK_PSUM_MB
#define PP_MSK_PSUM_UNITS
#define PP_MSK_POFM

/* Get the number of partitions on the tape. As a side effect reads the
   mode page into the tape buffer. */
static int nbr_partitions(struct scsi_tape *STp)
{}


static int format_medium(struct scsi_tape *STp, int format)
{}


/* Partition the tape into two partitions if size > 0 or one partition if
   size == 0.

   The block descriptors are read and written because Sony SDT-7000 does not
   work without this (suggestion from Michael Schaefer <[email protected]>).

   My HP C1533A drive returns only one partition size field. This is used to
   set the size of partition 1. There is no size field for the default partition.
   Michael Schaefer's Sony SDT-7000 returns two descriptors and the second is
   used to set the size of partition 1 (this is what the SCSI-3 standard specifies).
   The following algorithm is used to accommodate both drives: if the number of
   partition size fields is greater than the maximum number of additional partitions
   in the mode page, the second field is used. Otherwise the first field is used.

   For Seagate DDS drives the page length must be 8 when no partitions is defined
   and 10 when 1 partition is defined (information from Eric Lee Green). This is
   is acceptable also to some other old drives and enforced if the first partition
   size field is used for the first additional partition size.

   For drives that advertize SCSI-3 or newer, use the SSC-3 methods.
 */
static int partition_tape(struct scsi_tape *STp, int size)
{}



/* The ioctl command */
static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
{}

#ifdef CONFIG_COMPAT
static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
{}
#endif



/* Try to allocate a new tape buffer. Calling function must not hold
   dev_arr_lock. */
static struct st_buffer *new_tape_buffer(int max_sg)
{}


/* Try to allocate enough space in the tape buffer */
#define ST_MAX_ORDER

static int enlarge_buffer(struct st_buffer * STbuffer, int new_size)
{}


/* Make sure that no data from previous user is in the internal buffer */
static void clear_buffer(struct st_buffer * st_bp)
{}


/* Release the extra buffer */
static void normalize_buffer(struct st_buffer * STbuffer)
{}


/* Move data from the user buffer to the tape buffer. Returns zero (success) or
   negative error code. */
static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
{}


/* Move data from the tape buffer to the user buffer. Returns zero (success) or
   negative error code. */
static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
{}


/* Move data towards start of buffer */
static void move_buffer_data(struct st_buffer * st_bp, int offset)
{}

/* Validate the options from command line or module parameters */
static void validate_options(void)
{}

#ifndef MODULE
/* Set the boot options. Syntax is defined in Documenation/scsi/st.txt.
 */
static int __init st_setup(char *str)
{}

__setup();

#endif

static const struct file_operations st_fops =;

static int create_one_cdev(struct scsi_tape *tape, int mode, int rew)
{}

static int create_cdevs(struct scsi_tape *tape)
{}

static void remove_cdevs(struct scsi_tape *tape)
{}

static int st_probe(struct device *dev)
{
	struct scsi_device *SDp = to_scsi_device(dev);
	struct scsi_tape *tpnt = NULL;
	struct st_modedef *STm;
	struct st_partstat *STps;
	struct st_buffer *buffer;
	int i, error;

	if (SDp->type != TYPE_TAPE)
		return -ENODEV;
	if (st_incompatible(SDp)) {
		sdev_printk(KERN_INFO, SDp,
			    "OnStream tapes are no longer supported;\n");
		sdev_printk(KERN_INFO, SDp,
			    "please mail to [email protected].\n");
		return -ENODEV;
	}

	scsi_autopm_get_device(SDp);
	i = queue_max_segments(SDp->request_queue);
	if (st_max_sg_segs < i)
		i = st_max_sg_segs;
	buffer = new_tape_buffer(i);
	if (buffer == NULL) {
		sdev_printk(KERN_ERR, SDp,
			    "st: Can't allocate new tape buffer. "
			    "Device not attached.\n");
		goto out;
	}

	tpnt = kzalloc(sizeof(struct scsi_tape), GFP_KERNEL);
	if (tpnt == NULL) {
		sdev_printk(KERN_ERR, SDp,
			    "st: Can't allocate device descriptor.\n");
		goto out_buffer_free;
	}
	kref_init(&tpnt->kref);

	tpnt->device = SDp;
	if (SDp->scsi_level <= 2)
		tpnt->tape_type = MT_ISSCSI1;
	else
		tpnt->tape_type = MT_ISSCSI2;

	tpnt->buffer = buffer;
	tpnt->buffer->last_SRpnt = NULL;

	tpnt->inited = 0;
	tpnt->dirty = 0;
	tpnt->in_use = 0;
	tpnt->drv_buffer = 1;	/* Try buffering if no mode sense */
	tpnt->use_pf = (SDp->scsi_level >= SCSI_2);
	tpnt->density = 0;
	tpnt->do_auto_lock = ST_AUTO_LOCK;
	tpnt->can_bsr = (SDp->scsi_level > 2 ? 1 : ST_IN_FILE_POS); /* BSR mandatory in SCSI3 */
	tpnt->can_partitions = 0;
	tpnt->two_fm = ST_TWO_FM;
	tpnt->fast_mteom = ST_FAST_MTEOM;
	tpnt->scsi2_logical = ST_SCSI2LOGICAL;
	tpnt->sili = ST_SILI;
	tpnt->immediate = ST_NOWAIT;
	tpnt->immediate_filemark = 0;
	tpnt->default_drvbuffer = 0xff;		/* No forced buffering */
	tpnt->partition = 0;
	tpnt->new_partition = 0;
	tpnt->nbr_partitions = 0;
	blk_queue_rq_timeout(tpnt->device->request_queue, ST_TIMEOUT);
	tpnt->long_timeout = ST_LONG_TIMEOUT;
	tpnt->try_dio = try_direct_io;

	for (i = 0; i < ST_NBR_MODES; i++) {
		STm = &(tpnt->modes[i]);
		STm->defined = 0;
		STm->sysv = ST_SYSV;
		STm->defaults_for_writes = 0;
		STm->do_async_writes = ST_ASYNC_WRITES;
		STm->do_buffer_writes = ST_BUFFER_WRITES;
		STm->do_read_ahead = ST_READ_AHEAD;
		STm->default_compression = ST_DONT_TOUCH;
		STm->default_blksize = (-1);	/* No forced size */
		STm->default_density = (-1);	/* No forced density */
		STm->tape = tpnt;
	}

	for (i = 0; i < ST_NBR_PARTITIONS; i++) {
		STps = &(tpnt->ps[i]);
		STps->rw = ST_IDLE;
		STps->eof = ST_NOEOF;
		STps->at_sm = 0;
		STps->last_block_valid = 0;
		STps->drv_block = (-1);
		STps->drv_file = (-1);
	}

	tpnt->current_mode = 0;
	tpnt->modes[0].defined = 1;

	tpnt->density_changed = tpnt->compression_changed =
	    tpnt->blksize_changed = 0;
	mutex_init(&tpnt->lock);

	idr_preload(GFP_KERNEL);
	spin_lock(&st_index_lock);
	error = idr_alloc(&st_index_idr, tpnt, 0, ST_MAX_TAPES + 1, GFP_NOWAIT);
	spin_unlock(&st_index_lock);
	idr_preload_end();
	if (error < 0) {
		pr_warn("st: idr allocation failed: %d\n", error);
		goto out_free_tape;
	}
	tpnt->index = error;
	sprintf(tpnt->name, "st%d", tpnt->index);
	tpnt->stats = kzalloc(sizeof(struct scsi_tape_stats), GFP_KERNEL);
	if (tpnt->stats == NULL) {
		sdev_printk(KERN_ERR, SDp,
			    "st: Can't allocate statistics.\n");
		goto out_idr_remove;
	}

	dev_set_drvdata(dev, tpnt);


	error = create_cdevs(tpnt);
	if (error)
		goto out_remove_devs;
	scsi_autopm_put_device(SDp);

	sdev_printk(KERN_NOTICE, SDp,
		    "Attached scsi tape %s\n", tpnt->name);
	sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n",
		    tpnt->name, tpnt->try_dio ? "yes" : "no",
		    queue_dma_alignment(SDp->request_queue) + 1);

	return 0;

out_remove_devs:
	remove_cdevs(tpnt);
	kfree(tpnt->stats);
out_idr_remove:
	spin_lock(&st_index_lock);
	idr_remove(&st_index_idr, tpnt->index);
	spin_unlock(&st_index_lock);
out_free_tape:
	kfree(tpnt);
out_buffer_free:
	kfree(buffer);
out:
	scsi_autopm_put_device(SDp);
	return -ENODEV;
};


static int st_remove(struct device *dev)
{}

/**
 *      scsi_tape_release - Called to free the Scsi_Tape structure
 *      @kref: pointer to embedded kref
 *
 *      st_ref_mutex must be held entering this routine.  Because it is
 *      called on last put, you should always use the scsi_tape_get()
 *      scsi_tape_put() helpers which manipulate the semaphore directly
 *      and never do a direct kref_put().
 **/
static void scsi_tape_release(struct kref *kref)
{}

static const struct class st_sysfs_class =;

static int __init init_st(void)
{}

static void __exit exit_st(void)
{}

module_init();
module_exit(exit_st);


/* The sysfs driver interface. Read-only at the moment */
static ssize_t try_direct_io_show(struct device_driver *ddp, char *buf)
{}
static DRIVER_ATTR_RO(try_direct_io);

static ssize_t fixed_buffer_size_show(struct device_driver *ddp, char *buf)
{}
static DRIVER_ATTR_RO(fixed_buffer_size);

static ssize_t max_sg_segs_show(struct device_driver *ddp, char *buf)
{}
static DRIVER_ATTR_RO(max_sg_segs);

static ssize_t version_show(struct device_driver *ddd, char *buf)
{}
static DRIVER_ATTR_RO(version);

#if DEBUG
static ssize_t debug_flag_store(struct device_driver *ddp,
	const char *buf, size_t count)
{}

static ssize_t debug_flag_show(struct device_driver *ddp, char *buf)
{}
static DRIVER_ATTR_RW(debug_flag);
#endif

static struct attribute *st_drv_attrs[] =;
ATTRIBUTE_GROUPS();

/* The sysfs simple class interface */
static ssize_t
defined_show(struct device *dev, struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(defined);

static ssize_t
default_blksize_show(struct device *dev, struct device_attribute *attr,
		     char *buf)
{}
static DEVICE_ATTR_RO(default_blksize);

static ssize_t
default_density_show(struct device *dev, struct device_attribute *attr,
		     char *buf)
{}
static DEVICE_ATTR_RO(default_density);

static ssize_t
default_compression_show(struct device *dev, struct device_attribute *attr,
			 char *buf)
{}
static DEVICE_ATTR_RO(default_compression);

static ssize_t
options_show(struct device *dev, struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(options);

/* Support for tape stats */

/**
 * read_cnt_show - return read count - count of reads made from tape drive
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t read_cnt_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(read_cnt);

/**
 * read_byte_cnt_show - return read byte count - tape drives
 * may use blocks less than 512 bytes this gives the raw byte count of
 * of data read from the tape drive.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t read_byte_cnt_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(read_byte_cnt);

/**
 * read_ns_show - return read ns - overall time spent waiting on reads in ns.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t read_ns_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(read_ns);

/**
 * write_cnt_show - write count - number of user calls
 * to write(2) that have written data to tape.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t write_cnt_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(write_cnt);

/**
 * write_byte_cnt_show - write byte count - raw count of
 * bytes written to tape.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t write_byte_cnt_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(write_byte_cnt);

/**
 * write_ns_show - write ns - number of nanoseconds waiting on write
 * requests to complete.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t write_ns_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(write_ns);

/**
 * in_flight_show - number of I/Os currently in flight -
 * in most cases this will be either 0 or 1. It may be higher if someone
 * has also issued other SCSI commands such as via an ioctl.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t in_flight_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(in_flight);

/**
 * io_ns_show - io wait ns - this is the number of ns spent
 * waiting on all I/O to complete. This includes tape movement commands
 * such as rewinding, seeking to end of file or tape, it also includes
 * read and write. To determine the time spent on tape movement
 * subtract the read and write ns from this value.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t io_ns_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(io_ns);

/**
 * other_cnt_show - other io count - this is the number of
 * I/O requests other than read and write requests.
 * Typically these are tape movement requests but will include driver
 * tape movement. This includes only requests issued by the st driver.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t other_cnt_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(other_cnt);

/**
 * resid_cnt_show - A count of the number of times we get a residual
 * count - this should indicate someone issuing reads larger than the
 * block size on tape.
 * @dev: struct device
 * @attr: attribute structure
 * @buf: buffer to return formatted data in
 */
static ssize_t resid_cnt_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{}
static DEVICE_ATTR_RO(resid_cnt);

static struct attribute *st_dev_attrs[] =;

static struct attribute *st_stats_attrs[] =;

static struct attribute_group stats_group =;

static struct attribute_group st_group =;

static const struct attribute_group *st_dev_groups[] =;

/* The following functions may be useful for a larger audience. */
static int sgl_map_user_pages(struct st_buffer *STbp,
			      const unsigned int max_pages, unsigned long uaddr,
			      size_t count, int rw)
{}


/* And unmap them... */
static int sgl_unmap_user_pages(struct st_buffer *STbp,
				const unsigned int nr_pages, int dirtied)
{}