blob: 6e5a5bb3131150012d24c3a8ac0fab668af289ef [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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 Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
7 Contribution and ideas from several people including (in alphabetical
8 order) Klaus Ehrenfried, Eugene Exarevsky, Eric Lee Green, Wolfgang Denk,
9 Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
10 Michael Schaefer, J"org Weule, and Eric Youngdale.
11
Kai Makisarafd66c1b2008-01-17 22:45:22 +020012 Copyright 1992 - 2008 Kai Makisara
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 email Kai.Makisara@kolumbus.fi
14
15 Some small formal changes - aeb, 950809
16
17 Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
18 */
19
Kai Makisara40f6b362008-02-24 22:23:24 +020020static const char *verstr = "20080224";
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
22#include <linux/module.h>
23
24#include <linux/fs.h>
25#include <linux/kernel.h>
26#include <linux/sched.h>
27#include <linux/mm.h>
28#include <linux/init.h>
29#include <linux/string.h>
30#include <linux/errno.h>
31#include <linux/mtio.h>
Kai Makisara 16c4b3e2005-05-01 18:11:55 +030032#include <linux/cdrom.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/ioctl.h>
34#include <linux/fcntl.h>
35#include <linux/spinlock.h>
36#include <linux/blkdev.h>
37#include <linux/moduleparam.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/cdev.h>
39#include <linux/delay.h>
Arjan van de Ven0b950672006-01-11 13:16:10 +010040#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#include <asm/uaccess.h>
43#include <asm/dma.h>
44#include <asm/system.h>
45
46#include <scsi/scsi.h>
47#include <scsi/scsi_dbg.h>
48#include <scsi/scsi_device.h>
49#include <scsi/scsi_driver.h>
50#include <scsi/scsi_eh.h>
51#include <scsi/scsi_host.h>
52#include <scsi/scsi_ioctl.h>
Kai Makisara 16c4b3e2005-05-01 18:11:55 +030053#include <scsi/sg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55
56/* The driver prints some debugging information on the console if DEBUG
57 is defined and non-zero. */
58#define DEBUG 0
59
60#if DEBUG
61/* The message level for the debug messages is currently set to KERN_NOTICE
62 so that people can easily see the messages. Later when the debugging messages
63 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
64#define ST_DEB_MSG KERN_NOTICE
65#define DEB(a) a
66#define DEBC(a) if (debugging) { a ; }
67#else
68#define DEB(a)
69#define DEBC(a)
70#endif
71
72#define ST_KILOBYTE 1024
73
74#include "st_options.h"
75#include "st.h"
76
77static int buffer_kbs;
78static int max_sg_segs;
79static int try_direct_io = TRY_DIRECT_IO;
80static int try_rdio = 1;
81static int try_wdio = 1;
82
83static int st_dev_max;
84static int st_nr_dev;
85
gregkh@suse.ded2538782005-03-23 09:55:22 -080086static struct class *st_sysfs_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88MODULE_AUTHOR("Kai Makisara");
Rene Hermanf018fa52006-03-08 00:14:20 -080089MODULE_DESCRIPTION("SCSI tape (st) driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -070090MODULE_LICENSE("GPL");
Rene Hermanf018fa52006-03-08 00:14:20 -080091MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR);
Michael Tokarevd7b8bcb2006-10-27 16:02:37 +040092MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
94/* Set 'perm' (4th argument) to 0 to disable module_param's definition
95 * of sysfs parameters (which module_param doesn't yet support).
96 * Sysfs parameters defined explicitly later.
97 */
98module_param_named(buffer_kbs, buffer_kbs, int, 0);
99MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size for fixed block mode (KB; 32)");
100module_param_named(max_sg_segs, max_sg_segs, int, 0);
101MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (256)");
102module_param_named(try_direct_io, try_direct_io, int, 0);
103MODULE_PARM_DESC(try_direct_io, "Try direct I/O between user buffer and tape drive (1)");
104
105/* Extra parameters for testing */
106module_param_named(try_rdio, try_rdio, int, 0);
107MODULE_PARM_DESC(try_rdio, "Try direct read i/o when possible");
108module_param_named(try_wdio, try_wdio, int, 0);
109MODULE_PARM_DESC(try_wdio, "Try direct write i/o when possible");
110
111#ifndef MODULE
112static int write_threshold_kbs; /* retained for compatibility */
113static struct st_dev_parm {
114 char *name;
115 int *val;
116} parms[] __initdata = {
117 {
118 "buffer_kbs", &buffer_kbs
119 },
120 { /* Retained for compatibility with 2.4 */
121 "write_threshold_kbs", &write_threshold_kbs
122 },
123 {
124 "max_sg_segs", NULL
125 },
126 {
127 "try_direct_io", &try_direct_io
128 }
129};
130#endif
131
132/* Restrict the number of modes so that names for all are assigned */
133#if ST_NBR_MODES > 16
134#error "Maximum number of modes is 16"
135#endif
136/* Bit reversed order to get same names for same minors with all
137 mode counts */
Arjan van de Ven0ad78202005-11-28 16:22:25 +0100138static const char *st_formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 "", "r", "k", "s", "l", "t", "o", "u",
140 "m", "v", "p", "x", "a", "y", "q", "z"};
141
142/* The default definitions have been moved to st_options.h */
143
144#define ST_FIXED_BUFFER_SIZE (ST_FIXED_BUFFER_BLOCKS * ST_KILOBYTE)
145
146/* The buffer size should fit into the 24 bits for length in the
147 6-byte SCSI read and write commands. */
148#if ST_FIXED_BUFFER_SIZE >= (2 << 24 - 1)
149#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
150#endif
151
152static int debugging = DEBUG;
153
154#define MAX_RETRIES 0
155#define MAX_WRITE_RETRIES 0
156#define MAX_READY_RETRIES 0
157#define NO_TAPE NOT_READY
158
159#define ST_TIMEOUT (900 * HZ)
160#define ST_LONG_TIMEOUT (14000 * HZ)
161
162/* Remove mode bits and auto-rewind bit (7) */
163#define TAPE_NR(x) ( ((iminor(x) & ~255) >> (ST_NBR_MODE_BITS + 1)) | \
164 (iminor(x) & ~(-1 << ST_MODE_SHIFT)) )
165#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
166
167/* Construct the minor number from the device (d), mode (m), and non-rewind (n) data */
168#define TAPE_MINOR(d, m, n) (((d & ~(255 >> (ST_NBR_MODE_BITS + 1))) << (ST_NBR_MODE_BITS + 1)) | \
169 (d & (255 >> (ST_NBR_MODE_BITS + 1))) | (m << ST_MODE_SHIFT) | ((n != 0) << 7) )
170
171/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
172 24 bits) */
173#define SET_DENS_AND_BLK 0x10001
174
175static DEFINE_RWLOCK(st_dev_arr_lock);
176
177static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE;
178static int st_max_sg_segs = ST_MAX_SG;
179
180static struct scsi_tape **scsi_tapes = NULL;
181
182static int modes_defined;
183
184static struct st_buffer *new_tape_buffer(int, int, int);
185static int enlarge_buffer(struct st_buffer *, int, int);
Kai Makisara40f6b362008-02-24 22:23:24 +0200186static void clear_buffer(struct st_buffer *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187static void normalize_buffer(struct st_buffer *);
188static int append_to_buffer(const char __user *, struct st_buffer *, int);
189static int from_buffer(struct st_buffer *, char __user *, int);
190static void move_buffer_data(struct st_buffer *, int);
191static void buf_to_sg(struct st_buffer *, unsigned int);
192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193static int sgl_map_user_pages(struct scatterlist *, const unsigned int,
194 unsigned long, size_t, int);
195static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
196
197static int st_probe(struct device *);
198static int st_remove(struct device *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100200static int do_create_sysfs_files(void);
201static void do_remove_sysfs_files(void);
Jeff Garzik13026a62006-10-04 06:00:38 -0400202static int do_create_class_files(struct scsi_tape *, int, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204static struct scsi_driver st_template = {
205 .owner = THIS_MODULE,
206 .gendrv = {
207 .name = "st",
208 .probe = st_probe,
209 .remove = st_remove,
210 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211};
212
213static int st_compression(struct scsi_tape *, int);
214
215static int find_partition(struct scsi_tape *);
216static int switch_partition(struct scsi_tape *);
217
218static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
219
Kai Makisaraf03a5672005-08-02 13:40:47 +0300220static void scsi_tape_release(struct kref *);
221
222#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
223
Arjan van de Ven0b950672006-01-11 13:16:10 +0100224static DEFINE_MUTEX(st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227#include "osst_detect.h"
228#ifndef SIGS_FROM_OSST
229#define SIGS_FROM_OSST \
230 {"OnStream", "SC-", "", "osst"}, \
231 {"OnStream", "DI-", "", "osst"}, \
232 {"OnStream", "DP-", "", "osst"}, \
233 {"OnStream", "USB", "", "osst"}, \
234 {"OnStream", "FW-", "", "osst"}
235#endif
236
Kai Makisaraf03a5672005-08-02 13:40:47 +0300237static struct scsi_tape *scsi_tape_get(int dev)
238{
239 struct scsi_tape *STp = NULL;
240
Arjan van de Ven0b950672006-01-11 13:16:10 +0100241 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300242 write_lock(&st_dev_arr_lock);
243
244 if (dev < st_dev_max && scsi_tapes != NULL)
245 STp = scsi_tapes[dev];
246 if (!STp) goto out;
247
248 kref_get(&STp->kref);
249
250 if (!STp->device)
251 goto out_put;
252
253 if (scsi_device_get(STp->device))
254 goto out_put;
255
256 goto out;
257
258out_put:
259 kref_put(&STp->kref, scsi_tape_release);
260 STp = NULL;
261out:
262 write_unlock(&st_dev_arr_lock);
Arjan van de Ven0b950672006-01-11 13:16:10 +0100263 mutex_unlock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300264 return STp;
265}
266
267static void scsi_tape_put(struct scsi_tape *STp)
268{
269 struct scsi_device *sdev = STp->device;
270
Arjan van de Ven0b950672006-01-11 13:16:10 +0100271 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300272 kref_put(&STp->kref, scsi_tape_release);
273 scsi_device_put(sdev);
Arjan van de Ven0b950672006-01-11 13:16:10 +0100274 mutex_unlock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300275}
276
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277struct st_reject_data {
278 char *vendor;
279 char *model;
280 char *rev;
281 char *driver_hint; /* Name of the correct driver, NULL if unknown */
282};
283
284static struct st_reject_data reject_list[] = {
285 /* {"XXX", "Yy-", "", NULL}, example */
286 SIGS_FROM_OSST,
287 {NULL, }};
288
289/* If the device signature is on the list of incompatible drives, the
290 function returns a pointer to the name of the correct driver (if known) */
291static char * st_incompatible(struct scsi_device* SDp)
292{
293 struct st_reject_data *rp;
294
295 for (rp=&(reject_list[0]); rp->vendor != NULL; rp++)
296 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
297 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
298 !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) {
299 if (rp->driver_hint)
300 return rp->driver_hint;
301 else
302 return "unknown";
303 }
304 return NULL;
305}
306
307
308static inline char *tape_name(struct scsi_tape *tape)
309{
310 return tape->disk->disk_name;
311}
312
313
Mike Christie8b05b772005-11-08 04:06:44 -0600314static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
316 const u8 *ucp;
Mike Christie8b05b772005-11-08 04:06:44 -0600317 const u8 *sense = SRpnt->sense;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
Mike Christie8b05b772005-11-08 04:06:44 -0600319 s->have_sense = scsi_normalize_sense(SRpnt->sense,
320 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 s->flags = 0;
322
323 if (s->have_sense) {
324 s->deferred = 0;
325 s->remainder_valid =
326 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
327 switch (sense[0] & 0x7f) {
328 case 0x71:
329 s->deferred = 1;
330 case 0x70:
331 s->fixed_format = 1;
332 s->flags = sense[2] & 0xe0;
333 break;
334 case 0x73:
335 s->deferred = 1;
336 case 0x72:
337 s->fixed_format = 0;
338 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
339 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
340 break;
341 }
342 }
343}
344
345
346/* Convert the result to success code */
Mike Christie8b05b772005-11-08 04:06:44 -0600347static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
Mike Christie8b05b772005-11-08 04:06:44 -0600349 int result = SRpnt->result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 u8 scode;
351 DEB(const char *stp;)
352 char *name = tape_name(STp);
353 struct st_cmdstatus *cmdstatp;
354
355 if (!result)
356 return 0;
357
358 cmdstatp = &STp->buffer->cmdstat;
Kai Makisaraf03a5672005-08-02 13:40:47 +0300359 st_analyze_sense(SRpnt, cmdstatp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361 if (cmdstatp->have_sense)
362 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
363 else
364 scode = 0;
365
366 DEB(
367 if (debugging) {
Mike Christie8b05b772005-11-08 04:06:44 -0600368 printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 name, result,
Mike Christie8b05b772005-11-08 04:06:44 -0600370 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
371 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 if (cmdstatp->have_sense)
Luben Tuikov4e73ea72006-07-07 00:02:18 -0700373 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 } ) /* end DEB */
375 if (!debugging) { /* Abnormal conditions for tape */
376 if (!cmdstatp->have_sense)
377 printk(KERN_WARNING
378 "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
379 name, result, suggestion(result),
380 driver_byte(result) & DRIVER_MASK, host_byte(result));
381 else if (cmdstatp->have_sense &&
382 scode != NO_SENSE &&
383 scode != RECOVERED_ERROR &&
384 /* scode != UNIT_ATTENTION && */
385 scode != BLANK_CHECK &&
386 scode != VOLUME_OVERFLOW &&
Mike Christie8b05b772005-11-08 04:06:44 -0600387 SRpnt->cmd[0] != MODE_SENSE &&
388 SRpnt->cmd[0] != TEST_UNIT_READY) {
Luben Tuikov4e73ea72006-07-07 00:02:18 -0700389
390 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 }
392 }
393
394 if (cmdstatp->fixed_format &&
395 STp->cln_mode >= EXTENDED_SENSE_START) { /* Only fixed format sense */
396 if (STp->cln_sense_value)
Mike Christie8b05b772005-11-08 04:06:44 -0600397 STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 STp->cln_sense_mask) == STp->cln_sense_value);
399 else
Mike Christie8b05b772005-11-08 04:06:44 -0600400 STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 STp->cln_sense_mask) != 0);
402 }
403 if (cmdstatp->have_sense &&
404 cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
405 STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
406
407 STp->pos_unknown |= STp->device->was_reset;
408
409 if (cmdstatp->have_sense &&
410 scode == RECOVERED_ERROR
411#if ST_RECOVERED_WRITE_FATAL
Mike Christie8b05b772005-11-08 04:06:44 -0600412 && SRpnt->cmd[0] != WRITE_6
413 && SRpnt->cmd[0] != WRITE_FILEMARKS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414#endif
415 ) {
416 STp->recover_count++;
417 STp->recover_reg++;
418
419 DEB(
420 if (debugging) {
Mike Christie8b05b772005-11-08 04:06:44 -0600421 if (SRpnt->cmd[0] == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 stp = "read";
Mike Christie8b05b772005-11-08 04:06:44 -0600423 else if (SRpnt->cmd[0] == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 stp = "write";
425 else
426 stp = "ioctl";
427 printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp,
428 STp->recover_count);
429 } ) /* end DEB */
430
431 if (cmdstatp->flags == 0)
432 return 0;
433 }
434 return (-EIO);
435}
436
437
438/* Wakeup from interrupt */
Mike Christie8b05b772005-11-08 04:06:44 -0600439static void st_sleep_done(void *data, char *sense, int result, int resid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
Mike Christie8b05b772005-11-08 04:06:44 -0600441 struct st_request *SRpnt = data;
442 struct scsi_tape *STp = SRpnt->stp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Mike Christie8b05b772005-11-08 04:06:44 -0600444 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
445 (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
Kai Makisara40f6b362008-02-24 22:23:24 +0200446 (STp->buffer)->cmdstat.residual = resid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 DEB( STp->write_pending = 0; )
448
Mike Christie8b05b772005-11-08 04:06:44 -0600449 if (SRpnt->waiting)
450 complete(SRpnt->waiting);
451}
452
453static struct st_request *st_allocate_request(void)
454{
455 return kzalloc(sizeof(struct st_request), GFP_KERNEL);
456}
457
458static void st_release_request(struct st_request *streq)
459{
460 kfree(streq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461}
462
463/* Do the scsi command. Waits until command performed if do_wait is true.
464 Otherwise write_behind_check() is used to check that the command
465 has finished. */
Mike Christie8b05b772005-11-08 04:06:44 -0600466static struct st_request *
467st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 int bytes, int direction, int timeout, int retries, int do_wait)
469{
Kai Makisaraf03a5672005-08-02 13:40:47 +0300470 struct completion *waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
Kai Makisaraf03a5672005-08-02 13:40:47 +0300472 /* if async, make sure there's no command outstanding */
473 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
474 printk(KERN_ERR "%s: Async command already active.\n",
475 tape_name(STp));
476 if (signal_pending(current))
477 (STp->buffer)->syscall_result = (-EINTR);
478 else
479 (STp->buffer)->syscall_result = (-EBUSY);
480 return NULL;
481 }
482
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 if (SRpnt == NULL) {
Mike Christie8b05b772005-11-08 04:06:44 -0600484 SRpnt = st_allocate_request();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if (SRpnt == NULL) {
486 DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n",
487 tape_name(STp)); );
488 if (signal_pending(current))
489 (STp->buffer)->syscall_result = (-EINTR);
490 else
491 (STp->buffer)->syscall_result = (-EBUSY);
492 return NULL;
493 }
Mike Christie8b05b772005-11-08 04:06:44 -0600494 SRpnt->stp = STp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 }
496
Kai Makisaraf03a5672005-08-02 13:40:47 +0300497 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
498 which IO is outstanding. It's nulled out when the IO completes. */
499 if (!do_wait)
500 (STp->buffer)->last_SRpnt = SRpnt;
501
502 waiting = &STp->wait;
503 init_completion(waiting);
Mike Christie8b05b772005-11-08 04:06:44 -0600504 SRpnt->waiting = waiting;
505
506 if (!STp->buffer->do_dio)
507 buf_to_sg(STp->buffer, bytes);
508
509 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 STp->buffer->cmdstat.have_sense = 0;
Mike Christie8b05b772005-11-08 04:06:44 -0600511 STp->buffer->syscall_result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
brking@us.ibm.combb1d1072006-01-23 15:03:22 -0600513 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction,
Mike Christie8b05b772005-11-08 04:06:44 -0600514 &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
Kai Makisara787926b2005-11-13 10:04:44 +0200515 timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
Mike Christie8b05b772005-11-08 04:06:44 -0600516 /* could not allocate the buffer or request was too large */
517 (STp->buffer)->syscall_result = (-EBUSY);
Kai Makisara787926b2005-11-13 10:04:44 +0200518 (STp->buffer)->last_SRpnt = NULL;
519 }
Mike Christie8b05b772005-11-08 04:06:44 -0600520 else if (do_wait) {
Kai Makisaraf03a5672005-08-02 13:40:47 +0300521 wait_for_completion(waiting);
Mike Christie8b05b772005-11-08 04:06:44 -0600522 SRpnt->waiting = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
524 }
Mike Christie8b05b772005-11-08 04:06:44 -0600525
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 return SRpnt;
527}
528
529
530/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
531 write has been correct but EOM early warning reached, -EIO if write ended in
532 error or zero if write successful. Asynchronous writes are used only in
533 variable block mode. */
534static int write_behind_check(struct scsi_tape * STp)
535{
536 int retval = 0;
537 struct st_buffer *STbuffer;
538 struct st_partstat *STps;
539 struct st_cmdstatus *cmdstatp;
Mike Christie8b05b772005-11-08 04:06:44 -0600540 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
542 STbuffer = STp->buffer;
543 if (!STbuffer->writing)
544 return 0;
545
546 DEB(
547 if (STp->write_pending)
548 STp->nbr_waits++;
549 else
550 STp->nbr_finished++;
551 ) /* end DEB */
552
553 wait_for_completion(&(STp->wait));
Kai Makisaraf03a5672005-08-02 13:40:47 +0300554 SRpnt = STbuffer->last_SRpnt;
555 STbuffer->last_SRpnt = NULL;
Mike Christie8b05b772005-11-08 04:06:44 -0600556 SRpnt->waiting = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Kai Makisaraf03a5672005-08-02 13:40:47 +0300558 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
Mike Christie8b05b772005-11-08 04:06:44 -0600559 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
561 STbuffer->buffer_bytes -= STbuffer->writing;
562 STps = &(STp->ps[STp->partition]);
563 if (STps->drv_block >= 0) {
564 if (STp->block_size == 0)
565 STps->drv_block++;
566 else
567 STps->drv_block += STbuffer->writing / STp->block_size;
568 }
569
570 cmdstatp = &STbuffer->cmdstat;
571 if (STbuffer->syscall_result) {
572 retval = -EIO;
573 if (cmdstatp->have_sense && !cmdstatp->deferred &&
574 (cmdstatp->flags & SENSE_EOM) &&
575 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
576 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR)) {
577 /* EOM at write-behind, has all data been written? */
578 if (!cmdstatp->remainder_valid ||
579 cmdstatp->uremainder64 == 0)
580 retval = -ENOSPC;
581 }
582 if (retval == -EIO)
583 STps->drv_block = -1;
584 }
585 STbuffer->writing = 0;
586
587 DEB(if (debugging && retval)
588 printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n",
589 tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
590
591 return retval;
592}
593
594
595/* Step over EOF if it has been inadvertently crossed (ioctl not used because
596 it messes up the block number). */
597static int cross_eof(struct scsi_tape * STp, int forward)
598{
Mike Christie8b05b772005-11-08 04:06:44 -0600599 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 unsigned char cmd[MAX_COMMAND_SIZE];
601
602 cmd[0] = SPACE;
603 cmd[1] = 0x01; /* Space FileMarks */
604 if (forward) {
605 cmd[2] = cmd[3] = 0;
606 cmd[4] = 1;
607 } else
608 cmd[2] = cmd[3] = cmd[4] = 0xff; /* -1 filemarks */
609 cmd[5] = 0;
610
611 DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",
612 tape_name(STp), forward ? "forward" : "backward"));
613
614 SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
615 STp->device->timeout, MAX_RETRIES, 1);
616 if (!SRpnt)
617 return (STp->buffer)->syscall_result;
618
Mike Christie8b05b772005-11-08 04:06:44 -0600619 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 SRpnt = NULL;
621
622 if ((STp->buffer)->cmdstat.midlevel_result != 0)
623 printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
624 tape_name(STp), forward ? "forward" : "backward");
625
626 return (STp->buffer)->syscall_result;
627}
628
629
630/* Flush the write buffer (never need to write if variable blocksize). */
Adrian Bunk8ef8d592008-04-14 17:17:16 +0300631static int st_flush_write_buffer(struct scsi_tape * STp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
633 int offset, transfer, blks;
634 int result;
635 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -0600636 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 struct st_partstat *STps;
638
639 result = write_behind_check(STp);
640 if (result)
641 return result;
642
643 result = 0;
644 if (STp->dirty == 1) {
645
646 offset = (STp->buffer)->buffer_bytes;
647 transfer = ((offset + STp->block_size - 1) /
648 STp->block_size) * STp->block_size;
649 DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
650 tape_name(STp), transfer));
651
652 memset((STp->buffer)->b_data + offset, 0, transfer - offset);
653
654 memset(cmd, 0, MAX_COMMAND_SIZE);
655 cmd[0] = WRITE_6;
656 cmd[1] = 1;
657 blks = transfer / STp->block_size;
658 cmd[2] = blks >> 16;
659 cmd[3] = blks >> 8;
660 cmd[4] = blks;
661
662 SRpnt = st_do_scsi(NULL, STp, cmd, transfer, DMA_TO_DEVICE,
663 STp->device->timeout, MAX_WRITE_RETRIES, 1);
664 if (!SRpnt)
665 return (STp->buffer)->syscall_result;
666
667 STps = &(STp->ps[STp->partition]);
668 if ((STp->buffer)->syscall_result != 0) {
669 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
670
671 if (cmdstatp->have_sense && !cmdstatp->deferred &&
672 (cmdstatp->flags & SENSE_EOM) &&
673 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
674 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
675 (!cmdstatp->remainder_valid ||
676 cmdstatp->uremainder64 == 0)) { /* All written at EOM early warning */
677 STp->dirty = 0;
678 (STp->buffer)->buffer_bytes = 0;
679 if (STps->drv_block >= 0)
680 STps->drv_block += blks;
681 result = (-ENOSPC);
682 } else {
683 printk(KERN_ERR "%s: Error on flush.\n",
684 tape_name(STp));
685 STps->drv_block = (-1);
686 result = (-EIO);
687 }
688 } else {
689 if (STps->drv_block >= 0)
690 STps->drv_block += blks;
691 STp->dirty = 0;
692 (STp->buffer)->buffer_bytes = 0;
693 }
Mike Christie8b05b772005-11-08 04:06:44 -0600694 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 SRpnt = NULL;
696 }
697 return result;
698}
699
700
701/* Flush the tape buffer. The tape will be positioned correctly unless
702 seek_next is true. */
703static int flush_buffer(struct scsi_tape *STp, int seek_next)
704{
705 int backspace, result;
706 struct st_buffer *STbuffer;
707 struct st_partstat *STps;
708
709 STbuffer = STp->buffer;
710
711 /*
712 * If there was a bus reset, block further access
713 * to this device.
714 */
715 if (STp->pos_unknown)
716 return (-EIO);
717
718 if (STp->ready != ST_READY)
719 return 0;
720 STps = &(STp->ps[STp->partition]);
721 if (STps->rw == ST_WRITING) /* Writing */
Adrian Bunk8ef8d592008-04-14 17:17:16 +0300722 return st_flush_write_buffer(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 if (STp->block_size == 0)
725 return 0;
726
727 backspace = ((STp->buffer)->buffer_bytes +
728 (STp->buffer)->read_pointer) / STp->block_size -
729 ((STp->buffer)->read_pointer + STp->block_size - 1) /
730 STp->block_size;
731 (STp->buffer)->buffer_bytes = 0;
732 (STp->buffer)->read_pointer = 0;
733 result = 0;
734 if (!seek_next) {
735 if (STps->eof == ST_FM_HIT) {
736 result = cross_eof(STp, 0); /* Back over the EOF hit */
737 if (!result)
738 STps->eof = ST_NOEOF;
739 else {
740 if (STps->drv_file >= 0)
741 STps->drv_file++;
742 STps->drv_block = 0;
743 }
744 }
745 if (!result && backspace > 0)
746 result = st_int_ioctl(STp, MTBSR, backspace);
747 } else if (STps->eof == ST_FM_HIT) {
748 if (STps->drv_file >= 0)
749 STps->drv_file++;
750 STps->drv_block = 0;
751 STps->eof = ST_NOEOF;
752 }
753 return result;
754
755}
756
757/* Set the mode parameters */
758static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
759{
760 int set_it = 0;
761 unsigned long arg;
762 char *name = tape_name(STp);
763
764 if (!STp->density_changed &&
765 STm->default_density >= 0 &&
766 STm->default_density != STp->density) {
767 arg = STm->default_density;
768 set_it = 1;
769 } else
770 arg = STp->density;
771 arg <<= MT_ST_DENSITY_SHIFT;
772 if (!STp->blksize_changed &&
773 STm->default_blksize >= 0 &&
774 STm->default_blksize != STp->block_size) {
775 arg |= STm->default_blksize;
776 set_it = 1;
777 } else
778 arg |= STp->block_size;
779 if (set_it &&
780 st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {
781 printk(KERN_WARNING
782 "%s: Can't set default block size to %d bytes and density %x.\n",
783 name, STm->default_blksize, STm->default_density);
784 if (modes_defined)
785 return (-EINVAL);
786 }
787 return 0;
788}
789
790
Mike Christie8b05b772005-11-08 04:06:44 -0600791/* Lock or unlock the drive door. Don't use when st_request allocated. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792static int do_door_lock(struct scsi_tape * STp, int do_lock)
793{
794 int retval, cmd;
795 DEB(char *name = tape_name(STp);)
796
797
798 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
799 DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name,
800 do_lock ? "L" : "Unl"));
801 retval = scsi_ioctl(STp->device, cmd, NULL);
802 if (!retval) {
803 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
804 }
805 else {
806 STp->door_locked = ST_LOCK_FAILS;
807 }
808 return retval;
809}
810
811
812/* Set the internal state after reset */
813static void reset_state(struct scsi_tape *STp)
814{
815 int i;
816 struct st_partstat *STps;
817
818 STp->pos_unknown = 0;
819 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
820 STps = &(STp->ps[i]);
821 STps->rw = ST_IDLE;
822 STps->eof = ST_NOEOF;
823 STps->at_sm = 0;
824 STps->last_block_valid = 0;
825 STps->drv_block = -1;
826 STps->drv_file = -1;
827 }
828 if (STp->can_partitions) {
829 STp->partition = find_partition(STp);
830 if (STp->partition < 0)
831 STp->partition = 0;
832 STp->new_partition = STp->partition;
833 }
834}
835
836/* Test if the drive is ready. Returns either one of the codes below or a negative system
837 error code. */
838#define CHKRES_READY 0
839#define CHKRES_NEW_SESSION 1
840#define CHKRES_NOT_READY 2
841#define CHKRES_NO_TAPE 3
842
843#define MAX_ATTENTIONS 10
844
845static int test_ready(struct scsi_tape *STp, int do_wait)
846{
847 int attentions, waits, max_wait, scode;
848 int retval = CHKRES_READY, new_session = 0;
849 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -0600850 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
852
853 max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
854
855 for (attentions=waits=0; ; ) {
856 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
857 cmd[0] = TEST_UNIT_READY;
858 SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
859 STp->long_timeout, MAX_READY_RETRIES, 1);
860
861 if (!SRpnt) {
862 retval = (STp->buffer)->syscall_result;
863 break;
864 }
865
866 if (cmdstatp->have_sense) {
867
868 scode = cmdstatp->sense_hdr.sense_key;
869
870 if (scode == UNIT_ATTENTION) { /* New media? */
871 new_session = 1;
872 if (attentions < MAX_ATTENTIONS) {
873 attentions++;
874 continue;
875 }
876 else {
877 retval = (-EIO);
878 break;
879 }
880 }
881
882 if (scode == NOT_READY) {
883 if (waits < max_wait) {
884 if (msleep_interruptible(1000)) {
885 retval = (-EINTR);
886 break;
887 }
888 waits++;
889 continue;
890 }
891 else {
892 if ((STp->device)->scsi_level >= SCSI_2 &&
893 cmdstatp->sense_hdr.asc == 0x3a) /* Check ASC */
894 retval = CHKRES_NO_TAPE;
895 else
896 retval = CHKRES_NOT_READY;
897 break;
898 }
899 }
900 }
901
902 retval = (STp->buffer)->syscall_result;
903 if (!retval)
904 retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;
905 break;
906 }
907
908 if (SRpnt != NULL)
Mike Christie8b05b772005-11-08 04:06:44 -0600909 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 return retval;
911}
912
913
914/* See if the drive is ready and gather information about the tape. Return values:
915 < 0 negative error code from errno.h
916 0 drive ready
917 1 drive not ready (possibly no tape)
918*/
919static int check_tape(struct scsi_tape *STp, struct file *filp)
920{
921 int i, retval, new_session = 0, do_wait;
922 unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
923 unsigned short st_flags = filp->f_flags;
Mike Christie8b05b772005-11-08 04:06:44 -0600924 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 struct st_modedef *STm;
926 struct st_partstat *STps;
927 char *name = tape_name(STp);
Josef Sipek7ac62072006-12-08 02:37:37 -0800928 struct inode *inode = filp->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 int mode = TAPE_MODE(inode);
930
931 STp->ready = ST_READY;
932
933 if (mode != STp->current_mode) {
934 DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n",
935 name, STp->current_mode, mode));
936 new_session = 1;
937 STp->current_mode = mode;
938 }
939 STm = &(STp->modes[STp->current_mode]);
940
941 saved_cleaning = STp->cleaning_req;
942 STp->cleaning_req = 0;
943
944 do_wait = ((filp->f_flags & O_NONBLOCK) == 0);
945 retval = test_ready(STp, do_wait);
946
947 if (retval < 0)
948 goto err_out;
949
950 if (retval == CHKRES_NEW_SESSION) {
951 STp->pos_unknown = 0;
952 STp->partition = STp->new_partition = 0;
953 if (STp->can_partitions)
954 STp->nbr_partitions = 1; /* This guess will be updated later
955 if necessary */
956 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
957 STps = &(STp->ps[i]);
958 STps->rw = ST_IDLE;
959 STps->eof = ST_NOEOF;
960 STps->at_sm = 0;
961 STps->last_block_valid = 0;
962 STps->drv_block = 0;
963 STps->drv_file = 0;
964 }
965 new_session = 1;
966 }
967 else {
968 STp->cleaning_req |= saved_cleaning;
969
970 if (retval == CHKRES_NOT_READY || retval == CHKRES_NO_TAPE) {
971 if (retval == CHKRES_NO_TAPE)
972 STp->ready = ST_NO_TAPE;
973 else
974 STp->ready = ST_NOT_READY;
975
976 STp->density = 0; /* Clear the erroneous "residue" */
977 STp->write_prot = 0;
978 STp->block_size = 0;
979 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
980 STp->partition = STp->new_partition = 0;
981 STp->door_locked = ST_UNLOCKED;
982 return CHKRES_NOT_READY;
983 }
984 }
985
986 if (STp->omit_blklims)
987 STp->min_block = STp->max_block = (-1);
988 else {
989 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
990 cmd[0] = READ_BLOCK_LIMITS;
991
992 SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE,
993 STp->device->timeout, MAX_READY_RETRIES, 1);
994 if (!SRpnt) {
995 retval = (STp->buffer)->syscall_result;
996 goto err_out;
997 }
998
Mike Christie8b05b772005-11-08 04:06:44 -0600999 if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 STp->max_block = ((STp->buffer)->b_data[1] << 16) |
1001 ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
1002 STp->min_block = ((STp->buffer)->b_data[4] << 8) |
1003 (STp->buffer)->b_data[5];
1004 if ( DEB( debugging || ) !STp->inited)
Kai Makisara422528542006-11-07 21:56:38 +02001005 printk(KERN_INFO
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 "%s: Block limits %d - %d bytes.\n", name,
1007 STp->min_block, STp->max_block);
1008 } else {
1009 STp->min_block = STp->max_block = (-1);
1010 DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",
1011 name));
1012 }
1013 }
1014
1015 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
1016 cmd[0] = MODE_SENSE;
1017 cmd[4] = 12;
1018
1019 SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE,
1020 STp->device->timeout, MAX_READY_RETRIES, 1);
1021 if (!SRpnt) {
1022 retval = (STp->buffer)->syscall_result;
1023 goto err_out;
1024 }
1025
1026 if ((STp->buffer)->syscall_result != 0) {
1027 DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name));
1028 STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */
1029 (STp->buffer)->syscall_result = 0; /* Prevent error propagation */
1030 STp->drv_write_prot = 0;
1031 } else {
1032 DEBC(printk(ST_DEB_MSG
1033 "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
1034 name,
1035 (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
1036 (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]));
1037
1038 if ((STp->buffer)->b_data[3] >= 8) {
1039 STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
1040 STp->density = (STp->buffer)->b_data[4];
1041 STp->block_size = (STp->buffer)->b_data[9] * 65536 +
1042 (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
1043 DEBC(printk(ST_DEB_MSG
1044 "%s: Density %x, tape length: %x, drv buffer: %d\n",
1045 name, STp->density, (STp->buffer)->b_data[5] * 65536 +
1046 (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
1047 STp->drv_buffer));
1048 }
1049 STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
1050 }
Mike Christie8b05b772005-11-08 04:06:44 -06001051 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 SRpnt = NULL;
1053 STp->inited = 1;
1054
1055 if (STp->block_size > 0)
1056 (STp->buffer)->buffer_blocks =
1057 (STp->buffer)->buffer_size / STp->block_size;
1058 else
1059 (STp->buffer)->buffer_blocks = 1;
1060 (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
1061
1062 DEBC(printk(ST_DEB_MSG
1063 "%s: Block size: %d, buffer size: %d (%d blocks).\n", name,
1064 STp->block_size, (STp->buffer)->buffer_size,
1065 (STp->buffer)->buffer_blocks));
1066
1067 if (STp->drv_write_prot) {
1068 STp->write_prot = 1;
1069
1070 DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name));
1071
1072 if (do_wait &&
1073 ((st_flags & O_ACCMODE) == O_WRONLY ||
1074 (st_flags & O_ACCMODE) == O_RDWR)) {
1075 retval = (-EROFS);
1076 goto err_out;
1077 }
1078 }
1079
1080 if (STp->can_partitions && STp->nbr_partitions < 1) {
1081 /* This code is reached when the device is opened for the first time
1082 after the driver has been initialized with tape in the drive and the
1083 partition support has been enabled. */
1084 DEBC(printk(ST_DEB_MSG
1085 "%s: Updating partition number in status.\n", name));
1086 if ((STp->partition = find_partition(STp)) < 0) {
1087 retval = STp->partition;
1088 goto err_out;
1089 }
1090 STp->new_partition = STp->partition;
1091 STp->nbr_partitions = 1; /* This guess will be updated when necessary */
1092 }
1093
1094 if (new_session) { /* Change the drive parameters for the new mode */
1095 STp->density_changed = STp->blksize_changed = 0;
1096 STp->compression_changed = 0;
1097 if (!(STm->defaults_for_writes) &&
1098 (retval = set_mode_densblk(STp, STm)) < 0)
1099 goto err_out;
1100
1101 if (STp->default_drvbuffer != 0xff) {
1102 if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))
1103 printk(KERN_WARNING
1104 "%s: Can't set default drive buffering to %d.\n",
1105 name, STp->default_drvbuffer);
1106 }
1107 }
1108
1109 return CHKRES_READY;
1110
1111 err_out:
1112 return retval;
1113}
1114
1115
1116 /* Open the device. Needs to be called with BKL only because of incrementing the SCSI host
1117 module count. */
1118static int st_open(struct inode *inode, struct file *filp)
1119{
1120 int i, retval = (-EIO);
1121 struct scsi_tape *STp;
1122 struct st_partstat *STps;
1123 int dev = TAPE_NR(inode);
1124 char *name;
1125
1126 /*
1127 * We really want to do nonseekable_open(inode, filp); here, but some
1128 * versions of tar incorrectly call lseek on tapes and bail out if that
1129 * fails. So we disallow pread() and pwrite(), but permit lseeks.
1130 */
1131 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
1132
Kai Makisaraf03a5672005-08-02 13:40:47 +03001133 if (!(STp = scsi_tape_get(dev)))
1134 return -ENXIO;
1135
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 write_lock(&st_dev_arr_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 filp->private_data = STp;
1138 name = tape_name(STp);
1139
1140 if (STp->in_use) {
1141 write_unlock(&st_dev_arr_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001142 scsi_tape_put(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
1144 return (-EBUSY);
1145 }
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 STp->in_use = 1;
1148 write_unlock(&st_dev_arr_lock);
1149 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
1150
1151 if (!scsi_block_when_processing_errors(STp->device)) {
1152 retval = (-ENXIO);
1153 goto err_out;
1154 }
1155
1156 /* See that we have at least a one page buffer available */
1157 if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) {
1158 printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n",
1159 name);
1160 retval = (-EOVERFLOW);
1161 goto err_out;
1162 }
1163
Kai Makisara40f6b362008-02-24 22:23:24 +02001164 (STp->buffer)->cleared = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 (STp->buffer)->writing = 0;
1166 (STp->buffer)->syscall_result = 0;
1167
1168 STp->write_prot = ((filp->f_flags & O_ACCMODE) == O_RDONLY);
1169
1170 STp->dirty = 0;
1171 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
1172 STps = &(STp->ps[i]);
1173 STps->rw = ST_IDLE;
1174 }
Kai Makisara9abe16c2007-02-03 13:21:29 +02001175 STp->try_dio_now = STp->try_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 STp->recover_count = 0;
1177 DEB( STp->nbr_waits = STp->nbr_finished = 0;
Kai Makisaradeee13d2008-02-22 20:11:21 +02001178 STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = 0; )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
1180 retval = check_tape(STp, filp);
1181 if (retval < 0)
1182 goto err_out;
1183 if ((filp->f_flags & O_NONBLOCK) == 0 &&
1184 retval != CHKRES_READY) {
Kai Makisara413f7322006-10-05 22:59:46 +03001185 if (STp->ready == NO_TAPE)
1186 retval = (-ENOMEDIUM);
1187 else
1188 retval = (-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 goto err_out;
1190 }
1191 return 0;
1192
1193 err_out:
1194 normalize_buffer(STp->buffer);
1195 STp->in_use = 0;
Kai Makisaraf03a5672005-08-02 13:40:47 +03001196 scsi_tape_put(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 return retval;
1198
1199}
1200
1201
1202/* Flush the tape buffer before close */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001203static int st_flush(struct file *filp, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
1205 int result = 0, result2;
1206 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06001207 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 struct scsi_tape *STp = filp->private_data;
1209 struct st_modedef *STm = &(STp->modes[STp->current_mode]);
1210 struct st_partstat *STps = &(STp->ps[STp->partition]);
1211 char *name = tape_name(STp);
1212
1213 if (file_count(filp) > 1)
1214 return 0;
1215
1216 if (STps->rw == ST_WRITING && !STp->pos_unknown) {
Adrian Bunk8ef8d592008-04-14 17:17:16 +03001217 result = st_flush_write_buffer(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 if (result != 0 && result != (-ENOSPC))
1219 goto out;
1220 }
1221
1222 if (STp->can_partitions &&
1223 (result2 = switch_partition(STp)) < 0) {
1224 DEBC(printk(ST_DEB_MSG
1225 "%s: switch_partition at close failed.\n", name));
1226 if (result == 0)
1227 result = result2;
1228 goto out;
1229 }
1230
1231 DEBC( if (STp->nbr_requests)
Kai Makisaradeee13d2008-02-22 20:11:21 +02001232 printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n",
1233 name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
1235 if (STps->rw == ST_WRITING && !STp->pos_unknown) {
1236 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1237
1238 DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n",
1239 name, STp->nbr_waits, STp->nbr_finished);
1240 )
1241
1242 memset(cmd, 0, MAX_COMMAND_SIZE);
1243 cmd[0] = WRITE_FILEMARKS;
1244 cmd[4] = 1 + STp->two_fm;
1245
1246 SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
1247 STp->device->timeout, MAX_WRITE_RETRIES, 1);
1248 if (!SRpnt) {
1249 result = (STp->buffer)->syscall_result;
1250 goto out;
1251 }
1252
1253 if (STp->buffer->syscall_result == 0 ||
1254 (cmdstatp->have_sense && !cmdstatp->deferred &&
1255 (cmdstatp->flags & SENSE_EOM) &&
1256 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
1257 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
1258 (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
1259 /* Write successful at EOM */
Mike Christie8b05b772005-11-08 04:06:44 -06001260 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 SRpnt = NULL;
1262 if (STps->drv_file >= 0)
1263 STps->drv_file++;
1264 STps->drv_block = 0;
1265 if (STp->two_fm)
1266 cross_eof(STp, 0);
1267 STps->eof = ST_FM;
1268 }
1269 else { /* Write error */
Mike Christie8b05b772005-11-08 04:06:44 -06001270 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 SRpnt = NULL;
1272 printk(KERN_ERR "%s: Error on write filemark.\n", name);
1273 if (result == 0)
1274 result = (-EIO);
1275 }
1276
1277 DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n",
1278 name, cmd[4]));
1279 } else if (!STp->rew_at_close) {
1280 STps = &(STp->ps[STp->partition]);
1281 if (!STm->sysv || STps->rw != ST_READING) {
1282 if (STp->can_bsr)
1283 result = flush_buffer(STp, 0);
1284 else if (STps->eof == ST_FM_HIT) {
1285 result = cross_eof(STp, 0);
1286 if (result) {
1287 if (STps->drv_file >= 0)
1288 STps->drv_file++;
1289 STps->drv_block = 0;
1290 STps->eof = ST_FM;
1291 } else
1292 STps->eof = ST_NOEOF;
1293 }
1294 } else if ((STps->eof == ST_NOEOF &&
1295 !(result = cross_eof(STp, 1))) ||
1296 STps->eof == ST_FM_HIT) {
1297 if (STps->drv_file >= 0)
1298 STps->drv_file++;
1299 STps->drv_block = 0;
1300 STps->eof = ST_FM;
1301 }
1302 }
1303
1304 out:
1305 if (STp->rew_at_close) {
1306 result2 = st_int_ioctl(STp, MTREW, 1);
1307 if (result == 0)
1308 result = result2;
1309 }
1310 return result;
1311}
1312
1313
1314/* Close the device and release it. BKL is not needed: this is the only thread
1315 accessing this tape. */
1316static int st_release(struct inode *inode, struct file *filp)
1317{
1318 int result = 0;
1319 struct scsi_tape *STp = filp->private_data;
1320
1321 if (STp->door_locked == ST_LOCKED_AUTO)
1322 do_door_lock(STp, 0);
1323
1324 normalize_buffer(STp->buffer);
1325 write_lock(&st_dev_arr_lock);
1326 STp->in_use = 0;
1327 write_unlock(&st_dev_arr_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001328 scsi_tape_put(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
1330 return result;
1331}
1332
1333/* The checks common to both reading and writing */
1334static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count)
1335{
1336 ssize_t retval = 0;
1337
1338 /*
1339 * If we are in the middle of error recovery, don't let anyone
1340 * else try and use this device. Also, if error recovery fails, it
1341 * may try and take the device offline, in which case all further
1342 * access to the device is prohibited.
1343 */
1344 if (!scsi_block_when_processing_errors(STp->device)) {
1345 retval = (-ENXIO);
1346 goto out;
1347 }
1348
1349 if (STp->ready != ST_READY) {
1350 if (STp->ready == ST_NO_TAPE)
1351 retval = (-ENOMEDIUM);
1352 else
1353 retval = (-EIO);
1354 goto out;
1355 }
1356
1357 if (! STp->modes[STp->current_mode].defined) {
1358 retval = (-ENXIO);
1359 goto out;
1360 }
1361
1362
1363 /*
1364 * If there was a bus reset, block further access
1365 * to this device.
1366 */
1367 if (STp->pos_unknown) {
1368 retval = (-EIO);
1369 goto out;
1370 }
1371
1372 if (count == 0)
1373 goto out;
1374
1375 DEB(
1376 if (!STp->in_use) {
1377 printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp));
1378 retval = (-EIO);
1379 goto out;
1380 } ) /* end DEB */
1381
1382 if (STp->can_partitions &&
1383 (retval = switch_partition(STp)) < 0)
1384 goto out;
1385
1386 if (STp->block_size == 0 && STp->max_block > 0 &&
1387 (count < STp->min_block || count > STp->max_block)) {
1388 retval = (-EINVAL);
1389 goto out;
1390 }
1391
1392 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
1393 !do_door_lock(STp, 1))
1394 STp->door_locked = ST_LOCKED_AUTO;
1395
1396 out:
1397 return retval;
1398}
1399
1400
1401static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
1402 size_t count, int is_read)
1403{
1404 int i, bufsize, retval = 0;
1405 struct st_buffer *STbp = STp->buffer;
1406
1407 if (is_read)
Kai Makisara9abe16c2007-02-03 13:21:29 +02001408 i = STp->try_dio_now && try_rdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 else
Kai Makisara9abe16c2007-02-03 13:21:29 +02001410 i = STp->try_dio_now && try_wdio;
Mike Christie8b05b772005-11-08 04:06:44 -06001411
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 if (i && ((unsigned long)buf & queue_dma_alignment(
1413 STp->device->request_queue)) == 0) {
Mike Christie8b05b772005-11-08 04:06:44 -06001414 i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
1415 (unsigned long)buf, count, (is_read ? READ : WRITE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 if (i > 0) {
1417 STbp->do_dio = i;
1418 STbp->buffer_bytes = 0; /* can be used as transfer counter */
1419 }
1420 else
1421 STbp->do_dio = 0; /* fall back to buffering with any error */
1422 STbp->sg_segs = STbp->do_dio;
1423 STbp->frp_sg_current = 0;
1424 DEB(
1425 if (STbp->do_dio) {
1426 STp->nbr_dio++;
1427 STp->nbr_pages += STbp->do_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
1429 )
1430 } else
1431 STbp->do_dio = 0;
1432 DEB( STp->nbr_requests++; )
1433
1434 if (!STbp->do_dio) {
1435 if (STp->block_size)
1436 bufsize = STp->block_size > st_fixed_buffer_size ?
1437 STp->block_size : st_fixed_buffer_size;
Kai Makisara40f6b362008-02-24 22:23:24 +02001438 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 bufsize = count;
Kai Makisara40f6b362008-02-24 22:23:24 +02001440 /* Make sure that data from previous user is not leaked even if
1441 HBA does not return correct residual */
1442 if (is_read && STp->sili && !STbp->cleared)
1443 clear_buffer(STbp);
1444 }
1445
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (bufsize > STbp->buffer_size &&
1447 !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
1448 printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
1449 tape_name(STp), bufsize);
1450 retval = (-EOVERFLOW);
1451 goto out;
1452 }
1453 if (STp->block_size)
1454 STbp->buffer_blocks = bufsize / STp->block_size;
1455 }
1456
1457 out:
1458 return retval;
1459}
1460
1461
1462/* Can be called more than once after each setup_buffer() */
Kai Makisara787926b2005-11-13 10:04:44 +02001463static void release_buffering(struct scsi_tape *STp, int is_read)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
1465 struct st_buffer *STbp;
1466
1467 STbp = STp->buffer;
1468 if (STbp->do_dio) {
Kai Makisara787926b2005-11-13 10:04:44 +02001469 sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 STbp->do_dio = 0;
Kai Makisara787926b2005-11-13 10:04:44 +02001471 STbp->sg_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 }
1473}
1474
1475
1476/* Write command */
1477static ssize_t
1478st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
1479{
1480 ssize_t total;
1481 ssize_t i, do_count, blks, transfer;
1482 ssize_t retval;
1483 int undone, retry_eot = 0, scode;
1484 int async_write;
1485 unsigned char cmd[MAX_COMMAND_SIZE];
1486 const char __user *b_point;
Mike Christie8b05b772005-11-08 04:06:44 -06001487 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 struct scsi_tape *STp = filp->private_data;
1489 struct st_modedef *STm;
1490 struct st_partstat *STps;
1491 struct st_buffer *STbp;
1492 char *name = tape_name(STp);
1493
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001494 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 return -ERESTARTSYS;
1496
1497 retval = rw_checks(STp, filp, count);
1498 if (retval || count == 0)
1499 goto out;
1500
1501 /* Write must be integral number of blocks */
1502 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
1503 printk(KERN_WARNING "%s: Write not multiple of tape block size.\n",
1504 name);
1505 retval = (-EINVAL);
1506 goto out;
1507 }
1508
1509 STm = &(STp->modes[STp->current_mode]);
1510 STps = &(STp->ps[STp->partition]);
1511
1512 if (STp->write_prot) {
1513 retval = (-EACCES);
1514 goto out;
1515 }
1516
1517
1518 if (STps->rw == ST_READING) {
1519 retval = flush_buffer(STp, 0);
1520 if (retval)
1521 goto out;
1522 STps->rw = ST_WRITING;
1523 } else if (STps->rw != ST_WRITING &&
1524 STps->drv_file == 0 && STps->drv_block == 0) {
1525 if ((retval = set_mode_densblk(STp, STm)) < 0)
1526 goto out;
1527 if (STm->default_compression != ST_DONT_TOUCH &&
1528 !(STp->compression_changed)) {
1529 if (st_compression(STp, (STm->default_compression == ST_YES))) {
1530 printk(KERN_WARNING "%s: Can't set default compression.\n",
1531 name);
1532 if (modes_defined) {
1533 retval = (-EINVAL);
1534 goto out;
1535 }
1536 }
1537 }
1538 }
1539
1540 STbp = STp->buffer;
1541 i = write_behind_check(STp);
1542 if (i) {
1543 if (i == -ENOSPC)
1544 STps->eof = ST_EOM_OK;
1545 else
1546 STps->eof = ST_EOM_ERROR;
1547 }
1548
1549 if (STps->eof == ST_EOM_OK) {
1550 STps->eof = ST_EOD_1; /* allow next write */
1551 retval = (-ENOSPC);
1552 goto out;
1553 }
1554 else if (STps->eof == ST_EOM_ERROR) {
1555 retval = (-EIO);
1556 goto out;
1557 }
1558
1559 /* Check the buffer readability in cases where copy_user might catch
1560 the problems after some tape movement. */
1561 if (STp->block_size != 0 &&
1562 !STbp->do_dio &&
1563 (copy_from_user(&i, buf, 1) != 0 ||
1564 copy_from_user(&i, buf + count - 1, 1) != 0)) {
1565 retval = (-EFAULT);
1566 goto out;
1567 }
1568
1569 retval = setup_buffering(STp, buf, count, 0);
1570 if (retval)
1571 goto out;
1572
1573 total = count;
1574
1575 memset(cmd, 0, MAX_COMMAND_SIZE);
1576 cmd[0] = WRITE_6;
1577 cmd[1] = (STp->block_size != 0);
1578
1579 STps->rw = ST_WRITING;
1580
1581 b_point = buf;
1582 while (count > 0 && !retry_eot) {
1583
1584 if (STbp->do_dio) {
1585 do_count = count;
1586 }
1587 else {
1588 if (STp->block_size == 0)
1589 do_count = count;
1590 else {
1591 do_count = STbp->buffer_blocks * STp->block_size -
1592 STbp->buffer_bytes;
1593 if (do_count > count)
1594 do_count = count;
1595 }
1596
1597 i = append_to_buffer(b_point, STbp, do_count);
1598 if (i) {
1599 retval = i;
1600 goto out;
1601 }
1602 }
1603 count -= do_count;
1604 b_point += do_count;
1605
1606 async_write = STp->block_size == 0 && !STbp->do_dio &&
1607 STm->do_async_writes && STps->eof < ST_EOM_OK;
1608
1609 if (STp->block_size != 0 && STm->do_buffer_writes &&
Kai Makisara9abe16c2007-02-03 13:21:29 +02001610 !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 STbp->buffer_bytes < STbp->buffer_size) {
1612 STp->dirty = 1;
1613 /* Don't write a buffer that is not full enough. */
1614 if (!async_write && count == 0)
1615 break;
1616 }
1617
1618 retry_write:
1619 if (STp->block_size == 0)
1620 blks = transfer = do_count;
1621 else {
1622 if (!STbp->do_dio)
1623 blks = STbp->buffer_bytes;
1624 else
1625 blks = do_count;
1626 blks /= STp->block_size;
1627 transfer = blks * STp->block_size;
1628 }
1629 cmd[2] = blks >> 16;
1630 cmd[3] = blks >> 8;
1631 cmd[4] = blks;
1632
1633 SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
1634 STp->device->timeout, MAX_WRITE_RETRIES, !async_write);
1635 if (!SRpnt) {
1636 retval = STbp->syscall_result;
1637 goto out;
1638 }
Mike Christie8b05b772005-11-08 04:06:44 -06001639 if (async_write && !STbp->syscall_result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 STbp->writing = transfer;
1641 STp->dirty = !(STbp->writing ==
1642 STbp->buffer_bytes);
1643 SRpnt = NULL; /* Prevent releasing this request! */
1644 DEB( STp->write_pending = 1; )
1645 break;
1646 }
1647
1648 if (STbp->syscall_result != 0) {
1649 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1650
1651 DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));
1652 if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) {
1653 scode = cmdstatp->sense_hdr.sense_key;
1654 if (cmdstatp->remainder_valid)
1655 undone = (int)cmdstatp->uremainder64;
1656 else if (STp->block_size == 0 &&
1657 scode == VOLUME_OVERFLOW)
1658 undone = transfer;
1659 else
1660 undone = 0;
1661 if (STp->block_size != 0)
1662 undone *= STp->block_size;
1663 if (undone <= do_count) {
1664 /* Only data from this write is not written */
1665 count += undone;
1666 do_count -= undone;
1667 if (STp->block_size)
1668 blks = (transfer - undone) / STp->block_size;
1669 STps->eof = ST_EOM_OK;
1670 /* Continue in fixed block mode if all written
1671 in this request but still something left to write
1672 (retval left to zero)
1673 */
1674 if (STp->block_size == 0 ||
1675 undone > 0 || count == 0)
1676 retval = (-ENOSPC); /* EOM within current request */
1677 DEBC(printk(ST_DEB_MSG
1678 "%s: EOM with %d bytes unwritten.\n",
1679 name, (int)count));
1680 } else {
1681 /* EOT within data buffered earlier (possible only
1682 in fixed block mode without direct i/o) */
1683 if (!retry_eot && !cmdstatp->deferred &&
1684 (scode == NO_SENSE || scode == RECOVERED_ERROR)) {
1685 move_buffer_data(STp->buffer, transfer - undone);
1686 retry_eot = 1;
1687 if (STps->drv_block >= 0) {
1688 STps->drv_block += (transfer - undone) /
1689 STp->block_size;
1690 }
1691 STps->eof = ST_EOM_OK;
1692 DEBC(printk(ST_DEB_MSG
1693 "%s: Retry write of %d bytes at EOM.\n",
1694 name, STp->buffer->buffer_bytes));
1695 goto retry_write;
1696 }
1697 else {
1698 /* Either error within data buffered by driver or
1699 failed retry */
1700 count -= do_count;
1701 blks = do_count = 0;
1702 STps->eof = ST_EOM_ERROR;
1703 STps->drv_block = (-1); /* Too cautious? */
1704 retval = (-EIO); /* EOM for old data */
1705 DEBC(printk(ST_DEB_MSG
1706 "%s: EOM with lost data.\n",
1707 name));
1708 }
1709 }
1710 } else {
1711 count += do_count;
1712 STps->drv_block = (-1); /* Too cautious? */
Mike Christie8b05b772005-11-08 04:06:44 -06001713 retval = STbp->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 }
1715
1716 }
1717
1718 if (STps->drv_block >= 0) {
1719 if (STp->block_size == 0)
1720 STps->drv_block += (do_count > 0);
1721 else
1722 STps->drv_block += blks;
1723 }
1724
1725 STbp->buffer_bytes = 0;
1726 STp->dirty = 0;
1727
1728 if (retval || retry_eot) {
1729 if (count < total)
1730 retval = total - count;
1731 goto out;
1732 }
1733 }
1734
1735 if (STps->eof == ST_EOD_1)
1736 STps->eof = ST_EOM_OK;
1737 else if (STps->eof != ST_EOM_OK)
1738 STps->eof = ST_NOEOF;
1739 retval = total - count;
1740
1741 out:
1742 if (SRpnt != NULL)
Mike Christie8b05b772005-11-08 04:06:44 -06001743 st_release_request(SRpnt);
Kai Makisara787926b2005-11-13 10:04:44 +02001744 release_buffering(STp, 0);
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001745 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
1747 return retval;
1748}
1749
1750/* Read data from the tape. Returns zero in the normal case, one if the
1751 eof status has changed, and the negative error code in case of a
1752 fatal error. Otherwise updates the buffer and the eof state.
1753
1754 Does release user buffer mapping if it is set.
1755*/
1756static long read_tape(struct scsi_tape *STp, long count,
Mike Christie8b05b772005-11-08 04:06:44 -06001757 struct st_request ** aSRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758{
1759 int transfer, blks, bytes;
1760 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06001761 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 struct st_modedef *STm;
1763 struct st_partstat *STps;
1764 struct st_buffer *STbp;
1765 int retval = 0;
1766 char *name = tape_name(STp);
1767
1768 if (count == 0)
1769 return 0;
1770
1771 STm = &(STp->modes[STp->current_mode]);
1772 STps = &(STp->ps[STp->partition]);
1773 if (STps->eof == ST_FM_HIT)
1774 return 1;
1775 STbp = STp->buffer;
1776
1777 if (STp->block_size == 0)
1778 blks = bytes = count;
1779 else {
Kai Makisara9abe16c2007-02-03 13:21:29 +02001780 if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 blks = (STp->buffer)->buffer_blocks;
1782 bytes = blks * STp->block_size;
1783 } else {
1784 bytes = count;
1785 if (!STbp->do_dio && bytes > (STp->buffer)->buffer_size)
1786 bytes = (STp->buffer)->buffer_size;
1787 blks = bytes / STp->block_size;
1788 bytes = blks * STp->block_size;
1789 }
1790 }
1791
1792 memset(cmd, 0, MAX_COMMAND_SIZE);
1793 cmd[0] = READ_6;
1794 cmd[1] = (STp->block_size != 0);
Kai Makisara40f6b362008-02-24 22:23:24 +02001795 if (!cmd[1] && STp->sili)
1796 cmd[1] |= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 cmd[2] = blks >> 16;
1798 cmd[3] = blks >> 8;
1799 cmd[4] = blks;
1800
1801 SRpnt = *aSRpnt;
1802 SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE,
1803 STp->device->timeout, MAX_RETRIES, 1);
Kai Makisara787926b2005-11-13 10:04:44 +02001804 release_buffering(STp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 *aSRpnt = SRpnt;
1806 if (!SRpnt)
1807 return STbp->syscall_result;
1808
1809 STbp->read_pointer = 0;
1810 STps->at_sm = 0;
1811
1812 /* Something to check */
1813 if (STbp->syscall_result) {
1814 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1815
1816 retval = 1;
1817 DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1818 name,
Mike Christie8b05b772005-11-08 04:06:44 -06001819 SRpnt->sense[0], SRpnt->sense[1],
1820 SRpnt->sense[2], SRpnt->sense[3],
1821 SRpnt->sense[4], SRpnt->sense[5],
1822 SRpnt->sense[6], SRpnt->sense[7]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 if (cmdstatp->have_sense) {
1824
1825 if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
1826 cmdstatp->flags &= 0xcf; /* No need for EOM in this case */
1827
1828 if (cmdstatp->flags != 0) { /* EOF, EOM, or ILI */
1829 /* Compute the residual count */
1830 if (cmdstatp->remainder_valid)
1831 transfer = (int)cmdstatp->uremainder64;
1832 else
1833 transfer = 0;
1834 if (STp->block_size == 0 &&
1835 cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR)
1836 transfer = bytes;
1837
1838 if (cmdstatp->flags & SENSE_ILI) { /* ILI */
1839 if (STp->block_size == 0) {
1840 if (transfer <= 0) {
1841 if (transfer < 0)
1842 printk(KERN_NOTICE
1843 "%s: Failed to read %d byte block with %d byte transfer.\n",
1844 name, bytes - transfer, bytes);
1845 if (STps->drv_block >= 0)
1846 STps->drv_block += 1;
1847 STbp->buffer_bytes = 0;
1848 return (-ENOMEM);
1849 }
1850 STbp->buffer_bytes = bytes - transfer;
1851 } else {
Mike Christie8b05b772005-11-08 04:06:44 -06001852 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 SRpnt = *aSRpnt = NULL;
1854 if (transfer == blks) { /* We did not get anything, error */
1855 printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
1856 if (STps->drv_block >= 0)
1857 STps->drv_block += blks - transfer + 1;
1858 st_int_ioctl(STp, MTBSR, 1);
1859 return (-EIO);
1860 }
1861 /* We have some data, deliver it */
1862 STbp->buffer_bytes = (blks - transfer) *
1863 STp->block_size;
1864 DEBC(printk(ST_DEB_MSG
1865 "%s: ILI but enough data received %ld %d.\n",
1866 name, count, STbp->buffer_bytes));
1867 if (STps->drv_block >= 0)
1868 STps->drv_block += 1;
1869 if (st_int_ioctl(STp, MTBSR, 1))
1870 return (-EIO);
1871 }
1872 } else if (cmdstatp->flags & SENSE_FMK) { /* FM overrides EOM */
1873 if (STps->eof != ST_FM_HIT)
1874 STps->eof = ST_FM_HIT;
1875 else
1876 STps->eof = ST_EOD_2;
1877 if (STp->block_size == 0)
1878 STbp->buffer_bytes = 0;
1879 else
1880 STbp->buffer_bytes =
1881 bytes - transfer * STp->block_size;
1882 DEBC(printk(ST_DEB_MSG
1883 "%s: EOF detected (%d bytes read).\n",
1884 name, STbp->buffer_bytes));
1885 } else if (cmdstatp->flags & SENSE_EOM) {
1886 if (STps->eof == ST_FM)
1887 STps->eof = ST_EOD_1;
1888 else
1889 STps->eof = ST_EOM_OK;
1890 if (STp->block_size == 0)
1891 STbp->buffer_bytes = bytes - transfer;
1892 else
1893 STbp->buffer_bytes =
1894 bytes - transfer * STp->block_size;
1895
1896 DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n",
1897 name, STbp->buffer_bytes));
1898 }
1899 }
1900 /* end of EOF, EOM, ILI test */
1901 else { /* nonzero sense key */
1902 DEBC(printk(ST_DEB_MSG
1903 "%s: Tape error while reading.\n", name));
1904 STps->drv_block = (-1);
1905 if (STps->eof == ST_FM &&
1906 cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {
1907 DEBC(printk(ST_DEB_MSG
1908 "%s: Zero returned for first BLANK CHECK after EOF.\n",
1909 name));
1910 STps->eof = ST_EOD_2; /* First BLANK_CHECK after FM */
1911 } else /* Some other extended sense code */
1912 retval = (-EIO);
1913 }
1914
1915 if (STbp->buffer_bytes < 0) /* Caused by bogus sense data */
1916 STbp->buffer_bytes = 0;
1917 }
1918 /* End of extended sense test */
1919 else { /* Non-extended sense */
1920 retval = STbp->syscall_result;
1921 }
1922
1923 }
1924 /* End of error handling */
Kai Makisara40f6b362008-02-24 22:23:24 +02001925 else { /* Read successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 STbp->buffer_bytes = bytes;
Kai Makisara40f6b362008-02-24 22:23:24 +02001927 if (STp->sili) /* In fixed block mode residual is always zero here */
1928 STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
1929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930
1931 if (STps->drv_block >= 0) {
1932 if (STp->block_size == 0)
1933 STps->drv_block++;
1934 else
1935 STps->drv_block += STbp->buffer_bytes / STp->block_size;
1936 }
1937 return retval;
1938}
1939
1940
1941/* Read command */
1942static ssize_t
1943st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
1944{
1945 ssize_t total;
1946 ssize_t retval = 0;
1947 ssize_t i, transfer;
1948 int special, do_dio = 0;
Mike Christie8b05b772005-11-08 04:06:44 -06001949 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 struct scsi_tape *STp = filp->private_data;
1951 struct st_modedef *STm;
1952 struct st_partstat *STps;
1953 struct st_buffer *STbp = STp->buffer;
1954 DEB( char *name = tape_name(STp); )
1955
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001956 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 return -ERESTARTSYS;
1958
1959 retval = rw_checks(STp, filp, count);
1960 if (retval || count == 0)
1961 goto out;
1962
1963 STm = &(STp->modes[STp->current_mode]);
Kai Makisara9abe16c2007-02-03 13:21:29 +02001964 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
1965 if (!STm->do_read_ahead) {
1966 retval = (-EINVAL); /* Read must be integral number of blocks */
1967 goto out;
1968 }
1969 STp->try_dio_now = 0; /* Direct i/o can't handle split blocks */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 }
1971
1972 STps = &(STp->ps[STp->partition]);
1973 if (STps->rw == ST_WRITING) {
1974 retval = flush_buffer(STp, 0);
1975 if (retval)
1976 goto out;
1977 STps->rw = ST_READING;
1978 }
1979 DEB(
1980 if (debugging && STps->eof != ST_NOEOF)
1981 printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name,
1982 STps->eof, STbp->buffer_bytes);
1983 ) /* end DEB */
1984
1985 retval = setup_buffering(STp, buf, count, 1);
1986 if (retval)
1987 goto out;
1988 do_dio = STbp->do_dio;
1989
1990 if (STbp->buffer_bytes == 0 &&
1991 STps->eof >= ST_EOD_1) {
1992 if (STps->eof < ST_EOD) {
1993 STps->eof += 1;
1994 retval = 0;
1995 goto out;
1996 }
1997 retval = (-EIO); /* EOM or Blank Check */
1998 goto out;
1999 }
2000
2001 if (do_dio) {
2002 /* Check the buffer writability before any tape movement. Don't alter
2003 buffer data. */
2004 if (copy_from_user(&i, buf, 1) != 0 ||
2005 copy_to_user(buf, &i, 1) != 0 ||
2006 copy_from_user(&i, buf + count - 1, 1) != 0 ||
2007 copy_to_user(buf + count - 1, &i, 1) != 0) {
2008 retval = (-EFAULT);
2009 goto out;
2010 }
2011 }
2012
2013 STps->rw = ST_READING;
2014
2015
2016 /* Loop until enough data in buffer or a special condition found */
2017 for (total = 0, special = 0; total < count && !special;) {
2018
2019 /* Get new data if the buffer is empty */
2020 if (STbp->buffer_bytes == 0) {
2021 special = read_tape(STp, count - total, &SRpnt);
2022 if (special < 0) { /* No need to continue read */
2023 retval = special;
2024 goto out;
2025 }
2026 }
2027
2028 /* Move the data from driver buffer to user buffer */
2029 if (STbp->buffer_bytes > 0) {
2030 DEB(
2031 if (debugging && STps->eof != ST_NOEOF)
2032 printk(ST_DEB_MSG
2033 "%s: EOF up (%d). Left %d, needed %d.\n", name,
2034 STps->eof, STbp->buffer_bytes,
2035 (int)(count - total));
2036 ) /* end DEB */
2037 transfer = STbp->buffer_bytes < count - total ?
2038 STbp->buffer_bytes : count - total;
2039 if (!do_dio) {
2040 i = from_buffer(STbp, buf, transfer);
2041 if (i) {
2042 retval = i;
2043 goto out;
2044 }
2045 }
2046 buf += transfer;
2047 total += transfer;
2048 }
2049
2050 if (STp->block_size == 0)
2051 break; /* Read only one variable length block */
2052
2053 } /* for (total = 0, special = 0;
2054 total < count && !special; ) */
2055
2056 /* Change the eof state if no data from tape or buffer */
2057 if (total == 0) {
2058 if (STps->eof == ST_FM_HIT) {
2059 STps->eof = ST_FM;
2060 STps->drv_block = 0;
2061 if (STps->drv_file >= 0)
2062 STps->drv_file++;
2063 } else if (STps->eof == ST_EOD_1) {
2064 STps->eof = ST_EOD_2;
2065 STps->drv_block = 0;
2066 if (STps->drv_file >= 0)
2067 STps->drv_file++;
2068 } else if (STps->eof == ST_EOD_2)
2069 STps->eof = ST_EOD;
2070 } else if (STps->eof == ST_FM)
2071 STps->eof = ST_NOEOF;
2072 retval = total;
2073
2074 out:
2075 if (SRpnt != NULL) {
Mike Christie8b05b772005-11-08 04:06:44 -06002076 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 SRpnt = NULL;
2078 }
2079 if (do_dio) {
Kai Makisara787926b2005-11-13 10:04:44 +02002080 release_buffering(STp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 STbp->buffer_bytes = 0;
2082 }
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02002083 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
2085 return retval;
2086}
2087
2088
2089
2090DEB(
2091/* Set the driver options */
2092static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name)
2093{
2094 if (debugging) {
2095 printk(KERN_INFO
2096 "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
2097 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
2098 STm->do_read_ahead);
2099 printk(KERN_INFO
2100 "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
2101 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
2102 printk(KERN_INFO
2103 "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
2104 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
2105 STp->scsi2_logical);
2106 printk(KERN_INFO
Kai Makisara40f6b362008-02-24 22:23:24 +02002107 "%s: sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
2108 STp->sili);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 printk(KERN_INFO "%s: debugging: %d\n",
2110 name, debugging);
2111 }
2112}
2113 )
2114
2115
2116static int st_set_options(struct scsi_tape *STp, long options)
2117{
2118 int value;
2119 long code;
2120 struct st_modedef *STm;
2121 char *name = tape_name(STp);
2122 struct cdev *cd0, *cd1;
2123
2124 STm = &(STp->modes[STp->current_mode]);
2125 if (!STm->defined) {
2126 cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1];
2127 memcpy(STm, &(STp->modes[0]), sizeof(struct st_modedef));
2128 STm->cdevs[0] = cd0; STm->cdevs[1] = cd1;
2129 modes_defined = 1;
2130 DEBC(printk(ST_DEB_MSG
2131 "%s: Initialized mode %d definition from mode 0\n",
2132 name, STp->current_mode));
2133 }
2134
2135 code = options & MT_ST_OPTIONS;
2136 if (code == MT_ST_BOOLEANS) {
2137 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
2138 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
2139 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
2140 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
2141 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
2142 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
2143 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
2144 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
2145 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
2146 if ((STp->device)->scsi_level >= SCSI_2)
2147 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
2148 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
2149 STp->immediate = (options & MT_ST_NOWAIT) != 0;
2150 STm->sysv = (options & MT_ST_SYSV) != 0;
Kai Makisara40f6b362008-02-24 22:23:24 +02002151 STp->sili = (options & MT_ST_SILI) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
2153 st_log_options(STp, STm, name); )
2154 } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
2155 value = (code == MT_ST_SETBOOLEANS);
2156 if ((options & MT_ST_BUFFER_WRITES) != 0)
2157 STm->do_buffer_writes = value;
2158 if ((options & MT_ST_ASYNC_WRITES) != 0)
2159 STm->do_async_writes = value;
2160 if ((options & MT_ST_DEF_WRITES) != 0)
2161 STm->defaults_for_writes = value;
2162 if ((options & MT_ST_READ_AHEAD) != 0)
2163 STm->do_read_ahead = value;
2164 if ((options & MT_ST_TWO_FM) != 0)
2165 STp->two_fm = value;
2166 if ((options & MT_ST_FAST_MTEOM) != 0)
2167 STp->fast_mteom = value;
2168 if ((options & MT_ST_AUTO_LOCK) != 0)
2169 STp->do_auto_lock = value;
2170 if ((options & MT_ST_CAN_BSR) != 0)
2171 STp->can_bsr = value;
2172 if ((options & MT_ST_NO_BLKLIMS) != 0)
2173 STp->omit_blklims = value;
2174 if ((STp->device)->scsi_level >= SCSI_2 &&
2175 (options & MT_ST_CAN_PARTITIONS) != 0)
2176 STp->can_partitions = value;
2177 if ((options & MT_ST_SCSI2LOGICAL) != 0)
2178 STp->scsi2_logical = value;
2179 if ((options & MT_ST_NOWAIT) != 0)
2180 STp->immediate = value;
2181 if ((options & MT_ST_SYSV) != 0)
2182 STm->sysv = value;
Kai Makisara40f6b362008-02-24 22:23:24 +02002183 if ((options & MT_ST_SILI) != 0)
2184 STp->sili = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 DEB(
2186 if ((options & MT_ST_DEBUGGING) != 0)
2187 debugging = value;
2188 st_log_options(STp, STm, name); )
2189 } else if (code == MT_ST_WRITE_THRESHOLD) {
2190 /* Retained for compatibility */
2191 } else if (code == MT_ST_DEF_BLKSIZE) {
2192 value = (options & ~MT_ST_OPTIONS);
2193 if (value == ~MT_ST_OPTIONS) {
2194 STm->default_blksize = (-1);
2195 DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name));
2196 } else {
2197 STm->default_blksize = value;
2198 DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n",
2199 name, STm->default_blksize));
2200 if (STp->ready == ST_READY) {
2201 STp->blksize_changed = 0;
2202 set_mode_densblk(STp, STm);
2203 }
2204 }
2205 } else if (code == MT_ST_TIMEOUTS) {
2206 value = (options & ~MT_ST_OPTIONS);
2207 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
2208 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
2209 DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name,
2210 (value & ~MT_ST_SET_LONG_TIMEOUT)));
2211 } else {
2212 STp->device->timeout = value * HZ;
2213 DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n",
2214 name, value) );
2215 }
2216 } else if (code == MT_ST_SET_CLN) {
2217 value = (options & ~MT_ST_OPTIONS) & 0xff;
2218 if (value != 0 &&
2219 value < EXTENDED_SENSE_START && value >= SCSI_SENSE_BUFFERSIZE)
2220 return (-EINVAL);
2221 STp->cln_mode = value;
2222 STp->cln_sense_mask = (options >> 8) & 0xff;
2223 STp->cln_sense_value = (options >> 16) & 0xff;
2224 printk(KERN_INFO
2225 "%s: Cleaning request mode %d, mask %02x, value %02x\n",
2226 name, value, STp->cln_sense_mask, STp->cln_sense_value);
2227 } else if (code == MT_ST_DEF_OPTIONS) {
2228 code = (options & ~MT_ST_CLEAR_DEFAULT);
2229 value = (options & MT_ST_CLEAR_DEFAULT);
2230 if (code == MT_ST_DEF_DENSITY) {
2231 if (value == MT_ST_CLEAR_DEFAULT) {
2232 STm->default_density = (-1);
2233 DEBC( printk(KERN_INFO "%s: Density default disabled.\n",
2234 name));
2235 } else {
2236 STm->default_density = value & 0xff;
2237 DEBC( printk(KERN_INFO "%s: Density default set to %x\n",
2238 name, STm->default_density));
2239 if (STp->ready == ST_READY) {
2240 STp->density_changed = 0;
2241 set_mode_densblk(STp, STm);
2242 }
2243 }
2244 } else if (code == MT_ST_DEF_DRVBUFFER) {
2245 if (value == MT_ST_CLEAR_DEFAULT) {
2246 STp->default_drvbuffer = 0xff;
2247 DEBC( printk(KERN_INFO
2248 "%s: Drive buffer default disabled.\n", name));
2249 } else {
2250 STp->default_drvbuffer = value & 7;
2251 DEBC( printk(KERN_INFO
2252 "%s: Drive buffer default set to %x\n",
2253 name, STp->default_drvbuffer));
2254 if (STp->ready == ST_READY)
2255 st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer);
2256 }
2257 } else if (code == MT_ST_DEF_COMPRESSION) {
2258 if (value == MT_ST_CLEAR_DEFAULT) {
2259 STm->default_compression = ST_DONT_TOUCH;
2260 DEBC( printk(KERN_INFO
2261 "%s: Compression default disabled.\n", name));
2262 } else {
2263 if ((value & 0xff00) != 0) {
2264 STp->c_algo = (value & 0xff00) >> 8;
2265 DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n",
2266 name, STp->c_algo));
2267 }
2268 if ((value & 0xff) != 0xff) {
2269 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
2270 DEBC( printk(KERN_INFO "%s: Compression default set to %x\n",
2271 name, (value & 1)));
2272 if (STp->ready == ST_READY) {
2273 STp->compression_changed = 0;
2274 st_compression(STp, (STm->default_compression == ST_YES));
2275 }
2276 }
2277 }
2278 }
2279 } else
2280 return (-EIO);
2281
2282 return 0;
2283}
2284
2285#define MODE_HEADER_LENGTH 4
2286
2287/* Mode header and page byte offsets */
2288#define MH_OFF_DATA_LENGTH 0
2289#define MH_OFF_MEDIUM_TYPE 1
2290#define MH_OFF_DEV_SPECIFIC 2
2291#define MH_OFF_BDESCS_LENGTH 3
2292#define MP_OFF_PAGE_NBR 0
2293#define MP_OFF_PAGE_LENGTH 1
2294
2295/* Mode header and page bit masks */
2296#define MH_BIT_WP 0x80
2297#define MP_MSK_PAGE_NBR 0x3f
2298
2299/* Don't return block descriptors */
2300#define MODE_SENSE_OMIT_BDESCS 0x08
2301
2302#define MODE_SELECT_PAGE_FORMAT 0x10
2303
2304/* Read a mode page into the tape buffer. The block descriptors are included
2305 if incl_block_descs is true. The page control is ored to the page number
2306 parameter, if necessary. */
2307static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
2308{
2309 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002310 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311
2312 memset(cmd, 0, MAX_COMMAND_SIZE);
2313 cmd[0] = MODE_SENSE;
2314 if (omit_block_descs)
2315 cmd[1] = MODE_SENSE_OMIT_BDESCS;
2316 cmd[2] = page;
2317 cmd[4] = 255;
2318
2319 SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE,
2320 STp->device->timeout, 0, 1);
2321 if (SRpnt == NULL)
2322 return (STp->buffer)->syscall_result;
2323
Mike Christie8b05b772005-11-08 04:06:44 -06002324 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325
2326 return (STp->buffer)->syscall_result;
2327}
2328
2329
2330/* Send the mode page in the tape buffer to the drive. Assumes that the mode data
2331 in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */
2332static int write_mode_page(struct scsi_tape *STp, int page, int slow)
2333{
2334 int pgo;
2335 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002336 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
2338 memset(cmd, 0, MAX_COMMAND_SIZE);
2339 cmd[0] = MODE_SELECT;
2340 cmd[1] = MODE_SELECT_PAGE_FORMAT;
2341 pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH];
2342 cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2;
2343
2344 /* Clear reserved fields */
2345 (STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0;
2346 (STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0;
2347 (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
2348 (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
2349
2350 SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE,
2351 (slow ? STp->long_timeout : STp->device->timeout), 0, 1);
2352 if (SRpnt == NULL)
2353 return (STp->buffer)->syscall_result;
2354
Mike Christie8b05b772005-11-08 04:06:44 -06002355 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
2357 return (STp->buffer)->syscall_result;
2358}
2359
2360
2361#define COMPRESSION_PAGE 0x0f
2362#define COMPRESSION_PAGE_LENGTH 16
2363
2364#define CP_OFF_DCE_DCC 2
2365#define CP_OFF_C_ALGO 7
2366
2367#define DCE_MASK 0x80
2368#define DCC_MASK 0x40
2369#define RED_MASK 0x60
2370
2371
2372/* Control the compression with mode page 15. Algorithm not changed if zero.
2373
2374 The block descriptors are read and written because Sony SDT-7000 does not
2375 work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
2376 Including block descriptors should not cause any harm to other drives. */
2377
2378static int st_compression(struct scsi_tape * STp, int state)
2379{
2380 int retval;
2381 int mpoffs; /* Offset to mode page start */
2382 unsigned char *b_data = (STp->buffer)->b_data;
2383 DEB( char *name = tape_name(STp); )
2384
2385 if (STp->ready != ST_READY)
2386 return (-EIO);
2387
2388 /* Read the current page contents */
2389 retval = read_mode_page(STp, COMPRESSION_PAGE, 0);
2390 if (retval) {
2391 DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n",
2392 name));
2393 return (-EIO);
2394 }
2395
2396 mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH];
2397 DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name,
2398 (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
2399
2400 /* Check if compression can be changed */
2401 if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) {
2402 DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name));
2403 return (-EIO);
2404 }
2405
2406 /* Do the change */
2407 if (state) {
2408 b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK;
2409 if (STp->c_algo != 0)
2410 b_data[mpoffs + CP_OFF_C_ALGO] = STp->c_algo;
2411 }
2412 else {
2413 b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK;
2414 if (STp->c_algo != 0)
2415 b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */
2416 }
2417
2418 retval = write_mode_page(STp, COMPRESSION_PAGE, 0);
2419 if (retval) {
2420 DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name));
2421 return (-EIO);
2422 }
2423 DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n",
2424 name, state));
2425
2426 STp->compression_changed = 1;
2427 return 0;
2428}
2429
2430
2431/* Process the load and unload commands (does unload if the load code is zero) */
2432static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code)
2433{
2434 int retval = (-EIO), timeout;
2435 DEB( char *name = tape_name(STp); )
2436 unsigned char cmd[MAX_COMMAND_SIZE];
2437 struct st_partstat *STps;
Mike Christie8b05b772005-11-08 04:06:44 -06002438 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
2440 if (STp->ready != ST_READY && !load_code) {
2441 if (STp->ready == ST_NO_TAPE)
2442 return (-ENOMEDIUM);
2443 else
2444 return (-EIO);
2445 }
2446
2447 memset(cmd, 0, MAX_COMMAND_SIZE);
2448 cmd[0] = START_STOP;
2449 if (load_code)
2450 cmd[4] |= 1;
2451 /*
2452 * If arg >= 1 && arg <= 6 Enhanced load/unload in HP C1553A
2453 */
2454 if (load_code >= 1 + MT_ST_HPLOADER_OFFSET
2455 && load_code <= 6 + MT_ST_HPLOADER_OFFSET) {
2456 DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n",
2457 name, (cmd[4]) ? "" : "un",
2458 load_code - MT_ST_HPLOADER_OFFSET));
2459 cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
2460 }
2461 if (STp->immediate) {
2462 cmd[1] = 1; /* Don't wait for completion */
2463 timeout = STp->device->timeout;
2464 }
2465 else
2466 timeout = STp->long_timeout;
2467
2468 DEBC(
2469 if (!load_code)
2470 printk(ST_DEB_MSG "%s: Unloading tape.\n", name);
2471 else
2472 printk(ST_DEB_MSG "%s: Loading tape.\n", name);
2473 );
2474
2475 SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
2476 timeout, MAX_RETRIES, 1);
2477 if (!SRpnt)
2478 return (STp->buffer)->syscall_result;
2479
2480 retval = (STp->buffer)->syscall_result;
Mike Christie8b05b772005-11-08 04:06:44 -06002481 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
2483 if (!retval) { /* SCSI command successful */
2484
2485 if (!load_code) {
2486 STp->rew_at_close = 0;
2487 STp->ready = ST_NO_TAPE;
2488 }
2489 else {
2490 STp->rew_at_close = STp->autorew_dev;
2491 retval = check_tape(STp, filp);
2492 if (retval > 0)
2493 retval = 0;
2494 }
2495 }
2496 else {
2497 STps = &(STp->ps[STp->partition]);
2498 STps->drv_file = STps->drv_block = (-1);
2499 }
2500
2501 return retval;
2502}
2503
2504#if DEBUG
2505#define ST_DEB_FORWARD 0
2506#define ST_DEB_BACKWARD 1
2507static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd)
2508{
2509 s32 sc;
2510
2511 sc = cmd[2] & 0x80 ? 0xff000000 : 0;
2512 sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
2513 if (direction)
2514 sc = -sc;
2515 printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name,
2516 direction ? "backward" : "forward", sc, units);
2517}
2518#endif
2519
2520
2521/* Internal ioctl function */
2522static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned long arg)
2523{
2524 int timeout;
2525 long ltmp;
2526 int ioctl_result;
2527 int chg_eof = 1;
2528 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002529 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 struct st_partstat *STps;
2531 int fileno, blkno, at_sm, undone;
2532 int datalen = 0, direction = DMA_NONE;
2533 char *name = tape_name(STp);
2534
2535 WARN_ON(STp->buffer->do_dio != 0);
2536 if (STp->ready != ST_READY) {
2537 if (STp->ready == ST_NO_TAPE)
2538 return (-ENOMEDIUM);
2539 else
2540 return (-EIO);
2541 }
2542 timeout = STp->long_timeout;
2543 STps = &(STp->ps[STp->partition]);
2544 fileno = STps->drv_file;
2545 blkno = STps->drv_block;
2546 at_sm = STps->at_sm;
2547
2548 memset(cmd, 0, MAX_COMMAND_SIZE);
2549 switch (cmd_in) {
2550 case MTFSFM:
2551 chg_eof = 0; /* Changed from the FSF after this */
2552 case MTFSF:
2553 cmd[0] = SPACE;
2554 cmd[1] = 0x01; /* Space FileMarks */
2555 cmd[2] = (arg >> 16);
2556 cmd[3] = (arg >> 8);
2557 cmd[4] = arg;
2558 DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);)
2559 if (fileno >= 0)
2560 fileno += arg;
2561 blkno = 0;
2562 at_sm &= (arg == 0);
2563 break;
2564 case MTBSFM:
2565 chg_eof = 0; /* Changed from the FSF after this */
2566 case MTBSF:
2567 cmd[0] = SPACE;
2568 cmd[1] = 0x01; /* Space FileMarks */
2569 ltmp = (-arg);
2570 cmd[2] = (ltmp >> 16);
2571 cmd[3] = (ltmp >> 8);
2572 cmd[4] = ltmp;
2573 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);)
2574 if (fileno >= 0)
2575 fileno -= arg;
2576 blkno = (-1); /* We can't know the block number */
2577 at_sm &= (arg == 0);
2578 break;
2579 case MTFSR:
2580 cmd[0] = SPACE;
2581 cmd[1] = 0x00; /* Space Blocks */
2582 cmd[2] = (arg >> 16);
2583 cmd[3] = (arg >> 8);
2584 cmd[4] = arg;
2585 DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);)
2586 if (blkno >= 0)
2587 blkno += arg;
2588 at_sm &= (arg == 0);
2589 break;
2590 case MTBSR:
2591 cmd[0] = SPACE;
2592 cmd[1] = 0x00; /* Space Blocks */
2593 ltmp = (-arg);
2594 cmd[2] = (ltmp >> 16);
2595 cmd[3] = (ltmp >> 8);
2596 cmd[4] = ltmp;
2597 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);)
2598 if (blkno >= 0)
2599 blkno -= arg;
2600 at_sm &= (arg == 0);
2601 break;
2602 case MTFSS:
2603 cmd[0] = SPACE;
2604 cmd[1] = 0x04; /* Space Setmarks */
2605 cmd[2] = (arg >> 16);
2606 cmd[3] = (arg >> 8);
2607 cmd[4] = arg;
2608 DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);)
2609 if (arg != 0) {
2610 blkno = fileno = (-1);
2611 at_sm = 1;
2612 }
2613 break;
2614 case MTBSS:
2615 cmd[0] = SPACE;
2616 cmd[1] = 0x04; /* Space Setmarks */
2617 ltmp = (-arg);
2618 cmd[2] = (ltmp >> 16);
2619 cmd[3] = (ltmp >> 8);
2620 cmd[4] = ltmp;
2621 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);)
2622 if (arg != 0) {
2623 blkno = fileno = (-1);
2624 at_sm = 1;
2625 }
2626 break;
2627 case MTWEOF:
2628 case MTWSM:
2629 if (STp->write_prot)
2630 return (-EACCES);
2631 cmd[0] = WRITE_FILEMARKS;
2632 if (cmd_in == MTWSM)
2633 cmd[1] = 2;
2634 cmd[2] = (arg >> 16);
2635 cmd[3] = (arg >> 8);
2636 cmd[4] = arg;
2637 timeout = STp->device->timeout;
2638 DEBC(
2639 if (cmd_in == MTWEOF)
2640 printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
2641 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
2642 else
2643 printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name,
2644 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
2645 )
2646 if (fileno >= 0)
2647 fileno += arg;
2648 blkno = 0;
2649 at_sm = (cmd_in == MTWSM);
2650 break;
2651 case MTREW:
2652 cmd[0] = REZERO_UNIT;
2653 if (STp->immediate) {
2654 cmd[1] = 1; /* Don't wait for completion */
2655 timeout = STp->device->timeout;
2656 }
2657 DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name));
2658 fileno = blkno = at_sm = 0;
2659 break;
2660 case MTNOP:
2661 DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name));
2662 return 0; /* Should do something ? */
2663 break;
2664 case MTRETEN:
2665 cmd[0] = START_STOP;
2666 if (STp->immediate) {
2667 cmd[1] = 1; /* Don't wait for completion */
2668 timeout = STp->device->timeout;
2669 }
2670 cmd[4] = 3;
2671 DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name));
2672 fileno = blkno = at_sm = 0;
2673 break;
2674 case MTEOM:
2675 if (!STp->fast_mteom) {
2676 /* space to the end of tape */
2677 ioctl_result = st_int_ioctl(STp, MTFSF, 0x7fffff);
2678 fileno = STps->drv_file;
2679 if (STps->eof >= ST_EOD_1)
2680 return 0;
2681 /* The next lines would hide the number of spaced FileMarks
2682 That's why I inserted the previous lines. I had no luck
2683 with detecting EOM with FSF, so we go now to EOM.
2684 Joerg Weule */
2685 } else
2686 fileno = (-1);
2687 cmd[0] = SPACE;
2688 cmd[1] = 3;
2689 DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n",
2690 name));
2691 blkno = -1;
2692 at_sm = 0;
2693 break;
2694 case MTERASE:
2695 if (STp->write_prot)
2696 return (-EACCES);
2697 cmd[0] = ERASE;
2698 cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */
2699 if (STp->immediate) {
2700 cmd[1] |= 2; /* Don't wait for completion */
2701 timeout = STp->device->timeout;
2702 }
2703 else
2704 timeout = STp->long_timeout * 8;
2705
2706 DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name));
2707 fileno = blkno = at_sm = 0;
2708 break;
2709 case MTSETBLK: /* Set block length */
2710 case MTSETDENSITY: /* Set tape density */
2711 case MTSETDRVBUFFER: /* Set drive buffering */
2712 case SET_DENS_AND_BLK: /* Set density and block size */
2713 chg_eof = 0;
2714 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
2715 return (-EIO); /* Not allowed if data in buffer */
2716 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
2717 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
2718 STp->max_block > 0 &&
2719 ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
2720 (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) {
2721 printk(KERN_WARNING "%s: Illegal block size.\n", name);
2722 return (-EINVAL);
2723 }
2724 cmd[0] = MODE_SELECT;
2725 if ((STp->use_pf & USE_PF))
2726 cmd[1] = MODE_SELECT_PAGE_FORMAT;
2727 cmd[4] = datalen = 12;
2728 direction = DMA_TO_DEVICE;
2729
2730 memset((STp->buffer)->b_data, 0, 12);
2731 if (cmd_in == MTSETDRVBUFFER)
2732 (STp->buffer)->b_data[2] = (arg & 7) << 4;
2733 else
2734 (STp->buffer)->b_data[2] =
2735 STp->drv_buffer << 4;
2736 (STp->buffer)->b_data[3] = 8; /* block descriptor length */
2737 if (cmd_in == MTSETDENSITY) {
2738 (STp->buffer)->b_data[4] = arg;
2739 STp->density_changed = 1; /* At least we tried ;-) */
2740 } else if (cmd_in == SET_DENS_AND_BLK)
2741 (STp->buffer)->b_data[4] = arg >> 24;
2742 else
2743 (STp->buffer)->b_data[4] = STp->density;
2744 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
2745 ltmp = arg & MT_ST_BLKSIZE_MASK;
2746 if (cmd_in == MTSETBLK)
2747 STp->blksize_changed = 1; /* At least we tried ;-) */
2748 } else
2749 ltmp = STp->block_size;
2750 (STp->buffer)->b_data[9] = (ltmp >> 16);
2751 (STp->buffer)->b_data[10] = (ltmp >> 8);
2752 (STp->buffer)->b_data[11] = ltmp;
2753 timeout = STp->device->timeout;
2754 DEBC(
2755 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
2756 printk(ST_DEB_MSG
2757 "%s: Setting block size to %d bytes.\n", name,
2758 (STp->buffer)->b_data[9] * 65536 +
2759 (STp->buffer)->b_data[10] * 256 +
2760 (STp->buffer)->b_data[11]);
2761 if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK)
2762 printk(ST_DEB_MSG
2763 "%s: Setting density code to %x.\n", name,
2764 (STp->buffer)->b_data[4]);
2765 if (cmd_in == MTSETDRVBUFFER)
2766 printk(ST_DEB_MSG
2767 "%s: Setting drive buffer code to %d.\n", name,
2768 ((STp->buffer)->b_data[2] >> 4) & 7);
2769 )
2770 break;
2771 default:
2772 return (-ENOSYS);
2773 }
2774
2775 SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction,
2776 timeout, MAX_RETRIES, 1);
2777 if (!SRpnt)
2778 return (STp->buffer)->syscall_result;
2779
2780 ioctl_result = (STp->buffer)->syscall_result;
2781
2782 if (!ioctl_result) { /* SCSI command successful */
Mike Christie8b05b772005-11-08 04:06:44 -06002783 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 SRpnt = NULL;
2785 STps->drv_block = blkno;
2786 STps->drv_file = fileno;
2787 STps->at_sm = at_sm;
2788
2789 if (cmd_in == MTBSFM)
2790 ioctl_result = st_int_ioctl(STp, MTFSF, 1);
2791 else if (cmd_in == MTFSFM)
2792 ioctl_result = st_int_ioctl(STp, MTBSF, 1);
2793
2794 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
2795 int old_block_size = STp->block_size;
2796 STp->block_size = arg & MT_ST_BLKSIZE_MASK;
2797 if (STp->block_size != 0) {
2798 if (old_block_size == 0)
2799 normalize_buffer(STp->buffer);
2800 (STp->buffer)->buffer_blocks =
2801 (STp->buffer)->buffer_size / STp->block_size;
2802 }
2803 (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
2804 if (cmd_in == SET_DENS_AND_BLK)
2805 STp->density = arg >> MT_ST_DENSITY_SHIFT;
2806 } else if (cmd_in == MTSETDRVBUFFER)
2807 STp->drv_buffer = (arg & 7);
2808 else if (cmd_in == MTSETDENSITY)
2809 STp->density = arg;
2810
2811 if (cmd_in == MTEOM)
2812 STps->eof = ST_EOD;
2813 else if (cmd_in == MTFSF)
2814 STps->eof = ST_FM;
2815 else if (chg_eof)
2816 STps->eof = ST_NOEOF;
2817
2818 if (cmd_in == MTWEOF)
2819 STps->rw = ST_IDLE;
2820 } else { /* SCSI command was not completely successful. Don't return
2821 from this block without releasing the SCSI command block! */
2822 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
2823
2824 if (cmdstatp->flags & SENSE_EOM) {
2825 if (cmd_in != MTBSF && cmd_in != MTBSFM &&
2826 cmd_in != MTBSR && cmd_in != MTBSS)
2827 STps->eof = ST_EOM_OK;
2828 STps->drv_block = 0;
2829 }
2830
2831 if (cmdstatp->remainder_valid)
2832 undone = (int)cmdstatp->uremainder64;
2833 else
2834 undone = 0;
2835
2836 if (cmd_in == MTWEOF &&
2837 cmdstatp->have_sense &&
Kai Makisara91614c02007-01-26 00:38:39 +02002838 (cmdstatp->flags & SENSE_EOM)) {
2839 if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
2840 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
2841 ioctl_result = 0; /* EOF(s) written successfully at EOM */
2842 STps->eof = ST_NOEOF;
2843 } else { /* Writing EOF(s) failed */
2844 if (fileno >= 0)
2845 fileno -= undone;
2846 if (undone < arg)
2847 STps->eof = ST_NOEOF;
2848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 STps->drv_file = fileno;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 } else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
2851 if (fileno >= 0)
2852 STps->drv_file = fileno - undone;
2853 else
2854 STps->drv_file = fileno;
2855 STps->drv_block = -1;
2856 STps->eof = ST_NOEOF;
2857 } else if ((cmd_in == MTBSF) || (cmd_in == MTBSFM)) {
2858 if (arg > 0 && undone < 0) /* Some drives get this wrong */
2859 undone = (-undone);
2860 if (STps->drv_file >= 0)
2861 STps->drv_file = fileno + undone;
2862 STps->drv_block = 0;
2863 STps->eof = ST_NOEOF;
2864 } else if (cmd_in == MTFSR) {
2865 if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
2866 if (STps->drv_file >= 0)
2867 STps->drv_file++;
2868 STps->drv_block = 0;
2869 STps->eof = ST_FM;
2870 } else {
2871 if (blkno >= undone)
2872 STps->drv_block = blkno - undone;
2873 else
2874 STps->drv_block = (-1);
2875 STps->eof = ST_NOEOF;
2876 }
2877 } else if (cmd_in == MTBSR) {
2878 if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
2879 STps->drv_file--;
2880 STps->drv_block = (-1);
2881 } else {
2882 if (arg > 0 && undone < 0) /* Some drives get this wrong */
2883 undone = (-undone);
2884 if (STps->drv_block >= 0)
2885 STps->drv_block = blkno + undone;
2886 }
2887 STps->eof = ST_NOEOF;
2888 } else if (cmd_in == MTEOM) {
2889 STps->drv_file = (-1);
2890 STps->drv_block = (-1);
2891 STps->eof = ST_EOD;
2892 } else if (cmd_in == MTSETBLK ||
2893 cmd_in == MTSETDENSITY ||
2894 cmd_in == MTSETDRVBUFFER ||
2895 cmd_in == SET_DENS_AND_BLK) {
2896 if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST &&
2897 !(STp->use_pf & PF_TESTED)) {
2898 /* Try the other possible state of Page Format if not
2899 already tried */
2900 STp->use_pf = !STp->use_pf | PF_TESTED;
Mike Christie8b05b772005-11-08 04:06:44 -06002901 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 SRpnt = NULL;
2903 return st_int_ioctl(STp, cmd_in, arg);
2904 }
2905 } else if (chg_eof)
2906 STps->eof = ST_NOEOF;
2907
2908 if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
2909 STps->eof = ST_EOD;
2910
Mike Christie8b05b772005-11-08 04:06:44 -06002911 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912 SRpnt = NULL;
2913 }
2914
2915 return ioctl_result;
2916}
2917
2918
2919/* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
2920 structure. */
2921
2922static int get_location(struct scsi_tape *STp, unsigned int *block, int *partition,
2923 int logical)
2924{
2925 int result;
2926 unsigned char scmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002927 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 DEB( char *name = tape_name(STp); )
2929
2930 if (STp->ready != ST_READY)
2931 return (-EIO);
2932
2933 memset(scmd, 0, MAX_COMMAND_SIZE);
2934 if ((STp->device)->scsi_level < SCSI_2) {
2935 scmd[0] = QFA_REQUEST_BLOCK;
2936 scmd[4] = 3;
2937 } else {
2938 scmd[0] = READ_POSITION;
2939 if (!logical && !STp->scsi2_logical)
2940 scmd[1] = 1;
2941 }
2942 SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE,
2943 STp->device->timeout, MAX_READY_RETRIES, 1);
2944 if (!SRpnt)
2945 return (STp->buffer)->syscall_result;
2946
2947 if ((STp->buffer)->syscall_result != 0 ||
2948 (STp->device->scsi_level >= SCSI_2 &&
2949 ((STp->buffer)->b_data[0] & 4) != 0)) {
2950 *block = *partition = 0;
2951 DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name));
2952 result = (-EIO);
2953 } else {
2954 result = 0;
2955 if ((STp->device)->scsi_level < SCSI_2) {
2956 *block = ((STp->buffer)->b_data[0] << 16)
2957 + ((STp->buffer)->b_data[1] << 8)
2958 + (STp->buffer)->b_data[2];
2959 *partition = 0;
2960 } else {
2961 *block = ((STp->buffer)->b_data[4] << 24)
2962 + ((STp->buffer)->b_data[5] << 16)
2963 + ((STp->buffer)->b_data[6] << 8)
2964 + (STp->buffer)->b_data[7];
2965 *partition = (STp->buffer)->b_data[1];
2966 if (((STp->buffer)->b_data[0] & 0x80) &&
2967 (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */
2968 STp->ps[0].drv_block = STp->ps[0].drv_file = 0;
2969 }
2970 DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
2971 *block, *partition));
2972 }
Mike Christie8b05b772005-11-08 04:06:44 -06002973 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974 SRpnt = NULL;
2975
2976 return result;
2977}
2978
2979
2980/* Set the tape block and partition. Negative partition means that only the
2981 block should be set in vendor specific way. */
2982static int set_location(struct scsi_tape *STp, unsigned int block, int partition,
2983 int logical)
2984{
2985 struct st_partstat *STps;
2986 int result, p;
2987 unsigned int blk;
2988 int timeout;
2989 unsigned char scmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002990 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 DEB( char *name = tape_name(STp); )
2992
2993 if (STp->ready != ST_READY)
2994 return (-EIO);
2995 timeout = STp->long_timeout;
2996 STps = &(STp->ps[STp->partition]);
2997
2998 DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n",
2999 name, block, partition));
3000 DEB(if (partition < 0)
3001 return (-EIO); )
3002
3003 /* Update the location at the partition we are leaving */
3004 if ((!STp->can_partitions && partition != 0) ||
3005 partition >= ST_NBR_PARTITIONS)
3006 return (-EINVAL);
3007 if (partition != STp->partition) {
3008 if (get_location(STp, &blk, &p, 1))
3009 STps->last_block_valid = 0;
3010 else {
3011 STps->last_block_valid = 1;
3012 STps->last_block_visited = blk;
3013 DEBC(printk(ST_DEB_MSG
3014 "%s: Visited block %d for partition %d saved.\n",
3015 name, blk, STp->partition));
3016 }
3017 }
3018
3019 memset(scmd, 0, MAX_COMMAND_SIZE);
3020 if ((STp->device)->scsi_level < SCSI_2) {
3021 scmd[0] = QFA_SEEK_BLOCK;
3022 scmd[2] = (block >> 16);
3023 scmd[3] = (block >> 8);
3024 scmd[4] = block;
3025 scmd[5] = 0;
3026 } else {
3027 scmd[0] = SEEK_10;
3028 scmd[3] = (block >> 24);
3029 scmd[4] = (block >> 16);
3030 scmd[5] = (block >> 8);
3031 scmd[6] = block;
3032 if (!logical && !STp->scsi2_logical)
3033 scmd[1] = 4;
3034 if (STp->partition != partition) {
3035 scmd[1] |= 2;
3036 scmd[8] = partition;
3037 DEBC(printk(ST_DEB_MSG
3038 "%s: Trying to change partition from %d to %d\n",
3039 name, STp->partition, partition));
3040 }
3041 }
3042 if (STp->immediate) {
3043 scmd[1] |= 1; /* Don't wait for completion */
3044 timeout = STp->device->timeout;
3045 }
3046
3047 SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE,
3048 timeout, MAX_READY_RETRIES, 1);
3049 if (!SRpnt)
3050 return (STp->buffer)->syscall_result;
3051
3052 STps->drv_block = STps->drv_file = (-1);
3053 STps->eof = ST_NOEOF;
3054 if ((STp->buffer)->syscall_result != 0) {
3055 result = (-EIO);
3056 if (STp->can_partitions &&
3057 (STp->device)->scsi_level >= SCSI_2 &&
3058 (p = find_partition(STp)) >= 0)
3059 STp->partition = p;
3060 } else {
3061 if (STp->can_partitions) {
3062 STp->partition = partition;
3063 STps = &(STp->ps[partition]);
3064 if (!STps->last_block_valid ||
3065 STps->last_block_visited != block) {
3066 STps->at_sm = 0;
3067 STps->rw = ST_IDLE;
3068 }
3069 } else
3070 STps->at_sm = 0;
3071 if (block == 0)
3072 STps->drv_block = STps->drv_file = 0;
3073 result = 0;
3074 }
3075
Mike Christie8b05b772005-11-08 04:06:44 -06003076 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 SRpnt = NULL;
3078
3079 return result;
3080}
3081
3082
3083/* Find the current partition number for the drive status. Called from open and
3084 returns either partition number of negative error code. */
3085static int find_partition(struct scsi_tape *STp)
3086{
3087 int i, partition;
3088 unsigned int block;
3089
3090 if ((i = get_location(STp, &block, &partition, 1)) < 0)
3091 return i;
3092 if (partition >= ST_NBR_PARTITIONS)
3093 return (-EIO);
3094 return partition;
3095}
3096
3097
3098/* Change the partition if necessary */
3099static int switch_partition(struct scsi_tape *STp)
3100{
3101 struct st_partstat *STps;
3102
3103 if (STp->partition == STp->new_partition)
3104 return 0;
3105 STps = &(STp->ps[STp->new_partition]);
3106 if (!STps->last_block_valid)
3107 STps->last_block_visited = 0;
3108 return set_location(STp, STps->last_block_visited, STp->new_partition, 1);
3109}
3110
3111/* Functions for reading and writing the medium partition mode page. */
3112
3113#define PART_PAGE 0x11
3114#define PART_PAGE_FIXED_LENGTH 8
3115
3116#define PP_OFF_MAX_ADD_PARTS 2
3117#define PP_OFF_NBR_ADD_PARTS 3
3118#define PP_OFF_FLAGS 4
3119#define PP_OFF_PART_UNITS 6
3120#define PP_OFF_RESERVED 7
3121
3122#define PP_BIT_IDP 0x20
3123#define PP_MSK_PSUM_MB 0x10
3124
3125/* Get the number of partitions on the tape. As a side effect reads the
3126 mode page into the tape buffer. */
3127static int nbr_partitions(struct scsi_tape *STp)
3128{
3129 int result;
3130 DEB( char *name = tape_name(STp); )
3131
3132 if (STp->ready != ST_READY)
3133 return (-EIO);
3134
3135 result = read_mode_page(STp, PART_PAGE, 1);
3136
3137 if (result) {
3138 DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n",
3139 name));
3140 result = (-EIO);
3141 } else {
3142 result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
3143 PP_OFF_NBR_ADD_PARTS] + 1;
3144 DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result));
3145 }
3146
3147 return result;
3148}
3149
3150
3151/* Partition the tape into two partitions if size > 0 or one partition if
3152 size == 0.
3153
3154 The block descriptors are read and written because Sony SDT-7000 does not
3155 work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
3156
3157 My HP C1533A drive returns only one partition size field. This is used to
3158 set the size of partition 1. There is no size field for the default partition.
3159 Michael Schaefer's Sony SDT-7000 returns two descriptors and the second is
3160 used to set the size of partition 1 (this is what the SCSI-3 standard specifies).
3161 The following algorithm is used to accommodate both drives: if the number of
3162 partition size fields is greater than the maximum number of additional partitions
3163 in the mode page, the second field is used. Otherwise the first field is used.
3164
3165 For Seagate DDS drives the page length must be 8 when no partitions is defined
3166 and 10 when 1 partition is defined (information from Eric Lee Green). This is
3167 is acceptable also to some other old drives and enforced if the first partition
3168 size field is used for the first additional partition size.
3169 */
3170static int partition_tape(struct scsi_tape *STp, int size)
3171{
3172 char *name = tape_name(STp);
3173 int result;
3174 int pgo, psd_cnt, psdo;
3175 unsigned char *bp;
3176
3177 result = read_mode_page(STp, PART_PAGE, 0);
3178 if (result) {
3179 DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name));
3180 return result;
3181 }
3182 /* The mode page is in the buffer. Let's modify it and write it. */
3183 bp = (STp->buffer)->b_data;
3184 pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
3185 DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n",
3186 name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
3187
3188 psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
3189 psdo = pgo + PART_PAGE_FIXED_LENGTH;
3190 if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
3191 bp[psdo] = bp[psdo + 1] = 0xff; /* Rest of the tape */
3192 psdo += 2;
3193 }
3194 memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
3195
3196 DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name,
3197 psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
3198 bp[pgo + PP_OFF_NBR_ADD_PARTS]));
3199
3200 if (size <= 0) {
3201 bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
3202 if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
3203 bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
3204 DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n",
3205 name));
3206 } else {
3207 bp[psdo] = (size >> 8) & 0xff;
3208 bp[psdo + 1] = size & 0xff;
3209 bp[pgo + 3] = 1;
3210 if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8)
3211 bp[pgo + MP_OFF_PAGE_LENGTH] = 8;
3212 DEBC(printk(ST_DEB_MSG
3213 "%s: Formatting tape with two partitions (1 = %d MB).\n",
3214 name, size));
3215 }
3216 bp[pgo + PP_OFF_PART_UNITS] = 0;
3217 bp[pgo + PP_OFF_RESERVED] = 0;
3218 bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
3219
3220 result = write_mode_page(STp, PART_PAGE, 1);
3221 if (result) {
3222 printk(KERN_INFO "%s: Partitioning of tape failed.\n", name);
3223 result = (-EIO);
3224 }
3225
3226 return result;
3227}
3228
3229
3230
3231/* The ioctl command */
Kai Makisarafd66c1b2008-01-17 22:45:22 +02003232static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233{
3234 int i, cmd_nr, cmd_type, bt;
3235 int retval = 0;
3236 unsigned int blk;
3237 struct scsi_tape *STp = file->private_data;
3238 struct st_modedef *STm;
3239 struct st_partstat *STps;
3240 char *name = tape_name(STp);
3241 void __user *p = (void __user *)arg;
3242
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003243 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 return -ERESTARTSYS;
3245
3246 DEB(
3247 if (debugging && !STp->in_use) {
3248 printk(ST_DEB_MSG "%s: Incorrect device.\n", name);
3249 retval = (-EIO);
3250 goto out;
3251 } ) /* end DEB */
3252
3253 STm = &(STp->modes[STp->current_mode]);
3254 STps = &(STp->ps[STp->partition]);
3255
3256 /*
3257 * If we are in the middle of error recovery, don't let anyone
3258 * else try and use this device. Also, if error recovery fails, it
3259 * may try and take the device offline, in which case all further
3260 * access to the device is prohibited.
3261 */
3262 retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p, file);
3263 if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV)
3264 goto out;
3265 retval = 0;
3266
3267 cmd_type = _IOC_TYPE(cmd_in);
3268 cmd_nr = _IOC_NR(cmd_in);
3269
3270 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
3271 struct mtop mtc;
3272
3273 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
3274 retval = (-EINVAL);
3275 goto out;
3276 }
3277
3278 i = copy_from_user(&mtc, p, sizeof(struct mtop));
3279 if (i) {
3280 retval = (-EFAULT);
3281 goto out;
3282 }
3283
3284 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
3285 printk(KERN_WARNING
3286 "%s: MTSETDRVBUFFER only allowed for root.\n", name);
3287 retval = (-EPERM);
3288 goto out;
3289 }
3290 if (!STm->defined &&
3291 (mtc.mt_op != MTSETDRVBUFFER &&
3292 (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
3293 retval = (-ENXIO);
3294 goto out;
3295 }
3296
3297 if (!STp->pos_unknown) {
3298
3299 if (STps->eof == ST_FM_HIT) {
3300 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
3301 mtc.mt_op == MTEOM) {
3302 mtc.mt_count -= 1;
3303 if (STps->drv_file >= 0)
3304 STps->drv_file += 1;
3305 } else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
3306 mtc.mt_count += 1;
3307 if (STps->drv_file >= 0)
3308 STps->drv_file += 1;
3309 }
3310 }
3311
3312 if (mtc.mt_op == MTSEEK) {
3313 /* Old position must be restored if partition will be
3314 changed */
3315 i = !STp->can_partitions ||
3316 (STp->new_partition != STp->partition);
3317 } else {
3318 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
3319 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
3320 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
3321 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
3322 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
3323 mtc.mt_op == MTCOMPRESSION;
3324 }
3325 i = flush_buffer(STp, i);
3326 if (i < 0) {
3327 retval = i;
3328 goto out;
3329 }
3330 if (STps->rw == ST_WRITING &&
3331 (mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
3332 mtc.mt_op == MTSEEK ||
3333 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)) {
3334 i = st_int_ioctl(STp, MTWEOF, 1);
3335 if (i < 0) {
3336 retval = i;
3337 goto out;
3338 }
3339 if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)
3340 mtc.mt_count++;
3341 STps->rw = ST_IDLE;
3342 }
3343
3344 } else {
3345 /*
3346 * If there was a bus reset, block further access
3347 * to this device. If the user wants to rewind the tape,
3348 * then reset the flag and allow access again.
3349 */
3350 if (mtc.mt_op != MTREW &&
3351 mtc.mt_op != MTOFFL &&
3352 mtc.mt_op != MTRETEN &&
3353 mtc.mt_op != MTERASE &&
3354 mtc.mt_op != MTSEEK &&
3355 mtc.mt_op != MTEOM) {
3356 retval = (-EIO);
3357 goto out;
3358 }
3359 reset_state(STp);
3360 /* remove this when the midlevel properly clears was_reset */
3361 STp->device->was_reset = 0;
3362 }
3363
3364 if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
3365 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTWSM &&
3366 mtc.mt_op != MTSETDRVBUFFER && mtc.mt_op != MTSETPART)
3367 STps->rw = ST_IDLE; /* Prevent automatic WEOF and fsf */
3368
3369 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
3370 do_door_lock(STp, 0); /* Ignore result! */
3371
3372 if (mtc.mt_op == MTSETDRVBUFFER &&
3373 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
3374 retval = st_set_options(STp, mtc.mt_count);
3375 goto out;
3376 }
3377
3378 if (mtc.mt_op == MTSETPART) {
3379 if (!STp->can_partitions ||
3380 mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS) {
3381 retval = (-EINVAL);
3382 goto out;
3383 }
3384 if (mtc.mt_count >= STp->nbr_partitions &&
3385 (STp->nbr_partitions = nbr_partitions(STp)) < 0) {
3386 retval = (-EIO);
3387 goto out;
3388 }
3389 if (mtc.mt_count >= STp->nbr_partitions) {
3390 retval = (-EINVAL);
3391 goto out;
3392 }
3393 STp->new_partition = mtc.mt_count;
3394 retval = 0;
3395 goto out;
3396 }
3397
3398 if (mtc.mt_op == MTMKPART) {
3399 if (!STp->can_partitions) {
3400 retval = (-EINVAL);
3401 goto out;
3402 }
3403 if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
3404 (i = partition_tape(STp, mtc.mt_count)) < 0) {
3405 retval = i;
3406 goto out;
3407 }
3408 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3409 STp->ps[i].rw = ST_IDLE;
3410 STp->ps[i].at_sm = 0;
3411 STp->ps[i].last_block_valid = 0;
3412 }
3413 STp->partition = STp->new_partition = 0;
3414 STp->nbr_partitions = 1; /* Bad guess ?-) */
3415 STps->drv_block = STps->drv_file = 0;
3416 retval = 0;
3417 goto out;
3418 }
3419
3420 if (mtc.mt_op == MTSEEK) {
3421 i = set_location(STp, mtc.mt_count, STp->new_partition, 0);
3422 if (!STp->can_partitions)
3423 STp->ps[0].rw = ST_IDLE;
3424 retval = i;
3425 goto out;
3426 }
3427
3428 if (mtc.mt_op == MTUNLOAD || mtc.mt_op == MTOFFL) {
3429 retval = do_load_unload(STp, file, 0);
3430 goto out;
3431 }
3432
3433 if (mtc.mt_op == MTLOAD) {
3434 retval = do_load_unload(STp, file, max(1, mtc.mt_count));
3435 goto out;
3436 }
3437
3438 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
3439 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
3440 goto out;
3441 }
3442
3443 if (STp->can_partitions && STp->ready == ST_READY &&
3444 (i = switch_partition(STp)) < 0) {
3445 retval = i;
3446 goto out;
3447 }
3448
3449 if (mtc.mt_op == MTCOMPRESSION)
3450 retval = st_compression(STp, (mtc.mt_count & 1));
3451 else
3452 retval = st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
3453 goto out;
3454 }
3455 if (!STm->defined) {
3456 retval = (-ENXIO);
3457 goto out;
3458 }
3459
3460 if ((i = flush_buffer(STp, 0)) < 0) {
3461 retval = i;
3462 goto out;
3463 }
3464 if (STp->can_partitions &&
3465 (i = switch_partition(STp)) < 0) {
3466 retval = i;
3467 goto out;
3468 }
3469
3470 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
3471 struct mtget mt_status;
3472
3473 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
3474 retval = (-EINVAL);
3475 goto out;
3476 }
3477
3478 mt_status.mt_type = STp->tape_type;
3479 mt_status.mt_dsreg =
3480 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
3481 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
3482 mt_status.mt_blkno = STps->drv_block;
3483 mt_status.mt_fileno = STps->drv_file;
3484 if (STp->block_size != 0) {
3485 if (STps->rw == ST_WRITING)
3486 mt_status.mt_blkno +=
3487 (STp->buffer)->buffer_bytes / STp->block_size;
3488 else if (STps->rw == ST_READING)
3489 mt_status.mt_blkno -=
3490 ((STp->buffer)->buffer_bytes +
3491 STp->block_size - 1) / STp->block_size;
3492 }
3493
3494 mt_status.mt_gstat = 0;
3495 if (STp->drv_write_prot)
3496 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
3497 if (mt_status.mt_blkno == 0) {
3498 if (mt_status.mt_fileno == 0)
3499 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
3500 else
3501 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
3502 }
3503 mt_status.mt_erreg = (STp->recover_reg << MT_ST_SOFTERR_SHIFT);
3504 mt_status.mt_resid = STp->partition;
3505 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
3506 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
3507 else if (STps->eof >= ST_EOM_OK)
3508 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
3509 if (STp->density == 1)
3510 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
3511 else if (STp->density == 2)
3512 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
3513 else if (STp->density == 3)
3514 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
3515 if (STp->ready == ST_READY)
3516 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
3517 if (STp->ready == ST_NO_TAPE)
3518 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
3519 if (STps->at_sm)
3520 mt_status.mt_gstat |= GMT_SM(0xffffffff);
3521 if (STm->do_async_writes ||
3522 (STm->do_buffer_writes && STp->block_size != 0) ||
3523 STp->drv_buffer != 0)
3524 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
3525 if (STp->cleaning_req)
3526 mt_status.mt_gstat |= GMT_CLN(0xffffffff);
3527
3528 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
3529 if (i) {
3530 retval = (-EFAULT);
3531 goto out;
3532 }
3533
3534 STp->recover_reg = 0; /* Clear after read */
3535 retval = 0;
3536 goto out;
3537 } /* End of MTIOCGET */
3538 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
3539 struct mtpos mt_pos;
3540 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
3541 retval = (-EINVAL);
3542 goto out;
3543 }
3544 if ((i = get_location(STp, &blk, &bt, 0)) < 0) {
3545 retval = i;
3546 goto out;
3547 }
3548 mt_pos.mt_blkno = blk;
3549 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
3550 if (i)
3551 retval = (-EFAULT);
3552 goto out;
3553 }
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003554 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 switch (cmd_in) {
3556 case SCSI_IOCTL_GET_IDLUN:
3557 case SCSI_IOCTL_GET_BUS_NUMBER:
3558 break;
3559 default:
Kai Makisara 16c4b3e2005-05-01 18:11:55 +03003560 if ((cmd_in == SG_IO ||
3561 cmd_in == SCSI_IOCTL_SEND_COMMAND ||
3562 cmd_in == CDROM_SEND_PACKET) &&
3563 !capable(CAP_SYS_RAWIO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564 i = -EPERM;
3565 else
FUJITA Tomonori45e79a32007-07-09 12:39:20 +02003566 i = scsi_cmd_ioctl(file, STp->disk->queue,
3567 STp->disk, cmd_in, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 if (i != -ENOTTY)
3569 return i;
3570 break;
3571 }
Kai Makisara 16c4b3e2005-05-01 18:11:55 +03003572 retval = scsi_ioctl(STp->device, cmd_in, p);
3573 if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */
3574 STp->rew_at_close = 0;
3575 STp->ready = ST_NO_TAPE;
3576 }
3577 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579 out:
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003580 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 return retval;
3582}
3583
3584#ifdef CONFIG_COMPAT
3585static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3586{
3587 struct scsi_tape *STp = file->private_data;
3588 struct scsi_device *sdev = STp->device;
3589 int ret = -ENOIOCTLCMD;
3590 if (sdev->host->hostt->compat_ioctl) {
3591
3592 ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
3593
3594 }
3595 return ret;
3596}
3597#endif
3598
3599
3600
3601/* Try to allocate a new tape buffer. Calling function must not hold
3602 dev_arr_lock. */
3603static struct st_buffer *
3604 new_tape_buffer(int from_initialization, int need_dma, int max_sg)
3605{
Mike Christie8b05b772005-11-08 04:06:44 -06003606 int i, got = 0;
Al Viroc53033f2005-10-21 03:22:08 -04003607 gfp_t priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 struct st_buffer *tb;
3609
3610 if (from_initialization)
3611 priority = GFP_ATOMIC;
3612 else
3613 priority = GFP_KERNEL;
3614
3615 i = sizeof(struct st_buffer) + (max_sg - 1) * sizeof(struct scatterlist) +
3616 max_sg * sizeof(struct st_buf_fragment);
Jes Sorensen24669f752006-01-16 10:31:18 -05003617 tb = kzalloc(i, priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 if (!tb) {
3619 printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
3620 return NULL;
3621 }
Mike Christie8b05b772005-11-08 04:06:44 -06003622 tb->frp_segs = tb->orig_frp_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 tb->use_sg = max_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
3625
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 tb->dma = need_dma;
3627 tb->buffer_size = got;
FUJITA Tomonoricd816212007-12-15 15:51:55 +09003628 sg_init_table(tb->sg, max_sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
3630 return tb;
3631}
3632
3633
3634/* Try to allocate enough space in the tape buffer */
3635static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
3636{
Al Viroc53033f2005-10-21 03:22:08 -04003637 int segs, nbr, max_segs, b_size, order, got;
3638 gfp_t priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639
3640 if (new_size <= STbuffer->buffer_size)
3641 return 1;
3642
3643 if (STbuffer->buffer_size <= PAGE_SIZE)
3644 normalize_buffer(STbuffer); /* Avoid extra segment */
3645
3646 max_segs = STbuffer->use_sg;
3647 nbr = max_segs - STbuffer->frp_segs;
3648 if (nbr <= 0)
3649 return 0;
3650
3651 priority = GFP_KERNEL | __GFP_NOWARN;
3652 if (need_dma)
3653 priority |= GFP_DMA;
Mike Christie8b05b772005-11-08 04:06:44 -06003654 for (b_size = PAGE_SIZE, order=0; order <= 6 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 b_size < new_size - STbuffer->buffer_size;
3656 order++, b_size *= 2)
3657 ; /* empty */
3658
3659 for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size;
3660 segs < max_segs && got < new_size;) {
3661 STbuffer->frp[segs].page = alloc_pages(priority, order);
3662 if (STbuffer->frp[segs].page == NULL) {
3663 if (new_size - got <= (max_segs - segs) * b_size / 2) {
3664 b_size /= 2; /* Large enough for the rest of the buffers */
3665 order--;
3666 continue;
3667 }
3668 DEB(STbuffer->buffer_size = got);
3669 normalize_buffer(STbuffer);
3670 return 0;
3671 }
3672 STbuffer->frp[segs].length = b_size;
3673 STbuffer->frp_segs += 1;
3674 got += b_size;
3675 STbuffer->buffer_size = got;
Kai Makisara40f6b362008-02-24 22:23:24 +02003676 if (STbuffer->cleared)
3677 memset(page_address(STbuffer->frp[segs].page), 0, b_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678 segs++;
3679 }
3680 STbuffer->b_data = page_address(STbuffer->frp[0].page);
3681
3682 return 1;
3683}
3684
3685
Kai Makisara40f6b362008-02-24 22:23:24 +02003686/* Make sure that no data from previous user is in the internal buffer */
3687static void clear_buffer(struct st_buffer * st_bp)
3688{
3689 int i;
3690
3691 for (i=0; i < st_bp->frp_segs; i++)
3692 memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
3693 st_bp->cleared = 1;
3694}
3695
3696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697/* Release the extra buffer */
3698static void normalize_buffer(struct st_buffer * STbuffer)
3699{
3700 int i, order;
3701
3702 for (i = STbuffer->orig_frp_segs; i < STbuffer->frp_segs; i++) {
3703 order = get_order(STbuffer->frp[i].length);
3704 __free_pages(STbuffer->frp[i].page, order);
3705 STbuffer->buffer_size -= STbuffer->frp[i].length;
3706 }
3707 STbuffer->frp_segs = STbuffer->orig_frp_segs;
3708 STbuffer->frp_sg_current = 0;
Mike Christie8b05b772005-11-08 04:06:44 -06003709 STbuffer->sg_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710}
3711
3712
3713/* Move data from the user buffer to the tape buffer. Returns zero (success) or
3714 negative error code. */
3715static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
3716{
3717 int i, cnt, res, offset;
3718
3719 for (i = 0, offset = st_bp->buffer_bytes;
3720 i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
3721 offset -= st_bp->frp[i].length;
3722 if (i == st_bp->frp_segs) { /* Should never happen */
3723 printk(KERN_WARNING "st: append_to_buffer offset overflow.\n");
3724 return (-EIO);
3725 }
3726 for (; i < st_bp->frp_segs && do_count > 0; i++) {
3727 cnt = st_bp->frp[i].length - offset < do_count ?
3728 st_bp->frp[i].length - offset : do_count;
3729 res = copy_from_user(page_address(st_bp->frp[i].page) + offset, ubp, cnt);
3730 if (res)
3731 return (-EFAULT);
3732 do_count -= cnt;
3733 st_bp->buffer_bytes += cnt;
3734 ubp += cnt;
3735 offset = 0;
3736 }
3737 if (do_count) /* Should never happen */
3738 return (-EIO);
3739
3740 return 0;
3741}
3742
3743
3744/* Move data from the tape buffer to the user buffer. Returns zero (success) or
3745 negative error code. */
3746static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
3747{
3748 int i, cnt, res, offset;
3749
3750 for (i = 0, offset = st_bp->read_pointer;
3751 i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
3752 offset -= st_bp->frp[i].length;
3753 if (i == st_bp->frp_segs) { /* Should never happen */
3754 printk(KERN_WARNING "st: from_buffer offset overflow.\n");
3755 return (-EIO);
3756 }
3757 for (; i < st_bp->frp_segs && do_count > 0; i++) {
3758 cnt = st_bp->frp[i].length - offset < do_count ?
3759 st_bp->frp[i].length - offset : do_count;
3760 res = copy_to_user(ubp, page_address(st_bp->frp[i].page) + offset, cnt);
3761 if (res)
3762 return (-EFAULT);
3763 do_count -= cnt;
3764 st_bp->buffer_bytes -= cnt;
3765 st_bp->read_pointer += cnt;
3766 ubp += cnt;
3767 offset = 0;
3768 }
3769 if (do_count) /* Should never happen */
3770 return (-EIO);
3771
3772 return 0;
3773}
3774
3775
3776/* Move data towards start of buffer */
3777static void move_buffer_data(struct st_buffer * st_bp, int offset)
3778{
3779 int src_seg, dst_seg, src_offset = 0, dst_offset;
3780 int count, total;
3781
3782 if (offset == 0)
3783 return;
3784
3785 total=st_bp->buffer_bytes - offset;
3786 for (src_seg=0; src_seg < st_bp->frp_segs; src_seg++) {
3787 src_offset = offset;
3788 if (src_offset < st_bp->frp[src_seg].length)
3789 break;
3790 offset -= st_bp->frp[src_seg].length;
3791 }
3792
3793 st_bp->buffer_bytes = st_bp->read_pointer = total;
3794 for (dst_seg=dst_offset=0; total > 0; ) {
3795 count = min(st_bp->frp[dst_seg].length - dst_offset,
3796 st_bp->frp[src_seg].length - src_offset);
3797 memmove(page_address(st_bp->frp[dst_seg].page) + dst_offset,
3798 page_address(st_bp->frp[src_seg].page) + src_offset, count);
3799 src_offset += count;
3800 if (src_offset >= st_bp->frp[src_seg].length) {
3801 src_seg++;
3802 src_offset = 0;
3803 }
3804 dst_offset += count;
3805 if (dst_offset >= st_bp->frp[dst_seg].length) {
3806 dst_seg++;
3807 dst_offset = 0;
3808 }
3809 total -= count;
3810 }
3811}
3812
3813
3814/* Fill the s/g list up to the length required for this transfer */
3815static void buf_to_sg(struct st_buffer *STbp, unsigned int length)
3816{
3817 int i;
3818 unsigned int count;
3819 struct scatterlist *sg;
3820 struct st_buf_fragment *frp;
3821
3822 if (length == STbp->frp_sg_current)
3823 return; /* work already done */
3824
3825 sg = &(STbp->sg[0]);
3826 frp = STbp->frp;
3827 for (i=count=0; count < length; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 if (length - count > frp[i].length)
Jens Axboe642f1492007-10-24 11:20:47 +02003829 sg_set_page(&sg[i], frp[i].page, frp[i].length, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 else
Jens Axboe642f1492007-10-24 11:20:47 +02003831 sg_set_page(&sg[i], frp[i].page, length - count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832 count += sg[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 }
3834 STbp->sg_segs = i;
3835 STbp->frp_sg_current = length;
3836}
3837
3838
3839/* Validate the options from command line or module parameters */
3840static void validate_options(void)
3841{
3842 if (buffer_kbs > 0)
3843 st_fixed_buffer_size = buffer_kbs * ST_KILOBYTE;
3844 if (max_sg_segs >= ST_FIRST_SG)
3845 st_max_sg_segs = max_sg_segs;
3846}
3847
3848#ifndef MODULE
3849/* Set the boot options. Syntax is defined in Documenation/scsi/st.txt.
3850 */
3851static int __init st_setup(char *str)
3852{
3853 int i, len, ints[5];
3854 char *stp;
3855
3856 stp = get_options(str, ARRAY_SIZE(ints), ints);
3857
3858 if (ints[0] > 0) {
3859 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
3860 if (parms[i].val)
3861 *parms[i].val = ints[i + 1];
3862 } else {
3863 while (stp != NULL) {
3864 for (i = 0; i < ARRAY_SIZE(parms); i++) {
3865 len = strlen(parms[i].name);
3866 if (!strncmp(stp, parms[i].name, len) &&
3867 (*(stp + len) == ':' || *(stp + len) == '=')) {
3868 if (parms[i].val)
3869 *parms[i].val =
3870 simple_strtoul(stp + len + 1, NULL, 0);
3871 else
3872 printk(KERN_WARNING "st: Obsolete parameter %s\n",
3873 parms[i].name);
3874 break;
3875 }
3876 }
Tobias Klauser6391a112006-06-08 22:23:48 -07003877 if (i >= ARRAY_SIZE(parms))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 printk(KERN_WARNING "st: invalid parameter in '%s'\n",
3879 stp);
3880 stp = strchr(stp, ',');
3881 if (stp)
3882 stp++;
3883 }
3884 }
3885
3886 validate_options();
3887
3888 return 1;
3889}
3890
3891__setup("st=", st_setup);
3892
3893#endif
3894
Arjan van de Ven00977a52007-02-12 00:55:34 -08003895static const struct file_operations st_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896{
3897 .owner = THIS_MODULE,
3898 .read = st_read,
3899 .write = st_write,
Kai Makisarafd66c1b2008-01-17 22:45:22 +02003900 .unlocked_ioctl = st_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901#ifdef CONFIG_COMPAT
3902 .compat_ioctl = st_compat_ioctl,
3903#endif
3904 .open = st_open,
3905 .flush = st_flush,
3906 .release = st_release,
3907};
3908
3909static int st_probe(struct device *dev)
3910{
3911 struct scsi_device *SDp = to_scsi_device(dev);
3912 struct gendisk *disk = NULL;
3913 struct cdev *cdev = NULL;
3914 struct scsi_tape *tpnt = NULL;
3915 struct st_modedef *STm;
3916 struct st_partstat *STps;
3917 struct st_buffer *buffer;
3918 int i, j, mode, dev_num, error;
3919 char *stp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
3921 if (SDp->type != TYPE_TAPE)
3922 return -ENODEV;
3923 if ((stp = st_incompatible(SDp))) {
Jeff Garzik3bf743e2005-10-24 18:04:06 -04003924 sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 printk(KERN_INFO "st: The suggested driver is %s.\n", stp);
3926 return -ENODEV;
3927 }
3928
Mike Christie8b05b772005-11-08 04:06:44 -06003929 i = min(SDp->request_queue->max_hw_segments,
3930 SDp->request_queue->max_phys_segments);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 if (st_max_sg_segs < i)
3932 i = st_max_sg_segs;
3933 buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i);
3934 if (buffer == NULL) {
3935 printk(KERN_ERR
3936 "st: Can't allocate new tape buffer. Device not attached.\n");
3937 goto out;
3938 }
3939
3940 disk = alloc_disk(1);
3941 if (!disk) {
3942 printk(KERN_ERR "st: out of memory. Device not attached.\n");
3943 goto out_buffer_free;
3944 }
3945
3946 write_lock(&st_dev_arr_lock);
3947 if (st_nr_dev >= st_dev_max) {
3948 struct scsi_tape **tmp_da;
3949 int tmp_dev_max;
3950
3951 tmp_dev_max = max(st_nr_dev * 2, 8);
3952 if (tmp_dev_max > ST_MAX_TAPES)
3953 tmp_dev_max = ST_MAX_TAPES;
3954 if (tmp_dev_max <= st_nr_dev) {
3955 write_unlock(&st_dev_arr_lock);
3956 printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
3957 ST_MAX_TAPES);
3958 goto out_put_disk;
3959 }
3960
Jes Sorensen24669f752006-01-16 10:31:18 -05003961 tmp_da = kzalloc(tmp_dev_max * sizeof(struct scsi_tape *), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 if (tmp_da == NULL) {
3963 write_unlock(&st_dev_arr_lock);
3964 printk(KERN_ERR "st: Can't extend device array.\n");
3965 goto out_put_disk;
3966 }
3967
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 if (scsi_tapes != NULL) {
3969 memcpy(tmp_da, scsi_tapes,
3970 st_dev_max * sizeof(struct scsi_tape *));
3971 kfree(scsi_tapes);
3972 }
3973 scsi_tapes = tmp_da;
3974
3975 st_dev_max = tmp_dev_max;
3976 }
3977
3978 for (i = 0; i < st_dev_max; i++)
3979 if (scsi_tapes[i] == NULL)
3980 break;
3981 if (i >= st_dev_max)
3982 panic("scsi_devices corrupt (st)");
3983
Jes Sorensen24669f752006-01-16 10:31:18 -05003984 tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 if (tpnt == NULL) {
3986 write_unlock(&st_dev_arr_lock);
3987 printk(KERN_ERR "st: Can't allocate device descriptor.\n");
3988 goto out_put_disk;
3989 }
Kai Makisaraf03a5672005-08-02 13:40:47 +03003990 kref_init(&tpnt->kref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 tpnt->disk = disk;
3992 sprintf(disk->disk_name, "st%d", i);
3993 disk->private_data = &tpnt->driver;
3994 disk->queue = SDp->request_queue;
3995 tpnt->driver = &st_template;
3996 scsi_tapes[i] = tpnt;
3997 dev_num = i;
3998
3999 tpnt->device = SDp;
4000 if (SDp->scsi_level <= 2)
4001 tpnt->tape_type = MT_ISSCSI1;
4002 else
4003 tpnt->tape_type = MT_ISSCSI2;
4004
4005 tpnt->buffer = buffer;
Kai Makisaraf03a5672005-08-02 13:40:47 +03004006 tpnt->buffer->last_SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
4008 tpnt->inited = 0;
4009 tpnt->dirty = 0;
4010 tpnt->in_use = 0;
4011 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
4012 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
4013 tpnt->use_pf = (SDp->scsi_level >= SCSI_2);
4014 tpnt->density = 0;
4015 tpnt->do_auto_lock = ST_AUTO_LOCK;
4016 tpnt->can_bsr = (SDp->scsi_level > 2 ? 1 : ST_IN_FILE_POS); /* BSR mandatory in SCSI3 */
4017 tpnt->can_partitions = 0;
4018 tpnt->two_fm = ST_TWO_FM;
4019 tpnt->fast_mteom = ST_FAST_MTEOM;
4020 tpnt->scsi2_logical = ST_SCSI2LOGICAL;
Kai Makisara40f6b362008-02-24 22:23:24 +02004021 tpnt->sili = ST_SILI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 tpnt->immediate = ST_NOWAIT;
4023 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
4024 tpnt->partition = 0;
4025 tpnt->new_partition = 0;
4026 tpnt->nbr_partitions = 0;
4027 tpnt->device->timeout = ST_TIMEOUT;
4028 tpnt->long_timeout = ST_LONG_TIMEOUT;
4029 tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
4030
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 for (i = 0; i < ST_NBR_MODES; i++) {
4032 STm = &(tpnt->modes[i]);
4033 STm->defined = 0;
4034 STm->sysv = ST_SYSV;
4035 STm->defaults_for_writes = 0;
4036 STm->do_async_writes = ST_ASYNC_WRITES;
4037 STm->do_buffer_writes = ST_BUFFER_WRITES;
4038 STm->do_read_ahead = ST_READ_AHEAD;
4039 STm->default_compression = ST_DONT_TOUCH;
4040 STm->default_blksize = (-1); /* No forced size */
4041 STm->default_density = (-1); /* No forced density */
4042 }
4043
4044 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
4045 STps = &(tpnt->ps[i]);
4046 STps->rw = ST_IDLE;
4047 STps->eof = ST_NOEOF;
4048 STps->at_sm = 0;
4049 STps->last_block_valid = 0;
4050 STps->drv_block = (-1);
4051 STps->drv_file = (-1);
4052 }
4053
4054 tpnt->current_mode = 0;
4055 tpnt->modes[0].defined = 1;
4056
4057 tpnt->density_changed = tpnt->compression_changed =
4058 tpnt->blksize_changed = 0;
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02004059 mutex_init(&tpnt->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
4061 st_nr_dev++;
4062 write_unlock(&st_dev_arr_lock);
4063
4064 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
4065 STm = &(tpnt->modes[mode]);
4066 for (j=0; j < 2; j++) {
4067 cdev = cdev_alloc();
4068 if (!cdev) {
4069 printk(KERN_ERR
4070 "st%d: out of memory. Device not attached.\n",
4071 dev_num);
4072 goto out_free_tape;
4073 }
4074 cdev->owner = THIS_MODULE;
4075 cdev->ops = &st_fops;
4076
4077 error = cdev_add(cdev,
4078 MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, j)),
4079 1);
4080 if (error) {
4081 printk(KERN_ERR "st%d: Can't add %s-rewind mode %d\n",
4082 dev_num, j ? "non" : "auto", mode);
4083 printk(KERN_ERR "st%d: Device not attached.\n", dev_num);
4084 goto out_free_tape;
4085 }
4086 STm->cdevs[j] = cdev;
4087
4088 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004089 error = do_create_class_files(tpnt, dev_num, mode);
4090 if (error)
4091 goto out_free_tape;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 }
4093
Kai Makisara422528542006-11-07 21:56:38 +02004094 sdev_printk(KERN_NOTICE, SDp,
Rene Herman8b1ea242006-05-20 15:00:22 -07004095 "Attached scsi tape %s\n", tape_name(tpnt));
Kai Makisara422528542006-11-07 21:56:38 +02004096 sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n",
4097 tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
4098 queue_dma_alignment(SDp->request_queue) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
4100 return 0;
4101
4102out_free_tape:
4103 for (mode=0; mode < ST_NBR_MODES; mode++) {
4104 STm = &(tpnt->modes[mode]);
4105 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
4106 "tape");
4107 for (j=0; j < 2; j++) {
4108 if (STm->cdevs[j]) {
4109 if (cdev == STm->cdevs[j])
4110 cdev = NULL;
Tony Jonesee959b02008-02-22 00:13:36 +01004111 device_destroy(st_sysfs_class,
4112 MKDEV(SCSI_TAPE_MAJOR,
4113 TAPE_MINOR(i, mode, j)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 cdev_del(STm->cdevs[j]);
4115 }
4116 }
4117 }
4118 if (cdev)
4119 cdev_del(cdev);
4120 write_lock(&st_dev_arr_lock);
4121 scsi_tapes[dev_num] = NULL;
4122 st_nr_dev--;
4123 write_unlock(&st_dev_arr_lock);
4124out_put_disk:
4125 put_disk(disk);
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004126 kfree(tpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127out_buffer_free:
4128 kfree(buffer);
4129out:
4130 return -ENODEV;
4131};
4132
4133
4134static int st_remove(struct device *dev)
4135{
4136 struct scsi_device *SDp = to_scsi_device(dev);
4137 struct scsi_tape *tpnt;
4138 int i, j, mode;
4139
4140 write_lock(&st_dev_arr_lock);
4141 for (i = 0; i < st_dev_max; i++) {
4142 tpnt = scsi_tapes[i];
4143 if (tpnt != NULL && tpnt->device == SDp) {
4144 scsi_tapes[i] = NULL;
4145 st_nr_dev--;
4146 write_unlock(&st_dev_arr_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
4148 "tape");
4149 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 for (j=0; j < 2; j++) {
Tony Jonesee959b02008-02-22 00:13:36 +01004151 device_destroy(st_sysfs_class,
4152 MKDEV(SCSI_TAPE_MAJOR,
4153 TAPE_MINOR(i, mode, j)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 cdev_del(tpnt->modes[mode].cdevs[j]);
4155 tpnt->modes[mode].cdevs[j] = NULL;
4156 }
4157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
Arjan van de Ven0b950672006-01-11 13:16:10 +01004159 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +03004160 kref_put(&tpnt->kref, scsi_tape_release);
Arjan van de Ven0b950672006-01-11 13:16:10 +01004161 mutex_unlock(&st_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 return 0;
4163 }
4164 }
4165
4166 write_unlock(&st_dev_arr_lock);
4167 return 0;
4168}
4169
Kai Makisaraf03a5672005-08-02 13:40:47 +03004170/**
4171 * scsi_tape_release - Called to free the Scsi_Tape structure
4172 * @kref: pointer to embedded kref
4173 *
Arjan van de Ven0b950672006-01-11 13:16:10 +01004174 * st_ref_mutex must be held entering this routine. Because it is
Kai Makisaraf03a5672005-08-02 13:40:47 +03004175 * called on last put, you should always use the scsi_tape_get()
4176 * scsi_tape_put() helpers which manipulate the semaphore directly
4177 * and never do a direct kref_put().
4178 **/
4179static void scsi_tape_release(struct kref *kref)
4180{
4181 struct scsi_tape *tpnt = to_scsi_tape(kref);
4182 struct gendisk *disk = tpnt->disk;
4183
4184 tpnt->device = NULL;
4185
4186 if (tpnt->buffer) {
4187 tpnt->buffer->orig_frp_segs = 0;
4188 normalize_buffer(tpnt->buffer);
4189 kfree(tpnt->buffer);
4190 }
4191
4192 disk->private_data = NULL;
4193 put_disk(disk);
4194 kfree(tpnt);
4195 return;
4196}
4197
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198static int __init init_st(void)
4199{
Jeff Garzik13026a62006-10-04 06:00:38 -04004200 int err;
4201
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 validate_options();
4203
Jeff Garzik13026a62006-10-04 06:00:38 -04004204 printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 verstr, st_fixed_buffer_size, st_max_sg_segs);
4206
gregkh@suse.ded2538782005-03-23 09:55:22 -08004207 st_sysfs_class = class_create(THIS_MODULE, "scsi_tape");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 if (IS_ERR(st_sysfs_class)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n");
Jeff Garzik13026a62006-10-04 06:00:38 -04004210 return PTR_ERR(st_sysfs_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 }
4212
Jeff Garzik13026a62006-10-04 06:00:38 -04004213 err = register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4214 ST_MAX_TAPE_ENTRIES, "st");
4215 if (err) {
4216 printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
4217 SCSI_TAPE_MAJOR);
4218 goto err_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004220
4221 err = scsi_register_driver(&st_template.gendrv);
4222 if (err)
4223 goto err_chrdev;
4224
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004225 err = do_create_sysfs_files();
Jeff Garzik13026a62006-10-04 06:00:38 -04004226 if (err)
4227 goto err_scsidrv;
4228
4229 return 0;
4230
4231err_scsidrv:
4232 scsi_unregister_driver(&st_template.gendrv);
4233err_chrdev:
4234 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4235 ST_MAX_TAPE_ENTRIES);
4236err_class:
Kai Makisarac2c96f42005-08-02 12:21:51 +03004237 class_destroy(st_sysfs_class);
Jeff Garzik13026a62006-10-04 06:00:38 -04004238 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239}
4240
4241static void __exit exit_st(void)
4242{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004243 do_remove_sysfs_files();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 scsi_unregister_driver(&st_template.gendrv);
4245 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4246 ST_MAX_TAPE_ENTRIES);
Kai Makisarac2c96f42005-08-02 12:21:51 +03004247 class_destroy(st_sysfs_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 kfree(scsi_tapes);
4249 printk(KERN_INFO "st: Unloaded.\n");
4250}
4251
4252module_init(init_st);
4253module_exit(exit_st);
4254
4255
4256/* The sysfs driver interface. Read-only at the moment */
4257static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
4258{
4259 return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
4260}
4261static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
4262
4263static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
4264{
4265 return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
4266}
4267static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
4268
4269static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
4270{
4271 return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
4272}
4273static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
4274
4275static ssize_t st_version_show(struct device_driver *ddd, char *buf)
4276{
4277 return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
4278}
4279static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
4280
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004281static int do_create_sysfs_files(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004283 struct device_driver *sysfs = &st_template.gendrv;
Jeff Garzik13026a62006-10-04 06:00:38 -04004284 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004286 err = driver_create_file(sysfs, &driver_attr_try_direct_io);
Jeff Garzik13026a62006-10-04 06:00:38 -04004287 if (err)
4288 return err;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004289 err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size);
Jeff Garzik13026a62006-10-04 06:00:38 -04004290 if (err)
4291 goto err_try_direct_io;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004292 err = driver_create_file(sysfs, &driver_attr_max_sg_segs);
Jeff Garzik13026a62006-10-04 06:00:38 -04004293 if (err)
4294 goto err_attr_fixed_buf;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004295 err = driver_create_file(sysfs, &driver_attr_version);
Jeff Garzik13026a62006-10-04 06:00:38 -04004296 if (err)
4297 goto err_attr_max_sg;
4298
4299 return 0;
4300
4301err_attr_max_sg:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004302 driver_remove_file(sysfs, &driver_attr_max_sg_segs);
Jeff Garzik13026a62006-10-04 06:00:38 -04004303err_attr_fixed_buf:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004304 driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
Jeff Garzik13026a62006-10-04 06:00:38 -04004305err_try_direct_io:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004306 driver_remove_file(sysfs, &driver_attr_try_direct_io);
Jeff Garzik13026a62006-10-04 06:00:38 -04004307 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308}
4309
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004310static void do_remove_sysfs_files(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004312 struct device_driver *sysfs = &st_template.gendrv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004314 driver_remove_file(sysfs, &driver_attr_version);
4315 driver_remove_file(sysfs, &driver_attr_max_sg_segs);
4316 driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
4317 driver_remove_file(sysfs, &driver_attr_try_direct_io);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318}
4319
4320
4321/* The sysfs simple class interface */
Tony Jonesee959b02008-02-22 00:13:36 +01004322static ssize_t
4323st_defined_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004325 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 ssize_t l = 0;
4327
4328 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
4329 return l;
4330}
4331
Tony Jonesee959b02008-02-22 00:13:36 +01004332DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
Tony Jonesee959b02008-02-22 00:13:36 +01004334static ssize_t
4335st_defblk_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004337 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 ssize_t l = 0;
4339
4340 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
4341 return l;
4342}
4343
Tony Jonesee959b02008-02-22 00:13:36 +01004344DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Tony Jonesee959b02008-02-22 00:13:36 +01004346static ssize_t
4347st_defdensity_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004349 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 ssize_t l = 0;
4351 char *fmt;
4352
4353 fmt = STm->default_density >= 0 ? "0x%02x\n" : "%d\n";
4354 l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density);
4355 return l;
4356}
4357
Tony Jonesee959b02008-02-22 00:13:36 +01004358DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
Tony Jonesee959b02008-02-22 00:13:36 +01004360static ssize_t
4361st_defcompression_show(struct device *dev, struct device_attribute *attr,
4362 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004364 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 ssize_t l = 0;
4366
4367 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
4368 return l;
4369}
4370
Tony Jonesee959b02008-02-22 00:13:36 +01004371DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
Tony Jonesee959b02008-02-22 00:13:36 +01004373static ssize_t
4374st_options_show(struct device *dev, struct device_attribute *attr, char *buf)
Kai Makisarab174be02008-02-24 22:29:12 +02004375{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004376 struct st_modedef *STm = dev_get_drvdata(dev);
Kai Makisarab174be02008-02-24 22:29:12 +02004377 struct scsi_tape *STp;
4378 int i, j, options;
4379 ssize_t l = 0;
4380
4381 for (i=0; i < st_dev_max; i++) {
4382 for (j=0; j < ST_NBR_MODES; j++)
4383 if (&scsi_tapes[i]->modes[j] == STm)
4384 break;
4385 if (j < ST_NBR_MODES)
4386 break;
4387 }
4388 if (i == st_dev_max)
4389 return 0; /* should never happen */
4390
4391 STp = scsi_tapes[i];
4392
4393 options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
4394 options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
4395 options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
4396 DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
4397 options |= STp->two_fm ? MT_ST_TWO_FM : 0;
4398 options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
4399 options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
4400 options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
4401 options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
4402 options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
4403 options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
4404 options |= STm->sysv ? MT_ST_SYSV : 0;
4405 options |= STp->immediate ? MT_ST_NOWAIT : 0;
4406 options |= STp->sili ? MT_ST_SILI : 0;
4407
4408 l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
4409 return l;
4410}
4411
Tony Jonesee959b02008-02-22 00:13:36 +01004412DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL);
Kai Makisarab174be02008-02-24 22:29:12 +02004413
Jeff Garzik13026a62006-10-04 06:00:38 -04004414static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
4416 int i, rew, error;
4417 char name[10];
Tony Jonesee959b02008-02-22 00:13:36 +01004418 struct device *st_class_member;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420 for (rew=0; rew < 2; rew++) {
4421 /* Make sure that the minor numbers corresponding to the four
4422 first modes always get the same names */
4423 i = mode << (4 - ST_NBR_MODE_BITS);
4424 snprintf(name, 10, "%s%s%s", rew ? "n" : "",
4425 STp->disk->disk_name, st_formats[i]);
4426 st_class_member =
Greg Kroah-Hartman24b42562008-05-16 17:55:12 -07004427 device_create_drvdata(st_sysfs_class,
4428 &STp->device->sdev_gendev,
4429 MKDEV(SCSI_TAPE_MAJOR,
4430 TAPE_MINOR(dev_num,
4431 mode, rew)),
4432 &STp->modes[mode],
4433 "%s", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 if (IS_ERR(st_class_member)) {
Tony Jonesee959b02008-02-22 00:13:36 +01004435 printk(KERN_WARNING "st%d: device_create failed\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 dev_num);
Jeff Garzik13026a62006-10-04 06:00:38 -04004437 error = PTR_ERR(st_class_member);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 goto out;
4439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Tony Jonesee959b02008-02-22 00:13:36 +01004441 error = device_create_file(st_class_member,
4442 &dev_attr_defined);
Jeff Garzik13026a62006-10-04 06:00:38 -04004443 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004444 error = device_create_file(st_class_member,
4445 &dev_attr_default_blksize);
Jeff Garzik13026a62006-10-04 06:00:38 -04004446 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004447 error = device_create_file(st_class_member,
4448 &dev_attr_default_density);
Jeff Garzik13026a62006-10-04 06:00:38 -04004449 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004450 error = device_create_file(st_class_member,
4451 &dev_attr_default_compression);
Jeff Garzik13026a62006-10-04 06:00:38 -04004452 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004453 error = device_create_file(st_class_member,
4454 &dev_attr_options);
Kai Makisarab174be02008-02-24 22:29:12 +02004455 if (error) goto out;
Jeff Garzik13026a62006-10-04 06:00:38 -04004456
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 if (mode == 0 && rew == 0) {
4458 error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
4459 &st_class_member->kobj,
4460 "tape");
4461 if (error) {
4462 printk(KERN_ERR
4463 "st%d: Can't create sysfs link from SCSI device.\n",
4464 dev_num);
Jeff Garzik13026a62006-10-04 06:00:38 -04004465 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 }
4467 }
4468 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004469
4470 return 0;
4471
4472out:
4473 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474}
4475
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476/* The following functions may be useful for a larger audience. */
4477static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
4478 unsigned long uaddr, size_t count, int rw)
4479{
James Bottomley07542b82005-08-31 20:27:22 -04004480 unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
4481 unsigned long start = uaddr >> PAGE_SHIFT;
4482 const int nr_pages = end - start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483 int res, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484 struct page **pages;
4485
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 /* User attempted Overflow! */
4487 if ((uaddr + count) < uaddr)
4488 return -EINVAL;
4489
4490 /* Too big */
4491 if (nr_pages > max_pages)
4492 return -ENOMEM;
4493
4494 /* Hmm? */
4495 if (count == 0)
4496 return 0;
4497
4498 if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_KERNEL)) == NULL)
4499 return -ENOMEM;
4500
4501 /* Try to fault in all of the necessary pages */
4502 down_read(&current->mm->mmap_sem);
4503 /* rw==READ means read from drive, write into memory area */
4504 res = get_user_pages(
4505 current,
4506 current->mm,
4507 uaddr,
4508 nr_pages,
4509 rw == READ,
4510 0, /* don't force */
4511 pages,
4512 NULL);
4513 up_read(&current->mm->mmap_sem);
4514
4515 /* Errors and no page mapped should return here */
4516 if (res < nr_pages)
4517 goto out_unmap;
4518
4519 for (i=0; i < nr_pages; i++) {
4520 /* FIXME: flush superflous for rw==READ,
4521 * probably wrong function for rw==WRITE
4522 */
4523 flush_dcache_page(pages[i]);
4524 }
4525
4526 /* Populate the scatter/gather list */
Jens Axboe642f1492007-10-24 11:20:47 +02004527 sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 if (nr_pages > 1) {
4529 sgl[0].length = PAGE_SIZE - sgl[0].offset;
4530 count -= sgl[0].length;
4531 for (i=1; i < nr_pages ; i++) {
Jens Axboe642f1492007-10-24 11:20:47 +02004532 sg_set_page(&sgl[i], pages[i],
4533 count < PAGE_SIZE ? count : PAGE_SIZE, 0);;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534 count -= PAGE_SIZE;
4535 }
4536 }
4537 else {
4538 sgl[0].length = count;
4539 }
4540
4541 kfree(pages);
4542 return nr_pages;
4543
4544 out_unmap:
4545 if (res > 0) {
4546 for (j=0; j < res; j++)
4547 page_cache_release(pages[j]);
Hugh Dickins6bc733e2005-12-01 20:21:57 +00004548 res = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549 }
4550 kfree(pages);
4551 return res;
4552}
4553
4554
4555/* And unmap them... */
4556static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
4557 int dirtied)
4558{
4559 int i;
4560
4561 for (i=0; i < nr_pages; i++) {
Jens Axboe45711f12007-10-22 21:19:53 +02004562 struct page *page = sg_page(&sgl[i]);
Nick Pigginb5810032005-10-29 18:16:12 -07004563
Nick Pigginb5810032005-10-29 18:16:12 -07004564 if (dirtied)
4565 SetPageDirty(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 /* FIXME: cache flush missing for rw==READ
4567 * FIXME: call the correct reference counting function
4568 */
Nick Pigginb5810032005-10-29 18:16:12 -07004569 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 }
4571
4572 return 0;
4573}