summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.com>2019-05-06 02:19:15 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2019-06-18 19:46:18 -0400
commit4e3ea141b5cb79ded7f4a67bb32e5b23a06a784a (patch)
treeba380a21e215cd52aadfd4f51cc996c019d2de8f
parent82a54da641f3cacfa31db36fc58a5e903f804c22 (diff)
scsi: osst: kill obsolete driver
The osst driver is becoming obsolete, as the manufacturer went out of business ages ago, and the maintainer has no means of testing any improvements anymore. Plus these days flash drives are cheaper and offer a higher capacity. So drop it completely. Cc: Willem Riede <osst@riede.org> Signed-off-by: Hannes Reinece <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--Documentation/scsi/osst.txt218
-rw-r--r--MAINTAINERS10
-rw-r--r--drivers/scsi/Kconfig22
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/osst.c6107
-rw-r--r--drivers/scsi/osst.h651
-rw-r--r--drivers/scsi/osst_detect.h7
-rw-r--r--drivers/scsi/osst_options.h107
-rw-r--r--drivers/scsi/st.c6
9 files changed, 3 insertions, 7126 deletions
diff --git a/Documentation/scsi/osst.txt b/Documentation/scsi/osst.txt
deleted file mode 100644
index 00c8ebb2fd18..000000000000
--- a/Documentation/scsi/osst.txt
+++ /dev/null
@@ -1,218 +0,0 @@
1README file for the osst driver
2===============================
3(w) Kurt Garloff <garloff@suse.de> 12/2000
4
5This file describes the osst driver as of version 0.8.x/0.9.x, the released
6version of the osst driver.
7It is intended to help advanced users to understand the role of osst and to
8get them started using (and maybe debugging) it.
9It won't address issues like "How do I compile a kernel?" or "How do I load
10a module?", as these are too basic.
11Once the OnStream got merged into the official kernel, the distro makers
12will provide the OnStream support for those who are not familiar with
13hacking their kernels.
14
15
16Purpose
17-------
18The osst driver was developed, because the standard SCSI tape driver in
19Linux, st, does not support the OnStream SC-x0 SCSI tape. The st is not to
20blame for that, as the OnStream tape drives do not support the standard SCSI
21command set for Serial Access Storage Devices (SASDs), which basically
22corresponds to the QIC-157 spec.
23Nevertheless, the OnStream tapes are nice pieces of hardware and therefore
24the osst driver has been written to make these tape devs supported by Linux.
25The driver is free software. It's released under the GNU GPL and planned to
26be integrated into the mainstream kernel.
27
28
29Implementation
30--------------
31The osst is a new high-level SCSI driver, just like st, sr, sd and sg. It
32can be compiled into the kernel or loaded as a module.
33As it represents a new device, it got assigned a new device node: /dev/osstX
34are character devices with major no 206 and minor numbers like the /dev/stX
35devices. If those are not present, you may create them by calling
36Makedevs.sh as root (see below).
37The driver started being a copy of st and as such, the osst devices'
38behavior looks very much the same as st to the userspace applications.
39
40
41History
42-------
43In the first place, osst shared its identity very much with st. That meant
44that it used the same kernel structures and the same device node as st.
45So you could only have either of them being present in the kernel. This has
46been fixed by registering an own device, now.
47st and osst can coexist, each only accessing the devices it can support by
48themselves.
49
50
51Installation
52------------
53osst got integrated into the linux kernel. Select it during kernel
54configuration as module or compile statically into the kernel.
55Compile your kernel and install the modules.
56
57Now, your osst driver is inside the kernel or available as a module,
58depending on your choice during kernel config. You may still need to create
59the device nodes by calling the Makedevs.sh script (see below) manually.
60
61To load your module, you may use the command
62modprobe osst
63as root. dmesg should show you, whether your OnStream tapes have been
64recognized.
65
66If you want to have the module autoloaded on access to /dev/osst, you may
67add something like
68alias char-major-206 osst
69to a file under /etc/modprobe.d/ directory.
70
71You may find it convenient to create a symbolic link
72ln -s nosst0 /dev/tape
73to make programs assuming a default name of /dev/tape more convenient to
74use.
75
76The device nodes for osst have to be created. Use the Makedevs.sh script
77attached to this file.
78
79
80Using it
81--------
82You may use the OnStream tape driver with your standard backup software,
83which may be tar, cpio, amanda, arkeia, BRU, Lone Tar, ...
84by specifying /dev/(n)osst0 as the tape device to use or using the above
85symlink trick. The IOCTLs to control tape operation are also mostly
86supported and you may try the mt (or mt_st) program to jump between
87filemarks, eject the tape, ...
88
89There's one limitation: You need to use a block size of 32kB.
90
91(This limitation is worked on and will be fixed in version 0.8.8 of
92 this driver.)
93
94If you just want to get started with standard software, here is an example
95for creating and restoring a full backup:
96# Backup
97tar cvf - / --exclude /proc | buffer -s 32k -m 24M -B -t -o /dev/nosst0
98# Restore
99buffer -s 32k -m 8M -B -t -i /dev/osst0 | tar xvf - -C /
100
101The buffer command has been used to buffer the data before it goes to the
102tape (or the file system) in order to smooth out the data stream and prevent
103the tape from needing to stop and rewind. The OnStream does have an internal
104buffer and a variable speed which help this, but especially on writing, the
105buffering still proves useful in most cases. It also pads the data to
106guarantees the block size of 32k. (Otherwise you may pass the -b64 option to
107tar.)
108Expect something like 1.8MB/s for the SC-x0 drives and 0.9MB/s for the DI-30.
109The USB drive will give you about 0.7MB/s.
110On a fast machine, you may profit from software data compression (z flag for
111tar).
112
113
114USB and IDE
115-----------
116Via the SCSI emulation layers usb-storage and ide-scsi, you can also use the
117osst driver to drive the USB-30 and the DI-30 drives. (Unfortunately, there
118is no such layer for the parallel port, otherwise the DP-30 would work as
119well.) For the USB support, you need the latest 2.4.0-test kernels and the
120latest usb-storage driver from
121http://www.linux-usb.org/
122http://sourceforge.net/cvs/?group_id=3581
123
124Note that the ide-tape driver as of 1.16f uses a slightly outdated on-tape
125format and therefore is not completely interoperable with osst tapes.
126
127The ADR-x0 line is fully SCSI-2 compliant and is supported by st, not osst.
128The on-tape format is supposed to be compatible with the one used by osst.
129
130
131Feedback and updates
132--------------------
133The driver development is coordinated through a mailing list
134<osst@linux1.onstream.nl>
135a CVS repository and some web pages.
136The tester's pages which contain recent news and updated drivers to download
137can be found on
138http://sourceforge.net/projects/osst/
139
140If you find any problems, please have a look at the tester's page in order
141to see whether the problem is already known and solved. Otherwise, please
142report it to the mailing list. Your feedback is welcome. (This holds also
143for reports of successful usage, of course.)
144In case of trouble, please do always provide the following info:
145* driver and kernel version used (see syslog)
146* driver messages (syslog)
147* SCSI config and OnStream Firmware (/proc/scsi/scsi)
148* description of error. Is it reproducible?
149* software and commands used
150
151You may subscribe to the mailing list, BTW, it's a majordomo list.
152
153
154Status
155------
1560.8.0 was the first widespread BETA release. Since then a lot of reports
157have been sent, but mostly reported success or only minor trouble.
158All the issues have been addressed.
159Check the web pages for more info about the current developments.
1600.9.x is the tree for the 2.3/2.4 kernel.
161
162
163Acknowledgments
164----------------
165The driver has been started by making a copy of Kai Makisara's st driver.
166Most of the development has been done by Willem Riede. The presence of the
167userspace program osg (onstreamsg) from Terry Hardie has been rather
168helpful. The same holds for Gadi Oxman's ide-tape support for the DI-30.
169I did add some patches to those drivers as well and coordinated things a
170little bit.
171Note that most of them did mostly spend their spare time for the creation of
172this driver.
173The people from OnStream, especially Jack Bombeeck did support this project
174and always tried to answer HW or FW related questions. Furthermore, he
175pushed the FW developers to do the right things.
176SuSE did support this project by allowing me to work on it during my working
177time for them and by integrating the driver into their distro.
178
179More people did help by sending useful comments. Sorry to those who have
180been forgotten. Thanks to all the GNU/FSF and Linux developers who made this
181platform such an interesting, nice and stable platform.
182Thanks go to those who tested the drivers and did send useful reports. Your
183help is needed!
184
185
186Makedevs.sh
187-----------
188#!/bin/sh
189# Script to create OnStream SC-x0 device nodes (major 206)
190# Usage: Makedevs.sh [nos [path to dev]]
191# $Id: README.osst.kernel,v 1.4 2000/12/20 14:13:15 garloff Exp $
192major=206
193nrs=4
194dir=/dev
195test -z "$1" || nrs=$1
196test -z "$2" || dir=$2
197declare -i nr
198nr=0
199test -d $dir || mkdir -p $dir
200while test $nr -lt $nrs; do
201 mknod $dir/osst$nr c $major $nr
202 chown 0.disk $dir/osst$nr; chmod 660 $dir/osst$nr;
203 mknod $dir/nosst$nr c $major $[nr+128]
204 chown 0.disk $dir/nosst$nr; chmod 660 $dir/nosst$nr;
205 mknod $dir/osst${nr}l c $major $[nr+32]
206 chown 0.disk $dir/osst${nr}l; chmod 660 $dir/osst${nr}l;
207 mknod $dir/nosst${nr}l c $major $[nr+160]
208 chown 0.disk $dir/nosst${nr}l; chmod 660 $dir/nosst${nr}l;
209 mknod $dir/osst${nr}m c $major $[nr+64]
210 chown 0.disk $dir/osst${nr}m; chmod 660 $dir/osst${nr}m;
211 mknod $dir/nosst${nr}m c $major $[nr+192]
212 chown 0.disk $dir/nosst${nr}m; chmod 660 $dir/nosst${nr}m;
213 mknod $dir/osst${nr}a c $major $[nr+96]
214 chown 0.disk $dir/osst${nr}a; chmod 660 $dir/osst${nr}a;
215 mknod $dir/nosst${nr}a c $major $[nr+224]
216 chown 0.disk $dir/nosst${nr}a; chmod 660 $dir/nosst${nr}a;
217 let nr+=1
218done
diff --git a/MAINTAINERS b/MAINTAINERS
index 5cfbea4ce575..adfb7ffb40ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11662,16 +11662,6 @@ S: Maintained
11662F: drivers/mtd/nand/onenand/ 11662F: drivers/mtd/nand/onenand/
11663F: include/linux/mtd/onenand*.h 11663F: include/linux/mtd/onenand*.h
11664 11664
11665ONSTREAM SCSI TAPE DRIVER
11666M: Willem Riede <osst@riede.org>
11667L: osst-users@lists.sourceforge.net
11668L: linux-scsi@vger.kernel.org
11669S: Maintained
11670F: Documentation/scsi/osst.txt
11671F: drivers/scsi/osst.*
11672F: drivers/scsi/osst_*.h
11673F: drivers/scsi/st.h
11674
11675OP-TEE DRIVER 11665OP-TEE DRIVER
11676M: Jens Wiklander <jens.wiklander@linaro.org> 11666M: Jens Wiklander <jens.wiklander@linaro.org>
11677S: Maintained 11667S: Maintained
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index d528018e6fa8..d81edb6ae9e3 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -98,28 +98,6 @@ config CHR_DEV_ST
98 To compile this driver as a module, choose M here and read 98 To compile this driver as a module, choose M here and read
99 <file:Documentation/scsi/scsi.txt>. The module will be called st. 99 <file:Documentation/scsi/scsi.txt>. The module will be called st.
100 100
101config CHR_DEV_OSST
102 tristate "SCSI OnStream SC-x0 tape support"
103 depends on SCSI
104 ---help---
105 The OnStream SC-x0 SCSI tape drives cannot be driven by the
106 standard st driver, but instead need this special osst driver and
107 use the /dev/osstX char device nodes (major 206). Via usb-storage,
108 you may be able to drive the USB-x0 and DI-x0 drives as well.
109 Note that there is also a second generation of OnStream
110 tape drives (ADR-x0) that supports the standard SCSI-2 commands for
111 tapes (QIC-157) and can be driven by the standard driver st.
112 For more information, you may have a look at the SCSI-HOWTO
113 <http://www.tldp.org/docs.html#howto> and
114 <file:Documentation/scsi/osst.txt> in the kernel source.
115 More info on the OnStream driver may be found on
116 <http://sourceforge.net/projects/osst/>
117 Please also have a look at the standard st docu, as most of it
118 applies to osst as well.
119
120 To compile this driver as a module, choose M here and read
121 <file:Documentation/scsi/scsi.txt>. The module will be called osst.
122
123config BLK_DEV_SR 101config BLK_DEV_SR
124 tristate "SCSI CDROM support" 102 tristate "SCSI CDROM support"
125 depends on SCSI && BLK_DEV 103 depends on SCSI && BLK_DEV
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 8826111fdf4a..f69ee35af2c8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -143,7 +143,6 @@ obj-$(CONFIG_SCSI_WD719X) += wd719x.o
143obj-$(CONFIG_ARM) += arm/ 143obj-$(CONFIG_ARM) += arm/
144 144
145obj-$(CONFIG_CHR_DEV_ST) += st.o 145obj-$(CONFIG_CHR_DEV_ST) += st.o
146obj-$(CONFIG_CHR_DEV_OSST) += osst.o
147obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o 146obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o
148obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o 147obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o
149obj-$(CONFIG_CHR_DEV_SG) += sg.o 148obj-$(CONFIG_CHR_DEV_SG) += sg.o
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
deleted file mode 100644
index 4bad54463eb2..000000000000
--- a/drivers/scsi/osst.c
+++ /dev/null
@@ -1,6107 +0,0 @@
1/*
2 SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
3 file Documentation/scsi/st.txt for more information.
4
5 History:
6
7 OnStream SCSI Tape support (osst) cloned from st.c by
8 Willem Riede (osst@riede.org) Feb 2000
9 Fixes ... Kurt Garloff <garloff@suse.de> Mar 2000
10
11 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
12 Contribution and ideas from several people including (in alphabetical
13 order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
14 Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
15
16 Copyright 1992 - 2002 Kai Makisara / 2000 - 2006 Willem Riede
17 email osst@riede.org
18
19 $Header: /cvsroot/osst/Driver/osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
20
21 Microscopic alterations - Rik Ling, 2000/12/21
22 Last st.c sync: Tue Oct 15 22:01:04 2002 by makisara
23 Some small formal changes - aeb, 950809
24*/
25
26static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
27static const char * osst_version = "0.99.4";
28
29/* The "failure to reconnect" firmware bug */
30#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
31#define OSST_FW_NEED_POLL_MAX 10704 /*(108D)*/
32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
33
34#include <linux/module.h>
35
36#include <linux/fs.h>
37#include <linux/kernel.h>
38#include <linux/sched/signal.h>
39#include <linux/proc_fs.h>
40#include <linux/mm.h>
41#include <linux/slab.h>
42#include <linux/init.h>
43#include <linux/string.h>
44#include <linux/errno.h>
45#include <linux/mtio.h>
46#include <linux/ioctl.h>
47#include <linux/fcntl.h>
48#include <linux/spinlock.h>
49#include <linux/vmalloc.h>
50#include <linux/blkdev.h>
51#include <linux/moduleparam.h>
52#include <linux/delay.h>
53#include <linux/jiffies.h>
54#include <linux/mutex.h>
55#include <linux/uaccess.h>
56#include <asm/dma.h>
57
58/* The driver prints some debugging information on the console if DEBUG
59 is defined and non-zero. */
60#define DEBUG 0
61
62/* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
65#define OSST_DEB_MSG KERN_NOTICE
66
67#include <scsi/scsi.h>
68#include <scsi/scsi_dbg.h>
69#include <scsi/scsi_device.h>
70#include <scsi/scsi_driver.h>
71#include <scsi/scsi_eh.h>
72#include <scsi/scsi_host.h>
73#include <scsi/scsi_ioctl.h>
74
75#define ST_KILOBYTE 1024
76
77#include "st.h"
78#include "osst.h"
79#include "osst_options.h"
80#include "osst_detect.h"
81
82static DEFINE_MUTEX(osst_int_mutex);
83static int max_dev = 0;
84static int write_threshold_kbs = 0;
85static int max_sg_segs = 0;
86
87#ifdef MODULE
88MODULE_AUTHOR("Willem Riede");
89MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
90MODULE_LICENSE("GPL");
91MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
92MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
93
94module_param(max_dev, int, 0444);
95MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
96
97module_param(write_threshold_kbs, int, 0644);
98MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
99
100module_param(max_sg_segs, int, 0644);
101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
102#else
103static struct osst_dev_parm {
104 char *name;
105 int *val;
106} parms[] __initdata = {
107 { "max_dev", &max_dev },
108 { "write_threshold_kbs", &write_threshold_kbs },
109 { "max_sg_segs", &max_sg_segs }
110};
111#endif
112
113/* Some default definitions have been moved to osst_options.h */
114#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
115#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
116
117/* The buffer size should fit into the 24 bits for length in the
118 6-byte SCSI read and write commands. */
119#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
120#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
121#endif
122
123#if DEBUG
124static int debugging = 1;
125/* uncomment define below to test error recovery */
126// #define OSST_INJECT_ERRORS 1
127#endif
128
129/* Do not retry! The drive firmware already retries when appropriate,
130 and when it tries to tell us something, we had better listen... */
131#define MAX_RETRIES 0
132
133#define NO_TAPE NOT_READY
134
135#define OSST_WAIT_POSITION_COMPLETE (HZ > 200 ? HZ / 200 : 1)
136#define OSST_WAIT_WRITE_COMPLETE (HZ / 12)
137#define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
138
139#define OSST_TIMEOUT (200 * HZ)
140#define OSST_LONG_TIMEOUT (1800 * HZ)
141
142#define TAPE_NR(x) (iminor(x) & ((1 << ST_MODE_SHIFT)-1))
143#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
144#define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
145#define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
146
147/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
148 24 bits) */
149#define SET_DENS_AND_BLK 0x10001
150
151static int osst_buffer_size = OSST_BUFFER_SIZE;
152static int osst_write_threshold = OSST_WRITE_THRESHOLD;
153static int osst_max_sg_segs = OSST_MAX_SG;
154static int osst_max_dev = OSST_MAX_TAPES;
155static int osst_nr_dev;
156
157static struct osst_tape **os_scsi_tapes = NULL;
158static DEFINE_RWLOCK(os_scsi_tapes_lock);
159
160static int modes_defined = 0;
161
162static struct osst_buffer *new_tape_buffer(int, int, int);
163static int enlarge_buffer(struct osst_buffer *, int);
164static void normalize_buffer(struct osst_buffer *);
165static int append_to_buffer(const char __user *, struct osst_buffer *, int);
166static int from_buffer(struct osst_buffer *, char __user *, int);
167static int osst_zero_buffer_tail(struct osst_buffer *);
168static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
169static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
170
171static int osst_probe(struct device *);
172static int osst_remove(struct device *);
173
174static struct scsi_driver osst_template = {
175 .gendrv = {
176 .name = "osst",
177 .owner = THIS_MODULE,
178 .probe = osst_probe,
179 .remove = osst_remove,
180 }
181};
182
183static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
184 unsigned int cmd_in, unsigned long arg);
185
186static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
187
188static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
189
190static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
191
192static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
193
194static inline char *tape_name(struct osst_tape *tape)
195{
196 return tape->drive->disk_name;
197}
198
199/* Routines that handle the interaction with mid-layer SCSI routines */
200
201
202/* Normalize Sense */
203static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
204{
205 const u8 *ucp;
206 const u8 *sense = SRpnt->sense;
207
208 s->have_sense = scsi_normalize_sense(SRpnt->sense,
209 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
210 s->flags = 0;
211
212 if (s->have_sense) {
213 s->deferred = 0;
214 s->remainder_valid =
215 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
216 switch (sense[0] & 0x7f) {
217 case 0x71:
218 s->deferred = 1;
219 /* fall through */
220 case 0x70:
221 s->fixed_format = 1;
222 s->flags = sense[2] & 0xe0;
223 break;
224 case 0x73:
225 s->deferred = 1;
226 /* fall through */
227 case 0x72:
228 s->fixed_format = 0;
229 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
230 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
231 break;
232 }
233 }
234}
235
236/* Convert the result to success code */
237static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
238{
239 char *name = tape_name(STp);
240 int result = SRpnt->result;
241 u8 * sense = SRpnt->sense, scode;
242#if DEBUG
243 const char *stp;
244#endif
245 struct st_cmdstatus *cmdstatp;
246
247 if (!result)
248 return 0;
249
250 cmdstatp = &STp->buffer->cmdstat;
251 osst_analyze_sense(SRpnt, cmdstatp);
252
253 if (cmdstatp->have_sense)
254 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
255 else
256 scode = 0;
257#if DEBUG
258 if (debugging) {
259 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
260 name, result,
261 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
262 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
263 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
264 name, scode, sense[12], sense[13]);
265 if (cmdstatp->have_sense)
266 __scsi_print_sense(STp->device, name,
267 SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
268 }
269 else
270#endif
271 if (cmdstatp->have_sense && (
272 scode != NO_SENSE &&
273 scode != RECOVERED_ERROR &&
274/* scode != UNIT_ATTENTION && */
275 scode != BLANK_CHECK &&
276 scode != VOLUME_OVERFLOW &&
277 SRpnt->cmd[0] != MODE_SENSE &&
278 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
279 if (cmdstatp->have_sense) {
280 printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
281 __scsi_print_sense(STp->device, name,
282 SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
283 }
284 else {
285 static int notyetprinted = 1;
286
287 printk(KERN_WARNING
288 "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
289 name, result, driver_byte(result),
290 host_byte(result));
291 if (notyetprinted) {
292 notyetprinted = 0;
293 printk(KERN_INFO
294 "%s:I: This warning may be caused by your scsi controller,\n", name);
295 printk(KERN_INFO
296 "%s:I: it has been reported with some Buslogic cards.\n", name);
297 }
298 }
299 }
300 STp->pos_unknown |= STp->device->was_reset;
301
302 if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
303 STp->recover_count++;
304 STp->recover_erreg++;
305#if DEBUG
306 if (debugging) {
307 if (SRpnt->cmd[0] == READ_6)
308 stp = "read";
309 else if (SRpnt->cmd[0] == WRITE_6)
310 stp = "write";
311 else
312 stp = "ioctl";
313 printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
314 STp->recover_count);
315 }
316#endif
317 if ((sense[2] & 0xe0) == 0)
318 return 0;
319 }
320 return (-EIO);
321}
322
323
324/* Wakeup from interrupt */
325static void osst_end_async(struct request *req, blk_status_t status)
326{
327 struct scsi_request *rq = scsi_req(req);
328 struct osst_request *SRpnt = req->end_io_data;
329 struct osst_tape *STp = SRpnt->stp;
330 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
331
332 STp->buffer->cmdstat.midlevel_result = SRpnt->result = rq->result;
333#if DEBUG
334 STp->write_pending = 0;
335#endif
336 if (rq->sense_len)
337 memcpy(SRpnt->sense, rq->sense, SCSI_SENSE_BUFFERSIZE);
338 if (SRpnt->waiting)
339 complete(SRpnt->waiting);
340
341 if (SRpnt->bio) {
342 kfree(mdata->pages);
343 blk_rq_unmap_user(SRpnt->bio);
344 }
345
346 blk_put_request(req);
347}
348
349/* osst_request memory management */
350static struct osst_request *osst_allocate_request(void)
351{
352 return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
353}
354
355static void osst_release_request(struct osst_request *streq)
356{
357 kfree(streq);
358}
359
360static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
361 int cmd_len, int data_direction, void *buffer, unsigned bufflen,
362 int use_sg, int timeout, int retries)
363{
364 struct request *req;
365 struct scsi_request *rq;
366 struct page **pages = NULL;
367 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
368
369 int err = 0;
370 int write = (data_direction == DMA_TO_DEVICE);
371
372 req = blk_get_request(SRpnt->stp->device->request_queue,
373 write ? REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, 0);
374 if (IS_ERR(req))
375 return DRIVER_ERROR << 24;
376
377 rq = scsi_req(req);
378 req->rq_flags |= RQF_QUIET;
379
380 SRpnt->bio = NULL;
381
382 if (use_sg) {
383 struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
384 int i;
385
386 pages = kcalloc(use_sg, sizeof(struct page *), GFP_KERNEL);
387 if (!pages)
388 goto free_req;
389
390 for_each_sg(sgl, sg, use_sg, i)
391 pages[i] = sg_page(sg);
392
393 mdata->null_mapped = 1;
394
395 mdata->page_order = get_order(sgl[0].length);
396 mdata->nr_entries =
397 DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
398 mdata->offset = 0;
399
400 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
401 if (err) {
402 kfree(pages);
403 goto free_req;
404 }
405 SRpnt->bio = req->bio;
406 mdata->pages = pages;
407
408 } else if (bufflen) {
409 err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
410 if (err)
411 goto free_req;
412 }
413
414 rq->cmd_len = cmd_len;
415 memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
416 memcpy(rq->cmd, cmd, rq->cmd_len);
417 req->timeout = timeout;
418 rq->retries = retries;
419 req->end_io_data = SRpnt;
420
421 blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
422 return 0;
423free_req:
424 blk_put_request(req);
425 return DRIVER_ERROR << 24;
426}
427
428/* Do the scsi command. Waits until command performed if do_wait is true.
429 Otherwise osst_write_behind_check() is used to check that the command
430 has finished. */
431static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp,
432 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
433{
434 unsigned char *bp;
435 unsigned short use_sg;
436#ifdef OSST_INJECT_ERRORS
437 static int inject = 0;
438 static int repeat = 0;
439#endif
440 struct completion *waiting;
441
442 /* if async, make sure there's no command outstanding */
443 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
444 printk(KERN_ERR "%s: Async command already active.\n",
445 tape_name(STp));
446 if (signal_pending(current))
447 (STp->buffer)->syscall_result = (-EINTR);
448 else
449 (STp->buffer)->syscall_result = (-EBUSY);
450 return NULL;
451 }
452
453 if (SRpnt == NULL) {
454 SRpnt = osst_allocate_request();
455 if (SRpnt == NULL) {
456 printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
457 tape_name(STp));
458 if (signal_pending(current))
459 (STp->buffer)->syscall_result = (-EINTR);
460 else
461 (STp->buffer)->syscall_result = (-EBUSY);
462 return NULL;
463 }
464 SRpnt->stp = STp;
465 }
466
467 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
468 which IO is outstanding. It's nulled out when the IO completes. */
469 if (!do_wait)
470 (STp->buffer)->last_SRpnt = SRpnt;
471
472 waiting = &STp->wait;
473 init_completion(waiting);
474 SRpnt->waiting = waiting;
475
476 use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
477 if (use_sg) {
478 bp = (char *)&(STp->buffer->sg[0]);
479 if (STp->buffer->sg_segs < use_sg)
480 use_sg = STp->buffer->sg_segs;
481 }
482 else
483 bp = (STp->buffer)->b_data;
484
485 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
486 STp->buffer->cmdstat.have_sense = 0;
487 STp->buffer->syscall_result = 0;
488
489 if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
490 use_sg, timeout, retries))
491 /* could not allocate the buffer or request was too large */
492 (STp->buffer)->syscall_result = (-EBUSY);
493 else if (do_wait) {
494 wait_for_completion(waiting);
495 SRpnt->waiting = NULL;
496 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
497#ifdef OSST_INJECT_ERRORS
498 if (STp->buffer->syscall_result == 0 &&
499 cmd[0] == READ_6 &&
500 cmd[4] &&
501 ( (++ inject % 83) == 29 ||
502 (STp->first_frame_position == 240
503 /* or STp->read_error_frame to fail again on the block calculated above */ &&
504 ++repeat < 3))) {
505 printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
506 STp->buffer->last_result_fatal = 1;
507 }
508#endif
509 }
510 return SRpnt;
511}
512
513
514/* Handle the write-behind checking (downs the semaphore) */
515static void osst_write_behind_check(struct osst_tape *STp)
516{
517 struct osst_buffer * STbuffer;
518
519 STbuffer = STp->buffer;
520
521#if DEBUG
522 if (STp->write_pending)
523 STp->nbr_waits++;
524 else
525 STp->nbr_finished++;
526#endif
527 wait_for_completion(&(STp->wait));
528 STp->buffer->last_SRpnt->waiting = NULL;
529
530 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
531
532 if (STp->buffer->syscall_result)
533 STp->buffer->syscall_result =
534 osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
535 else
536 STp->first_frame_position++;
537
538 osst_release_request(STp->buffer->last_SRpnt);
539
540 if (STbuffer->writing < STbuffer->buffer_bytes)
541 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
542
543 STbuffer->last_SRpnt = NULL;
544 STbuffer->buffer_bytes -= STbuffer->writing;
545 STbuffer->writing = 0;
546
547 return;
548}
549
550
551
552/* Onstream specific Routines */
553/*
554 * Initialize the OnStream AUX
555 */
556static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
557 int logical_blk_num, int blk_sz, int blk_cnt)
558{
559 os_aux_t *aux = STp->buffer->aux;
560 os_partition_t *par = &aux->partition;
561 os_dat_t *dat = &aux->dat;
562
563 if (STp->raw) return;
564
565 memset(aux, 0, sizeof(*aux));
566 aux->format_id = htonl(0);
567 memcpy(aux->application_sig, "LIN4", 4);
568 aux->hdwr = htonl(0);
569 aux->frame_type = frame_type;
570
571 switch (frame_type) {
572 case OS_FRAME_TYPE_HEADER:
573 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
574 par->partition_num = OS_CONFIG_PARTITION;
575 par->par_desc_ver = OS_PARTITION_VERSION;
576 par->wrt_pass_cntr = htons(0xffff);
577 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
578 par->first_frame_ppos = htonl(0);
579 par->last_frame_ppos = htonl(0xbb7);
580 aux->frame_seq_num = htonl(0);
581 aux->logical_blk_num_high = htonl(0);
582 aux->logical_blk_num = htonl(0);
583 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
584 break;
585 case OS_FRAME_TYPE_DATA:
586 case OS_FRAME_TYPE_MARKER:
587 dat->dat_sz = 8;
588 dat->reserved1 = 0;
589 dat->entry_cnt = 1;
590 dat->reserved3 = 0;
591 dat->dat_list[0].blk_sz = htonl(blk_sz);
592 dat->dat_list[0].blk_cnt = htons(blk_cnt);
593 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
594 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
595 dat->dat_list[0].reserved = 0;
596 /* fall through */
597 case OS_FRAME_TYPE_EOD:
598 aux->update_frame_cntr = htonl(0);
599 par->partition_num = OS_DATA_PARTITION;
600 par->par_desc_ver = OS_PARTITION_VERSION;
601 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
602 par->first_frame_ppos = htonl(STp->first_data_ppos);
603 par->last_frame_ppos = htonl(STp->capacity);
604 aux->frame_seq_num = htonl(frame_seq_number);
605 aux->logical_blk_num_high = htonl(0);
606 aux->logical_blk_num = htonl(logical_blk_num);
607 break;
608 default: ; /* probably FILL */
609 }
610 aux->filemark_cnt = htonl(STp->filemark_cnt);
611 aux->phys_fm = htonl(0xffffffff);
612 aux->last_mark_ppos = htonl(STp->last_mark_ppos);
613 aux->last_mark_lbn = htonl(STp->last_mark_lbn);
614}
615
616/*
617 * Verify that we have the correct tape frame
618 */
619static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
620{
621 char * name = tape_name(STp);
622 os_aux_t * aux = STp->buffer->aux;
623 os_partition_t * par = &(aux->partition);
624 struct st_partstat * STps = &(STp->ps[STp->partition]);
625 unsigned int blk_cnt, blk_sz, i;
626
627 if (STp->raw) {
628 if (STp->buffer->syscall_result) {
629 for (i=0; i < STp->buffer->sg_segs; i++)
630 memset(page_address(sg_page(&STp->buffer->sg[i])),
631 0, STp->buffer->sg[i].length);
632 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
633 } else
634 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
635 return 1;
636 }
637 if (STp->buffer->syscall_result) {
638#if DEBUG
639 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
640#endif
641 return 0;
642 }
643 if (ntohl(aux->format_id) != 0) {
644#if DEBUG
645 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
646#endif
647 goto err_out;
648 }
649 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
650 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
651#if DEBUG
652 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
653#endif
654 goto err_out;
655 }
656 if (par->partition_num != OS_DATA_PARTITION) {
657 if (!STp->linux_media || STp->linux_media_version != 2) {
658#if DEBUG
659 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
660 name, par->partition_num);
661#endif
662 goto err_out;
663 }
664 }
665 if (par->par_desc_ver != OS_PARTITION_VERSION) {
666#if DEBUG
667 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
668#endif
669 goto err_out;
670 }
671 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
672#if DEBUG
673 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
674 name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
675#endif
676 goto err_out;
677 }
678 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
679 aux->frame_type != OS_FRAME_TYPE_EOD &&
680 aux->frame_type != OS_FRAME_TYPE_MARKER) {
681 if (!quiet) {
682#if DEBUG
683 printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
684#endif
685 }
686 goto err_out;
687 }
688 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
689 STp->first_frame_position < STp->eod_frame_ppos) {
690 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
691 STp->first_frame_position);
692 goto err_out;
693 }
694 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
695 if (!quiet) {
696#if DEBUG
697 printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n",
698 name, ntohl(aux->frame_seq_num), frame_seq_number);
699#endif
700 }
701 goto err_out;
702 }
703 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
704 STps->eof = ST_FM_HIT;
705
706 i = ntohl(aux->filemark_cnt);
707 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
708 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
709#if DEBUG
710 printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
711 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
712 i, STp->first_frame_position - 1);
713#endif
714 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
715 if (i >= STp->filemark_cnt)
716 STp->filemark_cnt = i+1;
717 }
718 }
719 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
720 STps->eof = ST_EOD_1;
721 STp->frame_in_buffer = 1;
722 }
723 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
724 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
725 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
726 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
727 STp->buffer->read_pointer = 0;
728 STp->frame_in_buffer = 1;
729
730 /* See what block size was used to write file */
731 if (STp->block_size != blk_sz && blk_sz > 0) {
732 printk(KERN_INFO
733 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
734 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
735 STp->block_size<1024?STp->block_size:STp->block_size/1024,
736 STp->block_size<1024?'b':'k');
737 STp->block_size = blk_sz;
738 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
739 }
740 STps->eof = ST_NOEOF;
741 }
742 STp->frame_seq_number = ntohl(aux->frame_seq_num);
743 STp->logical_blk_num = ntohl(aux->logical_blk_num);
744 return 1;
745
746err_out:
747 if (STp->read_error_frame == 0)
748 STp->read_error_frame = STp->first_frame_position - 1;
749 return 0;
750}
751
752/*
753 * Wait for the unit to become Ready
754 */
755static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
756 unsigned timeout, int initial_delay)
757{
758 unsigned char cmd[MAX_COMMAND_SIZE];
759 struct osst_request * SRpnt;
760 unsigned long startwait = jiffies;
761#if DEBUG
762 int dbg = debugging;
763 char * name = tape_name(STp);
764
765 printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
766#endif
767
768 if (initial_delay > 0)
769 msleep(jiffies_to_msecs(initial_delay));
770
771 memset(cmd, 0, MAX_COMMAND_SIZE);
772 cmd[0] = TEST_UNIT_READY;
773
774 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
775 *aSRpnt = SRpnt;
776 if (!SRpnt) return (-EBUSY);
777
778 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
779 (( SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
780 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8) ) ||
781 ( SRpnt->sense[2] == 6 && SRpnt->sense[12] == 0x28 &&
782 SRpnt->sense[13] == 0 ) )) {
783#if DEBUG
784 if (debugging) {
785 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
786 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
787 debugging = 0;
788 }
789#endif
790 msleep(100);
791
792 memset(cmd, 0, MAX_COMMAND_SIZE);
793 cmd[0] = TEST_UNIT_READY;
794
795 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
796 }
797 *aSRpnt = SRpnt;
798#if DEBUG
799 debugging = dbg;
800#endif
801 if ( STp->buffer->syscall_result &&
802 osst_write_error_recovery(STp, aSRpnt, 0) ) {
803#if DEBUG
804 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
805 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
806 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
807 SRpnt->sense[12], SRpnt->sense[13]);
808#endif
809 return (-EIO);
810 }
811#if DEBUG
812 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
813#endif
814 return 0;
815}
816
817/*
818 * Wait for a tape to be inserted in the unit
819 */
820static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
821{
822 unsigned char cmd[MAX_COMMAND_SIZE];
823 struct osst_request * SRpnt;
824 unsigned long startwait = jiffies;
825#if DEBUG
826 int dbg = debugging;
827 char * name = tape_name(STp);
828
829 printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
830#endif
831
832 memset(cmd, 0, MAX_COMMAND_SIZE);
833 cmd[0] = TEST_UNIT_READY;
834
835 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
836 *aSRpnt = SRpnt;
837 if (!SRpnt) return (-EBUSY);
838
839 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
840 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0 ) {
841#if DEBUG
842 if (debugging) {
843 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
844 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
845 debugging = 0;
846 }
847#endif
848 msleep(100);
849
850 memset(cmd, 0, MAX_COMMAND_SIZE);
851 cmd[0] = TEST_UNIT_READY;
852
853 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
854 }
855 *aSRpnt = SRpnt;
856#if DEBUG
857 debugging = dbg;
858#endif
859 if ( STp->buffer->syscall_result && SRpnt->sense[2] != 2 &&
860 SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
861#if DEBUG
862 printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
863 printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
864 STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
865 SRpnt->sense[12], SRpnt->sense[13]);
866#endif
867 return 0;
868 }
869#if DEBUG
870 printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
871#endif
872 return 1;
873}
874
875static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
876{
877 int retval;
878
879 osst_wait_ready(STp, aSRpnt, 15 * 60, 0); /* TODO - can this catch a write error? */
880 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
881 if (retval) return (retval);
882 osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
883 return (osst_get_frame_position(STp, aSRpnt));
884}
885
886/*
887 * Wait for write(s) to complete
888 */
889static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
890{
891 unsigned char cmd[MAX_COMMAND_SIZE];
892 struct osst_request * SRpnt;
893 int result = 0;
894 int delay = OSST_WAIT_WRITE_COMPLETE;
895#if DEBUG
896 char * name = tape_name(STp);
897
898 printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
899#endif
900
901 memset(cmd, 0, MAX_COMMAND_SIZE);
902 cmd[0] = WRITE_FILEMARKS;
903 cmd[1] = 1;
904
905 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
906 *aSRpnt = SRpnt;
907 if (!SRpnt) return (-EBUSY);
908 if (STp->buffer->syscall_result) {
909 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
910 if (SRpnt->sense[13] == 8) {
911 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
912 }
913 } else
914 result = osst_write_error_recovery(STp, aSRpnt, 0);
915 }
916 result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
917 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
918
919 return (result);
920}
921
922#define OSST_POLL_PER_SEC 10
923static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
924{
925 unsigned long startwait = jiffies;
926 char * name = tape_name(STp);
927#if DEBUG
928 char notyetprinted = 1;
929#endif
930 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
931 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
932
933 while (time_before (jiffies, startwait + to*HZ))
934 {
935 int result;
936 result = osst_get_frame_position(STp, aSRpnt);
937 if (result == -EIO)
938 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
939 return 0; /* successful recovery leaves drive ready for frame */
940 if (result < 0) break;
941 if (STp->first_frame_position == curr &&
942 ((minlast < 0 &&
943 (signed)STp->last_frame_position > (signed)curr + minlast) ||
944 (minlast >= 0 && STp->cur_frames > minlast)
945 ) && result >= 0)
946 {
947#if DEBUG
948 if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
949 printk (OSST_DEB_MSG
950 "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
951 name, curr, curr+minlast, STp->first_frame_position,
952 STp->last_frame_position, STp->cur_frames,
953 result, (jiffies-startwait)/HZ,
954 (((jiffies-startwait)%HZ)*10)/HZ);
955#endif
956 return 0;
957 }
958#if DEBUG
959 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
960 {
961 printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
962 name, curr, curr+minlast, STp->first_frame_position,
963 STp->last_frame_position, STp->cur_frames, result);
964 notyetprinted--;
965 }
966#endif
967 msleep(1000 / OSST_POLL_PER_SEC);
968 }
969#if DEBUG
970 printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
971 name, curr, curr+minlast, STp->first_frame_position,
972 STp->last_frame_position, STp->cur_frames,
973 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
974#endif
975 return -EBUSY;
976}
977
978static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
979{
980 struct osst_request * SRpnt;
981 unsigned char cmd[MAX_COMMAND_SIZE];
982 unsigned long startwait = jiffies;
983 int retval = 1;
984 char * name = tape_name(STp);
985
986 if (writing) {
987 char mybuf[24];
988 char * olddata = STp->buffer->b_data;
989 int oldsize = STp->buffer->buffer_size;
990
991 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
992
993 memset(cmd, 0, MAX_COMMAND_SIZE);
994 cmd[0] = WRITE_FILEMARKS;
995 cmd[1] = 1;
996 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
997 MAX_RETRIES, 1);
998
999 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
1000
1001 if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
1002
1003 /* some failure - not just not-ready */
1004 retval = osst_write_error_recovery(STp, aSRpnt, 0);
1005 break;
1006 }
1007 schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
1008
1009 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1010 memset(cmd, 0, MAX_COMMAND_SIZE);
1011 cmd[0] = READ_POSITION;
1012
1013 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1014 MAX_RETRIES, 1);
1015
1016 retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1017 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1018 }
1019 if (retval)
1020 printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1021 } else
1022 /* TODO - figure out which error conditions can be handled */
1023 if (STp->buffer->syscall_result)
1024 printk(KERN_WARNING
1025 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1026 (*aSRpnt)->sense[ 2] & 0x0f,
1027 (*aSRpnt)->sense[12],
1028 (*aSRpnt)->sense[13]);
1029
1030 return retval;
1031}
1032
1033/*
1034 * Read the next OnStream tape frame at the current location
1035 */
1036static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1037{
1038 unsigned char cmd[MAX_COMMAND_SIZE];
1039 struct osst_request * SRpnt;
1040 int retval = 0;
1041#if DEBUG
1042 os_aux_t * aux = STp->buffer->aux;
1043 char * name = tape_name(STp);
1044#endif
1045
1046 if (STp->poll)
1047 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1048 retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1049
1050 memset(cmd, 0, MAX_COMMAND_SIZE);
1051 cmd[0] = READ_6;
1052 cmd[1] = 1;
1053 cmd[4] = 1;
1054
1055#if DEBUG
1056 if (debugging)
1057 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1058#endif
1059 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1060 STp->timeout, MAX_RETRIES, 1);
1061 *aSRpnt = SRpnt;
1062 if (!SRpnt)
1063 return (-EBUSY);
1064
1065 if ((STp->buffer)->syscall_result) {
1066 retval = 1;
1067 if (STp->read_error_frame == 0) {
1068 STp->read_error_frame = STp->first_frame_position;
1069#if DEBUG
1070 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1071#endif
1072 }
1073#if DEBUG
1074 if (debugging)
1075 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1076 name,
1077 SRpnt->sense[0], SRpnt->sense[1],
1078 SRpnt->sense[2], SRpnt->sense[3],
1079 SRpnt->sense[4], SRpnt->sense[5],
1080 SRpnt->sense[6], SRpnt->sense[7]);
1081#endif
1082 }
1083 else
1084 STp->first_frame_position++;
1085#if DEBUG
1086 if (debugging) {
1087 char sig[8]; int i;
1088 for (i=0;i<4;i++)
1089 sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1090 sig[4] = '\0';
1091 printk(OSST_DEB_MSG
1092 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1093 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1094 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1095 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
1096 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1097 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1098 if (aux->frame_type==2)
1099 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1100 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1101 printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1102 }
1103#endif
1104 return (retval);
1105}
1106
1107static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1108{
1109 struct st_partstat * STps = &(STp->ps[STp->partition]);
1110 struct osst_request * SRpnt ;
1111 unsigned char cmd[MAX_COMMAND_SIZE];
1112 int retval = 0;
1113 char * name = tape_name(STp);
1114
1115 if (STps->rw != ST_READING) { /* Initialize read operation */
1116 if (STps->rw == ST_WRITING || STp->dirty) {
1117 STp->write_type = OS_WRITE_DATA;
1118 osst_flush_write_buffer(STp, aSRpnt);
1119 osst_flush_drive_buffer(STp, aSRpnt);
1120 }
1121 STps->rw = ST_READING;
1122 STp->frame_in_buffer = 0;
1123
1124 /*
1125 * Issue a read 0 command to get the OnStream drive
1126 * read frames into its buffer.
1127 */
1128 memset(cmd, 0, MAX_COMMAND_SIZE);
1129 cmd[0] = READ_6;
1130 cmd[1] = 1;
1131
1132#if DEBUG
1133 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1134#endif
1135 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1136 *aSRpnt = SRpnt;
1137 if ((retval = STp->buffer->syscall_result))
1138 printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1139 }
1140
1141 return retval;
1142}
1143
1144static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1145 int frame_seq_number, int quiet)
1146{
1147 struct st_partstat * STps = &(STp->ps[STp->partition]);
1148 char * name = tape_name(STp);
1149 int cnt = 0,
1150 bad = 0,
1151 past = 0,
1152 x,
1153 position;
1154
1155 /*
1156 * If we want just any frame (-1) and there is a frame in the buffer, return it
1157 */
1158 if (frame_seq_number == -1 && STp->frame_in_buffer) {
1159#if DEBUG
1160 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1161#endif
1162 return (STps->eof);
1163 }
1164 /*
1165 * Search and wait for the next logical tape frame
1166 */
1167 while (1) {
1168 if (cnt++ > 400) {
1169 printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1170 name, frame_seq_number);
1171 if (STp->read_error_frame) {
1172 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1173#if DEBUG
1174 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1175 name, STp->read_error_frame);
1176#endif
1177 STp->read_error_frame = 0;
1178 STp->abort_count++;
1179 }
1180 return (-EIO);
1181 }
1182#if DEBUG
1183 if (debugging)
1184 printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1185 name, frame_seq_number, cnt);
1186#endif
1187 if ( osst_initiate_read(STp, aSRpnt)
1188 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1189 if (STp->raw)
1190 return (-EIO);
1191 position = osst_get_frame_position(STp, aSRpnt);
1192 if (position >= 0xbae && position < 0xbb8)
1193 position = 0xbb8;
1194 else if (position > STp->eod_frame_ppos || ++bad == 10) {
1195 position = STp->read_error_frame - 1;
1196 bad = 0;
1197 }
1198 else {
1199 position += 29;
1200 cnt += 19;
1201 }
1202#if DEBUG
1203 printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1204 name, position);
1205#endif
1206 osst_set_frame_position(STp, aSRpnt, position, 0);
1207 continue;
1208 }
1209 if (osst_verify_frame(STp, frame_seq_number, quiet))
1210 break;
1211 if (osst_verify_frame(STp, -1, quiet)) {
1212 x = ntohl(STp->buffer->aux->frame_seq_num);
1213 if (STp->fast_open) {
1214 printk(KERN_WARNING
1215 "%s:W: Found logical frame %d instead of %d after fast open\n",
1216 name, x, frame_seq_number);
1217 STp->header_ok = 0;
1218 STp->read_error_frame = 0;
1219 return (-EIO);
1220 }
1221 if (x > frame_seq_number) {
1222 if (++past > 3) {
1223 /* positioning backwards did not bring us to the desired frame */
1224 position = STp->read_error_frame - 1;
1225 }
1226 else {
1227 position = osst_get_frame_position(STp, aSRpnt)
1228 + frame_seq_number - x - 1;
1229
1230 if (STp->first_frame_position >= 3000 && position < 3000)
1231 position -= 10;
1232 }
1233#if DEBUG
1234 printk(OSST_DEB_MSG
1235 "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1236 name, x, frame_seq_number,
1237 STp->first_frame_position - position);
1238#endif
1239 osst_set_frame_position(STp, aSRpnt, position, 0);
1240 cnt += 10;
1241 }
1242 else
1243 past = 0;
1244 }
1245 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1246#if DEBUG
1247 printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1248#endif
1249 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1250 cnt--;
1251 }
1252 STp->frame_in_buffer = 0;
1253 }
1254 if (cnt > 1) {
1255 STp->recover_count++;
1256 STp->recover_erreg++;
1257 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n",
1258 name, STp->read_error_frame);
1259 }
1260 STp->read_count++;
1261
1262#if DEBUG
1263 if (debugging || STps->eof)
1264 printk(OSST_DEB_MSG
1265 "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1266 name, frame_seq_number, STp->frame_seq_number, STps->eof);
1267#endif
1268 STp->fast_open = 0;
1269 STp->read_error_frame = 0;
1270 return (STps->eof);
1271}
1272
1273static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1274{
1275 struct st_partstat * STps = &(STp->ps[STp->partition]);
1276 char * name = tape_name(STp);
1277 int retries = 0;
1278 int frame_seq_estimate, ppos_estimate, move;
1279
1280 if (logical_blk_num < 0) logical_blk_num = 0;
1281#if DEBUG
1282 printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1283 name, logical_blk_num, STp->logical_blk_num,
1284 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1285 STp->block_size<1024?'b':'k');
1286#endif
1287 /* Do we know where we are? */
1288 if (STps->drv_block >= 0) {
1289 move = logical_blk_num - STp->logical_blk_num;
1290 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1291 move /= (OS_DATA_SIZE / STp->block_size);
1292 frame_seq_estimate = STp->frame_seq_number + move;
1293 } else
1294 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1295
1296 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1297 else ppos_estimate = frame_seq_estimate + 20;
1298 while (++retries < 10) {
1299 if (ppos_estimate > STp->eod_frame_ppos-2) {
1300 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1301 ppos_estimate = STp->eod_frame_ppos - 2;
1302 }
1303 if (frame_seq_estimate < 0) {
1304 frame_seq_estimate = 0;
1305 ppos_estimate = 10;
1306 }
1307 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1308 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1309 /* we've located the estimated frame, now does it have our block? */
1310 if (logical_blk_num < STp->logical_blk_num ||
1311 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1312 if (STps->eof == ST_FM_HIT)
1313 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1314 else {
1315 move = logical_blk_num - STp->logical_blk_num;
1316 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1317 move /= (OS_DATA_SIZE / STp->block_size);
1318 }
1319 if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1320#if DEBUG
1321 printk(OSST_DEB_MSG
1322 "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1323 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1324 STp->logical_blk_num, logical_blk_num, move);
1325#endif
1326 frame_seq_estimate += move;
1327 ppos_estimate += move;
1328 continue;
1329 } else {
1330 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1331 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1332 STp->logical_blk_num = logical_blk_num;
1333#if DEBUG
1334 printk(OSST_DEB_MSG
1335 "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1336 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1337 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1338 STp->block_size);
1339#endif
1340 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1341 if (STps->eof == ST_FM_HIT) {
1342 STps->drv_file++;
1343 STps->drv_block = 0;
1344 } else {
1345 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1346 STp->logical_blk_num -
1347 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1348 -1;
1349 }
1350 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1351 return 0;
1352 }
1353 }
1354 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1355 goto error;
1356 /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1357#if DEBUG
1358 printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1359 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1360 STp->logical_blk_num, logical_blk_num);
1361#endif
1362 if (frame_seq_estimate != STp->frame_seq_number)
1363 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1364 else
1365 break;
1366 }
1367error:
1368 printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1369 name, logical_blk_num, STp->logical_blk_num, retries);
1370 return (-EIO);
1371}
1372
1373/* The values below are based on the OnStream frame payload size of 32K == 2**15,
1374 * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1375 * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1376 * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1377 */
1378#define OSST_FRAME_SHIFT 6
1379#define OSST_SECTOR_SHIFT 9
1380#define OSST_SECTOR_MASK 0x03F
1381
1382static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1383{
1384 int sector;
1385#if DEBUG
1386 char * name = tape_name(STp);
1387
1388 printk(OSST_DEB_MSG
1389 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1390 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1391 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1392 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1393 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1394 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1395#endif
1396 /* do we know where we are inside a file? */
1397 if (STp->ps[STp->partition].drv_block >= 0) {
1398 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1399 STp->first_frame_position) << OSST_FRAME_SHIFT;
1400 if (STp->ps[STp->partition].rw == ST_WRITING)
1401 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1402 else
1403 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1404 } else {
1405 sector = osst_get_frame_position(STp, aSRpnt);
1406 if (sector > 0)
1407 sector <<= OSST_FRAME_SHIFT;
1408 }
1409 return sector;
1410}
1411
1412static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1413{
1414 struct st_partstat * STps = &(STp->ps[STp->partition]);
1415 int frame = sector >> OSST_FRAME_SHIFT,
1416 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1417 r;
1418#if DEBUG
1419 char * name = tape_name(STp);
1420
1421 printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1422 name, sector, frame, offset);
1423#endif
1424 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1425
1426 if (frame <= STp->first_data_ppos) {
1427 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1428 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1429 }
1430 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1431 if (r < 0) return r;
1432
1433 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1434 if (r < 0) return r;
1435
1436 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1437
1438 if (offset) {
1439 STp->logical_blk_num += offset / STp->block_size;
1440 STp->buffer->read_pointer = offset;
1441 STp->buffer->buffer_bytes -= offset;
1442 } else {
1443 STp->frame_seq_number++;
1444 STp->frame_in_buffer = 0;
1445 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1446 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1447 }
1448 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1449 if (STps->eof == ST_FM_HIT) {
1450 STps->drv_file++;
1451 STps->drv_block = 0;
1452 } else {
1453 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1454 STp->logical_blk_num -
1455 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1456 -1;
1457 }
1458 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1459#if DEBUG
1460 printk(OSST_DEB_MSG
1461 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1462 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1463 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1464#endif
1465 return 0;
1466}
1467
1468/*
1469 * Read back the drive's internal buffer contents, as a part
1470 * of the write error recovery mechanism for old OnStream
1471 * firmware revisions.
1472 * Precondition for this function to work: all frames in the
1473 * drive's buffer must be of one type (DATA, MARK or EOD)!
1474 */
1475static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1476 unsigned int frame, unsigned int skip, int pending)
1477{
1478 struct osst_request * SRpnt = * aSRpnt;
1479 unsigned char * buffer, * p;
1480 unsigned char cmd[MAX_COMMAND_SIZE];
1481 int flag, new_frame, i;
1482 int nframes = STp->cur_frames;
1483 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1484 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1485 - (nframes + pending - 1);
1486 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1487 - (nframes + pending - 1) * blks_per_frame;
1488 char * name = tape_name(STp);
1489 unsigned long startwait = jiffies;
1490#if DEBUG
1491 int dbg = debugging;
1492#endif
1493
1494 if ((buffer = vmalloc(array_size((nframes + 1), OS_DATA_SIZE))) == NULL)
1495 return (-EIO);
1496
1497 printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1498 name, nframes, pending?" and one that was pending":"");
1499
1500 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1501#if DEBUG
1502 if (pending && debugging)
1503 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1504 name, frame_seq_number + nframes,
1505 logical_blk_num + nframes * blks_per_frame,
1506 p[0], p[1], p[2], p[3]);
1507#endif
1508 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1509
1510 memset(cmd, 0, MAX_COMMAND_SIZE);
1511 cmd[0] = 0x3C; /* Buffer Read */
1512 cmd[1] = 6; /* Retrieve Faulty Block */
1513 cmd[7] = 32768 >> 8;
1514 cmd[8] = 32768 & 0xff;
1515
1516 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1517 STp->timeout, MAX_RETRIES, 1);
1518
1519 if ((STp->buffer)->syscall_result || !SRpnt) {
1520 printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1521 vfree(buffer);
1522 *aSRpnt = SRpnt;
1523 return (-EIO);
1524 }
1525 osst_copy_from_buffer(STp->buffer, p);
1526#if DEBUG
1527 if (debugging)
1528 printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1529 name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1530#endif
1531 }
1532 *aSRpnt = SRpnt;
1533 osst_get_frame_position(STp, aSRpnt);
1534
1535#if DEBUG
1536 printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1537#endif
1538 /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1539 /* In the header we don't actually re-write the frames that fail, just the ones after them */
1540
1541 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1542
1543 if (flag) {
1544 if (STp->write_type == OS_WRITE_HEADER) {
1545 i += skip;
1546 p += skip * OS_DATA_SIZE;
1547 }
1548 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1549 new_frame = 3000-i;
1550 else
1551 new_frame += skip;
1552#if DEBUG
1553 printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1554 name, new_frame+i, frame_seq_number+i);
1555#endif
1556 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1557 osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1558 osst_get_frame_position(STp, aSRpnt);
1559 SRpnt = * aSRpnt;
1560
1561 if (new_frame > frame + 1000) {
1562 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1563 vfree(buffer);
1564 return (-EIO);
1565 }
1566 if ( i >= nframes + pending ) break;
1567 flag = 0;
1568 }
1569 osst_copy_to_buffer(STp->buffer, p);
1570 /*
1571 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1572 */
1573 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1574 logical_blk_num + i*blks_per_frame,
1575 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1576 memset(cmd, 0, MAX_COMMAND_SIZE);
1577 cmd[0] = WRITE_6;
1578 cmd[1] = 1;
1579 cmd[4] = 1;
1580
1581#if DEBUG
1582 if (debugging)
1583 printk(OSST_DEB_MSG
1584 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1585 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1586 p[0], p[1], p[2], p[3]);
1587#endif
1588 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1589 STp->timeout, MAX_RETRIES, 1);
1590
1591 if (STp->buffer->syscall_result)
1592 flag = 1;
1593 else {
1594 p += OS_DATA_SIZE; i++;
1595
1596 /* if we just sent the last frame, wait till all successfully written */
1597 if ( i == nframes + pending ) {
1598#if DEBUG
1599 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1600#endif
1601 memset(cmd, 0, MAX_COMMAND_SIZE);
1602 cmd[0] = WRITE_FILEMARKS;
1603 cmd[1] = 1;
1604 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1605 STp->timeout, MAX_RETRIES, 1);
1606#if DEBUG
1607 if (debugging) {
1608 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1609 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1610 debugging = 0;
1611 }
1612#endif
1613 flag = STp->buffer->syscall_result;
1614 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1615
1616 memset(cmd, 0, MAX_COMMAND_SIZE);
1617 cmd[0] = TEST_UNIT_READY;
1618
1619 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1620 MAX_RETRIES, 1);
1621
1622 if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1623 (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1624 /* in the process of becoming ready */
1625 msleep(100);
1626 continue;
1627 }
1628 if (STp->buffer->syscall_result)
1629 flag = 1;
1630 break;
1631 }
1632#if DEBUG
1633 debugging = dbg;
1634 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1635#endif
1636 }
1637 }
1638 *aSRpnt = SRpnt;
1639 if (flag) {
1640 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1641 SRpnt->sense[12] == 0 &&
1642 SRpnt->sense[13] == 2) {
1643 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1644 vfree(buffer);
1645 return (-EIO); /* hit end of tape = fail */
1646 }
1647 i = ((SRpnt->sense[3] << 24) |
1648 (SRpnt->sense[4] << 16) |
1649 (SRpnt->sense[5] << 8) |
1650 SRpnt->sense[6] ) - new_frame;
1651 p = &buffer[i * OS_DATA_SIZE];
1652#if DEBUG
1653 printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1654#endif
1655 osst_get_frame_position(STp, aSRpnt);
1656#if DEBUG
1657 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1658 name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1659#endif
1660 }
1661 }
1662 if (flag) {
1663 /* error recovery did not successfully complete */
1664 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1665 STp->write_type == OS_WRITE_HEADER?"header":"body");
1666 }
1667 if (!pending)
1668 osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */
1669 vfree(buffer);
1670 return 0;
1671}
1672
1673static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1674 unsigned int frame, unsigned int skip, int pending)
1675{
1676 unsigned char cmd[MAX_COMMAND_SIZE];
1677 struct osst_request * SRpnt;
1678 char * name = tape_name(STp);
1679 int expected = 0;
1680 int attempts = 1000 / skip;
1681 int flag = 1;
1682 unsigned long startwait = jiffies;
1683#if DEBUG
1684 int dbg = debugging;
1685#endif
1686
1687 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1688 if (flag) {
1689#if DEBUG
1690 debugging = dbg;
1691#endif
1692 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1693 frame = 3000-skip;
1694 expected = frame+skip+STp->cur_frames+pending;
1695#if DEBUG
1696 printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1697 name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1698#endif
1699 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1700 flag = 0;
1701 attempts--;
1702 schedule_timeout_interruptible(msecs_to_jiffies(100));
1703 }
1704 if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
1705#if DEBUG
1706 printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1707 name, STp->first_frame_position,
1708 STp->last_frame_position, STp->cur_frames);
1709#endif
1710 frame = STp->last_frame_position;
1711 flag = 1;
1712 continue;
1713 }
1714 if (pending && STp->cur_frames < 50) {
1715
1716 memset(cmd, 0, MAX_COMMAND_SIZE);
1717 cmd[0] = WRITE_6;
1718 cmd[1] = 1;
1719 cmd[4] = 1;
1720#if DEBUG
1721 printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1722 name, STp->frame_seq_number-1, STp->first_frame_position);
1723#endif
1724 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1725 STp->timeout, MAX_RETRIES, 1);
1726 *aSRpnt = SRpnt;
1727
1728 if (STp->buffer->syscall_result) { /* additional write error */
1729 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1730 SRpnt->sense[12] == 0 &&
1731 SRpnt->sense[13] == 2) {
1732 printk(KERN_ERR
1733 "%s:E: Volume overflow in write error recovery\n",
1734 name);
1735 break; /* hit end of tape = fail */
1736 }
1737 flag = 1;
1738 }
1739 else
1740 pending = 0;
1741
1742 continue;
1743 }
1744 if (STp->cur_frames == 0) {
1745#if DEBUG
1746 debugging = dbg;
1747 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1748#endif
1749 if (STp->first_frame_position != expected) {
1750 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n",
1751 name, STp->first_frame_position, expected);
1752 return (-EIO);
1753 }
1754 return 0;
1755 }
1756#if DEBUG
1757 if (debugging) {
1758 printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1759 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1760 debugging = 0;
1761 }
1762#endif
1763 schedule_timeout_interruptible(msecs_to_jiffies(100));
1764 }
1765 printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1766#if DEBUG
1767 debugging = dbg;
1768#endif
1769 return (-EIO);
1770}
1771
1772/*
1773 * Error recovery algorithm for the OnStream tape.
1774 */
1775
1776static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1777{
1778 struct osst_request * SRpnt = * aSRpnt;
1779 struct st_partstat * STps = & STp->ps[STp->partition];
1780 char * name = tape_name(STp);
1781 int retval = 0;
1782 int rw_state;
1783 unsigned int frame, skip;
1784
1785 rw_state = STps->rw;
1786
1787 if ((SRpnt->sense[ 2] & 0x0f) != 3
1788 || SRpnt->sense[12] != 12
1789 || SRpnt->sense[13] != 0) {
1790#if DEBUG
1791 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1792 SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1793#endif
1794 return (-EIO);
1795 }
1796 frame = (SRpnt->sense[3] << 24) |
1797 (SRpnt->sense[4] << 16) |
1798 (SRpnt->sense[5] << 8) |
1799 SRpnt->sense[6];
1800 skip = SRpnt->sense[9];
1801
1802#if DEBUG
1803 printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1804#endif
1805 osst_get_frame_position(STp, aSRpnt);
1806#if DEBUG
1807 printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1808 name, STp->first_frame_position, STp->last_frame_position);
1809#endif
1810 switch (STp->write_type) {
1811 case OS_WRITE_DATA:
1812 case OS_WRITE_EOD:
1813 case OS_WRITE_NEW_MARK:
1814 printk(KERN_WARNING
1815 "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1816 name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1817 if (STp->os_fw_rev >= 10600)
1818 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1819 else
1820 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1821 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1822 retval?"E" :"I",
1823 retval?"" :"Don't worry, ",
1824 retval?" not ":" ");
1825 break;
1826 case OS_WRITE_LAST_MARK:
1827 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1828 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1829 retval = -EIO;
1830 break;
1831 case OS_WRITE_HEADER:
1832 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1833 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1834 break;
1835 default:
1836 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1837 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1838 }
1839 osst_get_frame_position(STp, aSRpnt);
1840#if DEBUG
1841 printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1842 name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1843 printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1844#endif
1845 if (retval == 0) {
1846 STp->recover_count++;
1847 STp->recover_erreg++;
1848 } else
1849 STp->abort_count++;
1850
1851 STps->rw = rw_state;
1852 return retval;
1853}
1854
1855static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1856 int mt_op, int mt_count)
1857{
1858 char * name = tape_name(STp);
1859 int cnt;
1860 int last_mark_ppos = -1;
1861
1862#if DEBUG
1863 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1864#endif
1865 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1866#if DEBUG
1867 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1868#endif
1869 return -EIO;
1870 }
1871 if (STp->linux_media_version >= 4) {
1872 /*
1873 * direct lookup in header filemark list
1874 */
1875 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1876 if (STp->header_ok &&
1877 STp->header_cache != NULL &&
1878 (cnt - mt_count) >= 0 &&
1879 (cnt - mt_count) < OS_FM_TAB_MAX &&
1880 (cnt - mt_count) < STp->filemark_cnt &&
1881 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1882
1883 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1884#if DEBUG
1885 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1886 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1887 STp->header_cache == NULL?"lack of header cache":"count out of range");
1888 else
1889 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1890 name, cnt,
1891 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1892 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1893 STp->buffer->aux->last_mark_ppos))?"match":"error",
1894 mt_count, last_mark_ppos);
1895#endif
1896 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1897 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1898 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1899#if DEBUG
1900 printk(OSST_DEB_MSG
1901 "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1902#endif
1903 return (-EIO);
1904 }
1905 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1906 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1907 name, last_mark_ppos);
1908 return (-EIO);
1909 }
1910 goto found;
1911 }
1912#if DEBUG
1913 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1914#endif
1915 }
1916 cnt = 0;
1917 while (cnt != mt_count) {
1918 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1919 if (last_mark_ppos == -1)
1920 return (-EIO);
1921#if DEBUG
1922 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1923#endif
1924 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1925 cnt++;
1926 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1927#if DEBUG
1928 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1929#endif
1930 return (-EIO);
1931 }
1932 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1933 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1934 name, last_mark_ppos);
1935 return (-EIO);
1936 }
1937 }
1938found:
1939 if (mt_op == MTBSFM) {
1940 STp->frame_seq_number++;
1941 STp->frame_in_buffer = 0;
1942 STp->buffer->buffer_bytes = 0;
1943 STp->buffer->read_pointer = 0;
1944 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1945 }
1946 return 0;
1947}
1948
1949/*
1950 * ADRL 1.1 compatible "slow" space filemarks fwd version
1951 *
1952 * Just scans for the filemark sequentially.
1953 */
1954static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1955 int mt_op, int mt_count)
1956{
1957 int cnt = 0;
1958#if DEBUG
1959 char * name = tape_name(STp);
1960
1961 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1962#endif
1963 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1964#if DEBUG
1965 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1966#endif
1967 return (-EIO);
1968 }
1969 while (1) {
1970 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1971#if DEBUG
1972 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1973#endif
1974 return (-EIO);
1975 }
1976 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1977 cnt++;
1978 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1979#if DEBUG
1980 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1981#endif
1982 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1983#if DEBUG
1984 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1985 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1986#endif
1987 STp->eod_frame_ppos = STp->first_frame_position-1;
1988 }
1989 return (-EIO);
1990 }
1991 if (cnt == mt_count)
1992 break;
1993 STp->frame_in_buffer = 0;
1994 }
1995 if (mt_op == MTFSF) {
1996 STp->frame_seq_number++;
1997 STp->frame_in_buffer = 0;
1998 STp->buffer->buffer_bytes = 0;
1999 STp->buffer->read_pointer = 0;
2000 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2001 }
2002 return 0;
2003}
2004
2005/*
2006 * Fast linux specific version of OnStream FSF
2007 */
2008static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2009 int mt_op, int mt_count)
2010{
2011 char * name = tape_name(STp);
2012 int cnt = 0,
2013 next_mark_ppos = -1;
2014
2015#if DEBUG
2016 printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2017#endif
2018 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2019#if DEBUG
2020 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2021#endif
2022 return (-EIO);
2023 }
2024
2025 if (STp->linux_media_version >= 4) {
2026 /*
2027 * direct lookup in header filemark list
2028 */
2029 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2030 if (STp->header_ok &&
2031 STp->header_cache != NULL &&
2032 (cnt + mt_count) < OS_FM_TAB_MAX &&
2033 (cnt + mt_count) < STp->filemark_cnt &&
2034 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2035 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2036
2037 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2038#if DEBUG
2039 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2040 printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2041 STp->header_cache == NULL?"lack of header cache":"count out of range");
2042 else
2043 printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2044 name, cnt,
2045 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2046 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2047 STp->buffer->aux->last_mark_ppos))?"match":"error",
2048 mt_count, next_mark_ppos);
2049#endif
2050 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2051#if DEBUG
2052 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2053#endif
2054 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2055 } else {
2056 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2057 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2058#if DEBUG
2059 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2060 name);
2061#endif
2062 return (-EIO);
2063 }
2064 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2065 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2066 name, next_mark_ppos);
2067 return (-EIO);
2068 }
2069 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2070 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2071 name, cnt+mt_count, next_mark_ppos,
2072 ntohl(STp->buffer->aux->filemark_cnt));
2073 return (-EIO);
2074 }
2075 }
2076 } else {
2077 /*
2078 * Find nearest (usually previous) marker, then jump from marker to marker
2079 */
2080 while (1) {
2081 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2082 break;
2083 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2084#if DEBUG
2085 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2086#endif
2087 return (-EIO);
2088 }
2089 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2090 if (STp->first_mark_ppos == -1) {
2091#if DEBUG
2092 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2093#endif
2094 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2095 }
2096 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2097 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2098#if DEBUG
2099 printk(OSST_DEB_MSG
2100 "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2101 name);
2102#endif
2103 return (-EIO);
2104 }
2105 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2106 printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2107 name, STp->first_mark_ppos);
2108 return (-EIO);
2109 }
2110 } else {
2111 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2112 return (-EIO);
2113 mt_count++;
2114 }
2115 }
2116 cnt++;
2117 while (cnt != mt_count) {
2118 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2119 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2120#if DEBUG
2121 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2122#endif
2123 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2124 }
2125#if DEBUG
2126 else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2127#endif
2128 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2129 cnt++;
2130 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2131#if DEBUG
2132 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2133 name);
2134#endif
2135 return (-EIO);
2136 }
2137 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2138 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2139 name, next_mark_ppos);
2140 return (-EIO);
2141 }
2142 }
2143 }
2144 if (mt_op == MTFSF) {
2145 STp->frame_seq_number++;
2146 STp->frame_in_buffer = 0;
2147 STp->buffer->buffer_bytes = 0;
2148 STp->buffer->read_pointer = 0;
2149 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2150 }
2151 return 0;
2152}
2153
2154/*
2155 * In debug mode, we want to see as many errors as possible
2156 * to test the error recovery mechanism.
2157 */
2158#if DEBUG
2159static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2160{
2161 unsigned char cmd[MAX_COMMAND_SIZE];
2162 struct osst_request * SRpnt = * aSRpnt;
2163 char * name = tape_name(STp);
2164
2165 memset(cmd, 0, MAX_COMMAND_SIZE);
2166 cmd[0] = MODE_SELECT;
2167 cmd[1] = 0x10;
2168 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2169
2170 (STp->buffer)->b_data[0] = cmd[4] - 1;
2171 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
2172 (STp->buffer)->b_data[2] = 0; /* Reserved */
2173 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
2174 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2175 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2176 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2177 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2178
2179 if (debugging)
2180 printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2181
2182 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2183 *aSRpnt = SRpnt;
2184
2185 if ((STp->buffer)->syscall_result)
2186 printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2187}
2188#endif
2189
2190
2191static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2192{
2193 int result;
2194 int this_mark_ppos = STp->first_frame_position;
2195 int this_mark_lbn = STp->logical_blk_num;
2196#if DEBUG
2197 char * name = tape_name(STp);
2198#endif
2199
2200 if (STp->raw) return 0;
2201
2202 STp->write_type = OS_WRITE_NEW_MARK;
2203#if DEBUG
2204 printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
2205 name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2206#endif
2207 STp->dirty = 1;
2208 result = osst_flush_write_buffer(STp, aSRpnt);
2209 result |= osst_flush_drive_buffer(STp, aSRpnt);
2210 STp->last_mark_ppos = this_mark_ppos;
2211 STp->last_mark_lbn = this_mark_lbn;
2212 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2213 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2214 if (STp->filemark_cnt++ == 0)
2215 STp->first_mark_ppos = this_mark_ppos;
2216 return result;
2217}
2218
2219static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2220{
2221 int result;
2222#if DEBUG
2223 char * name = tape_name(STp);
2224#endif
2225
2226 if (STp->raw) return 0;
2227
2228 STp->write_type = OS_WRITE_EOD;
2229 STp->eod_frame_ppos = STp->first_frame_position;
2230#if DEBUG
2231 printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2232 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2233#endif
2234 STp->dirty = 1;
2235
2236 result = osst_flush_write_buffer(STp, aSRpnt);
2237 result |= osst_flush_drive_buffer(STp, aSRpnt);
2238 STp->eod_frame_lfa = --(STp->frame_seq_number);
2239 return result;
2240}
2241
2242static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2243{
2244 char * name = tape_name(STp);
2245
2246#if DEBUG
2247 printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2248#endif
2249 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2250 osst_set_frame_position(STp, aSRpnt, where, 0);
2251 STp->write_type = OS_WRITE_FILLER;
2252 while (count--) {
2253 memcpy(STp->buffer->b_data, "Filler", 6);
2254 STp->buffer->buffer_bytes = 6;
2255 STp->dirty = 1;
2256 if (osst_flush_write_buffer(STp, aSRpnt)) {
2257 printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2258 return (-EIO);
2259 }
2260 }
2261#if DEBUG
2262 printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2263#endif
2264 return osst_flush_drive_buffer(STp, aSRpnt);
2265}
2266
2267static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2268{
2269 char * name = tape_name(STp);
2270 int result;
2271
2272#if DEBUG
2273 printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2274#endif
2275 osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2276 osst_set_frame_position(STp, aSRpnt, where, 0);
2277 STp->write_type = OS_WRITE_HEADER;
2278 while (count--) {
2279 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2280 STp->buffer->buffer_bytes = sizeof(os_header_t);
2281 STp->dirty = 1;
2282 if (osst_flush_write_buffer(STp, aSRpnt)) {
2283 printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2284 return (-EIO);
2285 }
2286 }
2287 result = osst_flush_drive_buffer(STp, aSRpnt);
2288#if DEBUG
2289 printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2290#endif
2291 return result;
2292}
2293
2294static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2295{
2296 os_header_t * header;
2297 int result;
2298 char * name = tape_name(STp);
2299
2300#if DEBUG
2301 printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2302#endif
2303 if (STp->raw) return 0;
2304
2305 if (STp->header_cache == NULL) {
2306 if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2307 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2308 return (-ENOMEM);
2309 }
2310 memset(STp->header_cache, 0, sizeof(os_header_t));
2311#if DEBUG
2312 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2313#endif
2314 }
2315 if (STp->header_ok) STp->update_frame_cntr++;
2316 else STp->update_frame_cntr = 0;
2317
2318 header = STp->header_cache;
2319 strcpy(header->ident_str, "ADR_SEQ");
2320 header->major_rev = 1;
2321 header->minor_rev = 4;
2322 header->ext_trk_tb_off = htons(17192);
2323 header->pt_par_num = 1;
2324 header->partition[0].partition_num = OS_DATA_PARTITION;
2325 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2326 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2327 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2328 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2329 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2330 header->cfg_col_width = htonl(20);
2331 header->dat_col_width = htonl(1500);
2332 header->qfa_col_width = htonl(0);
2333 header->ext_track_tb.nr_stream_part = 1;
2334 header->ext_track_tb.et_ent_sz = 32;
2335 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2336 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2337 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2338 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2339 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2340 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2341 header->dat_fm_tab.fm_part_num = 0;
2342 header->dat_fm_tab.fm_tab_ent_sz = 4;
2343 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2344 STp->filemark_cnt:OS_FM_TAB_MAX);
2345
2346 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2347 if (STp->update_frame_cntr == 0)
2348 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2349 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2350
2351 if (locate_eod) {
2352#if DEBUG
2353 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2354#endif
2355 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2356 }
2357 if (result)
2358 printk(KERN_ERR "%s:E: Write header failed\n", name);
2359 else {
2360 memcpy(STp->application_sig, "LIN4", 4);
2361 STp->linux_media = 1;
2362 STp->linux_media_version = 4;
2363 STp->header_ok = 1;
2364 }
2365 return result;
2366}
2367
2368static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2369{
2370 if (STp->header_cache != NULL)
2371 memset(STp->header_cache, 0, sizeof(os_header_t));
2372
2373 STp->logical_blk_num = STp->frame_seq_number = 0;
2374 STp->frame_in_buffer = 0;
2375 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2376 STp->filemark_cnt = 0;
2377 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2378 return osst_write_header(STp, aSRpnt, 1);
2379}
2380
2381static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2382{
2383 char * name = tape_name(STp);
2384 os_header_t * header;
2385 os_aux_t * aux;
2386 char id_string[8];
2387 int linux_media_version,
2388 update_frame_cntr;
2389
2390 if (STp->raw)
2391 return 1;
2392
2393 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2394 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2395 printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2396 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2397 if (osst_initiate_read (STp, aSRpnt)) {
2398 printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2399 return 0;
2400 }
2401 }
2402 if (osst_read_frame(STp, aSRpnt, 180)) {
2403#if DEBUG
2404 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2405#endif
2406 return 0;
2407 }
2408 header = (os_header_t *) STp->buffer->b_data; /* warning: only first segment addressable */
2409 aux = STp->buffer->aux;
2410 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2411#if DEBUG
2412 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2413#endif
2414 return 0;
2415 }
2416 if (ntohl(aux->frame_seq_num) != 0 ||
2417 ntohl(aux->logical_blk_num) != 0 ||
2418 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2419 ntohl(aux->partition.first_frame_ppos) != 0 ||
2420 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2421#if DEBUG
2422 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2423 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2424 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2425 ntohl(aux->partition.last_frame_ppos));
2426#endif
2427 return 0;
2428 }
2429 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2430 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2431 strlcpy(id_string, header->ident_str, 8);
2432#if DEBUG
2433 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2434#endif
2435 return 0;
2436 }
2437 update_frame_cntr = ntohl(aux->update_frame_cntr);
2438 if (update_frame_cntr < STp->update_frame_cntr) {
2439#if DEBUG
2440 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2441 name, ppos, update_frame_cntr, STp->update_frame_cntr);
2442#endif
2443 return 0;
2444 }
2445 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2446#if DEBUG
2447 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n",
2448 name, (header->major_rev != 1 || header->minor_rev < 2 ||
2449 header->minor_rev > 4 )? "Invalid" : "Warning:",
2450 header->major_rev, header->minor_rev);
2451#endif
2452 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2453 return 0;
2454 }
2455#if DEBUG
2456 if (header->pt_par_num != 1)
2457 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n",
2458 name, header->pt_par_num);
2459#endif
2460 memcpy(id_string, aux->application_sig, 4);
2461 id_string[4] = 0;
2462 if (memcmp(id_string, "LIN", 3) == 0) {
2463 STp->linux_media = 1;
2464 linux_media_version = id_string[3] - '0';
2465 if (linux_media_version != 4)
2466 printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2467 name, linux_media_version);
2468 } else {
2469 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2470 return 0;
2471 }
2472 if (linux_media_version < STp->linux_media_version) {
2473#if DEBUG
2474 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2475 name, ppos, linux_media_version);
2476#endif
2477 return 0;
2478 }
2479 if (linux_media_version > STp->linux_media_version) {
2480#if DEBUG
2481 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2482 name, ppos, linux_media_version);
2483#endif
2484 memcpy(STp->application_sig, id_string, 5);
2485 STp->linux_media_version = linux_media_version;
2486 STp->update_frame_cntr = -1;
2487 }
2488 if (update_frame_cntr > STp->update_frame_cntr) {
2489#if DEBUG
2490 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2491 name, ppos, update_frame_cntr);
2492#endif
2493 if (STp->header_cache == NULL) {
2494 if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
2495 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2496 return 0;
2497 }
2498#if DEBUG
2499 printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2500#endif
2501 }
2502 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2503 header = STp->header_cache; /* further accesses from cached (full) copy */
2504
2505 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2506 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2507 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2508 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2509 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2510 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2511 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2512 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2513 STp->update_frame_cntr = update_frame_cntr;
2514#if DEBUG
2515 printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2516 name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2517 printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2518 STp->first_data_ppos,
2519 ntohl(header->partition[0].last_frame_ppos),
2520 ntohl(header->partition[0].eod_frame_ppos));
2521 printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2522 name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2523#endif
2524 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2525#if DEBUG
2526 printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2527#endif
2528 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2529 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2530 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2531 }
2532 if (header->minor_rev == 4 &&
2533 (header->ext_trk_tb_off != htons(17192) ||
2534 header->partition[0].partition_num != OS_DATA_PARTITION ||
2535 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2536 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2537 header->cfg_col_width != htonl(20) ||
2538 header->dat_col_width != htonl(1500) ||
2539 header->qfa_col_width != htonl(0) ||
2540 header->ext_track_tb.nr_stream_part != 1 ||
2541 header->ext_track_tb.et_ent_sz != 32 ||
2542 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2543 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2544 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2545 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2546 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2547 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2548 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2549 header->dat_fm_tab.fm_tab_ent_cnt !=
2550 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2551 printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2552
2553 }
2554
2555 return 1;
2556}
2557
2558static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2559{
2560 int position, ppos;
2561 int first, last;
2562 int valid = 0;
2563 char * name = tape_name(STp);
2564
2565 position = osst_get_frame_position(STp, aSRpnt);
2566
2567 if (STp->raw) {
2568 STp->header_ok = STp->linux_media = 1;
2569 STp->linux_media_version = 0;
2570 return 1;
2571 }
2572 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2573 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2574 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2575 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2576#if DEBUG
2577 printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2578#endif
2579
2580 /* optimization for speed - if we are positioned at ppos 10, read second group first */
2581 /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2582
2583 first = position==10?0xbae: 5;
2584 last = position==10?0xbb3:10;
2585
2586 for (ppos = first; ppos < last; ppos++)
2587 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2588 valid = 1;
2589
2590 first = position==10? 5:0xbae;
2591 last = position==10?10:0xbb3;
2592
2593 for (ppos = first; ppos < last; ppos++)
2594 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2595 valid = 1;
2596
2597 if (!valid) {
2598 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2599 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2600 osst_set_frame_position(STp, aSRpnt, 10, 0);
2601 return 0;
2602 }
2603 if (position <= STp->first_data_ppos) {
2604 position = STp->first_data_ppos;
2605 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2606 }
2607 osst_set_frame_position(STp, aSRpnt, position, 0);
2608 STp->header_ok = 1;
2609
2610 return 1;
2611}
2612
2613static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2614{
2615 int frame_position = STp->first_frame_position;
2616 int frame_seq_numbr = STp->frame_seq_number;
2617 int logical_blk_num = STp->logical_blk_num;
2618 int halfway_frame = STp->frame_in_buffer;
2619 int read_pointer = STp->buffer->read_pointer;
2620 int prev_mark_ppos = -1;
2621 int actual_mark_ppos, i, n;
2622#if DEBUG
2623 char * name = tape_name(STp);
2624
2625 printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2626#endif
2627 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2628 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2629#if DEBUG
2630 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2631#endif
2632 return (-EIO);
2633 }
2634 if (STp->linux_media_version >= 4) {
2635 for (i=0; i<STp->filemark_cnt; i++)
2636 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2637 prev_mark_ppos = n;
2638 } else
2639 prev_mark_ppos = frame_position - 1; /* usually - we don't really know */
2640 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2641 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2642 if (frame_position != STp->first_frame_position ||
2643 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2644 prev_mark_ppos != actual_mark_ppos ) {
2645#if DEBUG
2646 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2647 STp->first_frame_position, frame_position,
2648 STp->frame_seq_number + (halfway_frame?0:1),
2649 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2650#endif
2651 return (-EIO);
2652 }
2653 if (halfway_frame) {
2654 /* prepare buffer for append and rewrite on top of original */
2655 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2656 STp->buffer->buffer_bytes = read_pointer;
2657 STp->ps[STp->partition].rw = ST_WRITING;
2658 STp->dirty = 1;
2659 }
2660 STp->frame_in_buffer = halfway_frame;
2661 STp->frame_seq_number = frame_seq_numbr;
2662 STp->logical_blk_num = logical_blk_num;
2663 return 0;
2664}
2665
2666/* Acc. to OnStream, the vers. numbering is the following:
2667 * X.XX for released versions (X=digit),
2668 * XXXY for unreleased versions (Y=letter)
2669 * Ordering 1.05 < 106A < 106B < ... < 106a < ... < 1.06
2670 * This fn makes monoton numbers out of this scheme ...
2671 */
2672static unsigned int osst_parse_firmware_rev (const char * str)
2673{
2674 if (str[1] == '.') {
2675 return (str[0]-'0')*10000
2676 +(str[2]-'0')*1000
2677 +(str[3]-'0')*100;
2678 } else {
2679 return (str[0]-'0')*10000
2680 +(str[1]-'0')*1000
2681 +(str[2]-'0')*100 - 100
2682 +(str[3]-'@');
2683 }
2684}
2685
2686/*
2687 * Configure the OnStream SCII tape drive for default operation
2688 */
2689static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2690{
2691 unsigned char cmd[MAX_COMMAND_SIZE];
2692 char * name = tape_name(STp);
2693 struct osst_request * SRpnt = * aSRpnt;
2694 osst_mode_parameter_header_t * header;
2695 osst_block_size_page_t * bs;
2696 osst_capabilities_page_t * cp;
2697 osst_tape_paramtr_page_t * prm;
2698 int drive_buffer_size;
2699
2700 if (STp->ready != ST_READY) {
2701#if DEBUG
2702 printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2703#endif
2704 return (-EIO);
2705 }
2706
2707 if (STp->os_fw_rev < 10600) {
2708 printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2709 printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2710 }
2711
2712 /*
2713 * Configure 32.5KB (data+aux) frame size.
2714 * Get the current frame size from the block size mode page
2715 */
2716 memset(cmd, 0, MAX_COMMAND_SIZE);
2717 cmd[0] = MODE_SENSE;
2718 cmd[1] = 8;
2719 cmd[2] = BLOCK_SIZE_PAGE;
2720 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2721
2722 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2723 if (SRpnt == NULL) {
2724#if DEBUG
2725 printk(OSST_DEB_MSG "osst :D: Busy\n");
2726#endif
2727 return (-EBUSY);
2728 }
2729 *aSRpnt = SRpnt;
2730 if ((STp->buffer)->syscall_result != 0) {
2731 printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2732 return (-EIO);
2733 }
2734
2735 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2736 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2737
2738#if DEBUG
2739 printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n", name, bs->play32 ? "Yes" : "No");
2740 printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5 ? "Yes" : "No");
2741 printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n", name, bs->record32 ? "Yes" : "No");
2742 printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n", name, bs->record32_5 ? "Yes" : "No");
2743#endif
2744
2745 /*
2746 * Configure default auto columns mode, 32.5KB transfer mode
2747 */
2748 bs->one = 1;
2749 bs->play32 = 0;
2750 bs->play32_5 = 1;
2751 bs->record32 = 0;
2752 bs->record32_5 = 1;
2753
2754 memset(cmd, 0, MAX_COMMAND_SIZE);
2755 cmd[0] = MODE_SELECT;
2756 cmd[1] = 0x10;
2757 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2758
2759 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2760 *aSRpnt = SRpnt;
2761 if ((STp->buffer)->syscall_result != 0) {
2762 printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2763 return (-EIO);
2764 }
2765
2766#if DEBUG
2767 printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2768 /*
2769 * In debug mode, we want to see as many errors as possible
2770 * to test the error recovery mechanism.
2771 */
2772 osst_set_retries(STp, aSRpnt, 0);
2773 SRpnt = * aSRpnt;
2774#endif
2775
2776 /*
2777 * Set vendor name to 'LIN4' for "Linux support version 4".
2778 */
2779
2780 memset(cmd, 0, MAX_COMMAND_SIZE);
2781 cmd[0] = MODE_SELECT;
2782 cmd[1] = 0x10;
2783 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2784
2785 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2786 header->medium_type = 0; /* Medium Type - ignoring */
2787 header->dsp = 0; /* Reserved */
2788 header->bdl = 0; /* Block Descriptor Length */
2789
2790 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2791 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2792 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2793 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2794 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2795 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2796 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2797 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2798
2799 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2800 *aSRpnt = SRpnt;
2801
2802 if ((STp->buffer)->syscall_result != 0) {
2803 printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name,
2804 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2805 return (-EIO);
2806 }
2807
2808 memset(cmd, 0, MAX_COMMAND_SIZE);
2809 cmd[0] = MODE_SENSE;
2810 cmd[1] = 8;
2811 cmd[2] = CAPABILITIES_PAGE;
2812 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2813
2814 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2815 *aSRpnt = SRpnt;
2816
2817 if ((STp->buffer)->syscall_result != 0) {
2818 printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2819 return (-EIO);
2820 }
2821
2822 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2823 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2824 sizeof(osst_mode_parameter_header_t) + header->bdl);
2825
2826 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2827
2828 memset(cmd, 0, MAX_COMMAND_SIZE);
2829 cmd[0] = MODE_SENSE;
2830 cmd[1] = 8;
2831 cmd[2] = TAPE_PARAMTR_PAGE;
2832 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2833
2834 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2835 *aSRpnt = SRpnt;
2836
2837 if ((STp->buffer)->syscall_result != 0) {
2838 printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2839 return (-EIO);
2840 }
2841
2842 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2843 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2844 sizeof(osst_mode_parameter_header_t) + header->bdl);
2845
2846 STp->density = prm->density;
2847 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2848#if DEBUG
2849 printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2850 name, STp->density, STp->capacity / 32, drive_buffer_size);
2851#endif
2852
2853 return 0;
2854
2855}
2856
2857
2858/* Step over EOF if it has been inadvertently crossed (ioctl not used because
2859 it messes up the block number). */
2860static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2861{
2862 int result;
2863 char * name = tape_name(STp);
2864
2865#if DEBUG
2866 if (debugging)
2867 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2868 name, forward ? "forward" : "backward");
2869#endif
2870
2871 if (forward) {
2872 /* assumes that the filemark is already read by the drive, so this is low cost */
2873 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2874 }
2875 else
2876 /* assumes this is only called if we just read the filemark! */
2877 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2878
2879 if (result < 0)
2880 printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2881 name, forward ? "forward" : "backward");
2882
2883 return result;
2884}
2885
2886
2887/* Get the tape position. */
2888
2889static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2890{
2891 unsigned char scmd[MAX_COMMAND_SIZE];
2892 struct osst_request * SRpnt;
2893 int result = 0;
2894 char * name = tape_name(STp);
2895
2896 /* KG: We want to be able to use it for checking Write Buffer availability
2897 * and thus don't want to risk to overwrite anything. Exchange buffers ... */
2898 char mybuf[24];
2899 char * olddata = STp->buffer->b_data;
2900 int oldsize = STp->buffer->buffer_size;
2901
2902 if (STp->ready != ST_READY) return (-EIO);
2903
2904 memset (scmd, 0, MAX_COMMAND_SIZE);
2905 scmd[0] = READ_POSITION;
2906
2907 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2908 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2909 STp->timeout, MAX_RETRIES, 1);
2910 if (!SRpnt) {
2911 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2912 return (-EBUSY);
2913 }
2914 *aSRpnt = SRpnt;
2915
2916 if (STp->buffer->syscall_result)
2917 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL; /* 3: Write Error */
2918
2919 if (result == -EINVAL)
2920 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2921 else {
2922 if (result == -EIO) { /* re-read position - this needs to preserve media errors */
2923 unsigned char mysense[16];
2924 memcpy (mysense, SRpnt->sense, 16);
2925 memset (scmd, 0, MAX_COMMAND_SIZE);
2926 scmd[0] = READ_POSITION;
2927 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2928 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2929 STp->timeout, MAX_RETRIES, 1);
2930#if DEBUG
2931 printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2932 name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2933 SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2934#endif
2935 if (!STp->buffer->syscall_result)
2936 memcpy (SRpnt->sense, mysense, 16);
2937 else
2938 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2939 }
2940 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2941 + ((STp->buffer)->b_data[5] << 16)
2942 + ((STp->buffer)->b_data[6] << 8)
2943 + (STp->buffer)->b_data[7];
2944 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2945 + ((STp->buffer)->b_data[ 9] << 16)
2946 + ((STp->buffer)->b_data[10] << 8)
2947 + (STp->buffer)->b_data[11];
2948 STp->cur_frames = (STp->buffer)->b_data[15];
2949#if DEBUG
2950 if (debugging) {
2951 printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2952 STp->first_frame_position, STp->last_frame_position,
2953 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2954 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2955 STp->cur_frames);
2956 }
2957#endif
2958 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2959#if DEBUG
2960 printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2961 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2962#endif
2963 STp->first_frame_position = STp->last_frame_position;
2964 }
2965 }
2966 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2967
2968 return (result == 0 ? STp->first_frame_position : result);
2969}
2970
2971
2972/* Set the tape block */
2973static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2974{
2975 unsigned char scmd[MAX_COMMAND_SIZE];
2976 struct osst_request * SRpnt;
2977 struct st_partstat * STps;
2978 int result = 0;
2979 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2980 char * name = tape_name(STp);
2981
2982 if (STp->ready != ST_READY) return (-EIO);
2983
2984 STps = &(STp->ps[STp->partition]);
2985
2986 if (ppos < 0 || ppos > STp->capacity) {
2987 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2988 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2989 result = (-EINVAL);
2990 }
2991
2992 do {
2993#if DEBUG
2994 if (debugging)
2995 printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2996#endif
2997 memset (scmd, 0, MAX_COMMAND_SIZE);
2998 scmd[0] = SEEK_10;
2999 scmd[1] = 1;
3000 scmd[3] = (pp >> 24);
3001 scmd[4] = (pp >> 16);
3002 scmd[5] = (pp >> 8);
3003 scmd[6] = pp;
3004 if (skip)
3005 scmd[9] = 0x80;
3006
3007 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
3008 MAX_RETRIES, 1);
3009 if (!SRpnt)
3010 return (-EBUSY);
3011 *aSRpnt = SRpnt;
3012
3013 if ((STp->buffer)->syscall_result != 0) {
3014#if DEBUG
3015 printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3016 name, STp->first_frame_position, pp);
3017#endif
3018 result = (-EIO);
3019 }
3020 if (pp != ppos)
3021 osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3022 } while ((pp != ppos) && (pp = ppos));
3023 STp->first_frame_position = STp->last_frame_position = ppos;
3024 STps->eof = ST_NOEOF;
3025 STps->at_sm = 0;
3026 STps->rw = ST_IDLE;
3027 STp->frame_in_buffer = 0;
3028 return result;
3029}
3030
3031static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3032{
3033 struct st_partstat * STps = &(STp->ps[STp->partition]);
3034 int result = 0;
3035
3036 if (STp->write_type != OS_WRITE_NEW_MARK) {
3037 /* true unless the user wrote the filemark for us */
3038 result = osst_flush_drive_buffer(STp, aSRpnt);
3039 if (result < 0) goto out;
3040 result = osst_write_filemark(STp, aSRpnt);
3041 if (result < 0) goto out;
3042
3043 if (STps->drv_file >= 0)
3044 STps->drv_file++ ;
3045 STps->drv_block = 0;
3046 }
3047 result = osst_write_eod(STp, aSRpnt);
3048 osst_write_header(STp, aSRpnt, leave_at_EOT);
3049
3050 STps->eof = ST_FM;
3051out:
3052 return result;
3053}
3054
3055/* osst versions of st functions - augmented and stripped to suit OnStream only */
3056
3057/* Flush the write buffer (never need to write if variable blocksize). */
3058static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3059{
3060 int offset, transfer, blks = 0;
3061 int result = 0;
3062 unsigned char cmd[MAX_COMMAND_SIZE];
3063 struct osst_request * SRpnt = *aSRpnt;
3064 struct st_partstat * STps;
3065 char * name = tape_name(STp);
3066
3067 if ((STp->buffer)->writing) {
3068 if (SRpnt == (STp->buffer)->last_SRpnt)
3069#if DEBUG
3070 { printk(OSST_DEB_MSG
3071 "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3072#endif
3073 *aSRpnt = SRpnt = NULL;
3074#if DEBUG
3075 } else if (SRpnt)
3076 printk(OSST_DEB_MSG
3077 "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3078#endif
3079 osst_write_behind_check(STp);
3080 if ((STp->buffer)->syscall_result) {
3081#if DEBUG
3082 if (debugging)
3083 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3084 name, (STp->buffer)->midlevel_result);
3085#endif
3086 if ((STp->buffer)->midlevel_result == INT_MAX)
3087 return (-ENOSPC);
3088 return (-EIO);
3089 }
3090 }
3091
3092 result = 0;
3093 if (STp->dirty == 1) {
3094
3095 STp->write_count++;
3096 STps = &(STp->ps[STp->partition]);
3097 STps->rw = ST_WRITING;
3098 offset = STp->buffer->buffer_bytes;
3099 blks = (offset + STp->block_size - 1) / STp->block_size;
3100 transfer = OS_FRAME_SIZE;
3101
3102 if (offset < OS_DATA_SIZE)
3103 osst_zero_buffer_tail(STp->buffer);
3104
3105 if (STp->poll)
3106 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3107 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3108
3109 memset(cmd, 0, MAX_COMMAND_SIZE);
3110 cmd[0] = WRITE_6;
3111 cmd[1] = 1;
3112 cmd[4] = 1;
3113
3114 switch (STp->write_type) {
3115 case OS_WRITE_DATA:
3116#if DEBUG
3117 if (debugging)
3118 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3119 name, blks, STp->frame_seq_number,
3120 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3121#endif
3122 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3123 STp->logical_blk_num - blks, STp->block_size, blks);
3124 break;
3125 case OS_WRITE_EOD:
3126 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3127 STp->logical_blk_num, 0, 0);
3128 break;
3129 case OS_WRITE_NEW_MARK:
3130 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3131 STp->logical_blk_num++, 0, blks=1);
3132 break;
3133 case OS_WRITE_HEADER:
3134 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3135 break;
3136 default: /* probably FILLER */
3137 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3138 }
3139#if DEBUG
3140 if (debugging)
3141 printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
3142 name, offset, transfer, blks);
3143#endif
3144
3145 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3146 STp->timeout, MAX_RETRIES, 1);
3147 *aSRpnt = SRpnt;
3148 if (!SRpnt)
3149 return (-EBUSY);
3150
3151 if ((STp->buffer)->syscall_result != 0) {
3152#if DEBUG
3153 printk(OSST_DEB_MSG
3154 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3155 name, SRpnt->sense[0], SRpnt->sense[2],
3156 SRpnt->sense[12], SRpnt->sense[13]);
3157#endif
3158 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3159 (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3160 (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3161 STp->dirty = 0;
3162 (STp->buffer)->buffer_bytes = 0;
3163 result = (-ENOSPC);
3164 }
3165 else {
3166 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3167 printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3168 result = (-EIO);
3169 }
3170 }
3171 STps->drv_block = (-1); /* FIXME - even if write recovery succeeds? */
3172 }
3173 else {
3174 STp->first_frame_position++;
3175 STp->dirty = 0;
3176 (STp->buffer)->buffer_bytes = 0;
3177 }
3178 }
3179#if DEBUG
3180 printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3181#endif
3182 return result;
3183}
3184
3185
3186/* Flush the tape buffer. The tape will be positioned correctly unless
3187 seek_next is true. */
3188static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3189{
3190 struct st_partstat * STps;
3191 int backspace = 0, result = 0;
3192#if DEBUG
3193 char * name = tape_name(STp);
3194#endif
3195
3196 /*
3197 * If there was a bus reset, block further access
3198 * to this device.
3199 */
3200 if( STp->pos_unknown)
3201 return (-EIO);
3202
3203 if (STp->ready != ST_READY)
3204 return 0;
3205
3206 STps = &(STp->ps[STp->partition]);
3207 if (STps->rw == ST_WRITING || STp->dirty) { /* Writing */
3208 STp->write_type = OS_WRITE_DATA;
3209 return osst_flush_write_buffer(STp, aSRpnt);
3210 }
3211 if (STp->block_size == 0)
3212 return 0;
3213
3214#if DEBUG
3215 printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3216#endif
3217
3218 if (!STp->can_bsr) {
3219 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3220 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
3221 (STp->buffer)->buffer_bytes = 0;
3222 (STp->buffer)->read_pointer = 0;
3223 STp->frame_in_buffer = 0; /* FIXME is this relevant w. OSST? */
3224 }
3225
3226 if (!seek_next) {
3227 if (STps->eof == ST_FM_HIT) {
3228 result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3229 if (!result)
3230 STps->eof = ST_NOEOF;
3231 else {
3232 if (STps->drv_file >= 0)
3233 STps->drv_file++;
3234 STps->drv_block = 0;
3235 }
3236 }
3237 if (!result && backspace > 0) /* TODO -- design and run a test case for this */
3238 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3239 }
3240 else if (STps->eof == ST_FM_HIT) {
3241 if (STps->drv_file >= 0)
3242 STps->drv_file++;
3243 STps->drv_block = 0;
3244 STps->eof = ST_NOEOF;
3245 }
3246
3247 return result;
3248}
3249
3250static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3251{
3252 unsigned char cmd[MAX_COMMAND_SIZE];
3253 struct osst_request * SRpnt;
3254 int blks;
3255#if DEBUG
3256 char * name = tape_name(STp);
3257#endif
3258
3259 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3260#if DEBUG
3261 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3262#endif
3263 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3264 return (-EIO);
3265 }
3266 /* error recovery may have bumped us past the header partition */
3267 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3268#if DEBUG
3269 printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3270#endif
3271 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3272 }
3273 }
3274
3275 if (STp->poll)
3276 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3277 if (osst_recover_wait_frame(STp, aSRpnt, 1))
3278 return (-EIO);
3279
3280// osst_build_stats(STp, &SRpnt);
3281
3282 STp->ps[STp->partition].rw = ST_WRITING;
3283 STp->write_type = OS_WRITE_DATA;
3284
3285 memset(cmd, 0, MAX_COMMAND_SIZE);
3286 cmd[0] = WRITE_6;
3287 cmd[1] = 1;
3288 cmd[4] = 1; /* one frame at a time... */
3289 blks = STp->buffer->buffer_bytes / STp->block_size;
3290#if DEBUG
3291 if (debugging)
3292 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks,
3293 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3294#endif
3295 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3296 STp->logical_blk_num - blks, STp->block_size, blks);
3297
3298#if DEBUG
3299 if (!synchronous)
3300 STp->write_pending = 1;
3301#endif
3302 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3303 MAX_RETRIES, synchronous);
3304 if (!SRpnt)
3305 return (-EBUSY);
3306 *aSRpnt = SRpnt;
3307
3308 if (synchronous) {
3309 if (STp->buffer->syscall_result != 0) {
3310#if DEBUG
3311 if (debugging)
3312 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3313#endif
3314 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3315 (SRpnt->sense[2] & 0x40)) {
3316 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3317 return (-ENOSPC);
3318 }
3319 else {
3320 if (osst_write_error_recovery(STp, aSRpnt, 1))
3321 return (-EIO);
3322 }
3323 }
3324 else
3325 STp->first_frame_position++;
3326 }
3327
3328 STp->write_count++;
3329
3330 return 0;
3331}
3332
3333/* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3334static int do_door_lock(struct osst_tape * STp, int do_lock)
3335{
3336 int retval;
3337
3338#if DEBUG
3339 printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3340#endif
3341
3342 retval = scsi_set_medium_removal(STp->device,
3343 do_lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
3344 if (!retval)
3345 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3346 else
3347 STp->door_locked = ST_LOCK_FAILS;
3348 return retval;
3349}
3350
3351/* Set the internal state after reset */
3352static void reset_state(struct osst_tape *STp)
3353{
3354 int i;
3355 struct st_partstat *STps;
3356
3357 STp->pos_unknown = 0;
3358 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3359 STps = &(STp->ps[i]);
3360 STps->rw = ST_IDLE;
3361 STps->eof = ST_NOEOF;
3362 STps->at_sm = 0;
3363 STps->last_block_valid = 0;
3364 STps->drv_block = -1;
3365 STps->drv_file = -1;
3366 }
3367}
3368
3369
3370/* Entry points to osst */
3371
3372/* Write command */
3373static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3374{
3375 ssize_t total, retval = 0;
3376 ssize_t i, do_count, blks, transfer;
3377 int write_threshold;
3378 int doing_write = 0;
3379 const char __user * b_point;
3380 struct osst_request * SRpnt = NULL;
3381 struct st_modedef * STm;
3382 struct st_partstat * STps;
3383 struct osst_tape * STp = filp->private_data;
3384 char * name = tape_name(STp);
3385
3386
3387 if (mutex_lock_interruptible(&STp->lock))
3388 return (-ERESTARTSYS);
3389
3390 /*
3391 * If we are in the middle of error recovery, don't let anyone
3392 * else try and use this device. Also, if error recovery fails, it
3393 * may try and take the device offline, in which case all further
3394 * access to the device is prohibited.
3395 */
3396 if( !scsi_block_when_processing_errors(STp->device) ) {
3397 retval = (-ENXIO);
3398 goto out;
3399 }
3400
3401 if (STp->ready != ST_READY) {
3402 if (STp->ready == ST_NO_TAPE)
3403 retval = (-ENOMEDIUM);
3404 else
3405 retval = (-EIO);
3406 goto out;
3407 }
3408 STm = &(STp->modes[STp->current_mode]);
3409 if (!STm->defined) {
3410 retval = (-ENXIO);
3411 goto out;
3412 }
3413 if (count == 0)
3414 goto out;
3415
3416 /*
3417 * If there was a bus reset, block further access
3418 * to this device.
3419 */
3420 if (STp->pos_unknown) {
3421 retval = (-EIO);
3422 goto out;
3423 }
3424
3425#if DEBUG
3426 if (!STp->in_use) {
3427 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3428 retval = (-EIO);
3429 goto out;
3430 }
3431#endif
3432
3433 if (STp->write_prot) {
3434 retval = (-EACCES);
3435 goto out;
3436 }
3437
3438 /* Write must be integral number of blocks */
3439 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3440 printk(KERN_ERR "%s:E: Write (%zd bytes) not multiple of tape block size (%d%c).\n",
3441 name, count, STp->block_size<1024?
3442 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3443 retval = (-EINVAL);
3444 goto out;
3445 }
3446
3447 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3448 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3449 name, STp->first_frame_position);
3450 retval = (-ENOSPC);
3451 goto out;
3452 }
3453
3454 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3455 STp->door_locked = ST_LOCKED_AUTO;
3456
3457 STps = &(STp->ps[STp->partition]);
3458
3459 if (STps->rw == ST_READING) {
3460#if DEBUG
3461 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name,
3462 STps->drv_file, STps->drv_block);
3463#endif
3464 retval = osst_flush_buffer(STp, &SRpnt, 0);
3465 if (retval)
3466 goto out;
3467 STps->rw = ST_IDLE;
3468 }
3469 if (STps->rw != ST_WRITING) {
3470 /* Are we totally rewriting this tape? */
3471 if (!STp->header_ok ||
3472 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3473 (STps->drv_file == 0 && STps->drv_block == 0)) {
3474 STp->wrt_pass_cntr++;
3475#if DEBUG
3476 printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3477 name, STp->wrt_pass_cntr);
3478#endif
3479 osst_reset_header(STp, &SRpnt);
3480 STps->drv_file = STps->drv_block = 0;
3481 }
3482 /* Do we know where we'll be writing on the tape? */
3483 else {
3484 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3485 STps->drv_file < 0 || STps->drv_block < 0) {
3486 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3487 STps->drv_file = STp->filemark_cnt;
3488 STps->drv_block = 0;
3489 }
3490 else {
3491 /* We have no idea where the tape is positioned - give up */
3492#if DEBUG
3493 printk(OSST_DEB_MSG
3494 "%s:D: Cannot write at indeterminate position.\n", name);
3495#endif
3496 retval = (-EIO);
3497 goto out;
3498 }
3499 }
3500 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3501 STp->filemark_cnt = STps->drv_file;
3502 STp->last_mark_ppos =
3503 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3504 printk(KERN_WARNING
3505 "%s:W: Overwriting file %d with old write pass counter %d\n",
3506 name, STps->drv_file, STp->wrt_pass_cntr);
3507 printk(KERN_WARNING
3508 "%s:W: may lead to stale data being accepted on reading back!\n",
3509 name);
3510#if DEBUG
3511 printk(OSST_DEB_MSG
3512 "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3513 name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3514#endif
3515 }
3516 }
3517 STp->fast_open = 0;
3518 }
3519 if (!STp->header_ok) {
3520#if DEBUG
3521 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3522#endif
3523 retval = (-EIO);
3524 goto out;
3525 }
3526
3527 if ((STp->buffer)->writing) {
3528if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3529 osst_write_behind_check(STp);
3530 if ((STp->buffer)->syscall_result) {
3531#if DEBUG
3532 if (debugging)
3533 printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3534 (STp->buffer)->midlevel_result);
3535#endif
3536 if ((STp->buffer)->midlevel_result == INT_MAX)
3537 STps->eof = ST_EOM_OK;
3538 else
3539 STps->eof = ST_EOM_ERROR;
3540 }
3541 }
3542 if (STps->eof == ST_EOM_OK) {
3543 retval = (-ENOSPC);
3544 goto out;
3545 }
3546 else if (STps->eof == ST_EOM_ERROR) {
3547 retval = (-EIO);
3548 goto out;
3549 }
3550
3551 /* Check the buffer readability in cases where copy_user might catch
3552 the problems after some tape movement. */
3553 if ((copy_from_user(&i, buf, 1) != 0 ||
3554 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3555 retval = (-EFAULT);
3556 goto out;
3557 }
3558
3559 if (!STm->do_buffer_writes) {
3560 write_threshold = 1;
3561 }
3562 else
3563 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3564 if (!STm->do_async_writes)
3565 write_threshold--;
3566
3567 total = count;
3568#if DEBUG
3569 if (debugging)
3570 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3571 name, (int) count, STps->drv_file, STps->drv_block,
3572 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3573#endif
3574 b_point = buf;
3575 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3576 {
3577 doing_write = 1;
3578 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3579 (STp->buffer)->buffer_bytes;
3580 if (do_count > count)
3581 do_count = count;
3582
3583 i = append_to_buffer(b_point, STp->buffer, do_count);
3584 if (i) {
3585 retval = i;
3586 goto out;
3587 }
3588
3589 blks = do_count / STp->block_size;
3590 STp->logical_blk_num += blks; /* logical_blk_num is incremented as data is moved from user */
3591
3592 i = osst_write_frame(STp, &SRpnt, 1);
3593
3594 if (i == (-ENOSPC)) {
3595 transfer = STp->buffer->writing; /* FIXME -- check this logic */
3596 if (transfer <= do_count) {
3597 *ppos += do_count - transfer;
3598 count -= do_count - transfer;
3599 if (STps->drv_block >= 0) {
3600 STps->drv_block += (do_count - transfer) / STp->block_size;
3601 }
3602 STps->eof = ST_EOM_OK;
3603 retval = (-ENOSPC); /* EOM within current request */
3604#if DEBUG
3605 if (debugging)
3606 printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3607 name, (int) transfer);
3608#endif
3609 }
3610 else {
3611 STps->eof = ST_EOM_ERROR;
3612 STps->drv_block = (-1); /* Too cautious? */
3613 retval = (-EIO); /* EOM for old data */
3614#if DEBUG
3615 if (debugging)
3616 printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3617#endif
3618 }
3619 }
3620 else
3621 retval = i;
3622
3623 if (retval < 0) {
3624 if (SRpnt != NULL) {
3625 osst_release_request(SRpnt);
3626 SRpnt = NULL;
3627 }
3628 STp->buffer->buffer_bytes = 0;
3629 STp->dirty = 0;
3630 if (count < total)
3631 retval = total - count;
3632 goto out;
3633 }
3634
3635 *ppos += do_count;
3636 b_point += do_count;
3637 count -= do_count;
3638 if (STps->drv_block >= 0) {
3639 STps->drv_block += blks;
3640 }
3641 STp->buffer->buffer_bytes = 0;
3642 STp->dirty = 0;
3643 } /* end while write threshold exceeded */
3644
3645 if (count != 0) {
3646 STp->dirty = 1;
3647 i = append_to_buffer(b_point, STp->buffer, count);
3648 if (i) {
3649 retval = i;
3650 goto out;
3651 }
3652 blks = count / STp->block_size;
3653 STp->logical_blk_num += blks;
3654 if (STps->drv_block >= 0) {
3655 STps->drv_block += blks;
3656 }
3657 *ppos += count;
3658 count = 0;
3659 }
3660
3661 if (doing_write && (STp->buffer)->syscall_result != 0) {
3662 retval = (STp->buffer)->syscall_result;
3663 goto out;
3664 }
3665
3666 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3667 /* Schedule an asynchronous write */
3668 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3669 STp->block_size) * STp->block_size;
3670 STp->dirty = !((STp->buffer)->writing ==
3671 (STp->buffer)->buffer_bytes);
3672
3673 i = osst_write_frame(STp, &SRpnt, 0);
3674 if (i < 0) {
3675 retval = (-EIO);
3676 goto out;
3677 }
3678 SRpnt = NULL; /* Prevent releasing this request! */
3679 }
3680 STps->at_sm &= (total == 0);
3681 if (total > 0)
3682 STps->eof = ST_NOEOF;
3683
3684 retval = total;
3685
3686out:
3687 if (SRpnt != NULL) osst_release_request(SRpnt);
3688
3689 mutex_unlock(&STp->lock);
3690
3691 return retval;
3692}
3693
3694
3695/* Read command */
3696static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3697{
3698 ssize_t total, retval = 0;
3699 ssize_t i, transfer;
3700 int special;
3701 struct st_modedef * STm;
3702 struct st_partstat * STps;
3703 struct osst_request * SRpnt = NULL;
3704 struct osst_tape * STp = filp->private_data;
3705 char * name = tape_name(STp);
3706
3707
3708 if (mutex_lock_interruptible(&STp->lock))
3709 return (-ERESTARTSYS);
3710
3711 /*
3712 * If we are in the middle of error recovery, don't let anyone
3713 * else try and use this device. Also, if error recovery fails, it
3714 * may try and take the device offline, in which case all further
3715 * access to the device is prohibited.
3716 */
3717 if( !scsi_block_when_processing_errors(STp->device) ) {
3718 retval = (-ENXIO);
3719 goto out;
3720 }
3721
3722 if (STp->ready != ST_READY) {
3723 if (STp->ready == ST_NO_TAPE)
3724 retval = (-ENOMEDIUM);
3725 else
3726 retval = (-EIO);
3727 goto out;
3728 }
3729 STm = &(STp->modes[STp->current_mode]);
3730 if (!STm->defined) {
3731 retval = (-ENXIO);
3732 goto out;
3733 }
3734#if DEBUG
3735 if (!STp->in_use) {
3736 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3737 retval = (-EIO);
3738 goto out;
3739 }
3740#endif
3741 /* Must have initialized medium */
3742 if (!STp->header_ok) {
3743 retval = (-EIO);
3744 goto out;
3745 }
3746
3747 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3748 STp->door_locked = ST_LOCKED_AUTO;
3749
3750 STps = &(STp->ps[STp->partition]);
3751 if (STps->rw == ST_WRITING) {
3752 retval = osst_flush_buffer(STp, &SRpnt, 0);
3753 if (retval)
3754 goto out;
3755 STps->rw = ST_IDLE;
3756 /* FIXME -- this may leave the tape without EOD and up2date headers */
3757 }
3758
3759 if ((count % STp->block_size) != 0) {
3760 printk(KERN_WARNING
3761 "%s:W: Read (%zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3762 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3763 }
3764
3765#if DEBUG
3766 if (debugging && STps->eof != ST_NOEOF)
3767 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3768 STps->eof, (STp->buffer)->buffer_bytes);
3769#endif
3770 if ((STp->buffer)->buffer_bytes == 0 &&
3771 STps->eof >= ST_EOD_1) {
3772 if (STps->eof < ST_EOD) {
3773 STps->eof += 1;
3774 retval = 0;
3775 goto out;
3776 }
3777 retval = (-EIO); /* EOM or Blank Check */
3778 goto out;
3779 }
3780
3781 /* Check the buffer writability before any tape movement. Don't alter
3782 buffer data. */
3783 if (copy_from_user(&i, buf, 1) != 0 ||
3784 copy_to_user (buf, &i, 1) != 0 ||
3785 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3786 copy_to_user (buf + count - 1, &i, 1) != 0) {
3787 retval = (-EFAULT);
3788 goto out;
3789 }
3790
3791 /* Loop until enough data in buffer or a special condition found */
3792 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3793
3794 /* Get new data if the buffer is empty */
3795 if ((STp->buffer)->buffer_bytes == 0) {
3796 if (STps->eof == ST_FM_HIT)
3797 break;
3798 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3799 if (special < 0) { /* No need to continue read */
3800 STp->frame_in_buffer = 0;
3801 retval = special;
3802 goto out;
3803 }
3804 }
3805
3806 /* Move the data from driver buffer to user buffer */
3807 if ((STp->buffer)->buffer_bytes > 0) {
3808#if DEBUG
3809 if (debugging && STps->eof != ST_NOEOF)
3810 printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3811 STps->eof, (STp->buffer)->buffer_bytes, (int) (count - total));
3812#endif
3813 /* force multiple of block size, note block_size may have been adjusted */
3814 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3815 (STp->buffer)->buffer_bytes : count - total)/
3816 STp->block_size) * STp->block_size;
3817
3818 if (transfer == 0) {
3819 printk(KERN_WARNING
3820 "%s:W: Nothing can be transferred, requested %zd, tape block size (%d%c).\n",
3821 name, count, STp->block_size < 1024?
3822 STp->block_size:STp->block_size/1024,
3823 STp->block_size<1024?'b':'k');
3824 break;
3825 }
3826 i = from_buffer(STp->buffer, buf, transfer);
3827 if (i) {
3828 retval = i;
3829 goto out;
3830 }
3831 STp->logical_blk_num += transfer / STp->block_size;
3832 STps->drv_block += transfer / STp->block_size;
3833 *ppos += transfer;
3834 buf += transfer;
3835 total += transfer;
3836 }
3837
3838 if ((STp->buffer)->buffer_bytes == 0) {
3839#if DEBUG
3840 if (debugging)
3841 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3842 name, STp->frame_seq_number);
3843#endif
3844 STp->frame_in_buffer = 0;
3845 STp->frame_seq_number++; /* frame to look for next time */
3846 }
3847 } /* for (total = 0, special = 0; total < count && !special; ) */
3848
3849 /* Change the eof state if no data from tape or buffer */
3850 if (total == 0) {
3851 if (STps->eof == ST_FM_HIT) {
3852 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3853 STps->drv_block = 0;
3854 if (STps->drv_file >= 0)
3855 STps->drv_file++;
3856 }
3857 else if (STps->eof == ST_EOD_1) {
3858 STps->eof = ST_EOD_2;
3859 if (STps->drv_block > 0 && STps->drv_file >= 0)
3860 STps->drv_file++;
3861 STps->drv_block = 0;
3862 }
3863 else if (STps->eof == ST_EOD_2)
3864 STps->eof = ST_EOD;
3865 }
3866 else if (STps->eof == ST_FM)
3867 STps->eof = ST_NOEOF;
3868
3869 retval = total;
3870
3871out:
3872 if (SRpnt != NULL) osst_release_request(SRpnt);
3873
3874 mutex_unlock(&STp->lock);
3875
3876 return retval;
3877}
3878
3879
3880/* Set the driver options */
3881static void osst_log_options(struct osst_tape *STp, struct st_modedef *STm, char *name)
3882{
3883 printk(KERN_INFO
3884"%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3885 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3886 STm->do_read_ahead);
3887 printk(KERN_INFO
3888"%s:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3889 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3890 printk(KERN_INFO
3891"%s:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3892 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3893 STp->scsi2_logical);
3894 printk(KERN_INFO
3895"%s:I: sysv: %d\n", name, STm->sysv);
3896#if DEBUG
3897 printk(KERN_INFO
3898 "%s:D: debugging: %d\n",
3899 name, debugging);
3900#endif
3901}
3902
3903
3904static int osst_set_options(struct osst_tape *STp, long options)
3905{
3906 int value;
3907 long code;
3908 struct st_modedef * STm;
3909 char * name = tape_name(STp);
3910
3911 STm = &(STp->modes[STp->current_mode]);
3912 if (!STm->defined) {
3913 memcpy(STm, &(STp->modes[0]), sizeof(*STm));
3914 modes_defined = 1;
3915#if DEBUG
3916 if (debugging)
3917 printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3918 name, STp->current_mode);
3919#endif
3920 }
3921
3922 code = options & MT_ST_OPTIONS;
3923 if (code == MT_ST_BOOLEANS) {
3924 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3925 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3926 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3927 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3928 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3929 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3930 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3931 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3932 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3933 if ((STp->device)->scsi_level >= SCSI_2)
3934 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3935 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3936 STm->sysv = (options & MT_ST_SYSV) != 0;
3937#if DEBUG
3938 debugging = (options & MT_ST_DEBUGGING) != 0;
3939#endif
3940 osst_log_options(STp, STm, name);
3941 }
3942 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3943 value = (code == MT_ST_SETBOOLEANS);
3944 if ((options & MT_ST_BUFFER_WRITES) != 0)
3945 STm->do_buffer_writes = value;
3946 if ((options & MT_ST_ASYNC_WRITES) != 0)
3947 STm->do_async_writes = value;
3948 if ((options & MT_ST_DEF_WRITES) != 0)
3949 STm->defaults_for_writes = value;
3950 if ((options & MT_ST_READ_AHEAD) != 0)
3951 STm->do_read_ahead = value;
3952 if ((options & MT_ST_TWO_FM) != 0)
3953 STp->two_fm = value;
3954 if ((options & MT_ST_FAST_MTEOM) != 0)
3955 STp->fast_mteom = value;
3956 if ((options & MT_ST_AUTO_LOCK) != 0)
3957 STp->do_auto_lock = value;
3958 if ((options & MT_ST_CAN_BSR) != 0)
3959 STp->can_bsr = value;
3960 if ((options & MT_ST_NO_BLKLIMS) != 0)
3961 STp->omit_blklims = value;
3962 if ((STp->device)->scsi_level >= SCSI_2 &&
3963 (options & MT_ST_CAN_PARTITIONS) != 0)
3964 STp->can_partitions = value;
3965 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3966 STp->scsi2_logical = value;
3967 if ((options & MT_ST_SYSV) != 0)
3968 STm->sysv = value;
3969#if DEBUG
3970 if ((options & MT_ST_DEBUGGING) != 0)
3971 debugging = value;
3972#endif
3973 osst_log_options(STp, STm, name);
3974 }
3975 else if (code == MT_ST_WRITE_THRESHOLD) {
3976 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3977 if (value < 1 || value > osst_buffer_size) {
3978 printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3979 name, value);
3980 return (-EIO);
3981 }
3982 STp->write_threshold = value;
3983 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3984 name, value);
3985 }
3986 else if (code == MT_ST_DEF_BLKSIZE) {
3987 value = (options & ~MT_ST_OPTIONS);
3988 if (value == ~MT_ST_OPTIONS) {
3989 STm->default_blksize = (-1);
3990 printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3991 }
3992 else {
3993 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3994 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3995 name, value);
3996 return (-EINVAL);
3997 }
3998 STm->default_blksize = value;
3999 printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
4000 name, STm->default_blksize);
4001 }
4002 }
4003 else if (code == MT_ST_TIMEOUTS) {
4004 value = (options & ~MT_ST_OPTIONS);
4005 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
4006 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
4007 printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
4008 (value & ~MT_ST_SET_LONG_TIMEOUT));
4009 }
4010 else {
4011 STp->timeout = value * HZ;
4012 printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
4013 }
4014 }
4015 else if (code == MT_ST_DEF_OPTIONS) {
4016 code = (options & ~MT_ST_CLEAR_DEFAULT);
4017 value = (options & MT_ST_CLEAR_DEFAULT);
4018 if (code == MT_ST_DEF_DENSITY) {
4019 if (value == MT_ST_CLEAR_DEFAULT) {
4020 STm->default_density = (-1);
4021 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
4022 }
4023 else {
4024 STm->default_density = value & 0xff;
4025 printk(KERN_INFO "%s:I: Density default set to %x\n",
4026 name, STm->default_density);
4027 }
4028 }
4029 else if (code == MT_ST_DEF_DRVBUFFER) {
4030 if (value == MT_ST_CLEAR_DEFAULT) {
4031 STp->default_drvbuffer = 0xff;
4032 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
4033 }
4034 else {
4035 STp->default_drvbuffer = value & 7;
4036 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
4037 name, STp->default_drvbuffer);
4038 }
4039 }
4040 else if (code == MT_ST_DEF_COMPRESSION) {
4041 if (value == MT_ST_CLEAR_DEFAULT) {
4042 STm->default_compression = ST_DONT_TOUCH;
4043 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
4044 }
4045 else {
4046 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
4047 printk(KERN_INFO "%s:I: Compression default set to %x\n",
4048 name, (value & 1));
4049 }
4050 }
4051 }
4052 else
4053 return (-EIO);
4054
4055 return 0;
4056}
4057
4058
4059/* Internal ioctl function */
4060static int osst_int_ioctl(struct osst_tape * STp, struct osst_request ** aSRpnt,
4061 unsigned int cmd_in, unsigned long arg)
4062{
4063 int timeout;
4064 long ltmp;
4065 int i, ioctl_result;
4066 int chg_eof = 1;
4067 unsigned char cmd[MAX_COMMAND_SIZE];
4068 struct osst_request * SRpnt = * aSRpnt;
4069 struct st_partstat * STps;
4070 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
4071 int datalen = 0, direction = DMA_NONE;
4072 char * name = tape_name(STp);
4073
4074 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
4075 if (STp->ready == ST_NO_TAPE)
4076 return (-ENOMEDIUM);
4077 else
4078 return (-EIO);
4079 }
4080 timeout = STp->long_timeout;
4081 STps = &(STp->ps[STp->partition]);
4082 fileno = STps->drv_file;
4083 blkno = STps->drv_block;
4084 at_sm = STps->at_sm;
4085 frame_seq_numbr = STp->frame_seq_number;
4086 logical_blk_num = STp->logical_blk_num;
4087
4088 memset(cmd, 0, MAX_COMMAND_SIZE);
4089 switch (cmd_in) {
4090 case MTFSFM:
4091 chg_eof = 0; /* Changed from the FSF after this */
4092 /* fall through */
4093 case MTFSF:
4094 if (STp->raw)
4095 return (-EIO);
4096 if (STp->linux_media)
4097 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
4098 else
4099 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
4100 if (fileno >= 0)
4101 fileno += arg;
4102 blkno = 0;
4103 at_sm &= (arg == 0);
4104 goto os_bypass;
4105
4106 case MTBSF:
4107 chg_eof = 0; /* Changed from the FSF after this */
4108 /* fall through */
4109 case MTBSFM:
4110 if (STp->raw)
4111 return (-EIO);
4112 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
4113 if (fileno >= 0)
4114 fileno -= arg;
4115 blkno = (-1); /* We can't know the block number */
4116 at_sm &= (arg == 0);
4117 goto os_bypass;
4118
4119 case MTFSR:
4120 case MTBSR:
4121#if DEBUG
4122 if (debugging)
4123 printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
4124 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
4125#endif
4126 if (cmd_in == MTFSR) {
4127 logical_blk_num += arg;
4128 if (blkno >= 0) blkno += arg;
4129 }
4130 else {
4131 logical_blk_num -= arg;
4132 if (blkno >= 0) blkno -= arg;
4133 }
4134 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
4135 fileno = STps->drv_file;
4136 blkno = STps->drv_block;
4137 at_sm &= (arg == 0);
4138 goto os_bypass;
4139
4140 case MTFSS:
4141 cmd[0] = SPACE;
4142 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4143 cmd[2] = (arg >> 16);
4144 cmd[3] = (arg >> 8);
4145 cmd[4] = arg;
4146#if DEBUG
4147 if (debugging)
4148 printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
4149 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4150#endif
4151 if (arg != 0) {
4152 blkno = fileno = (-1);
4153 at_sm = 1;
4154 }
4155 break;
4156 case MTBSS:
4157 cmd[0] = SPACE;
4158 cmd[1] = 0x04; /* Space Setmarks */ /* FIXME -- OS can't do this? */
4159 ltmp = (-arg);
4160 cmd[2] = (ltmp >> 16);
4161 cmd[3] = (ltmp >> 8);
4162 cmd[4] = ltmp;
4163#if DEBUG
4164 if (debugging) {
4165 if (cmd[2] & 0x80)
4166 ltmp = 0xff000000;
4167 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
4168 printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
4169 name, (-ltmp));
4170 }
4171#endif
4172 if (arg != 0) {
4173 blkno = fileno = (-1);
4174 at_sm = 1;
4175 }
4176 break;
4177 case MTWEOF:
4178 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4179 STp->write_type = OS_WRITE_DATA;
4180 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
4181 } else
4182 ioctl_result = 0;
4183#if DEBUG
4184 if (debugging)
4185 printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
4186#endif
4187 for (i=0; i<arg; i++)
4188 ioctl_result |= osst_write_filemark(STp, &SRpnt);
4189 if (fileno >= 0) fileno += arg;
4190 if (blkno >= 0) blkno = 0;
4191 goto os_bypass;
4192
4193 case MTWSM:
4194 if (STp->write_prot)
4195 return (-EACCES);
4196 if (!STp->raw)
4197 return 0;
4198 cmd[0] = WRITE_FILEMARKS; /* FIXME -- need OS version */
4199 if (cmd_in == MTWSM)
4200 cmd[1] = 2;
4201 cmd[2] = (arg >> 16);
4202 cmd[3] = (arg >> 8);
4203 cmd[4] = arg;
4204 timeout = STp->timeout;
4205#if DEBUG
4206 if (debugging)
4207 printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4208 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4209#endif
4210 if (fileno >= 0)
4211 fileno += arg;
4212 blkno = 0;
4213 at_sm = (cmd_in == MTWSM);
4214 break;
4215 case MTOFFL:
4216 case MTLOAD:
4217 case MTUNLOAD:
4218 case MTRETEN:
4219 cmd[0] = START_STOP;
4220 cmd[1] = 1; /* Don't wait for completion */
4221 if (cmd_in == MTLOAD) {
4222 if (STp->ready == ST_NO_TAPE)
4223 cmd[4] = 4; /* open tray */
4224 else
4225 cmd[4] = 1; /* load */
4226 }
4227 if (cmd_in == MTRETEN)
4228 cmd[4] = 3; /* retension then mount */
4229 if (cmd_in == MTOFFL)
4230 cmd[4] = 4; /* rewind then eject */
4231 timeout = STp->timeout;
4232#if DEBUG
4233 if (debugging) {
4234 switch (cmd_in) {
4235 case MTUNLOAD:
4236 printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4237 break;
4238 case MTLOAD:
4239 printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4240 break;
4241 case MTRETEN:
4242 printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4243 break;
4244 case MTOFFL:
4245 printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4246 break;
4247 }
4248 }
4249#endif
4250 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4251 break;
4252 case MTNOP:
4253#if DEBUG
4254 if (debugging)
4255 printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4256#endif
4257 return 0; /* Should do something ? */
4258 break;
4259 case MTEOM:
4260#if DEBUG
4261 if (debugging)
4262 printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4263#endif
4264 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4265 (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0)) {
4266 ioctl_result = -EIO;
4267 goto os_bypass;
4268 }
4269 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4270#if DEBUG
4271 printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4272#endif
4273 ioctl_result = -EIO;
4274 goto os_bypass;
4275 }
4276 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4277 fileno = STp->filemark_cnt;
4278 blkno = at_sm = 0;
4279 goto os_bypass;
4280
4281 case MTERASE:
4282 if (STp->write_prot)
4283 return (-EACCES);
4284 ioctl_result = osst_reset_header(STp, &SRpnt);
4285 i = osst_write_eod(STp, &SRpnt);
4286 if (i < ioctl_result) ioctl_result = i;
4287 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4288 if (i < ioctl_result) ioctl_result = i;
4289 fileno = blkno = at_sm = 0 ;
4290 goto os_bypass;
4291
4292 case MTREW:
4293 cmd[0] = REZERO_UNIT; /* rewind */
4294 cmd[1] = 1;
4295#if DEBUG
4296 if (debugging)
4297 printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4298#endif
4299 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4300 break;
4301
4302 case MTSETBLK: /* Set block length */
4303 if ((STps->drv_block == 0 ) &&
4304 !STp->dirty &&
4305 ((STp->buffer)->buffer_bytes == 0) &&
4306 ((arg & MT_ST_BLKSIZE_MASK) >= 512 ) &&
4307 ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4308 !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK)) ) {
4309 /*
4310 * Only allowed to change the block size if you opened the
4311 * device at the beginning of a file before writing anything.
4312 * Note, that when reading, changing block_size is futile,
4313 * as the size used when writing overrides it.
4314 */
4315 STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4316 printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4317 name, STp->block_size);
4318 return 0;
4319 }
4320 /* fall through */
4321 case MTSETDENSITY: /* Set tape density */
4322 case MTSETDRVBUFFER: /* Set drive buffering */
4323 case SET_DENS_AND_BLK: /* Set density and block size */
4324 chg_eof = 0;
4325 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4326 return (-EIO); /* Not allowed if data in buffer */
4327 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4328 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4329 (arg & MT_ST_BLKSIZE_MASK) != STp->block_size ) {
4330 printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4331 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4332 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4333 return (-EINVAL);
4334 }
4335 return 0; /* FIXME silently ignore if block size didn't change */
4336
4337 default:
4338 return (-ENOSYS);
4339 }
4340
4341 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, 1);
4342
4343 ioctl_result = (STp->buffer)->syscall_result;
4344
4345 if (!SRpnt) {
4346#if DEBUG
4347 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4348#endif
4349 return ioctl_result;
4350 }
4351
4352 if (!ioctl_result) { /* SCSI command successful */
4353 STp->frame_seq_number = frame_seq_numbr;
4354 STp->logical_blk_num = logical_blk_num;
4355 }
4356
4357os_bypass:
4358#if DEBUG
4359 if (debugging)
4360 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4361#endif
4362
4363 if (!ioctl_result) { /* success */
4364
4365 if (cmd_in == MTFSFM) {
4366 fileno--;
4367 blkno--;
4368 }
4369 if (cmd_in == MTBSFM) {
4370 fileno++;
4371 blkno++;
4372 }
4373 STps->drv_block = blkno;
4374 STps->drv_file = fileno;
4375 STps->at_sm = at_sm;
4376
4377 if (cmd_in == MTEOM)
4378 STps->eof = ST_EOD;
4379 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4380 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4381 STps->drv_block++;
4382 STp->logical_blk_num++;
4383 STp->frame_seq_number++;
4384 STp->frame_in_buffer = 0;
4385 STp->buffer->read_pointer = 0;
4386 }
4387 else if (cmd_in == MTFSF)
4388 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4389 else if (chg_eof)
4390 STps->eof = ST_NOEOF;
4391
4392 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4393 STp->rew_at_close = 0;
4394 else if (cmd_in == MTLOAD) {
4395 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4396 STp->ps[i].rw = ST_IDLE;
4397 STp->ps[i].last_block_valid = 0;/* FIXME - where else is this field maintained? */
4398 }
4399 STp->partition = 0;
4400 }
4401
4402 if (cmd_in == MTREW) {
4403 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4404 if (ioctl_result > 0)
4405 ioctl_result = 0;
4406 }
4407
4408 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4409 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4410 STps->drv_file = STps->drv_block = -1;
4411 else
4412 STps->drv_file = STps->drv_block = 0;
4413 STps->eof = ST_NOEOF;
4414 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4415 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4416 STps->drv_file = STps->drv_block = -1;
4417 else {
4418 STps->drv_file = STp->filemark_cnt;
4419 STps->drv_block = 0;
4420 }
4421 STps->eof = ST_EOD;
4422 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4423 STps->drv_file = STps->drv_block = (-1);
4424 STps->eof = ST_NOEOF;
4425 STp->header_ok = 0;
4426 } else if (cmd_in == MTERASE) {
4427 STp->header_ok = 0;
4428 } else if (SRpnt) { /* SCSI command was not completely successful. */
4429 if (SRpnt->sense[2] & 0x40) {
4430 STps->eof = ST_EOM_OK;
4431 STps->drv_block = 0;
4432 }
4433 if (chg_eof)
4434 STps->eof = ST_NOEOF;
4435
4436 if ((SRpnt->sense[2] & 0x0f) == BLANK_CHECK)
4437 STps->eof = ST_EOD;
4438
4439 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4440 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4441 }
4442 *aSRpnt = SRpnt;
4443
4444 return ioctl_result;
4445}
4446
4447
4448/* Open the device */
4449static int __os_scsi_tape_open(struct inode * inode, struct file * filp)
4450{
4451 unsigned short flags;
4452 int i, b_size, new_session = 0, retval = 0;
4453 unsigned char cmd[MAX_COMMAND_SIZE];
4454 struct osst_request * SRpnt = NULL;
4455 struct osst_tape * STp;
4456 struct st_modedef * STm;
4457 struct st_partstat * STps;
4458 char * name;
4459 int dev = TAPE_NR(inode);
4460 int mode = TAPE_MODE(inode);
4461
4462 /*
4463 * We really want to do nonseekable_open(inode, filp); here, but some
4464 * versions of tar incorrectly call lseek on tapes and bail out if that
4465 * fails. So we disallow pread() and pwrite(), but permit lseeks.
4466 */
4467 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
4468
4469 write_lock(&os_scsi_tapes_lock);
4470 if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4471 (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4472 write_unlock(&os_scsi_tapes_lock);
4473 return (-ENXIO);
4474 }
4475
4476 name = tape_name(STp);
4477
4478 if (STp->in_use) {
4479 write_unlock(&os_scsi_tapes_lock);
4480#if DEBUG
4481 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4482#endif
4483 return (-EBUSY);
4484 }
4485 if (scsi_device_get(STp->device)) {
4486 write_unlock(&os_scsi_tapes_lock);
4487#if DEBUG
4488 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4489#endif
4490 return (-ENXIO);
4491 }
4492 filp->private_data = STp;
4493 STp->in_use = 1;
4494 write_unlock(&os_scsi_tapes_lock);
4495 STp->rew_at_close = TAPE_REWIND(inode);
4496
4497 if( !scsi_block_when_processing_errors(STp->device) ) {
4498 return -ENXIO;
4499 }
4500
4501 if (mode != STp->current_mode) {
4502#if DEBUG
4503 if (debugging)
4504 printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4505 name, STp->current_mode, mode);
4506#endif
4507 new_session = 1;
4508 STp->current_mode = mode;
4509 }
4510 STm = &(STp->modes[STp->current_mode]);
4511
4512 flags = filp->f_flags;
4513 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4514
4515 STp->raw = TAPE_IS_RAW(inode);
4516 if (STp->raw)
4517 STp->header_ok = 0;
4518
4519 /* Allocate data segments for this device's tape buffer */
4520 if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4521 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4522 retval = (-EOVERFLOW);
4523 goto err_out;
4524 }
4525 if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4526 for (i = 0, b_size = 0;
4527 (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE);
4528 b_size += STp->buffer->sg[i++].length);
4529 STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size);
4530#if DEBUG
4531 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4532 STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4533 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4534 STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4535#endif
4536 } else {
4537 STp->buffer->aux = NULL; /* this had better never happen! */
4538 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4539 retval = (-EIO);
4540 goto err_out;
4541 }
4542 STp->buffer->writing = 0;
4543 STp->buffer->syscall_result = 0;
4544 STp->dirty = 0;
4545 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4546 STps = &(STp->ps[i]);
4547 STps->rw = ST_IDLE;
4548 }
4549 STp->ready = ST_READY;
4550#if DEBUG
4551 STp->nbr_waits = STp->nbr_finished = 0;
4552#endif
4553
4554 memset (cmd, 0, MAX_COMMAND_SIZE);
4555 cmd[0] = TEST_UNIT_READY;
4556
4557 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
4558 if (!SRpnt) {
4559 retval = (STp->buffer)->syscall_result; /* FIXME - valid? */
4560 goto err_out;
4561 }
4562 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4563 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4564 SRpnt->sense[12] == 4 ) {
4565#if DEBUG
4566 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sense[13]);
4567#endif
4568 if (filp->f_flags & O_NONBLOCK) {
4569 retval = -EAGAIN;
4570 goto err_out;
4571 }
4572 if (SRpnt->sense[13] == 2) { /* initialize command required (LOAD) */
4573 memset (cmd, 0, MAX_COMMAND_SIZE);
4574 cmd[0] = START_STOP;
4575 cmd[1] = 1;
4576 cmd[4] = 1;
4577 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4578 STp->timeout, MAX_RETRIES, 1);
4579 }
4580 osst_wait_ready(STp, &SRpnt, (SRpnt->sense[13]==1?15:3) * 60, 0);
4581 }
4582 if ((SRpnt->sense[0] & 0x70) == 0x70 &&
4583 (SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4584#if DEBUG
4585 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4586#endif
4587 STp->header_ok = 0;
4588
4589 for (i=0; i < 10; i++) {
4590
4591 memset (cmd, 0, MAX_COMMAND_SIZE);
4592 cmd[0] = TEST_UNIT_READY;
4593
4594 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4595 STp->timeout, MAX_RETRIES, 1);
4596 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4597 (SRpnt->sense[2] & 0x0f) != UNIT_ATTENTION)
4598 break;
4599 }
4600
4601 STp->pos_unknown = 0;
4602 STp->partition = STp->new_partition = 0;
4603 if (STp->can_partitions)
4604 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4605 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4606 STps = &(STp->ps[i]);
4607 STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */
4608 STps->eof = ST_NOEOF;
4609 STps->at_sm = 0;
4610 STps->last_block_valid = 0;
4611 STps->drv_block = 0;
4612 STps->drv_file = 0 ;
4613 }
4614 new_session = 1;
4615 STp->recover_count = 0;
4616 STp->abort_count = 0;
4617 }
4618 /*
4619 * if we have valid headers from before, and the drive/tape seem untouched,
4620 * open without reconfiguring and re-reading the headers
4621 */
4622 if (!STp->buffer->syscall_result && STp->header_ok &&
4623 !SRpnt->result && SRpnt->sense[0] == 0) {
4624
4625 memset(cmd, 0, MAX_COMMAND_SIZE);
4626 cmd[0] = MODE_SENSE;
4627 cmd[1] = 8;
4628 cmd[2] = VENDOR_IDENT_PAGE;
4629 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4630
4631 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
4632
4633 if (STp->buffer->syscall_result ||
4634 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4635 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4636 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4637 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4638#if DEBUG
4639 printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4640 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4641 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4642 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4643 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4644#endif
4645 STp->header_ok = 0;
4646 }
4647 i = STp->first_frame_position;
4648 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4649 if (STp->door_locked == ST_UNLOCKED) {
4650 if (do_door_lock(STp, 1))
4651 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4652 else
4653 STp->door_locked = ST_LOCKED_AUTO;
4654 }
4655 if (!STp->frame_in_buffer) {
4656 STp->block_size = (STm->default_blksize > 0) ?
4657 STm->default_blksize : OS_DATA_SIZE;
4658 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4659 }
4660 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4661 STp->fast_open = 1;
4662 osst_release_request(SRpnt);
4663 return 0;
4664 }
4665#if DEBUG
4666 if (i != STp->first_frame_position)
4667 printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4668 name, i, STp->first_frame_position);
4669#endif
4670 STp->header_ok = 0;
4671 }
4672 STp->fast_open = 0;
4673
4674 if ((STp->buffer)->syscall_result != 0 && /* in all error conditions except no medium */
4675 (SRpnt->sense[2] != 2 || SRpnt->sense[12] != 0x3A) ) {
4676
4677 memset(cmd, 0, MAX_COMMAND_SIZE);
4678 cmd[0] = MODE_SELECT;
4679 cmd[1] = 0x10;
4680 cmd[4] = 4 + MODE_HEADER_LENGTH;
4681
4682 (STp->buffer)->b_data[0] = cmd[4] - 1;
4683 (STp->buffer)->b_data[1] = 0; /* Medium Type - ignoring */
4684 (STp->buffer)->b_data[2] = 0; /* Reserved */
4685 (STp->buffer)->b_data[3] = 0; /* Block Descriptor Length */
4686 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4687 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4688 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4689 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4690
4691#if DEBUG
4692 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4693#endif
4694 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
4695
4696 STp->header_ok = 0;
4697
4698 for (i=0; i < 10; i++) {
4699
4700 memset (cmd, 0, MAX_COMMAND_SIZE);
4701 cmd[0] = TEST_UNIT_READY;
4702
4703 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
4704 STp->timeout, MAX_RETRIES, 1);
4705 if ((SRpnt->sense[0] & 0x70) != 0x70 ||
4706 (SRpnt->sense[2] & 0x0f) == NOT_READY)
4707 break;
4708
4709 if ((SRpnt->sense[2] & 0x0f) == UNIT_ATTENTION) {
4710 int j;
4711
4712 STp->pos_unknown = 0;
4713 STp->partition = STp->new_partition = 0;
4714 if (STp->can_partitions)
4715 STp->nbr_partitions = 1; /* This guess will be updated later if necessary */
4716 for (j = 0; j < ST_NBR_PARTITIONS; j++) {
4717 STps = &(STp->ps[j]);
4718 STps->rw = ST_IDLE;
4719 STps->eof = ST_NOEOF;
4720 STps->at_sm = 0;
4721 STps->last_block_valid = 0;
4722 STps->drv_block = 0;
4723 STps->drv_file = 0 ;
4724 }
4725 new_session = 1;
4726 }
4727 }
4728 }
4729
4730 if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0)) /* FIXME - not allowed with NOBLOCK */
4731 printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4732
4733 if ((STp->buffer)->syscall_result != 0) {
4734 if ((STp->device)->scsi_level >= SCSI_2 &&
4735 (SRpnt->sense[0] & 0x70) == 0x70 &&
4736 (SRpnt->sense[2] & 0x0f) == NOT_READY &&
4737 SRpnt->sense[12] == 0x3a) { /* Check ASC */
4738 STp->ready = ST_NO_TAPE;
4739 } else
4740 STp->ready = ST_NOT_READY;
4741 osst_release_request(SRpnt);
4742 SRpnt = NULL;
4743 STp->density = 0; /* Clear the erroneous "residue" */
4744 STp->write_prot = 0;
4745 STp->block_size = 0;
4746 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4747 STp->partition = STp->new_partition = 0;
4748 STp->door_locked = ST_UNLOCKED;
4749 return 0;
4750 }
4751
4752 osst_configure_onstream(STp, &SRpnt);
4753
4754 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4755 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4756 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4757 STp->buffer->buffer_bytes =
4758 STp->buffer->read_pointer =
4759 STp->frame_in_buffer = 0;
4760
4761#if DEBUG
4762 if (debugging)
4763 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4764 name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4765 (STp->buffer)->buffer_blocks);
4766#endif
4767
4768 if (STp->drv_write_prot) {
4769 STp->write_prot = 1;
4770#if DEBUG
4771 if (debugging)
4772 printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4773#endif
4774 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4775 retval = (-EROFS);
4776 goto err_out;
4777 }
4778 }
4779
4780 if (new_session) { /* Change the drive parameters for the new mode */
4781#if DEBUG
4782 if (debugging)
4783 printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4784#endif
4785 STp->density_changed = STp->blksize_changed = 0;
4786 STp->compression_changed = 0;
4787 }
4788
4789 /*
4790 * properly position the tape and check the ADR headers
4791 */
4792 if (STp->door_locked == ST_UNLOCKED) {
4793 if (do_door_lock(STp, 1))
4794 printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4795 else
4796 STp->door_locked = ST_LOCKED_AUTO;
4797 }
4798
4799 osst_analyze_headers(STp, &SRpnt);
4800
4801 osst_release_request(SRpnt);
4802 SRpnt = NULL;
4803
4804 return 0;
4805
4806err_out:
4807 if (SRpnt != NULL)
4808 osst_release_request(SRpnt);
4809 normalize_buffer(STp->buffer);
4810 STp->header_ok = 0;
4811 STp->in_use = 0;
4812 scsi_device_put(STp->device);
4813
4814 return retval;
4815}
4816
4817/* BKL pushdown: spaghetti avoidance wrapper */
4818static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4819{
4820 int ret;
4821
4822 mutex_lock(&osst_int_mutex);
4823 ret = __os_scsi_tape_open(inode, filp);
4824 mutex_unlock(&osst_int_mutex);
4825 return ret;
4826}
4827
4828
4829
4830/* Flush the tape buffer before close */
4831static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
4832{
4833 int result = 0, result2;
4834 struct osst_tape * STp = filp->private_data;
4835 struct st_modedef * STm = &(STp->modes[STp->current_mode]);
4836 struct st_partstat * STps = &(STp->ps[STp->partition]);
4837 struct osst_request * SRpnt = NULL;
4838 char * name = tape_name(STp);
4839
4840 if (file_count(filp) > 1)
4841 return 0;
4842
4843 if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4844 STp->write_type = OS_WRITE_DATA;
4845 result = osst_flush_write_buffer(STp, &SRpnt);
4846 if (result != 0 && result != (-ENOSPC))
4847 goto out;
4848 }
4849 if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4850
4851#if DEBUG
4852 if (debugging) {
4853 printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4854 name, (long)(filp->f_pos));
4855 printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4856 name, STp->nbr_waits, STp->nbr_finished);
4857 }
4858#endif
4859 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4860#if DEBUG
4861 if (debugging)
4862 printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4863 name, 1+STp->two_fm);
4864#endif
4865 }
4866 else if (!STp->rew_at_close) {
4867 STps = &(STp->ps[STp->partition]);
4868 if (!STm->sysv || STps->rw != ST_READING) {
4869 if (STp->can_bsr)
4870 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4871 else if (STps->eof == ST_FM_HIT) {
4872 result = cross_eof(STp, &SRpnt, 0);
4873 if (result) {
4874 if (STps->drv_file >= 0)
4875 STps->drv_file++;
4876 STps->drv_block = 0;
4877 STps->eof = ST_FM;
4878 }
4879 else
4880 STps->eof = ST_NOEOF;
4881 }
4882 }
4883 else if ((STps->eof == ST_NOEOF &&
4884 !(result = cross_eof(STp, &SRpnt, 1))) ||
4885 STps->eof == ST_FM_HIT) {
4886 if (STps->drv_file >= 0)
4887 STps->drv_file++;
4888 STps->drv_block = 0;
4889 STps->eof = ST_FM;
4890 }
4891 }
4892
4893out:
4894 if (STp->rew_at_close) {
4895 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4896 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4897 if (result == 0 && result2 < 0)
4898 result = result2;
4899 }
4900 if (SRpnt) osst_release_request(SRpnt);
4901
4902 if (STp->abort_count || STp->recover_count) {
4903 printk(KERN_INFO "%s:I:", name);
4904 if (STp->abort_count)
4905 printk(" %d unrecovered errors", STp->abort_count);
4906 if (STp->recover_count)
4907 printk(" %d recovered errors", STp->recover_count);
4908 if (STp->write_count)
4909 printk(" in %d frames written", STp->write_count);
4910 if (STp->read_count)
4911 printk(" in %d frames read", STp->read_count);
4912 printk("\n");
4913 STp->recover_count = 0;
4914 STp->abort_count = 0;
4915 }
4916 STp->write_count = 0;
4917 STp->read_count = 0;
4918
4919 return result;
4920}
4921
4922
4923/* Close the device and release it */
4924static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4925{
4926 int result = 0;
4927 struct osst_tape * STp = filp->private_data;
4928
4929 if (STp->door_locked == ST_LOCKED_AUTO)
4930 do_door_lock(STp, 0);
4931
4932 if (STp->raw)
4933 STp->header_ok = 0;
4934
4935 normalize_buffer(STp->buffer);
4936 write_lock(&os_scsi_tapes_lock);
4937 STp->in_use = 0;
4938 write_unlock(&os_scsi_tapes_lock);
4939
4940 scsi_device_put(STp->device);
4941
4942 return result;
4943}
4944
4945
4946/* The ioctl command */
4947static long osst_ioctl(struct file * file,
4948 unsigned int cmd_in, unsigned long arg)
4949{
4950 int i, cmd_nr, cmd_type, blk, retval = 0;
4951 struct st_modedef * STm;
4952 struct st_partstat * STps;
4953 struct osst_request * SRpnt = NULL;
4954 struct osst_tape * STp = file->private_data;
4955 char * name = tape_name(STp);
4956 void __user * p = (void __user *)arg;
4957
4958 mutex_lock(&osst_int_mutex);
4959 if (mutex_lock_interruptible(&STp->lock)) {
4960 mutex_unlock(&osst_int_mutex);
4961 return -ERESTARTSYS;
4962 }
4963
4964#if DEBUG
4965 if (debugging && !STp->in_use) {
4966 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4967 retval = (-EIO);
4968 goto out;
4969 }
4970#endif
4971 STm = &(STp->modes[STp->current_mode]);
4972 STps = &(STp->ps[STp->partition]);
4973
4974 /*
4975 * If we are in the middle of error recovery, don't let anyone
4976 * else try and use this device. Also, if error recovery fails, it
4977 * may try and take the device offline, in which case all further
4978 * access to the device is prohibited.
4979 */
4980 retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in,
4981 file->f_flags & O_NDELAY);
4982 if (retval)
4983 goto out;
4984
4985 cmd_type = _IOC_TYPE(cmd_in);
4986 cmd_nr = _IOC_NR(cmd_in);
4987#if DEBUG
4988 printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4989 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4990#endif
4991 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4992 struct mtop mtc;
4993 int auto_weof = 0;
4994
4995 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4996 retval = (-EINVAL);
4997 goto out;
4998 }
4999
5000 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
5001 if (i) {
5002 retval = (-EFAULT);
5003 goto out;
5004 }
5005
5006 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
5007 printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
5008 retval = (-EPERM);
5009 goto out;
5010 }
5011
5012 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
5013 retval = (-ENXIO);
5014 goto out;
5015 }
5016
5017 if (!STp->pos_unknown) {
5018
5019 if (STps->eof == ST_FM_HIT) {
5020 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
5021 mtc.mt_count -= 1;
5022 if (STps->drv_file >= 0)
5023 STps->drv_file += 1;
5024 }
5025 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
5026 mtc.mt_count += 1;
5027 if (STps->drv_file >= 0)
5028 STps->drv_file += 1;
5029 }
5030 }
5031
5032 if (mtc.mt_op == MTSEEK) {
5033 /* Old position must be restored if partition will be changed */
5034 i = !STp->can_partitions || (STp->new_partition != STp->partition);
5035 }
5036 else {
5037 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
5038 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
5039 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
5040 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
5041 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
5042 mtc.mt_op == MTCOMPRESSION;
5043 }
5044 i = osst_flush_buffer(STp, &SRpnt, i);
5045 if (i < 0) {
5046 retval = i;
5047 goto out;
5048 }
5049 }
5050 else {
5051 /*
5052 * If there was a bus reset, block further access
5053 * to this device. If the user wants to rewind the tape,
5054 * then reset the flag and allow access again.
5055 */
5056 if(mtc.mt_op != MTREW &&
5057 mtc.mt_op != MTOFFL &&
5058 mtc.mt_op != MTRETEN &&
5059 mtc.mt_op != MTERASE &&
5060 mtc.mt_op != MTSEEK &&
5061 mtc.mt_op != MTEOM) {
5062 retval = (-EIO);
5063 goto out;
5064 }
5065 reset_state(STp);
5066 /* remove this when the midlevel properly clears was_reset */
5067 STp->device->was_reset = 0;
5068 }
5069
5070 if (mtc.mt_op != MTCOMPRESSION && mtc.mt_op != MTLOCK &&
5071 mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
5072 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETDRVBUFFER &&
5073 mtc.mt_op != MTMKPART && mtc.mt_op != MTSETPART &&
5074 mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM ) {
5075
5076 /*
5077 * The user tells us to move to another position on the tape.
5078 * If we were appending to the tape content, that would leave
5079 * the tape without proper end, in that case write EOD and
5080 * update the header to reflect its position.
5081 */
5082#if DEBUG
5083 printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
5084 STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
5085 STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
5086 STp->logical_blk_num, STps->drv_file, STps->drv_block );
5087#endif
5088 if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
5089 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
5090 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5091 i = osst_write_trailer(STp, &SRpnt,
5092 !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
5093#if DEBUG
5094 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
5095 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
5096 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
5097#endif
5098 if (i < 0) {
5099 retval = i;
5100 goto out;
5101 }
5102 }
5103 STps->rw = ST_IDLE;
5104 }
5105
5106 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
5107 do_door_lock(STp, 0); /* Ignore result! */
5108
5109 if (mtc.mt_op == MTSETDRVBUFFER &&
5110 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
5111 retval = osst_set_options(STp, mtc.mt_count);
5112 goto out;
5113 }
5114
5115 if (mtc.mt_op == MTSETPART) {
5116 if (mtc.mt_count >= STp->nbr_partitions)
5117 retval = -EINVAL;
5118 else {
5119 STp->new_partition = mtc.mt_count;
5120 retval = 0;
5121 }
5122 goto out;
5123 }
5124
5125 if (mtc.mt_op == MTMKPART) {
5126 if (!STp->can_partitions) {
5127 retval = (-EINVAL);
5128 goto out;
5129 }
5130 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
5131 (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
5132 retval = i;
5133 goto out;
5134 }
5135 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5136 STp->ps[i].rw = ST_IDLE;
5137 STp->ps[i].at_sm = 0;
5138 STp->ps[i].last_block_valid = 0;
5139 }
5140 STp->partition = STp->new_partition = 0;
5141 STp->nbr_partitions = 1; /* Bad guess ?-) */
5142 STps->drv_block = STps->drv_file = 0;
5143 retval = 0;
5144 goto out;
5145 }
5146
5147 if (mtc.mt_op == MTSEEK) {
5148 if (STp->raw)
5149 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
5150 else
5151 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
5152 if (!STp->can_partitions)
5153 STp->ps[0].rw = ST_IDLE;
5154 retval = i;
5155 goto out;
5156 }
5157
5158 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
5159 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
5160 goto out;
5161 }
5162
5163 if (auto_weof)
5164 cross_eof(STp, &SRpnt, 0);
5165
5166 if (mtc.mt_op == MTCOMPRESSION)
5167 retval = -EINVAL; /* OnStream drives don't have compression hardware */
5168 else
5169 /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
5170 * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
5171 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
5172 goto out;
5173 }
5174
5175 if (!STm->defined) {
5176 retval = (-ENXIO);
5177 goto out;
5178 }
5179
5180 if ((i = osst_flush_buffer(STp, &SRpnt, 0)) < 0) {
5181 retval = i;
5182 goto out;
5183 }
5184
5185 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
5186 struct mtget mt_status;
5187
5188 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
5189 retval = (-EINVAL);
5190 goto out;
5191 }
5192
5193 mt_status.mt_type = MT_ISONSTREAM_SC;
5194 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
5195 mt_status.mt_dsreg =
5196 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
5197 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
5198 mt_status.mt_blkno = STps->drv_block;
5199 mt_status.mt_fileno = STps->drv_file;
5200 if (STp->block_size != 0) {
5201 if (STps->rw == ST_WRITING)
5202 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
5203 else if (STps->rw == ST_READING)
5204 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
5205 STp->block_size - 1) / STp->block_size;
5206 }
5207
5208 mt_status.mt_gstat = 0;
5209 if (STp->drv_write_prot)
5210 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
5211 if (mt_status.mt_blkno == 0) {
5212 if (mt_status.mt_fileno == 0)
5213 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
5214 else
5215 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
5216 }
5217 mt_status.mt_resid = STp->partition;
5218 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
5219 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
5220 else if (STps->eof >= ST_EOM_OK)
5221 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
5222 if (STp->density == 1)
5223 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
5224 else if (STp->density == 2)
5225 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
5226 else if (STp->density == 3)
5227 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
5228 if (STp->ready == ST_READY)
5229 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
5230 if (STp->ready == ST_NO_TAPE)
5231 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5232 if (STps->at_sm)
5233 mt_status.mt_gstat |= GMT_SM(0xffffffff);
5234 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5235 STp->drv_buffer != 0)
5236 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5237
5238 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5239 if (i) {
5240 retval = (-EFAULT);
5241 goto out;
5242 }
5243
5244 STp->recover_erreg = 0; /* Clear after read */
5245 retval = 0;
5246 goto out;
5247 } /* End of MTIOCGET */
5248
5249 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5250 struct mtpos mt_pos;
5251
5252 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5253 retval = (-EINVAL);
5254 goto out;
5255 }
5256 if (STp->raw)
5257 blk = osst_get_frame_position(STp, &SRpnt);
5258 else
5259 blk = osst_get_sector(STp, &SRpnt);
5260 if (blk < 0) {
5261 retval = blk;
5262 goto out;
5263 }
5264 mt_pos.mt_blkno = blk;
5265 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5266 if (i)
5267 retval = -EFAULT;
5268 goto out;
5269 }
5270 if (SRpnt) osst_release_request(SRpnt);
5271
5272 mutex_unlock(&STp->lock);
5273
5274 retval = scsi_ioctl(STp->device, cmd_in, p);
5275 mutex_unlock(&osst_int_mutex);
5276 return retval;
5277
5278out:
5279 if (SRpnt) osst_release_request(SRpnt);
5280
5281 mutex_unlock(&STp->lock);
5282 mutex_unlock(&osst_int_mutex);
5283
5284 return retval;
5285}
5286
5287#ifdef CONFIG_COMPAT
5288static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
5289{
5290 struct osst_tape *STp = file->private_data;
5291 struct scsi_device *sdev = STp->device;
5292 int ret = -ENOIOCTLCMD;
5293 if (sdev->host->hostt->compat_ioctl) {
5294
5295 ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
5296
5297 }
5298 return ret;
5299}
5300#endif
5301
5302
5303
5304/* Memory handling routines */
5305
5306/* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5307static struct osst_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5308{
5309 int i;
5310 gfp_t priority;
5311 struct osst_buffer *tb;
5312
5313 if (from_initialization)
5314 priority = GFP_ATOMIC;
5315 else
5316 priority = GFP_KERNEL;
5317
5318 i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5319 tb = kzalloc(i, priority);
5320 if (!tb) {
5321 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5322 return NULL;
5323 }
5324
5325 tb->sg_segs = tb->orig_sg_segs = 0;
5326 tb->use_sg = max_sg;
5327 tb->in_use = 1;
5328 tb->dma = need_dma;
5329 tb->buffer_size = 0;
5330#if DEBUG
5331 if (debugging)
5332 printk(OSST_DEB_MSG
5333 "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5334 i, max_sg, need_dma);
5335#endif
5336 return tb;
5337}
5338
5339/* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5340static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
5341{
5342 int segs, nbr, max_segs, b_size, order, got;
5343 gfp_t priority;
5344
5345 if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5346 return 1;
5347
5348 if (STbuffer->sg_segs) {
5349 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5350 normalize_buffer(STbuffer);
5351 }
5352 /* See how many segments we can use -- need at least two */
5353 nbr = max_segs = STbuffer->use_sg;
5354 if (nbr <= 2)
5355 return 0;
5356
5357 priority = GFP_KERNEL /* | __GFP_NOWARN */;
5358 if (need_dma)
5359 priority |= GFP_DMA;
5360
5361 /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5362 big enough to reach the goal (code assumes no segments in place) */
5363 for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5364 struct page *page = alloc_pages(priority, order);
5365
5366 STbuffer->sg[0].offset = 0;
5367 if (page != NULL) {
5368 sg_set_page(&STbuffer->sg[0], page, b_size, 0);
5369 STbuffer->b_data = page_address(page);
5370 break;
5371 }
5372 }
5373 if (sg_page(&STbuffer->sg[0]) == NULL) {
5374 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5375 return 0;
5376 }
5377 /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5378 for (segs=STbuffer->sg_segs=1, got=b_size;
5379 segs < max_segs && got < OS_FRAME_SIZE; ) {
5380 struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5381 STbuffer->sg[segs].offset = 0;
5382 if (page == NULL) {
5383 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5384 OS_FRAME_SIZE);
5385#if DEBUG
5386 STbuffer->buffer_size = got;
5387#endif
5388 normalize_buffer(STbuffer);
5389 return 0;
5390 }
5391 sg_set_page(&STbuffer->sg[segs], page, (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size, 0);
5392 got += STbuffer->sg[segs].length;
5393 STbuffer->buffer_size = got;
5394 STbuffer->sg_segs = ++segs;
5395 }
5396#if DEBUG
5397 if (debugging) {
5398 printk(OSST_DEB_MSG
5399 "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5400 got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5401 printk(OSST_DEB_MSG
5402 "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5403 STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5404 STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5405 }
5406#endif
5407
5408 return 1;
5409}
5410
5411
5412/* Release the segments */
5413static void normalize_buffer(struct osst_buffer *STbuffer)
5414{
5415 int i, order, b_size;
5416
5417 for (i=0; i < STbuffer->sg_segs; i++) {
5418
5419 for (b_size = PAGE_SIZE, order = 0;
5420 b_size < STbuffer->sg[i].length;
5421 b_size *= 2, order++);
5422
5423 __free_pages(sg_page(&STbuffer->sg[i]), order);
5424 STbuffer->buffer_size -= STbuffer->sg[i].length;
5425 }
5426#if DEBUG
5427 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5428 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5429 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5430#endif
5431 STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5432}
5433
5434
5435/* Move data from the user buffer to the tape buffer. Returns zero (success) or
5436 negative error code. */
5437static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, int do_count)
5438{
5439 int i, cnt, res, offset;
5440
5441 for (i=0, offset=st_bp->buffer_bytes;
5442 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5443 offset -= st_bp->sg[i].length;
5444 if (i == st_bp->sg_segs) { /* Should never happen */
5445 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5446 return (-EIO);
5447 }
5448 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5449 cnt = st_bp->sg[i].length - offset < do_count ?
5450 st_bp->sg[i].length - offset : do_count;
5451 res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt);
5452 if (res)
5453 return (-EFAULT);
5454 do_count -= cnt;
5455 st_bp->buffer_bytes += cnt;
5456 ubp += cnt;
5457 offset = 0;
5458 }
5459 if (do_count) { /* Should never happen */
5460 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5461 do_count);
5462 return (-EIO);
5463 }
5464 return 0;
5465}
5466
5467
5468/* Move data from the tape buffer to the user buffer. Returns zero (success) or
5469 negative error code. */
5470static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count)
5471{
5472 int i, cnt, res, offset;
5473
5474 for (i=0, offset=st_bp->read_pointer;
5475 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5476 offset -= st_bp->sg[i].length;
5477 if (i == st_bp->sg_segs) { /* Should never happen */
5478 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5479 return (-EIO);
5480 }
5481 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5482 cnt = st_bp->sg[i].length - offset < do_count ?
5483 st_bp->sg[i].length - offset : do_count;
5484 res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt);
5485 if (res)
5486 return (-EFAULT);
5487 do_count -= cnt;
5488 st_bp->buffer_bytes -= cnt;
5489 st_bp->read_pointer += cnt;
5490 ubp += cnt;
5491 offset = 0;
5492 }
5493 if (do_count) { /* Should never happen */
5494 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5495 return (-EIO);
5496 }
5497 return 0;
5498}
5499
5500/* Sets the tail of the buffer after fill point to zero.
5501 Returns zero (success) or negative error code. */
5502static int osst_zero_buffer_tail(struct osst_buffer *st_bp)
5503{
5504 int i, offset, do_count, cnt;
5505
5506 for (i = 0, offset = st_bp->buffer_bytes;
5507 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5508 offset -= st_bp->sg[i].length;
5509 if (i == st_bp->sg_segs) { /* Should never happen */
5510 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5511 return (-EIO);
5512 }
5513 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5514 i < st_bp->sg_segs && do_count > 0; i++) {
5515 cnt = st_bp->sg[i].length - offset < do_count ?
5516 st_bp->sg[i].length - offset : do_count ;
5517 memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt);
5518 do_count -= cnt;
5519 offset = 0;
5520 }
5521 if (do_count) { /* Should never happen */
5522 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5523 return (-EIO);
5524 }
5525 return 0;
5526}
5527
5528/* Copy a osst 32K chunk of memory into the buffer.
5529 Returns zero (success) or negative error code. */
5530static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5531{
5532 int i, cnt, do_count = OS_DATA_SIZE;
5533
5534 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5535 cnt = st_bp->sg[i].length < do_count ?
5536 st_bp->sg[i].length : do_count ;
5537 memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt);
5538 do_count -= cnt;
5539 ptr += cnt;
5540 }
5541 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5542 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5543 do_count, i);
5544 return (-EIO);
5545 }
5546 return 0;
5547}
5548
5549/* Copy a osst 32K chunk of memory from the buffer.
5550 Returns zero (success) or negative error code. */
5551static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr)
5552{
5553 int i, cnt, do_count = OS_DATA_SIZE;
5554
5555 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5556 cnt = st_bp->sg[i].length < do_count ?
5557 st_bp->sg[i].length : do_count ;
5558 memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt);
5559 do_count -= cnt;
5560 ptr += cnt;
5561 }
5562 if (do_count || i != st_bp->sg_segs-1) { /* Should never happen */
5563 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5564 do_count, i);
5565 return (-EIO);
5566 }
5567 return 0;
5568}
5569
5570
5571/* Module housekeeping */
5572
5573static void validate_options (void)
5574{
5575 if (max_dev > 0)
5576 osst_max_dev = max_dev;
5577 if (write_threshold_kbs > 0)
5578 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5579 if (osst_write_threshold > osst_buffer_size)
5580 osst_write_threshold = osst_buffer_size;
5581 if (max_sg_segs >= OSST_FIRST_SG)
5582 osst_max_sg_segs = max_sg_segs;
5583#if DEBUG
5584 printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5585 osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5586#endif
5587}
5588
5589#ifndef MODULE
5590/* Set the boot options. Syntax: osst=xxx,yyy,...
5591 where xxx is write threshold in 1024 byte blocks,
5592 and yyy is number of s/g segments to use. */
5593static int __init osst_setup (char *str)
5594{
5595 int i, ints[5];
5596 char *stp;
5597
5598 stp = get_options(str, ARRAY_SIZE(ints), ints);
5599
5600 if (ints[0] > 0) {
5601 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5602 *parms[i].val = ints[i + 1];
5603 } else {
5604 while (stp != NULL) {
5605 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5606 int len = strlen(parms[i].name);
5607 if (!strncmp(stp, parms[i].name, len) &&
5608 (*(stp + len) == ':' || *(stp + len) == '=')) {
5609 *parms[i].val =
5610 simple_strtoul(stp + len + 1, NULL, 0);
5611 break;
5612 }
5613 }
5614 if (i >= ARRAY_SIZE(parms))
5615 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5616 stp);
5617 stp = strchr(stp, ',');
5618 if (stp)
5619 stp++;
5620 }
5621 }
5622
5623 return 1;
5624}
5625
5626__setup("osst=", osst_setup);
5627
5628#endif
5629
5630static const struct file_operations osst_fops = {
5631 .owner = THIS_MODULE,
5632 .read = osst_read,
5633 .write = osst_write,
5634 .unlocked_ioctl = osst_ioctl,
5635#ifdef CONFIG_COMPAT
5636 .compat_ioctl = osst_compat_ioctl,
5637#endif
5638 .open = os_scsi_tape_open,
5639 .flush = os_scsi_tape_flush,
5640 .release = os_scsi_tape_close,
5641 .llseek = noop_llseek,
5642};
5643
5644static int osst_supports(struct scsi_device * SDp)
5645{
5646 struct osst_support_data {
5647 char *vendor;
5648 char *model;
5649 char *rev;
5650 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5651 };
5652
5653static struct osst_support_data support_list[] = {
5654 /* {"XXX", "Yy-", "", NULL}, example */
5655 SIGS_FROM_OSST,
5656 {NULL, }};
5657
5658 struct osst_support_data *rp;
5659
5660 /* We are willing to drive OnStream SC-x0 as well as the
5661 * * IDE, ParPort, FireWire, USB variants, if accessible by
5662 * * emulation layer (ide-scsi, usb-storage, ...) */
5663
5664 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5665 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5666 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5667 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5668 return 1;
5669 return 0;
5670}
5671
5672/*
5673 * sysfs support for osst driver parameter information
5674 */
5675
5676static ssize_t version_show(struct device_driver *ddd, char *buf)
5677{
5678 return snprintf(buf, PAGE_SIZE, "%s\n", osst_version);
5679}
5680
5681static DRIVER_ATTR_RO(version);
5682
5683static int osst_create_sysfs_files(struct device_driver *sysfs)
5684{
5685 return driver_create_file(sysfs, &driver_attr_version);
5686}
5687
5688static void osst_remove_sysfs_files(struct device_driver *sysfs)
5689{
5690 driver_remove_file(sysfs, &driver_attr_version);
5691}
5692
5693/*
5694 * sysfs support for accessing ADR header information
5695 */
5696
5697static ssize_t osst_adr_rev_show(struct device *dev,
5698 struct device_attribute *attr, char *buf)
5699{
5700 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5701 ssize_t l = 0;
5702
5703 if (STp && STp->header_ok && STp->linux_media)
5704 l = snprintf(buf, PAGE_SIZE, "%d.%d\n", STp->header_cache->major_rev, STp->header_cache->minor_rev);
5705 return l;
5706}
5707
5708DEVICE_ATTR(ADR_rev, S_IRUGO, osst_adr_rev_show, NULL);
5709
5710static ssize_t osst_linux_media_version_show(struct device *dev,
5711 struct device_attribute *attr,
5712 char *buf)
5713{
5714 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5715 ssize_t l = 0;
5716
5717 if (STp && STp->header_ok && STp->linux_media)
5718 l = snprintf(buf, PAGE_SIZE, "LIN%d\n", STp->linux_media_version);
5719 return l;
5720}
5721
5722DEVICE_ATTR(media_version, S_IRUGO, osst_linux_media_version_show, NULL);
5723
5724static ssize_t osst_capacity_show(struct device *dev,
5725 struct device_attribute *attr, char *buf)
5726{
5727 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5728 ssize_t l = 0;
5729
5730 if (STp && STp->header_ok && STp->linux_media)
5731 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->capacity);
5732 return l;
5733}
5734
5735DEVICE_ATTR(capacity, S_IRUGO, osst_capacity_show, NULL);
5736
5737static ssize_t osst_first_data_ppos_show(struct device *dev,
5738 struct device_attribute *attr,
5739 char *buf)
5740{
5741 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5742 ssize_t l = 0;
5743
5744 if (STp && STp->header_ok && STp->linux_media)
5745 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->first_data_ppos);
5746 return l;
5747}
5748
5749DEVICE_ATTR(BOT_frame, S_IRUGO, osst_first_data_ppos_show, NULL);
5750
5751static ssize_t osst_eod_frame_ppos_show(struct device *dev,
5752 struct device_attribute *attr,
5753 char *buf)
5754{
5755 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5756 ssize_t l = 0;
5757
5758 if (STp && STp->header_ok && STp->linux_media)
5759 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->eod_frame_ppos);
5760 return l;
5761}
5762
5763DEVICE_ATTR(EOD_frame, S_IRUGO, osst_eod_frame_ppos_show, NULL);
5764
5765static ssize_t osst_filemark_cnt_show(struct device *dev,
5766 struct device_attribute *attr, char *buf)
5767{
5768 struct osst_tape * STp = (struct osst_tape *) dev_get_drvdata (dev);
5769 ssize_t l = 0;
5770
5771 if (STp && STp->header_ok && STp->linux_media)
5772 l = snprintf(buf, PAGE_SIZE, "%d\n", STp->filemark_cnt);
5773 return l;
5774}
5775
5776DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
5777
5778static struct class *osst_sysfs_class;
5779
5780static int osst_sysfs_init(void)
5781{
5782 osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
5783 if (IS_ERR(osst_sysfs_class)) {
5784 printk(KERN_ERR "osst :W: Unable to register sysfs class\n");
5785 return PTR_ERR(osst_sysfs_class);
5786 }
5787
5788 return 0;
5789}
5790
5791static void osst_sysfs_destroy(dev_t dev)
5792{
5793 device_destroy(osst_sysfs_class, dev);
5794}
5795
5796static int osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * STp, char * name)
5797{
5798 struct device *osst_member;
5799 int err;
5800
5801 osst_member = device_create(osst_sysfs_class, device, dev, STp,
5802 "%s", name);
5803 if (IS_ERR(osst_member)) {
5804 printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
5805 return PTR_ERR(osst_member);
5806 }
5807
5808 err = device_create_file(osst_member, &dev_attr_ADR_rev);
5809 if (err)
5810 goto err_out;
5811 err = device_create_file(osst_member, &dev_attr_media_version);
5812 if (err)
5813 goto err_out;
5814 err = device_create_file(osst_member, &dev_attr_capacity);
5815 if (err)
5816 goto err_out;
5817 err = device_create_file(osst_member, &dev_attr_BOT_frame);
5818 if (err)
5819 goto err_out;
5820 err = device_create_file(osst_member, &dev_attr_EOD_frame);
5821 if (err)
5822 goto err_out;
5823 err = device_create_file(osst_member, &dev_attr_file_count);
5824 if (err)
5825 goto err_out;
5826
5827 return 0;
5828
5829err_out:
5830 osst_sysfs_destroy(dev);
5831 return err;
5832}
5833
5834static void osst_sysfs_cleanup(void)
5835{
5836 class_destroy(osst_sysfs_class);
5837}
5838
5839/*
5840 * osst startup / cleanup code
5841 */
5842
5843static int osst_probe(struct device *dev)
5844{
5845 struct scsi_device * SDp = to_scsi_device(dev);
5846 struct osst_tape * tpnt;
5847 struct st_modedef * STm;
5848 struct st_partstat * STps;
5849 struct osst_buffer * buffer;
5850 struct gendisk * drive;
5851 int i, dev_num, err = -ENODEV;
5852
5853 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5854 return -ENODEV;
5855
5856 drive = alloc_disk(1);
5857 if (!drive) {
5858 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5859 return -ENODEV;
5860 }
5861
5862 /* if this is the first attach, build the infrastructure */
5863 write_lock(&os_scsi_tapes_lock);
5864 if (os_scsi_tapes == NULL) {
5865 os_scsi_tapes = kmalloc_array(osst_max_dev,
5866 sizeof(struct osst_tape *),
5867 GFP_ATOMIC);
5868 if (os_scsi_tapes == NULL) {
5869 write_unlock(&os_scsi_tapes_lock);
5870 printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5871 goto out_put_disk;
5872 }
5873 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5874 }
5875
5876 if (osst_nr_dev >= osst_max_dev) {
5877 write_unlock(&os_scsi_tapes_lock);
5878 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5879 goto out_put_disk;
5880 }
5881
5882 /* find a free minor number */
5883 for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++)
5884 ;
5885 if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5886 dev_num = i;
5887
5888 /* allocate a struct osst_tape for this device */
5889 tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC);
5890 if (!tpnt) {
5891 write_unlock(&os_scsi_tapes_lock);
5892 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5893 goto out_put_disk;
5894 }
5895
5896 /* allocate a buffer for this device */
5897 i = SDp->host->sg_tablesize;
5898 if (osst_max_sg_segs < i)
5899 i = osst_max_sg_segs;
5900 buffer = new_tape_buffer(1, SDp->host->unchecked_isa_dma, i);
5901 if (buffer == NULL) {
5902 write_unlock(&os_scsi_tapes_lock);
5903 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5904 kfree(tpnt);
5905 goto out_put_disk;
5906 }
5907 os_scsi_tapes[dev_num] = tpnt;
5908 tpnt->buffer = buffer;
5909 tpnt->device = SDp;
5910 drive->private_data = &tpnt->driver;
5911 sprintf(drive->disk_name, "osst%d", dev_num);
5912 tpnt->driver = &osst_template;
5913 tpnt->drive = drive;
5914 tpnt->in_use = 0;
5915 tpnt->capacity = 0xfffff;
5916 tpnt->dirty = 0;
5917 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
5918 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5919 tpnt->density = 0;
5920 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5921 tpnt->can_bsr = OSST_IN_FILE_POS;
5922 tpnt->can_partitions = 0;
5923 tpnt->two_fm = OSST_TWO_FM;
5924 tpnt->fast_mteom = OSST_FAST_MTEOM;
5925 tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5926 tpnt->write_threshold = osst_write_threshold;
5927 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5928 tpnt->partition = 0;
5929 tpnt->new_partition = 0;
5930 tpnt->nbr_partitions = 0;
5931 tpnt->min_block = 512;
5932 tpnt->max_block = OS_DATA_SIZE;
5933 tpnt->timeout = OSST_TIMEOUT;
5934 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5935
5936 /* Recognize OnStream tapes */
5937 /* We don't need to test for OnStream, as this has been done in detect () */
5938 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5939 tpnt->omit_blklims = 1;
5940
5941 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) ||
5942 (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5943 tpnt->frame_in_buffer = 0;
5944 tpnt->header_ok = 0;
5945 tpnt->linux_media = 0;
5946 tpnt->header_cache = NULL;
5947
5948 for (i=0; i < ST_NBR_MODES; i++) {
5949 STm = &(tpnt->modes[i]);
5950 STm->defined = 0;
5951 STm->sysv = OSST_SYSV;
5952 STm->defaults_for_writes = 0;
5953 STm->do_async_writes = OSST_ASYNC_WRITES;
5954 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5955 STm->do_read_ahead = OSST_READ_AHEAD;
5956 STm->default_compression = ST_DONT_TOUCH;
5957 STm->default_blksize = 512;
5958 STm->default_density = (-1); /* No forced density */
5959 }
5960
5961 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5962 STps = &(tpnt->ps[i]);
5963 STps->rw = ST_IDLE;
5964 STps->eof = ST_NOEOF;
5965 STps->at_sm = 0;
5966 STps->last_block_valid = 0;
5967 STps->drv_block = (-1);
5968 STps->drv_file = (-1);
5969 }
5970
5971 tpnt->current_mode = 0;
5972 tpnt->modes[0].defined = 1;
5973 tpnt->modes[2].defined = 1;
5974 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0;
5975
5976 mutex_init(&tpnt->lock);
5977 osst_nr_dev++;
5978 write_unlock(&os_scsi_tapes_lock);
5979
5980 {
5981 char name[8];
5982
5983 /* Rewind entry */
5984 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num), dev, tpnt, tape_name(tpnt));
5985 if (err)
5986 goto out_free_buffer;
5987
5988 /* No-rewind entry */
5989 snprintf(name, 8, "%s%s", "n", tape_name(tpnt));
5990 err = osst_sysfs_add(MKDEV(OSST_MAJOR, dev_num + 128), dev, tpnt, name);
5991 if (err)
5992 goto out_free_sysfs1;
5993 }
5994
5995 sdev_printk(KERN_INFO, SDp,
5996 "osst :I: Attached OnStream %.5s tape as %s\n",
5997 SDp->model, tape_name(tpnt));
5998
5999 return 0;
6000
6001out_free_sysfs1:
6002 osst_sysfs_destroy(MKDEV(OSST_MAJOR, dev_num));
6003out_free_buffer:
6004 kfree(buffer);
6005out_put_disk:
6006 put_disk(drive);
6007 return err;
6008};
6009
6010static int osst_remove(struct device *dev)
6011{
6012 struct scsi_device * SDp = to_scsi_device(dev);
6013 struct osst_tape * tpnt;
6014 int i;
6015
6016 if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
6017 return 0;
6018
6019 write_lock(&os_scsi_tapes_lock);
6020 for(i=0; i < osst_max_dev; i++) {
6021 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
6022 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i));
6023 osst_sysfs_destroy(MKDEV(OSST_MAJOR, i+128));
6024 tpnt->device = NULL;
6025 put_disk(tpnt->drive);
6026 os_scsi_tapes[i] = NULL;
6027 osst_nr_dev--;
6028 write_unlock(&os_scsi_tapes_lock);
6029 vfree(tpnt->header_cache);
6030 if (tpnt->buffer) {
6031 normalize_buffer(tpnt->buffer);
6032 kfree(tpnt->buffer);
6033 }
6034 kfree(tpnt);
6035 return 0;
6036 }
6037 }
6038 write_unlock(&os_scsi_tapes_lock);
6039 return 0;
6040}
6041
6042static int __init init_osst(void)
6043{
6044 int err;
6045
6046 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
6047
6048 validate_options();
6049
6050 err = osst_sysfs_init();
6051 if (err)
6052 return err;
6053
6054 err = register_chrdev(OSST_MAJOR, "osst", &osst_fops);
6055 if (err < 0) {
6056 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
6057 goto err_out;
6058 }
6059
6060 err = scsi_register_driver(&osst_template.gendrv);
6061 if (err)
6062 goto err_out_chrdev;
6063
6064 err = osst_create_sysfs_files(&osst_template.gendrv);
6065 if (err)
6066 goto err_out_scsidrv;
6067
6068 return 0;
6069
6070err_out_scsidrv:
6071 scsi_unregister_driver(&osst_template.gendrv);
6072err_out_chrdev:
6073 unregister_chrdev(OSST_MAJOR, "osst");
6074err_out:
6075 osst_sysfs_cleanup();
6076 return err;
6077}
6078
6079static void __exit exit_osst (void)
6080{
6081 int i;
6082 struct osst_tape * STp;
6083
6084 osst_remove_sysfs_files(&osst_template.gendrv);
6085 scsi_unregister_driver(&osst_template.gendrv);
6086 unregister_chrdev(OSST_MAJOR, "osst");
6087 osst_sysfs_cleanup();
6088
6089 if (os_scsi_tapes) {
6090 for (i=0; i < osst_max_dev; ++i) {
6091 if (!(STp = os_scsi_tapes[i])) continue;
6092 /* This is defensive, supposed to happen during detach */
6093 vfree(STp->header_cache);
6094 if (STp->buffer) {
6095 normalize_buffer(STp->buffer);
6096 kfree(STp->buffer);
6097 }
6098 put_disk(STp->drive);
6099 kfree(STp);
6100 }
6101 kfree(os_scsi_tapes);
6102 }
6103 printk(KERN_INFO "osst :I: Unloaded.\n");
6104}
6105
6106module_init(init_osst);
6107module_exit(exit_osst);
diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h
deleted file mode 100644
index b90ae280853d..000000000000
--- a/drivers/scsi/osst.h
+++ /dev/null
@@ -1,651 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * $Header: /cvsroot/osst/Driver/osst.h,v 1.16 2005/01/01 21:13:35 wriede Exp $
4 */
5
6#include <asm/byteorder.h>
7#include <linux/completion.h>
8#include <linux/mutex.h>
9
10/* FIXME - rename and use the following two types or delete them!
11 * and the types really should go to st.h anyway...
12 * INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C)
13 */
14typedef struct {
15 unsigned device_type :5; /* Peripheral Device Type */
16 unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */
17 unsigned reserved1_6t0 :7; /* Reserved */
18 unsigned rmb :1; /* Removable Medium Bit */
19 unsigned ansi_version :3; /* ANSI Version */
20 unsigned ecma_version :3; /* ECMA Version */
21 unsigned iso_version :2; /* ISO Version */
22 unsigned response_format :4; /* Response Data Format */
23 unsigned reserved3_45 :2; /* Reserved */
24 unsigned reserved3_6 :1; /* TrmIOP - Reserved */
25 unsigned reserved3_7 :1; /* AENC - Reserved */
26 u8 additional_length; /* Additional Length (total_length-4) */
27 u8 rsv5, rsv6, rsv7; /* Reserved */
28 u8 vendor_id[8]; /* Vendor Identification */
29 u8 product_id[16]; /* Product Identification */
30 u8 revision_level[4]; /* Revision Level */
31 u8 vendor_specific[20]; /* Vendor Specific - Optional */
32 u8 reserved56t95[40]; /* Reserved - Optional */
33 /* Additional information may be returned */
34} idetape_inquiry_result_t;
35
36/*
37 * READ POSITION packet command - Data Format (From Table 6-57)
38 */
39typedef struct {
40 unsigned reserved0_10 :2; /* Reserved */
41 unsigned bpu :1; /* Block Position Unknown */
42 unsigned reserved0_543 :3; /* Reserved */
43 unsigned eop :1; /* End Of Partition */
44 unsigned bop :1; /* Beginning Of Partition */
45 u8 partition; /* Partition Number */
46 u8 reserved2, reserved3; /* Reserved */
47 u32 first_block; /* First Block Location */
48 u32 last_block; /* Last Block Location (Optional) */
49 u8 reserved12; /* Reserved */
50 u8 blocks_in_buffer[3]; /* Blocks In Buffer - (Optional) */
51 u32 bytes_in_buffer; /* Bytes In Buffer (Optional) */
52} idetape_read_position_result_t;
53
54/*
55 * Follows structures which are related to the SELECT SENSE / MODE SENSE
56 * packet commands.
57 */
58#define COMPRESSION_PAGE 0x0f
59#define COMPRESSION_PAGE_LENGTH 16
60
61#define CAPABILITIES_PAGE 0x2a
62#define CAPABILITIES_PAGE_LENGTH 20
63
64#define TAPE_PARAMTR_PAGE 0x2b
65#define TAPE_PARAMTR_PAGE_LENGTH 16
66
67#define NUMBER_RETRIES_PAGE 0x2f
68#define NUMBER_RETRIES_PAGE_LENGTH 4
69
70#define BLOCK_SIZE_PAGE 0x30
71#define BLOCK_SIZE_PAGE_LENGTH 4
72
73#define BUFFER_FILLING_PAGE 0x33
74#define BUFFER_FILLING_PAGE_LENGTH 4
75
76#define VENDOR_IDENT_PAGE 0x36
77#define VENDOR_IDENT_PAGE_LENGTH 8
78
79#define LOCATE_STATUS_PAGE 0x37
80#define LOCATE_STATUS_PAGE_LENGTH 0
81
82#define MODE_HEADER_LENGTH 4
83
84
85/*
86 * REQUEST SENSE packet command result - Data Format.
87 */
88typedef struct {
89 unsigned error_code :7; /* Current of deferred errors */
90 unsigned valid :1; /* The information field conforms to QIC-157C */
91 u8 reserved1 :8; /* Segment Number - Reserved */
92 unsigned sense_key :4; /* Sense Key */
93 unsigned reserved2_4 :1; /* Reserved */
94 unsigned ili :1; /* Incorrect Length Indicator */
95 unsigned eom :1; /* End Of Medium */
96 unsigned filemark :1; /* Filemark */
97 u32 information __attribute__ ((packed));
98 u8 asl; /* Additional sense length (n-7) */
99 u32 command_specific; /* Additional command specific information */
100 u8 asc; /* Additional Sense Code */
101 u8 ascq; /* Additional Sense Code Qualifier */
102 u8 replaceable_unit_code; /* Field Replaceable Unit Code */
103 unsigned sk_specific1 :7; /* Sense Key Specific */
104 unsigned sksv :1; /* Sense Key Specific information is valid */
105 u8 sk_specific2; /* Sense Key Specific */
106 u8 sk_specific3; /* Sense Key Specific */
107 u8 pad[2]; /* Padding to 20 bytes */
108} idetape_request_sense_result_t;
109
110/*
111 * Mode Parameter Header for the MODE SENSE packet command
112 */
113typedef struct {
114 u8 mode_data_length; /* Length of the following data transfer */
115 u8 medium_type; /* Medium Type */
116 u8 dsp; /* Device Specific Parameter */
117 u8 bdl; /* Block Descriptor Length */
118} osst_mode_parameter_header_t;
119
120/*
121 * Mode Parameter Block Descriptor the MODE SENSE packet command
122 *
123 * Support for block descriptors is optional.
124 */
125typedef struct {
126 u8 density_code; /* Medium density code */
127 u8 blocks[3]; /* Number of blocks */
128 u8 reserved4; /* Reserved */
129 u8 length[3]; /* Block Length */
130} osst_parameter_block_descriptor_t;
131
132/*
133 * The Data Compression Page, as returned by the MODE SENSE packet command.
134 */
135typedef struct {
136#if defined(__BIG_ENDIAN_BITFIELD)
137 unsigned ps :1;
138 unsigned reserved0 :1; /* Reserved */
139 unsigned page_code :6; /* Page Code - Should be 0xf */
140#elif defined(__LITTLE_ENDIAN_BITFIELD)
141 unsigned page_code :6; /* Page Code - Should be 0xf */
142 unsigned reserved0 :1; /* Reserved */
143 unsigned ps :1;
144#else
145#error "Please fix <asm/byteorder.h>"
146#endif
147 u8 page_length; /* Page Length - Should be 14 */
148#if defined(__BIG_ENDIAN_BITFIELD)
149 unsigned dce :1; /* Data Compression Enable */
150 unsigned dcc :1; /* Data Compression Capable */
151 unsigned reserved2 :6; /* Reserved */
152#elif defined(__LITTLE_ENDIAN_BITFIELD)
153 unsigned reserved2 :6; /* Reserved */
154 unsigned dcc :1; /* Data Compression Capable */
155 unsigned dce :1; /* Data Compression Enable */
156#else
157#error "Please fix <asm/byteorder.h>"
158#endif
159#if defined(__BIG_ENDIAN_BITFIELD)
160 unsigned dde :1; /* Data Decompression Enable */
161 unsigned red :2; /* Report Exception on Decompression */
162 unsigned reserved3 :5; /* Reserved */
163#elif defined(__LITTLE_ENDIAN_BITFIELD)
164 unsigned reserved3 :5; /* Reserved */
165 unsigned red :2; /* Report Exception on Decompression */
166 unsigned dde :1; /* Data Decompression Enable */
167#else
168#error "Please fix <asm/byteorder.h>"
169#endif
170 u32 ca; /* Compression Algorithm */
171 u32 da; /* Decompression Algorithm */
172 u8 reserved[4]; /* Reserved */
173} osst_data_compression_page_t;
174
175/*
176 * The Medium Partition Page, as returned by the MODE SENSE packet command.
177 */
178typedef struct {
179#if defined(__BIG_ENDIAN_BITFIELD)
180 unsigned ps :1;
181 unsigned reserved1_6 :1; /* Reserved */
182 unsigned page_code :6; /* Page Code - Should be 0x11 */
183#elif defined(__LITTLE_ENDIAN_BITFIELD)
184 unsigned page_code :6; /* Page Code - Should be 0x11 */
185 unsigned reserved1_6 :1; /* Reserved */
186 unsigned ps :1;
187#else
188#error "Please fix <asm/byteorder.h>"
189#endif
190 u8 page_length; /* Page Length - Should be 6 */
191 u8 map; /* Maximum Additional Partitions - Should be 0 */
192 u8 apd; /* Additional Partitions Defined - Should be 0 */
193#if defined(__BIG_ENDIAN_BITFIELD)
194 unsigned fdp :1; /* Fixed Data Partitions */
195 unsigned sdp :1; /* Should be 0 */
196 unsigned idp :1; /* Should be 0 */
197 unsigned psum :2; /* Should be 0 */
198 unsigned reserved4_012 :3; /* Reserved */
199#elif defined(__LITTLE_ENDIAN_BITFIELD)
200 unsigned reserved4_012 :3; /* Reserved */
201 unsigned psum :2; /* Should be 0 */
202 unsigned idp :1; /* Should be 0 */
203 unsigned sdp :1; /* Should be 0 */
204 unsigned fdp :1; /* Fixed Data Partitions */
205#else
206#error "Please fix <asm/byteorder.h>"
207#endif
208 u8 mfr; /* Medium Format Recognition */
209 u8 reserved[2]; /* Reserved */
210} osst_medium_partition_page_t;
211
212/*
213 * Capabilities and Mechanical Status Page
214 */
215typedef struct {
216#if defined(__BIG_ENDIAN_BITFIELD)
217 unsigned reserved1_67 :2;
218 unsigned page_code :6; /* Page code - Should be 0x2a */
219#elif defined(__LITTLE_ENDIAN_BITFIELD)
220 unsigned page_code :6; /* Page code - Should be 0x2a */
221 unsigned reserved1_67 :2;
222#else
223#error "Please fix <asm/byteorder.h>"
224#endif
225 u8 page_length; /* Page Length - Should be 0x12 */
226 u8 reserved2, reserved3;
227#if defined(__BIG_ENDIAN_BITFIELD)
228 unsigned reserved4_67 :2;
229 unsigned sprev :1; /* Supports SPACE in the reverse direction */
230 unsigned reserved4_1234 :4;
231 unsigned ro :1; /* Read Only Mode */
232#elif defined(__LITTLE_ENDIAN_BITFIELD)
233 unsigned ro :1; /* Read Only Mode */
234 unsigned reserved4_1234 :4;
235 unsigned sprev :1; /* Supports SPACE in the reverse direction */
236 unsigned reserved4_67 :2;
237#else
238#error "Please fix <asm/byteorder.h>"
239#endif
240#if defined(__BIG_ENDIAN_BITFIELD)
241 unsigned reserved5_67 :2;
242 unsigned qfa :1; /* Supports the QFA two partition formats */
243 unsigned reserved5_4 :1;
244 unsigned efmt :1; /* Supports ERASE command initiated formatting */
245 unsigned reserved5_012 :3;
246#elif defined(__LITTLE_ENDIAN_BITFIELD)
247 unsigned reserved5_012 :3;
248 unsigned efmt :1; /* Supports ERASE command initiated formatting */
249 unsigned reserved5_4 :1;
250 unsigned qfa :1; /* Supports the QFA two partition formats */
251 unsigned reserved5_67 :2;
252#else
253#error "Please fix <asm/byteorder.h>"
254#endif
255#if defined(__BIG_ENDIAN_BITFIELD)
256 unsigned cmprs :1; /* Supports data compression */
257 unsigned ecc :1; /* Supports error correction */
258 unsigned reserved6_45 :2; /* Reserved */
259 unsigned eject :1; /* The device can eject the volume */
260 unsigned prevent :1; /* The device defaults in the prevent state after power up */
261 unsigned locked :1; /* The volume is locked */
262 unsigned lock :1; /* Supports locking the volume */
263#elif defined(__LITTLE_ENDIAN_BITFIELD)
264 unsigned lock :1; /* Supports locking the volume */
265 unsigned locked :1; /* The volume is locked */
266 unsigned prevent :1; /* The device defaults in the prevent state after power up */
267 unsigned eject :1; /* The device can eject the volume */
268 unsigned reserved6_45 :2; /* Reserved */
269 unsigned ecc :1; /* Supports error correction */
270 unsigned cmprs :1; /* Supports data compression */
271#else
272#error "Please fix <asm/byteorder.h>"
273#endif
274#if defined(__BIG_ENDIAN_BITFIELD)
275 unsigned blk32768 :1; /* slowb - the device restricts the byte count for PIO */
276 /* transfers for slow buffer memory ??? */
277 /* Also 32768 block size in some cases */
278 unsigned reserved7_3_6 :4;
279 unsigned blk1024 :1; /* Supports 1024 bytes block size */
280 unsigned blk512 :1; /* Supports 512 bytes block size */
281 unsigned reserved7_0 :1;
282#elif defined(__LITTLE_ENDIAN_BITFIELD)
283 unsigned reserved7_0 :1;
284 unsigned blk512 :1; /* Supports 512 bytes block size */
285 unsigned blk1024 :1; /* Supports 1024 bytes block size */
286 unsigned reserved7_3_6 :4;
287 unsigned blk32768 :1; /* slowb - the device restricts the byte count for PIO */
288 /* transfers for slow buffer memory ??? */
289 /* Also 32768 block size in some cases */
290#else
291#error "Please fix <asm/byteorder.h>"
292#endif
293 __be16 max_speed; /* Maximum speed supported in KBps */
294 u8 reserved10, reserved11;
295 __be16 ctl; /* Continuous Transfer Limit in blocks */
296 __be16 speed; /* Current Speed, in KBps */
297 __be16 buffer_size; /* Buffer Size, in 512 bytes */
298 u8 reserved18, reserved19;
299} osst_capabilities_page_t;
300
301/*
302 * Block Size Page
303 */
304typedef struct {
305#if defined(__BIG_ENDIAN_BITFIELD)
306 unsigned ps :1;
307 unsigned reserved1_6 :1;
308 unsigned page_code :6; /* Page code - Should be 0x30 */
309#elif defined(__LITTLE_ENDIAN_BITFIELD)
310 unsigned page_code :6; /* Page code - Should be 0x30 */
311 unsigned reserved1_6 :1;
312 unsigned ps :1;
313#else
314#error "Please fix <asm/byteorder.h>"
315#endif
316 u8 page_length; /* Page Length - Should be 2 */
317 u8 reserved2;
318#if defined(__BIG_ENDIAN_BITFIELD)
319 unsigned one :1;
320 unsigned reserved2_6 :1;
321 unsigned record32_5 :1;
322 unsigned record32 :1;
323 unsigned reserved2_23 :2;
324 unsigned play32_5 :1;
325 unsigned play32 :1;
326#elif defined(__LITTLE_ENDIAN_BITFIELD)
327 unsigned play32 :1;
328 unsigned play32_5 :1;
329 unsigned reserved2_23 :2;
330 unsigned record32 :1;
331 unsigned record32_5 :1;
332 unsigned reserved2_6 :1;
333 unsigned one :1;
334#else
335#error "Please fix <asm/byteorder.h>"
336#endif
337} osst_block_size_page_t;
338
339/*
340 * Tape Parameters Page
341 */
342typedef struct {
343#if defined(__BIG_ENDIAN_BITFIELD)
344 unsigned ps :1;
345 unsigned reserved1_6 :1;
346 unsigned page_code :6; /* Page code - Should be 0x2b */
347#elif defined(__LITTLE_ENDIAN_BITFIELD)
348 unsigned page_code :6; /* Page code - Should be 0x2b */
349 unsigned reserved1_6 :1;
350 unsigned ps :1;
351#else
352#error "Please fix <asm/byteorder.h>"
353#endif
354 u8 reserved2;
355 u8 density;
356 u8 reserved3,reserved4;
357 __be16 segtrk;
358 __be16 trks;
359 u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10;
360} osst_tape_paramtr_page_t;
361
362/* OnStream definitions */
363
364#define OS_CONFIG_PARTITION (0xff)
365#define OS_DATA_PARTITION (0)
366#define OS_PARTITION_VERSION (1)
367
368/*
369 * partition
370 */
371typedef struct os_partition_s {
372 __u8 partition_num;
373 __u8 par_desc_ver;
374 __be16 wrt_pass_cntr;
375 __be32 first_frame_ppos;
376 __be32 last_frame_ppos;
377 __be32 eod_frame_ppos;
378} os_partition_t;
379
380/*
381 * DAT entry
382 */
383typedef struct os_dat_entry_s {
384 __be32 blk_sz;
385 __be16 blk_cnt;
386 __u8 flags;
387 __u8 reserved;
388} os_dat_entry_t;
389
390/*
391 * DAT
392 */
393#define OS_DAT_FLAGS_DATA (0xc)
394#define OS_DAT_FLAGS_MARK (0x1)
395
396typedef struct os_dat_s {
397 __u8 dat_sz;
398 __u8 reserved1;
399 __u8 entry_cnt;
400 __u8 reserved3;
401 os_dat_entry_t dat_list[16];
402} os_dat_t;
403
404/*
405 * Frame types
406 */
407#define OS_FRAME_TYPE_FILL (0)
408#define OS_FRAME_TYPE_EOD (1 << 0)
409#define OS_FRAME_TYPE_MARKER (1 << 1)
410#define OS_FRAME_TYPE_HEADER (1 << 3)
411#define OS_FRAME_TYPE_DATA (1 << 7)
412
413/*
414 * AUX
415 */
416typedef struct os_aux_s {
417 __be32 format_id; /* hardware compatibility AUX is based on */
418 char application_sig[4]; /* driver used to write this media */
419 __be32 hdwr; /* reserved */
420 __be32 update_frame_cntr; /* for configuration frame */
421 __u8 frame_type;
422 __u8 frame_type_reserved;
423 __u8 reserved_18_19[2];
424 os_partition_t partition;
425 __u8 reserved_36_43[8];
426 __be32 frame_seq_num;
427 __be32 logical_blk_num_high;
428 __be32 logical_blk_num;
429 os_dat_t dat;
430 __u8 reserved188_191[4];
431 __be32 filemark_cnt;
432 __be32 phys_fm;
433 __be32 last_mark_ppos;
434 __u8 reserved204_223[20];
435
436 /*
437 * __u8 app_specific[32];
438 *
439 * Linux specific fields:
440 */
441 __be32 next_mark_ppos; /* when known, points to next marker */
442 __be32 last_mark_lbn; /* storing log_blk_num of last mark is extends ADR spec */
443 __u8 linux_specific[24];
444
445 __u8 reserved_256_511[256];
446} os_aux_t;
447
448#define OS_FM_TAB_MAX 1024
449
450typedef struct os_fm_tab_s {
451 __u8 fm_part_num;
452 __u8 reserved_1;
453 __u8 fm_tab_ent_sz;
454 __u8 reserved_3;
455 __be16 fm_tab_ent_cnt;
456 __u8 reserved6_15[10];
457 __be32 fm_tab_ent[OS_FM_TAB_MAX];
458} os_fm_tab_t;
459
460typedef struct os_ext_trk_ey_s {
461 __u8 et_part_num;
462 __u8 fmt;
463 __be16 fm_tab_off;
464 __u8 reserved4_7[4];
465 __be32 last_hlb_hi;
466 __be32 last_hlb;
467 __be32 last_pp;
468 __u8 reserved20_31[12];
469} os_ext_trk_ey_t;
470
471typedef struct os_ext_trk_tb_s {
472 __u8 nr_stream_part;
473 __u8 reserved_1;
474 __u8 et_ent_sz;
475 __u8 reserved3_15[13];
476 os_ext_trk_ey_t dat_ext_trk_ey;
477 os_ext_trk_ey_t qfa_ext_trk_ey;
478} os_ext_trk_tb_t;
479
480typedef struct os_header_s {
481 char ident_str[8];
482 __u8 major_rev;
483 __u8 minor_rev;
484 __be16 ext_trk_tb_off;
485 __u8 reserved12_15[4];
486 __u8 pt_par_num;
487 __u8 pt_reserved1_3[3];
488 os_partition_t partition[16];
489 __be32 cfg_col_width;
490 __be32 dat_col_width;
491 __be32 qfa_col_width;
492 __u8 cartridge[16];
493 __u8 reserved304_511[208];
494 __be32 old_filemark_list[16680/4]; /* in ADR 1.4 __u8 track_table[16680] */
495 os_ext_trk_tb_t ext_track_tb;
496 __u8 reserved17272_17735[464];
497 os_fm_tab_t dat_fm_tab;
498 os_fm_tab_t qfa_fm_tab;
499 __u8 reserved25960_32767[6808];
500} os_header_t;
501
502
503/*
504 * OnStream ADRL frame
505 */
506#define OS_FRAME_SIZE (32 * 1024 + 512)
507#define OS_DATA_SIZE (32 * 1024)
508#define OS_AUX_SIZE (512)
509//#define OSST_MAX_SG 2
510
511/* The OnStream tape buffer descriptor. */
512struct osst_buffer {
513 unsigned char in_use;
514 unsigned char dma; /* DMA-able buffer */
515 int buffer_size;
516 int buffer_blocks;
517 int buffer_bytes;
518 int read_pointer;
519 int writing;
520 int midlevel_result;
521 int syscall_result;
522 struct osst_request *last_SRpnt;
523 struct st_cmdstatus cmdstat;
524 struct rq_map_data map_data;
525 unsigned char *b_data;
526 os_aux_t *aux; /* onstream AUX structure at end of each block */
527 unsigned short use_sg; /* zero or number of s/g segments for this adapter */
528 unsigned short sg_segs; /* number of segments in s/g list */
529 unsigned short orig_sg_segs; /* number of segments allocated at first try */
530 struct scatterlist sg[1]; /* MUST BE last item */
531} ;
532
533/* The OnStream tape drive descriptor */
534struct osst_tape {
535 struct scsi_driver *driver;
536 unsigned capacity;
537 struct scsi_device *device;
538 struct mutex lock; /* for serialization */
539 struct completion wait; /* for SCSI commands */
540 struct osst_buffer * buffer;
541
542 /* Drive characteristics */
543 unsigned char omit_blklims;
544 unsigned char do_auto_lock;
545 unsigned char can_bsr;
546 unsigned char can_partitions;
547 unsigned char two_fm;
548 unsigned char fast_mteom;
549 unsigned char restr_dma;
550 unsigned char scsi2_logical;
551 unsigned char default_drvbuffer; /* 0xff = don't touch, value 3 bits */
552 unsigned char pos_unknown; /* after reset position unknown */
553 int write_threshold;
554 int timeout; /* timeout for normal commands */
555 int long_timeout; /* timeout for commands known to take long time*/
556
557 /* Mode characteristics */
558 struct st_modedef modes[ST_NBR_MODES];
559 int current_mode;
560
561 /* Status variables */
562 int partition;
563 int new_partition;
564 int nbr_partitions; /* zero until partition support enabled */
565 struct st_partstat ps[ST_NBR_PARTITIONS];
566 unsigned char dirty;
567 unsigned char ready;
568 unsigned char write_prot;
569 unsigned char drv_write_prot;
570 unsigned char in_use;
571 unsigned char blksize_changed;
572 unsigned char density_changed;
573 unsigned char compression_changed;
574 unsigned char drv_buffer;
575 unsigned char density;
576 unsigned char door_locked;
577 unsigned char rew_at_close;
578 unsigned char inited;
579 int block_size;
580 int min_block;
581 int max_block;
582 int recover_count; /* from tape opening */
583 int abort_count;
584 int write_count;
585 int read_count;
586 int recover_erreg; /* from last status call */
587 /*
588 * OnStream specific data
589 */
590 int os_fw_rev; /* the firmware revision * 10000 */
591 unsigned char raw; /* flag OnStream raw access (32.5KB block size) */
592 unsigned char poll; /* flag that this drive needs polling (IDE|firmware) */
593 unsigned char frame_in_buffer; /* flag that the frame as per frame_seq_number
594 * has been read into STp->buffer and is valid */
595 int frame_seq_number; /* logical frame number */
596 int logical_blk_num; /* logical block number */
597 unsigned first_frame_position; /* physical frame to be transferred to/from host */
598 unsigned last_frame_position; /* physical frame to be transferd to/from tape */
599 int cur_frames; /* current number of frames in internal buffer */
600 int max_frames; /* max number of frames in internal buffer */
601 char application_sig[5]; /* application signature */
602 unsigned char fast_open; /* flag that reminds us we didn't check headers at open */
603 unsigned short wrt_pass_cntr; /* write pass counter */
604 int update_frame_cntr; /* update frame counter */
605 int onstream_write_error; /* write error recovery active */
606 int header_ok; /* header frame verified ok */
607 int linux_media; /* reading linux-specifc media */
608 int linux_media_version;
609 os_header_t * header_cache; /* cache is kept for filemark positions */
610 int filemark_cnt;
611 int first_mark_ppos;
612 int last_mark_ppos;
613 int last_mark_lbn; /* storing log_blk_num of last mark is extends ADR spec */
614 int first_data_ppos;
615 int eod_frame_ppos;
616 int eod_frame_lfa;
617 int write_type; /* used in write error recovery */
618 int read_error_frame; /* used in read error recovery */
619 unsigned long cmd_start_time;
620 unsigned long max_cmd_time;
621
622#if DEBUG
623 unsigned char write_pending;
624 int nbr_finished;
625 int nbr_waits;
626 unsigned char last_cmnd[6];
627 unsigned char last_sense[16];
628#endif
629 struct gendisk *drive;
630} ;
631
632/* scsi tape command */
633struct osst_request {
634 unsigned char cmd[MAX_COMMAND_SIZE];
635 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
636 int result;
637 struct osst_tape *stp;
638 struct completion *waiting;
639 struct bio *bio;
640};
641
642/* Values of write_type */
643#define OS_WRITE_DATA 0
644#define OS_WRITE_EOD 1
645#define OS_WRITE_NEW_MARK 2
646#define OS_WRITE_LAST_MARK 3
647#define OS_WRITE_HEADER 4
648#define OS_WRITE_FILLER 5
649
650/* Additional rw state */
651#define OS_WRITING_COMPLETE 3
diff --git a/drivers/scsi/osst_detect.h b/drivers/scsi/osst_detect.h
deleted file mode 100644
index 83c1d4fb11db..000000000000
--- a/drivers/scsi/osst_detect.h
+++ /dev/null
@@ -1,7 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#define SIGS_FROM_OSST \
3 {"OnStream", "SC-", "", "osst"}, \
4 {"OnStream", "DI-", "", "osst"}, \
5 {"OnStream", "DP-", "", "osst"}, \
6 {"OnStream", "FW-", "", "osst"}, \
7 {"OnStream", "USB", "", "osst"}
diff --git a/drivers/scsi/osst_options.h b/drivers/scsi/osst_options.h
deleted file mode 100644
index a6a389b88876..000000000000
--- a/drivers/scsi/osst_options.h
+++ /dev/null
@@ -1,107 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 The compile-time configurable defaults for the Linux SCSI tape driver.
4
5 Copyright 1995 Kai Makisara.
6
7 Last modified: Wed Sep 2 21:24:07 1998 by root@home
8
9 Changed (and renamed) for OnStream SCSI drives garloff@suse.de
10 2000-06-21
11
12 $Header: /cvsroot/osst/Driver/osst_options.h,v 1.6 2003/12/23 14:22:12 wriede Exp $
13*/
14
15#ifndef _OSST_OPTIONS_H
16#define _OSST_OPTIONS_H
17
18/* The minimum limit for the number of SCSI tape devices is determined by
19 OSST_MAX_TAPES. If the number of tape devices and the "slack" defined by
20 OSST_EXTRA_DEVS exceeds OSST_MAX_TAPES, the large number is used. */
21#define OSST_MAX_TAPES 4
22
23/* If OSST_IN_FILE_POS is nonzero, the driver positions the tape after the
24 record been read by the user program even if the tape has moved further
25 because of buffered reads. Should be set to zero to support also drives
26 that can't space backwards over records. NOTE: The tape will be
27 spaced backwards over an "accidentally" crossed filemark in any case. */
28#define OSST_IN_FILE_POS 1
29
30/* The tape driver buffer size in kilobytes. */
31/* Don't change, as this is the HW blocksize */
32#define OSST_BUFFER_BLOCKS 32
33
34/* The number of kilobytes of data in the buffer that triggers an
35 asynchronous write in fixed block mode. See also OSST_ASYNC_WRITES
36 below. */
37#define OSST_WRITE_THRESHOLD_BLOCKS 32
38
39/* OSST_EOM_RESERVE defines the number of frames are kept in reserve for
40 * * write error recovery when writing near end of medium. ENOSPC is returned
41 * * when write() is called and the tape write position is within this number
42 * * of blocks from the tape capacity. */
43#define OSST_EOM_RESERVE 300
44
45/* The maximum number of tape buffers the driver allocates. The number
46 is also constrained by the number of drives detected. Determines the
47 maximum number of concurrently active tape drives. */
48#define OSST_MAX_BUFFERS OSST_MAX_TAPES
49
50/* Maximum number of scatter/gather segments */
51/* Fit one buffer in pages and add one for the AUX header */
52#define OSST_MAX_SG (((OSST_BUFFER_BLOCKS*1024) / PAGE_SIZE) + 1)
53
54/* The number of scatter/gather segments to allocate at first try (must be
55 smaller or equal to the maximum). */
56#define OSST_FIRST_SG ((OSST_BUFFER_BLOCKS*1024) / PAGE_SIZE)
57
58/* The size of the first scatter/gather segments (determines the maximum block
59 size for SCSI adapters not supporting scatter/gather). The default is set
60 to try to allocate the buffer as one chunk. */
61#define OSST_FIRST_ORDER (15-PAGE_SHIFT)
62
63
64/* The following lines define defaults for properties that can be set
65 separately for each drive using the MTSTOPTIONS ioctl. */
66
67/* If OSST_TWO_FM is non-zero, the driver writes two filemarks after a
68 file being written. Some drives can't handle two filemarks at the
69 end of data. */
70#define OSST_TWO_FM 0
71
72/* If OSST_BUFFER_WRITES is non-zero, writes in fixed block mode are
73 buffered until the driver buffer is full or asynchronous write is
74 triggered. */
75#define OSST_BUFFER_WRITES 1
76
77/* If OSST_ASYNC_WRITES is non-zero, the SCSI write command may be started
78 without waiting for it to finish. May cause problems in multiple
79 tape backups. */
80#define OSST_ASYNC_WRITES 1
81
82/* If OSST_READ_AHEAD is non-zero, blocks are read ahead in fixed block
83 mode. */
84#define OSST_READ_AHEAD 1
85
86/* If OSST_AUTO_LOCK is non-zero, the drive door is locked at the first
87 read or write command after the device is opened. The door is opened
88 when the device is closed. */
89#define OSST_AUTO_LOCK 0
90
91/* If OSST_FAST_MTEOM is non-zero, the MTEOM ioctl is done using the
92 direct SCSI command. The file number status is lost but this method
93 is fast with some drives. Otherwise MTEOM is done by spacing over
94 files and the file number status is retained. */
95#define OSST_FAST_MTEOM 0
96
97/* If OSST_SCSI2LOGICAL is nonzero, the logical block addresses are used for
98 MTIOCPOS and MTSEEK by default. Vendor addresses are used if OSST_SCSI2LOGICAL
99 is zero. */
100#define OSST_SCSI2LOGICAL 0
101
102/* If OSST_SYSV is non-zero, the tape behaves according to the SYS V semantics.
103 The default is BSD semantics. */
104#define OSST_SYSV 0
105
106
107#endif
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 9c4c710dcccf..b9e7b291c129 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -228,7 +228,6 @@ static DEFINE_IDR(st_index_idr);
228 228
229 229
230 230
231#include "osst_detect.h"
232#ifndef SIGS_FROM_OSST 231#ifndef SIGS_FROM_OSST
233#define SIGS_FROM_OSST \ 232#define SIGS_FROM_OSST \
234 {"OnStream", "SC-", "", "osst"}, \ 233 {"OnStream", "SC-", "", "osst"}, \
@@ -4267,9 +4266,10 @@ static int st_probe(struct device *dev)
4267 if (SDp->type != TYPE_TAPE) 4266 if (SDp->type != TYPE_TAPE)
4268 return -ENODEV; 4267 return -ENODEV;
4269 if ((stp = st_incompatible(SDp))) { 4268 if ((stp = st_incompatible(SDp))) {
4270 sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n");
4271 sdev_printk(KERN_INFO, SDp, 4269 sdev_printk(KERN_INFO, SDp,
4272 "st: The suggested driver is %s.\n", stp); 4270 "OnStream tapes are no longer supported;\n");
4271 sdev_printk(KERN_INFO, SDp,
4272 "please mail to linux-scsi@vger.kernel.org.\n");
4273 return -ENODEV; 4273 return -ENODEV;
4274 } 4274 }
4275 4275