blob: 708e9e90678f63aedc3373f9126352fd35659a50 [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 Makisara626dcb12008-07-11 15:05:25 +030020static const char *verstr = "20080504";
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>
Jonathan Corbetb3369c62008-05-15 16:08:15 -060041#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#include <asm/uaccess.h>
44#include <asm/dma.h>
45#include <asm/system.h>
46
47#include <scsi/scsi.h>
48#include <scsi/scsi_dbg.h>
49#include <scsi/scsi_device.h>
50#include <scsi/scsi_driver.h>
51#include <scsi/scsi_eh.h>
52#include <scsi/scsi_host.h>
53#include <scsi/scsi_ioctl.h>
Kai Makisara 16c4b3e2005-05-01 18:11:55 +030054#include <scsi/sg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56
57/* The driver prints some debugging information on the console if DEBUG
58 is defined and non-zero. */
59#define DEBUG 0
60
61#if DEBUG
62/* The message level for the debug messages is currently set to KERN_NOTICE
63 so that people can easily see the messages. Later when the debugging messages
64 in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
65#define ST_DEB_MSG KERN_NOTICE
66#define DEB(a) a
67#define DEBC(a) if (debugging) { a ; }
68#else
69#define DEB(a)
70#define DEBC(a)
71#endif
72
73#define ST_KILOBYTE 1024
74
75#include "st_options.h"
76#include "st.h"
77
78static int buffer_kbs;
79static int max_sg_segs;
80static int try_direct_io = TRY_DIRECT_IO;
81static int try_rdio = 1;
82static int try_wdio = 1;
83
84static int st_dev_max;
85static int st_nr_dev;
86
gregkh@suse.ded2538782005-03-23 09:55:22 -080087static struct class *st_sysfs_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89MODULE_AUTHOR("Kai Makisara");
Rene Hermanf018fa52006-03-08 00:14:20 -080090MODULE_DESCRIPTION("SCSI tape (st) driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -070091MODULE_LICENSE("GPL");
Rene Hermanf018fa52006-03-08 00:14:20 -080092MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR);
Michael Tokarevd7b8bcb2006-10-27 16:02:37 +040093MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
95/* Set 'perm' (4th argument) to 0 to disable module_param's definition
96 * of sysfs parameters (which module_param doesn't yet support).
97 * Sysfs parameters defined explicitly later.
98 */
99module_param_named(buffer_kbs, buffer_kbs, int, 0);
100MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size for fixed block mode (KB; 32)");
101module_param_named(max_sg_segs, max_sg_segs, int, 0);
102MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (256)");
103module_param_named(try_direct_io, try_direct_io, int, 0);
104MODULE_PARM_DESC(try_direct_io, "Try direct I/O between user buffer and tape drive (1)");
105
106/* Extra parameters for testing */
107module_param_named(try_rdio, try_rdio, int, 0);
108MODULE_PARM_DESC(try_rdio, "Try direct read i/o when possible");
109module_param_named(try_wdio, try_wdio, int, 0);
110MODULE_PARM_DESC(try_wdio, "Try direct write i/o when possible");
111
112#ifndef MODULE
113static int write_threshold_kbs; /* retained for compatibility */
114static struct st_dev_parm {
115 char *name;
116 int *val;
117} parms[] __initdata = {
118 {
119 "buffer_kbs", &buffer_kbs
120 },
121 { /* Retained for compatibility with 2.4 */
122 "write_threshold_kbs", &write_threshold_kbs
123 },
124 {
125 "max_sg_segs", NULL
126 },
127 {
128 "try_direct_io", &try_direct_io
129 }
130};
131#endif
132
133/* Restrict the number of modes so that names for all are assigned */
134#if ST_NBR_MODES > 16
135#error "Maximum number of modes is 16"
136#endif
137/* Bit reversed order to get same names for same minors with all
138 mode counts */
Arjan van de Ven0ad78202005-11-28 16:22:25 +0100139static const char *st_formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 "", "r", "k", "s", "l", "t", "o", "u",
141 "m", "v", "p", "x", "a", "y", "q", "z"};
142
143/* The default definitions have been moved to st_options.h */
144
145#define ST_FIXED_BUFFER_SIZE (ST_FIXED_BUFFER_BLOCKS * ST_KILOBYTE)
146
147/* The buffer size should fit into the 24 bits for length in the
148 6-byte SCSI read and write commands. */
149#if ST_FIXED_BUFFER_SIZE >= (2 << 24 - 1)
150#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
151#endif
152
153static int debugging = DEBUG;
154
155#define MAX_RETRIES 0
156#define MAX_WRITE_RETRIES 0
157#define MAX_READY_RETRIES 0
158#define NO_TAPE NOT_READY
159
160#define ST_TIMEOUT (900 * HZ)
161#define ST_LONG_TIMEOUT (14000 * HZ)
162
163/* Remove mode bits and auto-rewind bit (7) */
164#define TAPE_NR(x) ( ((iminor(x) & ~255) >> (ST_NBR_MODE_BITS + 1)) | \
165 (iminor(x) & ~(-1 << ST_MODE_SHIFT)) )
166#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
167
168/* Construct the minor number from the device (d), mode (m), and non-rewind (n) data */
169#define TAPE_MINOR(d, m, n) (((d & ~(255 >> (ST_NBR_MODE_BITS + 1))) << (ST_NBR_MODE_BITS + 1)) | \
170 (d & (255 >> (ST_NBR_MODE_BITS + 1))) | (m << ST_MODE_SHIFT) | ((n != 0) << 7) )
171
172/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
173 24 bits) */
174#define SET_DENS_AND_BLK 0x10001
175
176static DEFINE_RWLOCK(st_dev_arr_lock);
177
178static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE;
179static int st_max_sg_segs = ST_MAX_SG;
180
181static struct scsi_tape **scsi_tapes = NULL;
182
183static int modes_defined;
184
185static struct st_buffer *new_tape_buffer(int, int, int);
186static int enlarge_buffer(struct st_buffer *, int, int);
Kai Makisara40f6b362008-02-24 22:23:24 +0200187static void clear_buffer(struct st_buffer *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188static void normalize_buffer(struct st_buffer *);
189static int append_to_buffer(const char __user *, struct st_buffer *, int);
190static int from_buffer(struct st_buffer *, char __user *, int);
191static void move_buffer_data(struct st_buffer *, int);
192static void buf_to_sg(struct st_buffer *, unsigned int);
193
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static int sgl_map_user_pages(struct scatterlist *, const unsigned int,
195 unsigned long, size_t, int);
196static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
197
198static int st_probe(struct device *);
199static int st_remove(struct device *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100201static int do_create_sysfs_files(void);
202static void do_remove_sysfs_files(void);
Jeff Garzik13026a62006-10-04 06:00:38 -0400203static int do_create_class_files(struct scsi_tape *, int, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205static struct scsi_driver st_template = {
206 .owner = THIS_MODULE,
207 .gendrv = {
208 .name = "st",
209 .probe = st_probe,
210 .remove = st_remove,
211 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212};
213
214static int st_compression(struct scsi_tape *, int);
215
216static int find_partition(struct scsi_tape *);
217static int switch_partition(struct scsi_tape *);
218
219static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
220
Kai Makisaraf03a5672005-08-02 13:40:47 +0300221static void scsi_tape_release(struct kref *);
222
223#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
224
Arjan van de Ven0b950672006-01-11 13:16:10 +0100225static DEFINE_MUTEX(st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228#include "osst_detect.h"
229#ifndef SIGS_FROM_OSST
230#define SIGS_FROM_OSST \
231 {"OnStream", "SC-", "", "osst"}, \
232 {"OnStream", "DI-", "", "osst"}, \
233 {"OnStream", "DP-", "", "osst"}, \
234 {"OnStream", "USB", "", "osst"}, \
235 {"OnStream", "FW-", "", "osst"}
236#endif
237
Kai Makisaraf03a5672005-08-02 13:40:47 +0300238static struct scsi_tape *scsi_tape_get(int dev)
239{
240 struct scsi_tape *STp = NULL;
241
Arjan van de Ven0b950672006-01-11 13:16:10 +0100242 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300243 write_lock(&st_dev_arr_lock);
244
245 if (dev < st_dev_max && scsi_tapes != NULL)
246 STp = scsi_tapes[dev];
247 if (!STp) goto out;
248
249 kref_get(&STp->kref);
250
251 if (!STp->device)
252 goto out_put;
253
254 if (scsi_device_get(STp->device))
255 goto out_put;
256
257 goto out;
258
259out_put:
260 kref_put(&STp->kref, scsi_tape_release);
261 STp = NULL;
262out:
263 write_unlock(&st_dev_arr_lock);
Arjan van de Ven0b950672006-01-11 13:16:10 +0100264 mutex_unlock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300265 return STp;
266}
267
268static void scsi_tape_put(struct scsi_tape *STp)
269{
270 struct scsi_device *sdev = STp->device;
271
Arjan van de Ven0b950672006-01-11 13:16:10 +0100272 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300273 kref_put(&STp->kref, scsi_tape_release);
274 scsi_device_put(sdev);
Arjan van de Ven0b950672006-01-11 13:16:10 +0100275 mutex_unlock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300276}
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278struct st_reject_data {
279 char *vendor;
280 char *model;
281 char *rev;
282 char *driver_hint; /* Name of the correct driver, NULL if unknown */
283};
284
285static struct st_reject_data reject_list[] = {
286 /* {"XXX", "Yy-", "", NULL}, example */
287 SIGS_FROM_OSST,
288 {NULL, }};
289
290/* If the device signature is on the list of incompatible drives, the
291 function returns a pointer to the name of the correct driver (if known) */
292static char * st_incompatible(struct scsi_device* SDp)
293{
294 struct st_reject_data *rp;
295
296 for (rp=&(reject_list[0]); rp->vendor != NULL; rp++)
297 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
298 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
299 !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) {
300 if (rp->driver_hint)
301 return rp->driver_hint;
302 else
303 return "unknown";
304 }
305 return NULL;
306}
307
308
309static inline char *tape_name(struct scsi_tape *tape)
310{
311 return tape->disk->disk_name;
312}
313
314
Mike Christie8b05b772005-11-08 04:06:44 -0600315static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316{
317 const u8 *ucp;
Mike Christie8b05b772005-11-08 04:06:44 -0600318 const u8 *sense = SRpnt->sense;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
Mike Christie8b05b772005-11-08 04:06:44 -0600320 s->have_sense = scsi_normalize_sense(SRpnt->sense,
321 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 s->flags = 0;
323
324 if (s->have_sense) {
325 s->deferred = 0;
326 s->remainder_valid =
327 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
328 switch (sense[0] & 0x7f) {
329 case 0x71:
330 s->deferred = 1;
331 case 0x70:
332 s->fixed_format = 1;
333 s->flags = sense[2] & 0xe0;
334 break;
335 case 0x73:
336 s->deferred = 1;
337 case 0x72:
338 s->fixed_format = 0;
339 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
340 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
341 break;
342 }
343 }
344}
345
346
347/* Convert the result to success code */
Mike Christie8b05b772005-11-08 04:06:44 -0600348static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349{
Mike Christie8b05b772005-11-08 04:06:44 -0600350 int result = SRpnt->result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 u8 scode;
352 DEB(const char *stp;)
353 char *name = tape_name(STp);
354 struct st_cmdstatus *cmdstatp;
355
356 if (!result)
357 return 0;
358
359 cmdstatp = &STp->buffer->cmdstat;
Kai Makisaraf03a5672005-08-02 13:40:47 +0300360 st_analyze_sense(SRpnt, cmdstatp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
362 if (cmdstatp->have_sense)
363 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
364 else
365 scode = 0;
366
367 DEB(
368 if (debugging) {
Mike Christie8b05b772005-11-08 04:06:44 -0600369 printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 name, result,
Mike Christie8b05b772005-11-08 04:06:44 -0600371 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
372 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 if (cmdstatp->have_sense)
Luben Tuikov4e73ea72006-07-07 00:02:18 -0700374 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 } ) /* end DEB */
376 if (!debugging) { /* Abnormal conditions for tape */
377 if (!cmdstatp->have_sense)
378 printk(KERN_WARNING
379 "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
380 name, result, suggestion(result),
381 driver_byte(result) & DRIVER_MASK, host_byte(result));
382 else if (cmdstatp->have_sense &&
383 scode != NO_SENSE &&
384 scode != RECOVERED_ERROR &&
385 /* scode != UNIT_ATTENTION && */
386 scode != BLANK_CHECK &&
387 scode != VOLUME_OVERFLOW &&
Mike Christie8b05b772005-11-08 04:06:44 -0600388 SRpnt->cmd[0] != MODE_SENSE &&
389 SRpnt->cmd[0] != TEST_UNIT_READY) {
Luben Tuikov4e73ea72006-07-07 00:02:18 -0700390
391 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 }
393 }
394
395 if (cmdstatp->fixed_format &&
396 STp->cln_mode >= EXTENDED_SENSE_START) { /* Only fixed format sense */
397 if (STp->cln_sense_value)
Mike Christie8b05b772005-11-08 04:06:44 -0600398 STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 STp->cln_sense_mask) == STp->cln_sense_value);
400 else
Mike Christie8b05b772005-11-08 04:06:44 -0600401 STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 STp->cln_sense_mask) != 0);
403 }
404 if (cmdstatp->have_sense &&
405 cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
406 STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
407
408 STp->pos_unknown |= STp->device->was_reset;
409
410 if (cmdstatp->have_sense &&
411 scode == RECOVERED_ERROR
412#if ST_RECOVERED_WRITE_FATAL
Mike Christie8b05b772005-11-08 04:06:44 -0600413 && SRpnt->cmd[0] != WRITE_6
414 && SRpnt->cmd[0] != WRITE_FILEMARKS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415#endif
416 ) {
417 STp->recover_count++;
418 STp->recover_reg++;
419
420 DEB(
421 if (debugging) {
Mike Christie8b05b772005-11-08 04:06:44 -0600422 if (SRpnt->cmd[0] == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 stp = "read";
Mike Christie8b05b772005-11-08 04:06:44 -0600424 else if (SRpnt->cmd[0] == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 stp = "write";
426 else
427 stp = "ioctl";
428 printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp,
429 STp->recover_count);
430 } ) /* end DEB */
431
432 if (cmdstatp->flags == 0)
433 return 0;
434 }
435 return (-EIO);
436}
437
438
439/* Wakeup from interrupt */
Mike Christie8b05b772005-11-08 04:06:44 -0600440static void st_sleep_done(void *data, char *sense, int result, int resid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Mike Christie8b05b772005-11-08 04:06:44 -0600442 struct st_request *SRpnt = data;
443 struct scsi_tape *STp = SRpnt->stp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Mike Christie8b05b772005-11-08 04:06:44 -0600445 memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
446 (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
Kai Makisara40f6b362008-02-24 22:23:24 +0200447 (STp->buffer)->cmdstat.residual = resid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 DEB( STp->write_pending = 0; )
449
Mike Christie8b05b772005-11-08 04:06:44 -0600450 if (SRpnt->waiting)
451 complete(SRpnt->waiting);
452}
453
FUJITA Tomonori4deba242008-12-05 15:25:20 +0900454static struct st_request *st_allocate_request(struct scsi_tape *stp)
Mike Christie8b05b772005-11-08 04:06:44 -0600455{
FUJITA Tomonori4deba242008-12-05 15:25:20 +0900456 struct st_request *streq;
457
458 streq = kzalloc(sizeof(*streq), GFP_KERNEL);
459 if (streq)
460 streq->stp = stp;
461 else {
462 DEBC(printk(KERN_ERR "%s: Can't get SCSI request.\n",
463 tape_name(stp)););
464 if (signal_pending(current))
465 stp->buffer->syscall_result = -EINTR;
466 else
467 stp->buffer->syscall_result = -EBUSY;
468 }
469
470 return streq;
Mike Christie8b05b772005-11-08 04:06:44 -0600471}
472
473static void st_release_request(struct st_request *streq)
474{
475 kfree(streq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476}
477
478/* Do the scsi command. Waits until command performed if do_wait is true.
479 Otherwise write_behind_check() is used to check that the command
480 has finished. */
Mike Christie8b05b772005-11-08 04:06:44 -0600481static struct st_request *
482st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 int bytes, int direction, int timeout, int retries, int do_wait)
484{
Kai Makisaraf03a5672005-08-02 13:40:47 +0300485 struct completion *waiting;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
Kai Makisaraf03a5672005-08-02 13:40:47 +0300487 /* if async, make sure there's no command outstanding */
488 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
489 printk(KERN_ERR "%s: Async command already active.\n",
490 tape_name(STp));
491 if (signal_pending(current))
492 (STp->buffer)->syscall_result = (-EINTR);
493 else
494 (STp->buffer)->syscall_result = (-EBUSY);
495 return NULL;
496 }
497
FUJITA Tomonori4deba242008-12-05 15:25:20 +0900498 if (!SRpnt) {
499 SRpnt = st_allocate_request(STp);
500 if (!SRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
503
Kai Makisaraf03a5672005-08-02 13:40:47 +0300504 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
505 which IO is outstanding. It's nulled out when the IO completes. */
506 if (!do_wait)
507 (STp->buffer)->last_SRpnt = SRpnt;
508
509 waiting = &STp->wait;
510 init_completion(waiting);
Mike Christie8b05b772005-11-08 04:06:44 -0600511 SRpnt->waiting = waiting;
512
513 if (!STp->buffer->do_dio)
514 buf_to_sg(STp->buffer, bytes);
515
516 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 STp->buffer->cmdstat.have_sense = 0;
Mike Christie8b05b772005-11-08 04:06:44 -0600518 STp->buffer->syscall_result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
brking@us.ibm.combb1d1072006-01-23 15:03:22 -0600520 if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction,
Mike Christie8b05b772005-11-08 04:06:44 -0600521 &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
Kai Makisara787926b2005-11-13 10:04:44 +0200522 timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
Mike Christie8b05b772005-11-08 04:06:44 -0600523 /* could not allocate the buffer or request was too large */
524 (STp->buffer)->syscall_result = (-EBUSY);
Kai Makisara787926b2005-11-13 10:04:44 +0200525 (STp->buffer)->last_SRpnt = NULL;
526 }
Mike Christie8b05b772005-11-08 04:06:44 -0600527 else if (do_wait) {
Kai Makisaraf03a5672005-08-02 13:40:47 +0300528 wait_for_completion(waiting);
Mike Christie8b05b772005-11-08 04:06:44 -0600529 SRpnt->waiting = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
531 }
Mike Christie8b05b772005-11-08 04:06:44 -0600532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 return SRpnt;
534}
535
FUJITA Tomonoriffb43492008-12-05 15:25:21 +0900536static int st_scsi_kern_execute(struct st_request *streq,
537 const unsigned char *cmd, int data_direction,
538 void *buffer, unsigned bufflen, int timeout,
539 int retries)
540{
541 struct scsi_tape *stp = streq->stp;
542 int ret, resid;
543
544 stp->buffer->cmdstat.have_sense = 0;
545 memcpy(streq->cmd, cmd, sizeof(streq->cmd));
546
547 ret = scsi_execute(stp->device, cmd, data_direction, buffer, bufflen,
548 streq->sense, timeout, retries, 0, &resid);
549 if (driver_byte(ret) & DRIVER_ERROR)
550 return -EBUSY;
551
552 stp->buffer->cmdstat.midlevel_result = streq->result = ret;
553 stp->buffer->cmdstat.residual = resid;
554 stp->buffer->syscall_result = st_chk_result(stp, streq);
555
556 return 0;
557}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
559/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
560 write has been correct but EOM early warning reached, -EIO if write ended in
561 error or zero if write successful. Asynchronous writes are used only in
562 variable block mode. */
563static int write_behind_check(struct scsi_tape * STp)
564{
565 int retval = 0;
566 struct st_buffer *STbuffer;
567 struct st_partstat *STps;
568 struct st_cmdstatus *cmdstatp;
Mike Christie8b05b772005-11-08 04:06:44 -0600569 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570
571 STbuffer = STp->buffer;
572 if (!STbuffer->writing)
573 return 0;
574
575 DEB(
576 if (STp->write_pending)
577 STp->nbr_waits++;
578 else
579 STp->nbr_finished++;
580 ) /* end DEB */
581
582 wait_for_completion(&(STp->wait));
Kai Makisaraf03a5672005-08-02 13:40:47 +0300583 SRpnt = STbuffer->last_SRpnt;
584 STbuffer->last_SRpnt = NULL;
Mike Christie8b05b772005-11-08 04:06:44 -0600585 SRpnt->waiting = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
Kai Makisaraf03a5672005-08-02 13:40:47 +0300587 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
Mike Christie8b05b772005-11-08 04:06:44 -0600588 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 STbuffer->buffer_bytes -= STbuffer->writing;
591 STps = &(STp->ps[STp->partition]);
592 if (STps->drv_block >= 0) {
593 if (STp->block_size == 0)
594 STps->drv_block++;
595 else
596 STps->drv_block += STbuffer->writing / STp->block_size;
597 }
598
599 cmdstatp = &STbuffer->cmdstat;
600 if (STbuffer->syscall_result) {
601 retval = -EIO;
602 if (cmdstatp->have_sense && !cmdstatp->deferred &&
603 (cmdstatp->flags & SENSE_EOM) &&
604 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
605 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR)) {
606 /* EOM at write-behind, has all data been written? */
607 if (!cmdstatp->remainder_valid ||
608 cmdstatp->uremainder64 == 0)
609 retval = -ENOSPC;
610 }
611 if (retval == -EIO)
612 STps->drv_block = -1;
613 }
614 STbuffer->writing = 0;
615
616 DEB(if (debugging && retval)
617 printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n",
618 tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
619
620 return retval;
621}
622
623
624/* Step over EOF if it has been inadvertently crossed (ioctl not used because
625 it messes up the block number). */
626static int cross_eof(struct scsi_tape * STp, int forward)
627{
Mike Christie8b05b772005-11-08 04:06:44 -0600628 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 unsigned char cmd[MAX_COMMAND_SIZE];
FUJITA Tomonori39ade4b2008-12-05 15:25:25 +0900630 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
632 cmd[0] = SPACE;
633 cmd[1] = 0x01; /* Space FileMarks */
634 if (forward) {
635 cmd[2] = cmd[3] = 0;
636 cmd[4] = 1;
637 } else
638 cmd[2] = cmd[3] = cmd[4] = 0xff; /* -1 filemarks */
639 cmd[5] = 0;
640
641 DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",
642 tape_name(STp), forward ? "forward" : "backward"));
643
FUJITA Tomonori39ade4b2008-12-05 15:25:25 +0900644 SRpnt = st_allocate_request(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (!SRpnt)
FUJITA Tomonori39ade4b2008-12-05 15:25:25 +0900646 return STp->buffer->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
FUJITA Tomonori39ade4b2008-12-05 15:25:25 +0900648 ret = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0,
649 STp->device->request_queue->rq_timeout,
650 MAX_RETRIES);
651 if (ret)
652 goto out;
653
654 ret = STp->buffer->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656 if ((STp->buffer)->cmdstat.midlevel_result != 0)
657 printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
658 tape_name(STp), forward ? "forward" : "backward");
659
FUJITA Tomonori39ade4b2008-12-05 15:25:25 +0900660out:
661 st_release_request(SRpnt);
662
663 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664}
665
666
667/* Flush the write buffer (never need to write if variable blocksize). */
Adrian Bunk8ef8d592008-04-14 17:17:16 +0300668static int st_flush_write_buffer(struct scsi_tape * STp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
Kai Makisara786231a2008-07-11 15:06:40 +0300670 int transfer, blks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 int result;
672 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -0600673 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 struct st_partstat *STps;
675
676 result = write_behind_check(STp);
677 if (result)
678 return result;
679
680 result = 0;
681 if (STp->dirty == 1) {
682
Kai Makisara786231a2008-07-11 15:06:40 +0300683 transfer = STp->buffer->buffer_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
685 tape_name(STp), transfer));
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 memset(cmd, 0, MAX_COMMAND_SIZE);
688 cmd[0] = WRITE_6;
689 cmd[1] = 1;
690 blks = transfer / STp->block_size;
691 cmd[2] = blks >> 16;
692 cmd[3] = blks >> 8;
693 cmd[4] = blks;
694
695 SRpnt = st_do_scsi(NULL, STp, cmd, transfer, DMA_TO_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -0600696 STp->device->request_queue->rq_timeout,
697 MAX_WRITE_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 if (!SRpnt)
699 return (STp->buffer)->syscall_result;
700
701 STps = &(STp->ps[STp->partition]);
702 if ((STp->buffer)->syscall_result != 0) {
703 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
704
705 if (cmdstatp->have_sense && !cmdstatp->deferred &&
706 (cmdstatp->flags & SENSE_EOM) &&
707 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
708 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
709 (!cmdstatp->remainder_valid ||
710 cmdstatp->uremainder64 == 0)) { /* All written at EOM early warning */
711 STp->dirty = 0;
712 (STp->buffer)->buffer_bytes = 0;
713 if (STps->drv_block >= 0)
714 STps->drv_block += blks;
715 result = (-ENOSPC);
716 } else {
717 printk(KERN_ERR "%s: Error on flush.\n",
718 tape_name(STp));
719 STps->drv_block = (-1);
720 result = (-EIO);
721 }
722 } else {
723 if (STps->drv_block >= 0)
724 STps->drv_block += blks;
725 STp->dirty = 0;
726 (STp->buffer)->buffer_bytes = 0;
727 }
Mike Christie8b05b772005-11-08 04:06:44 -0600728 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 SRpnt = NULL;
730 }
731 return result;
732}
733
734
735/* Flush the tape buffer. The tape will be positioned correctly unless
736 seek_next is true. */
737static int flush_buffer(struct scsi_tape *STp, int seek_next)
738{
739 int backspace, result;
740 struct st_buffer *STbuffer;
741 struct st_partstat *STps;
742
743 STbuffer = STp->buffer;
744
745 /*
746 * If there was a bus reset, block further access
747 * to this device.
748 */
749 if (STp->pos_unknown)
750 return (-EIO);
751
752 if (STp->ready != ST_READY)
753 return 0;
754 STps = &(STp->ps[STp->partition]);
755 if (STps->rw == ST_WRITING) /* Writing */
Adrian Bunk8ef8d592008-04-14 17:17:16 +0300756 return st_flush_write_buffer(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
758 if (STp->block_size == 0)
759 return 0;
760
761 backspace = ((STp->buffer)->buffer_bytes +
762 (STp->buffer)->read_pointer) / STp->block_size -
763 ((STp->buffer)->read_pointer + STp->block_size - 1) /
764 STp->block_size;
765 (STp->buffer)->buffer_bytes = 0;
766 (STp->buffer)->read_pointer = 0;
767 result = 0;
768 if (!seek_next) {
769 if (STps->eof == ST_FM_HIT) {
770 result = cross_eof(STp, 0); /* Back over the EOF hit */
771 if (!result)
772 STps->eof = ST_NOEOF;
773 else {
774 if (STps->drv_file >= 0)
775 STps->drv_file++;
776 STps->drv_block = 0;
777 }
778 }
779 if (!result && backspace > 0)
780 result = st_int_ioctl(STp, MTBSR, backspace);
781 } else if (STps->eof == ST_FM_HIT) {
782 if (STps->drv_file >= 0)
783 STps->drv_file++;
784 STps->drv_block = 0;
785 STps->eof = ST_NOEOF;
786 }
787 return result;
788
789}
790
791/* Set the mode parameters */
792static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
793{
794 int set_it = 0;
795 unsigned long arg;
796 char *name = tape_name(STp);
797
798 if (!STp->density_changed &&
799 STm->default_density >= 0 &&
800 STm->default_density != STp->density) {
801 arg = STm->default_density;
802 set_it = 1;
803 } else
804 arg = STp->density;
805 arg <<= MT_ST_DENSITY_SHIFT;
806 if (!STp->blksize_changed &&
807 STm->default_blksize >= 0 &&
808 STm->default_blksize != STp->block_size) {
809 arg |= STm->default_blksize;
810 set_it = 1;
811 } else
812 arg |= STp->block_size;
813 if (set_it &&
814 st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {
815 printk(KERN_WARNING
816 "%s: Can't set default block size to %d bytes and density %x.\n",
817 name, STm->default_blksize, STm->default_density);
818 if (modes_defined)
819 return (-EINVAL);
820 }
821 return 0;
822}
823
824
Mike Christie8b05b772005-11-08 04:06:44 -0600825/* Lock or unlock the drive door. Don't use when st_request allocated. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826static int do_door_lock(struct scsi_tape * STp, int do_lock)
827{
828 int retval, cmd;
829 DEB(char *name = tape_name(STp);)
830
831
832 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
833 DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name,
834 do_lock ? "L" : "Unl"));
835 retval = scsi_ioctl(STp->device, cmd, NULL);
836 if (!retval) {
837 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
838 }
839 else {
840 STp->door_locked = ST_LOCK_FAILS;
841 }
842 return retval;
843}
844
845
846/* Set the internal state after reset */
847static void reset_state(struct scsi_tape *STp)
848{
849 int i;
850 struct st_partstat *STps;
851
852 STp->pos_unknown = 0;
853 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
854 STps = &(STp->ps[i]);
855 STps->rw = ST_IDLE;
856 STps->eof = ST_NOEOF;
857 STps->at_sm = 0;
858 STps->last_block_valid = 0;
859 STps->drv_block = -1;
860 STps->drv_file = -1;
861 }
862 if (STp->can_partitions) {
863 STp->partition = find_partition(STp);
864 if (STp->partition < 0)
865 STp->partition = 0;
866 STp->new_partition = STp->partition;
867 }
868}
869
870/* Test if the drive is ready. Returns either one of the codes below or a negative system
871 error code. */
872#define CHKRES_READY 0
873#define CHKRES_NEW_SESSION 1
874#define CHKRES_NOT_READY 2
875#define CHKRES_NO_TAPE 3
876
877#define MAX_ATTENTIONS 10
878
879static int test_ready(struct scsi_tape *STp, int do_wait)
880{
881 int attentions, waits, max_wait, scode;
882 int retval = CHKRES_READY, new_session = 0;
883 unsigned char cmd[MAX_COMMAND_SIZE];
FUJITA Tomonori0944a722008-12-05 15:25:22 +0900884 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
886
FUJITA Tomonori0944a722008-12-05 15:25:22 +0900887 SRpnt = st_allocate_request(STp);
888 if (!SRpnt)
889 return STp->buffer->syscall_result;
890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
892
893 for (attentions=waits=0; ; ) {
894 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
895 cmd[0] = TEST_UNIT_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
FUJITA Tomonori0944a722008-12-05 15:25:22 +0900897 retval = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0,
898 STp->long_timeout,
899 MAX_READY_RETRIES);
900 if (retval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
903 if (cmdstatp->have_sense) {
904
905 scode = cmdstatp->sense_hdr.sense_key;
906
907 if (scode == UNIT_ATTENTION) { /* New media? */
908 new_session = 1;
909 if (attentions < MAX_ATTENTIONS) {
910 attentions++;
911 continue;
912 }
913 else {
914 retval = (-EIO);
915 break;
916 }
917 }
918
919 if (scode == NOT_READY) {
920 if (waits < max_wait) {
921 if (msleep_interruptible(1000)) {
922 retval = (-EINTR);
923 break;
924 }
925 waits++;
926 continue;
927 }
928 else {
929 if ((STp->device)->scsi_level >= SCSI_2 &&
930 cmdstatp->sense_hdr.asc == 0x3a) /* Check ASC */
931 retval = CHKRES_NO_TAPE;
932 else
933 retval = CHKRES_NOT_READY;
934 break;
935 }
936 }
937 }
938
939 retval = (STp->buffer)->syscall_result;
940 if (!retval)
941 retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;
942 break;
943 }
944
FUJITA Tomonori0944a722008-12-05 15:25:22 +0900945 st_release_request(SRpnt);
946
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 return retval;
948}
949
950
951/* See if the drive is ready and gather information about the tape. Return values:
952 < 0 negative error code from errno.h
953 0 drive ready
954 1 drive not ready (possibly no tape)
955*/
956static int check_tape(struct scsi_tape *STp, struct file *filp)
957{
958 int i, retval, new_session = 0, do_wait;
959 unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
960 unsigned short st_flags = filp->f_flags;
Mike Christie8b05b772005-11-08 04:06:44 -0600961 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 struct st_modedef *STm;
963 struct st_partstat *STps;
964 char *name = tape_name(STp);
Josef Sipek7ac62072006-12-08 02:37:37 -0800965 struct inode *inode = filp->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 int mode = TAPE_MODE(inode);
967
968 STp->ready = ST_READY;
969
970 if (mode != STp->current_mode) {
971 DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n",
972 name, STp->current_mode, mode));
973 new_session = 1;
974 STp->current_mode = mode;
975 }
976 STm = &(STp->modes[STp->current_mode]);
977
978 saved_cleaning = STp->cleaning_req;
979 STp->cleaning_req = 0;
980
981 do_wait = ((filp->f_flags & O_NONBLOCK) == 0);
982 retval = test_ready(STp, do_wait);
983
984 if (retval < 0)
985 goto err_out;
986
987 if (retval == CHKRES_NEW_SESSION) {
988 STp->pos_unknown = 0;
989 STp->partition = STp->new_partition = 0;
990 if (STp->can_partitions)
991 STp->nbr_partitions = 1; /* This guess will be updated later
992 if necessary */
993 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
994 STps = &(STp->ps[i]);
995 STps->rw = ST_IDLE;
996 STps->eof = ST_NOEOF;
997 STps->at_sm = 0;
998 STps->last_block_valid = 0;
999 STps->drv_block = 0;
1000 STps->drv_file = 0;
1001 }
1002 new_session = 1;
1003 }
1004 else {
1005 STp->cleaning_req |= saved_cleaning;
1006
1007 if (retval == CHKRES_NOT_READY || retval == CHKRES_NO_TAPE) {
1008 if (retval == CHKRES_NO_TAPE)
1009 STp->ready = ST_NO_TAPE;
1010 else
1011 STp->ready = ST_NOT_READY;
1012
1013 STp->density = 0; /* Clear the erroneous "residue" */
1014 STp->write_prot = 0;
1015 STp->block_size = 0;
1016 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
1017 STp->partition = STp->new_partition = 0;
1018 STp->door_locked = ST_UNLOCKED;
1019 return CHKRES_NOT_READY;
1020 }
1021 }
1022
1023 if (STp->omit_blklims)
1024 STp->min_block = STp->max_block = (-1);
1025 else {
1026 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
1027 cmd[0] = READ_BLOCK_LIMITS;
1028
1029 SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06001030 STp->device->request_queue->rq_timeout,
1031 MAX_READY_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 if (!SRpnt) {
1033 retval = (STp->buffer)->syscall_result;
1034 goto err_out;
1035 }
1036
Mike Christie8b05b772005-11-08 04:06:44 -06001037 if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 STp->max_block = ((STp->buffer)->b_data[1] << 16) |
1039 ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
1040 STp->min_block = ((STp->buffer)->b_data[4] << 8) |
1041 (STp->buffer)->b_data[5];
1042 if ( DEB( debugging || ) !STp->inited)
Kai Makisara42252852006-11-07 21:56:38 +02001043 printk(KERN_INFO
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 "%s: Block limits %d - %d bytes.\n", name,
1045 STp->min_block, STp->max_block);
1046 } else {
1047 STp->min_block = STp->max_block = (-1);
1048 DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",
1049 name));
1050 }
1051 }
1052
1053 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
1054 cmd[0] = MODE_SENSE;
1055 cmd[4] = 12;
1056
1057 SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06001058 STp->device->request_queue->rq_timeout,
1059 MAX_READY_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 if (!SRpnt) {
1061 retval = (STp->buffer)->syscall_result;
1062 goto err_out;
1063 }
1064
1065 if ((STp->buffer)->syscall_result != 0) {
1066 DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name));
1067 STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */
1068 (STp->buffer)->syscall_result = 0; /* Prevent error propagation */
1069 STp->drv_write_prot = 0;
1070 } else {
1071 DEBC(printk(ST_DEB_MSG
1072 "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
1073 name,
1074 (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
1075 (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]));
1076
1077 if ((STp->buffer)->b_data[3] >= 8) {
1078 STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
1079 STp->density = (STp->buffer)->b_data[4];
1080 STp->block_size = (STp->buffer)->b_data[9] * 65536 +
1081 (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
1082 DEBC(printk(ST_DEB_MSG
1083 "%s: Density %x, tape length: %x, drv buffer: %d\n",
1084 name, STp->density, (STp->buffer)->b_data[5] * 65536 +
1085 (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
1086 STp->drv_buffer));
1087 }
1088 STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
1089 }
Mike Christie8b05b772005-11-08 04:06:44 -06001090 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 SRpnt = NULL;
1092 STp->inited = 1;
1093
1094 if (STp->block_size > 0)
1095 (STp->buffer)->buffer_blocks =
1096 (STp->buffer)->buffer_size / STp->block_size;
1097 else
1098 (STp->buffer)->buffer_blocks = 1;
1099 (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
1100
1101 DEBC(printk(ST_DEB_MSG
1102 "%s: Block size: %d, buffer size: %d (%d blocks).\n", name,
1103 STp->block_size, (STp->buffer)->buffer_size,
1104 (STp->buffer)->buffer_blocks));
1105
1106 if (STp->drv_write_prot) {
1107 STp->write_prot = 1;
1108
1109 DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name));
1110
1111 if (do_wait &&
1112 ((st_flags & O_ACCMODE) == O_WRONLY ||
1113 (st_flags & O_ACCMODE) == O_RDWR)) {
1114 retval = (-EROFS);
1115 goto err_out;
1116 }
1117 }
1118
1119 if (STp->can_partitions && STp->nbr_partitions < 1) {
1120 /* This code is reached when the device is opened for the first time
1121 after the driver has been initialized with tape in the drive and the
1122 partition support has been enabled. */
1123 DEBC(printk(ST_DEB_MSG
1124 "%s: Updating partition number in status.\n", name));
1125 if ((STp->partition = find_partition(STp)) < 0) {
1126 retval = STp->partition;
1127 goto err_out;
1128 }
1129 STp->new_partition = STp->partition;
1130 STp->nbr_partitions = 1; /* This guess will be updated when necessary */
1131 }
1132
1133 if (new_session) { /* Change the drive parameters for the new mode */
1134 STp->density_changed = STp->blksize_changed = 0;
1135 STp->compression_changed = 0;
1136 if (!(STm->defaults_for_writes) &&
1137 (retval = set_mode_densblk(STp, STm)) < 0)
1138 goto err_out;
1139
1140 if (STp->default_drvbuffer != 0xff) {
1141 if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))
1142 printk(KERN_WARNING
1143 "%s: Can't set default drive buffering to %d.\n",
1144 name, STp->default_drvbuffer);
1145 }
1146 }
1147
1148 return CHKRES_READY;
1149
1150 err_out:
1151 return retval;
1152}
1153
1154
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001155 /* Open the device. Needs to take the BKL only because of incrementing the SCSI host
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 module count. */
1157static int st_open(struct inode *inode, struct file *filp)
1158{
1159 int i, retval = (-EIO);
1160 struct scsi_tape *STp;
1161 struct st_partstat *STps;
1162 int dev = TAPE_NR(inode);
1163 char *name;
1164
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001165 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 /*
1167 * We really want to do nonseekable_open(inode, filp); here, but some
1168 * versions of tar incorrectly call lseek on tapes and bail out if that
1169 * fails. So we disallow pread() and pwrite(), but permit lseeks.
1170 */
1171 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
1172
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001173 if (!(STp = scsi_tape_get(dev))) {
1174 unlock_kernel();
Kai Makisaraf03a5672005-08-02 13:40:47 +03001175 return -ENXIO;
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001176 }
Kai Makisaraf03a5672005-08-02 13:40:47 +03001177
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 write_lock(&st_dev_arr_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 filp->private_data = STp;
1180 name = tape_name(STp);
1181
1182 if (STp->in_use) {
1183 write_unlock(&st_dev_arr_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001184 scsi_tape_put(STp);
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001185 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
1187 return (-EBUSY);
1188 }
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 STp->in_use = 1;
1191 write_unlock(&st_dev_arr_lock);
1192 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
1193
1194 if (!scsi_block_when_processing_errors(STp->device)) {
1195 retval = (-ENXIO);
1196 goto err_out;
1197 }
1198
1199 /* See that we have at least a one page buffer available */
1200 if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) {
1201 printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n",
1202 name);
1203 retval = (-EOVERFLOW);
1204 goto err_out;
1205 }
1206
Kai Makisara40f6b362008-02-24 22:23:24 +02001207 (STp->buffer)->cleared = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 (STp->buffer)->writing = 0;
1209 (STp->buffer)->syscall_result = 0;
1210
1211 STp->write_prot = ((filp->f_flags & O_ACCMODE) == O_RDONLY);
1212
1213 STp->dirty = 0;
1214 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
1215 STps = &(STp->ps[i]);
1216 STps->rw = ST_IDLE;
1217 }
Kai Makisara9abe16c2007-02-03 13:21:29 +02001218 STp->try_dio_now = STp->try_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 STp->recover_count = 0;
1220 DEB( STp->nbr_waits = STp->nbr_finished = 0;
Kai Makisaradeee13d2008-02-22 20:11:21 +02001221 STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = 0; )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 retval = check_tape(STp, filp);
1224 if (retval < 0)
1225 goto err_out;
1226 if ((filp->f_flags & O_NONBLOCK) == 0 &&
1227 retval != CHKRES_READY) {
Kai Makisara413f7322006-10-05 22:59:46 +03001228 if (STp->ready == NO_TAPE)
1229 retval = (-ENOMEDIUM);
1230 else
1231 retval = (-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 goto err_out;
1233 }
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001234 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 return 0;
1236
1237 err_out:
1238 normalize_buffer(STp->buffer);
1239 STp->in_use = 0;
Kai Makisaraf03a5672005-08-02 13:40:47 +03001240 scsi_tape_put(STp);
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001241 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 return retval;
1243
1244}
1245
1246
1247/* Flush the tape buffer before close */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001248static int st_flush(struct file *filp, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249{
1250 int result = 0, result2;
1251 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06001252 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 struct scsi_tape *STp = filp->private_data;
1254 struct st_modedef *STm = &(STp->modes[STp->current_mode]);
1255 struct st_partstat *STps = &(STp->ps[STp->partition]);
1256 char *name = tape_name(STp);
1257
1258 if (file_count(filp) > 1)
1259 return 0;
1260
1261 if (STps->rw == ST_WRITING && !STp->pos_unknown) {
Adrian Bunk8ef8d592008-04-14 17:17:16 +03001262 result = st_flush_write_buffer(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 if (result != 0 && result != (-ENOSPC))
1264 goto out;
1265 }
1266
1267 if (STp->can_partitions &&
1268 (result2 = switch_partition(STp)) < 0) {
1269 DEBC(printk(ST_DEB_MSG
1270 "%s: switch_partition at close failed.\n", name));
1271 if (result == 0)
1272 result = result2;
1273 goto out;
1274 }
1275
1276 DEBC( if (STp->nbr_requests)
Kai Makisaradeee13d2008-02-22 20:11:21 +02001277 printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n",
1278 name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 if (STps->rw == ST_WRITING && !STp->pos_unknown) {
1281 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1282
1283 DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n",
1284 name, STp->nbr_waits, STp->nbr_finished);
1285 )
1286
1287 memset(cmd, 0, MAX_COMMAND_SIZE);
1288 cmd[0] = WRITE_FILEMARKS;
1289 cmd[4] = 1 + STp->two_fm;
1290
FUJITA Tomonori212cd8b2008-12-05 15:25:26 +09001291 SRpnt = st_allocate_request(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (!SRpnt) {
FUJITA Tomonori212cd8b2008-12-05 15:25:26 +09001293 result = STp->buffer->syscall_result;
1294 goto out;
1295 }
1296
1297 result = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0,
1298 STp->device->request_queue->rq_timeout,
1299 MAX_WRITE_RETRIES);
1300 if (result) {
1301 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 goto out;
1303 }
1304
1305 if (STp->buffer->syscall_result == 0 ||
1306 (cmdstatp->have_sense && !cmdstatp->deferred &&
1307 (cmdstatp->flags & SENSE_EOM) &&
1308 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
1309 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
1310 (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
1311 /* Write successful at EOM */
Mike Christie8b05b772005-11-08 04:06:44 -06001312 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 SRpnt = NULL;
1314 if (STps->drv_file >= 0)
1315 STps->drv_file++;
1316 STps->drv_block = 0;
1317 if (STp->two_fm)
1318 cross_eof(STp, 0);
1319 STps->eof = ST_FM;
1320 }
1321 else { /* Write error */
Mike Christie8b05b772005-11-08 04:06:44 -06001322 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 SRpnt = NULL;
1324 printk(KERN_ERR "%s: Error on write filemark.\n", name);
1325 if (result == 0)
1326 result = (-EIO);
1327 }
1328
1329 DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n",
1330 name, cmd[4]));
1331 } else if (!STp->rew_at_close) {
1332 STps = &(STp->ps[STp->partition]);
1333 if (!STm->sysv || STps->rw != ST_READING) {
1334 if (STp->can_bsr)
1335 result = flush_buffer(STp, 0);
1336 else if (STps->eof == ST_FM_HIT) {
1337 result = cross_eof(STp, 0);
1338 if (result) {
1339 if (STps->drv_file >= 0)
1340 STps->drv_file++;
1341 STps->drv_block = 0;
1342 STps->eof = ST_FM;
1343 } else
1344 STps->eof = ST_NOEOF;
1345 }
1346 } else if ((STps->eof == ST_NOEOF &&
1347 !(result = cross_eof(STp, 1))) ||
1348 STps->eof == ST_FM_HIT) {
1349 if (STps->drv_file >= 0)
1350 STps->drv_file++;
1351 STps->drv_block = 0;
1352 STps->eof = ST_FM;
1353 }
1354 }
1355
1356 out:
1357 if (STp->rew_at_close) {
1358 result2 = st_int_ioctl(STp, MTREW, 1);
1359 if (result == 0)
1360 result = result2;
1361 }
1362 return result;
1363}
1364
1365
1366/* Close the device and release it. BKL is not needed: this is the only thread
1367 accessing this tape. */
1368static int st_release(struct inode *inode, struct file *filp)
1369{
1370 int result = 0;
1371 struct scsi_tape *STp = filp->private_data;
1372
1373 if (STp->door_locked == ST_LOCKED_AUTO)
1374 do_door_lock(STp, 0);
1375
1376 normalize_buffer(STp->buffer);
1377 write_lock(&st_dev_arr_lock);
1378 STp->in_use = 0;
1379 write_unlock(&st_dev_arr_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001380 scsi_tape_put(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
1382 return result;
1383}
1384
1385/* The checks common to both reading and writing */
1386static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count)
1387{
1388 ssize_t retval = 0;
1389
1390 /*
1391 * If we are in the middle of error recovery, don't let anyone
1392 * else try and use this device. Also, if error recovery fails, it
1393 * may try and take the device offline, in which case all further
1394 * access to the device is prohibited.
1395 */
1396 if (!scsi_block_when_processing_errors(STp->device)) {
1397 retval = (-ENXIO);
1398 goto out;
1399 }
1400
1401 if (STp->ready != ST_READY) {
1402 if (STp->ready == ST_NO_TAPE)
1403 retval = (-ENOMEDIUM);
1404 else
1405 retval = (-EIO);
1406 goto out;
1407 }
1408
1409 if (! STp->modes[STp->current_mode].defined) {
1410 retval = (-ENXIO);
1411 goto out;
1412 }
1413
1414
1415 /*
1416 * If there was a bus reset, block further access
1417 * to this device.
1418 */
1419 if (STp->pos_unknown) {
1420 retval = (-EIO);
1421 goto out;
1422 }
1423
1424 if (count == 0)
1425 goto out;
1426
1427 DEB(
1428 if (!STp->in_use) {
1429 printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp));
1430 retval = (-EIO);
1431 goto out;
1432 } ) /* end DEB */
1433
1434 if (STp->can_partitions &&
1435 (retval = switch_partition(STp)) < 0)
1436 goto out;
1437
1438 if (STp->block_size == 0 && STp->max_block > 0 &&
1439 (count < STp->min_block || count > STp->max_block)) {
1440 retval = (-EINVAL);
1441 goto out;
1442 }
1443
1444 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
1445 !do_door_lock(STp, 1))
1446 STp->door_locked = ST_LOCKED_AUTO;
1447
1448 out:
1449 return retval;
1450}
1451
1452
1453static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
1454 size_t count, int is_read)
1455{
1456 int i, bufsize, retval = 0;
1457 struct st_buffer *STbp = STp->buffer;
1458
1459 if (is_read)
Kai Makisara9abe16c2007-02-03 13:21:29 +02001460 i = STp->try_dio_now && try_rdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 else
Kai Makisara9abe16c2007-02-03 13:21:29 +02001462 i = STp->try_dio_now && try_wdio;
Mike Christie8b05b772005-11-08 04:06:44 -06001463
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 if (i && ((unsigned long)buf & queue_dma_alignment(
1465 STp->device->request_queue)) == 0) {
Mike Christie8b05b772005-11-08 04:06:44 -06001466 i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
1467 (unsigned long)buf, count, (is_read ? READ : WRITE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if (i > 0) {
1469 STbp->do_dio = i;
1470 STbp->buffer_bytes = 0; /* can be used as transfer counter */
1471 }
1472 else
1473 STbp->do_dio = 0; /* fall back to buffering with any error */
1474 STbp->sg_segs = STbp->do_dio;
1475 STbp->frp_sg_current = 0;
1476 DEB(
1477 if (STbp->do_dio) {
1478 STp->nbr_dio++;
1479 STp->nbr_pages += STbp->do_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 }
1481 )
1482 } else
1483 STbp->do_dio = 0;
1484 DEB( STp->nbr_requests++; )
1485
1486 if (!STbp->do_dio) {
1487 if (STp->block_size)
1488 bufsize = STp->block_size > st_fixed_buffer_size ?
1489 STp->block_size : st_fixed_buffer_size;
Kai Makisara40f6b362008-02-24 22:23:24 +02001490 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 bufsize = count;
Kai Makisara40f6b362008-02-24 22:23:24 +02001492 /* Make sure that data from previous user is not leaked even if
1493 HBA does not return correct residual */
1494 if (is_read && STp->sili && !STbp->cleared)
1495 clear_buffer(STbp);
1496 }
1497
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 if (bufsize > STbp->buffer_size &&
1499 !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
1500 printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
1501 tape_name(STp), bufsize);
1502 retval = (-EOVERFLOW);
1503 goto out;
1504 }
1505 if (STp->block_size)
1506 STbp->buffer_blocks = bufsize / STp->block_size;
1507 }
1508
1509 out:
1510 return retval;
1511}
1512
1513
1514/* Can be called more than once after each setup_buffer() */
Kai Makisara787926b2005-11-13 10:04:44 +02001515static void release_buffering(struct scsi_tape *STp, int is_read)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
1517 struct st_buffer *STbp;
1518
1519 STbp = STp->buffer;
1520 if (STbp->do_dio) {
Kai Makisara787926b2005-11-13 10:04:44 +02001521 sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 STbp->do_dio = 0;
Kai Makisara787926b2005-11-13 10:04:44 +02001523 STbp->sg_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
1525}
1526
1527
1528/* Write command */
1529static ssize_t
1530st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
1531{
1532 ssize_t total;
1533 ssize_t i, do_count, blks, transfer;
1534 ssize_t retval;
1535 int undone, retry_eot = 0, scode;
1536 int async_write;
1537 unsigned char cmd[MAX_COMMAND_SIZE];
1538 const char __user *b_point;
Mike Christie8b05b772005-11-08 04:06:44 -06001539 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 struct scsi_tape *STp = filp->private_data;
1541 struct st_modedef *STm;
1542 struct st_partstat *STps;
1543 struct st_buffer *STbp;
1544 char *name = tape_name(STp);
1545
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001546 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 return -ERESTARTSYS;
1548
1549 retval = rw_checks(STp, filp, count);
1550 if (retval || count == 0)
1551 goto out;
1552
1553 /* Write must be integral number of blocks */
1554 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
1555 printk(KERN_WARNING "%s: Write not multiple of tape block size.\n",
1556 name);
1557 retval = (-EINVAL);
1558 goto out;
1559 }
1560
1561 STm = &(STp->modes[STp->current_mode]);
1562 STps = &(STp->ps[STp->partition]);
1563
1564 if (STp->write_prot) {
1565 retval = (-EACCES);
1566 goto out;
1567 }
1568
1569
1570 if (STps->rw == ST_READING) {
1571 retval = flush_buffer(STp, 0);
1572 if (retval)
1573 goto out;
1574 STps->rw = ST_WRITING;
1575 } else if (STps->rw != ST_WRITING &&
1576 STps->drv_file == 0 && STps->drv_block == 0) {
1577 if ((retval = set_mode_densblk(STp, STm)) < 0)
1578 goto out;
1579 if (STm->default_compression != ST_DONT_TOUCH &&
1580 !(STp->compression_changed)) {
1581 if (st_compression(STp, (STm->default_compression == ST_YES))) {
1582 printk(KERN_WARNING "%s: Can't set default compression.\n",
1583 name);
1584 if (modes_defined) {
1585 retval = (-EINVAL);
1586 goto out;
1587 }
1588 }
1589 }
1590 }
1591
1592 STbp = STp->buffer;
1593 i = write_behind_check(STp);
1594 if (i) {
1595 if (i == -ENOSPC)
1596 STps->eof = ST_EOM_OK;
1597 else
1598 STps->eof = ST_EOM_ERROR;
1599 }
1600
1601 if (STps->eof == ST_EOM_OK) {
1602 STps->eof = ST_EOD_1; /* allow next write */
1603 retval = (-ENOSPC);
1604 goto out;
1605 }
1606 else if (STps->eof == ST_EOM_ERROR) {
1607 retval = (-EIO);
1608 goto out;
1609 }
1610
1611 /* Check the buffer readability in cases where copy_user might catch
1612 the problems after some tape movement. */
1613 if (STp->block_size != 0 &&
1614 !STbp->do_dio &&
1615 (copy_from_user(&i, buf, 1) != 0 ||
1616 copy_from_user(&i, buf + count - 1, 1) != 0)) {
1617 retval = (-EFAULT);
1618 goto out;
1619 }
1620
1621 retval = setup_buffering(STp, buf, count, 0);
1622 if (retval)
1623 goto out;
1624
1625 total = count;
1626
1627 memset(cmd, 0, MAX_COMMAND_SIZE);
1628 cmd[0] = WRITE_6;
1629 cmd[1] = (STp->block_size != 0);
1630
1631 STps->rw = ST_WRITING;
1632
1633 b_point = buf;
1634 while (count > 0 && !retry_eot) {
1635
1636 if (STbp->do_dio) {
1637 do_count = count;
1638 }
1639 else {
1640 if (STp->block_size == 0)
1641 do_count = count;
1642 else {
1643 do_count = STbp->buffer_blocks * STp->block_size -
1644 STbp->buffer_bytes;
1645 if (do_count > count)
1646 do_count = count;
1647 }
1648
1649 i = append_to_buffer(b_point, STbp, do_count);
1650 if (i) {
1651 retval = i;
1652 goto out;
1653 }
1654 }
1655 count -= do_count;
1656 b_point += do_count;
1657
1658 async_write = STp->block_size == 0 && !STbp->do_dio &&
1659 STm->do_async_writes && STps->eof < ST_EOM_OK;
1660
1661 if (STp->block_size != 0 && STm->do_buffer_writes &&
Kai Makisara9abe16c2007-02-03 13:21:29 +02001662 !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 STbp->buffer_bytes < STbp->buffer_size) {
1664 STp->dirty = 1;
1665 /* Don't write a buffer that is not full enough. */
1666 if (!async_write && count == 0)
1667 break;
1668 }
1669
1670 retry_write:
1671 if (STp->block_size == 0)
1672 blks = transfer = do_count;
1673 else {
1674 if (!STbp->do_dio)
1675 blks = STbp->buffer_bytes;
1676 else
1677 blks = do_count;
1678 blks /= STp->block_size;
1679 transfer = blks * STp->block_size;
1680 }
1681 cmd[2] = blks >> 16;
1682 cmd[3] = blks >> 8;
1683 cmd[4] = blks;
1684
1685 SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06001686 STp->device->request_queue->rq_timeout,
1687 MAX_WRITE_RETRIES, !async_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 if (!SRpnt) {
1689 retval = STbp->syscall_result;
1690 goto out;
1691 }
Mike Christie8b05b772005-11-08 04:06:44 -06001692 if (async_write && !STbp->syscall_result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 STbp->writing = transfer;
1694 STp->dirty = !(STbp->writing ==
1695 STbp->buffer_bytes);
1696 SRpnt = NULL; /* Prevent releasing this request! */
1697 DEB( STp->write_pending = 1; )
1698 break;
1699 }
1700
1701 if (STbp->syscall_result != 0) {
1702 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1703
1704 DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));
1705 if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) {
1706 scode = cmdstatp->sense_hdr.sense_key;
1707 if (cmdstatp->remainder_valid)
1708 undone = (int)cmdstatp->uremainder64;
1709 else if (STp->block_size == 0 &&
1710 scode == VOLUME_OVERFLOW)
1711 undone = transfer;
1712 else
1713 undone = 0;
1714 if (STp->block_size != 0)
1715 undone *= STp->block_size;
1716 if (undone <= do_count) {
1717 /* Only data from this write is not written */
1718 count += undone;
Kai Makisara626dcb12008-07-11 15:05:25 +03001719 b_point -= undone;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 do_count -= undone;
1721 if (STp->block_size)
1722 blks = (transfer - undone) / STp->block_size;
1723 STps->eof = ST_EOM_OK;
1724 /* Continue in fixed block mode if all written
1725 in this request but still something left to write
1726 (retval left to zero)
1727 */
1728 if (STp->block_size == 0 ||
1729 undone > 0 || count == 0)
1730 retval = (-ENOSPC); /* EOM within current request */
1731 DEBC(printk(ST_DEB_MSG
1732 "%s: EOM with %d bytes unwritten.\n",
1733 name, (int)count));
1734 } else {
1735 /* EOT within data buffered earlier (possible only
1736 in fixed block mode without direct i/o) */
1737 if (!retry_eot && !cmdstatp->deferred &&
1738 (scode == NO_SENSE || scode == RECOVERED_ERROR)) {
1739 move_buffer_data(STp->buffer, transfer - undone);
1740 retry_eot = 1;
1741 if (STps->drv_block >= 0) {
1742 STps->drv_block += (transfer - undone) /
1743 STp->block_size;
1744 }
1745 STps->eof = ST_EOM_OK;
1746 DEBC(printk(ST_DEB_MSG
1747 "%s: Retry write of %d bytes at EOM.\n",
1748 name, STp->buffer->buffer_bytes));
1749 goto retry_write;
1750 }
1751 else {
1752 /* Either error within data buffered by driver or
1753 failed retry */
1754 count -= do_count;
1755 blks = do_count = 0;
1756 STps->eof = ST_EOM_ERROR;
1757 STps->drv_block = (-1); /* Too cautious? */
1758 retval = (-EIO); /* EOM for old data */
1759 DEBC(printk(ST_DEB_MSG
1760 "%s: EOM with lost data.\n",
1761 name));
1762 }
1763 }
1764 } else {
1765 count += do_count;
1766 STps->drv_block = (-1); /* Too cautious? */
Mike Christie8b05b772005-11-08 04:06:44 -06001767 retval = STbp->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 }
1769
1770 }
1771
1772 if (STps->drv_block >= 0) {
1773 if (STp->block_size == 0)
1774 STps->drv_block += (do_count > 0);
1775 else
1776 STps->drv_block += blks;
1777 }
1778
1779 STbp->buffer_bytes = 0;
1780 STp->dirty = 0;
1781
1782 if (retval || retry_eot) {
1783 if (count < total)
1784 retval = total - count;
1785 goto out;
1786 }
1787 }
1788
1789 if (STps->eof == ST_EOD_1)
1790 STps->eof = ST_EOM_OK;
1791 else if (STps->eof != ST_EOM_OK)
1792 STps->eof = ST_NOEOF;
1793 retval = total - count;
1794
1795 out:
1796 if (SRpnt != NULL)
Mike Christie8b05b772005-11-08 04:06:44 -06001797 st_release_request(SRpnt);
Kai Makisara787926b2005-11-13 10:04:44 +02001798 release_buffering(STp, 0);
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001799 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
1801 return retval;
1802}
1803
1804/* Read data from the tape. Returns zero in the normal case, one if the
1805 eof status has changed, and the negative error code in case of a
1806 fatal error. Otherwise updates the buffer and the eof state.
1807
1808 Does release user buffer mapping if it is set.
1809*/
1810static long read_tape(struct scsi_tape *STp, long count,
Mike Christie8b05b772005-11-08 04:06:44 -06001811 struct st_request ** aSRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812{
1813 int transfer, blks, bytes;
1814 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06001815 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 struct st_modedef *STm;
1817 struct st_partstat *STps;
1818 struct st_buffer *STbp;
1819 int retval = 0;
1820 char *name = tape_name(STp);
1821
1822 if (count == 0)
1823 return 0;
1824
1825 STm = &(STp->modes[STp->current_mode]);
1826 STps = &(STp->ps[STp->partition]);
1827 if (STps->eof == ST_FM_HIT)
1828 return 1;
1829 STbp = STp->buffer;
1830
1831 if (STp->block_size == 0)
1832 blks = bytes = count;
1833 else {
Kai Makisara9abe16c2007-02-03 13:21:29 +02001834 if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 blks = (STp->buffer)->buffer_blocks;
1836 bytes = blks * STp->block_size;
1837 } else {
1838 bytes = count;
1839 if (!STbp->do_dio && bytes > (STp->buffer)->buffer_size)
1840 bytes = (STp->buffer)->buffer_size;
1841 blks = bytes / STp->block_size;
1842 bytes = blks * STp->block_size;
1843 }
1844 }
1845
1846 memset(cmd, 0, MAX_COMMAND_SIZE);
1847 cmd[0] = READ_6;
1848 cmd[1] = (STp->block_size != 0);
Kai Makisara40f6b362008-02-24 22:23:24 +02001849 if (!cmd[1] && STp->sili)
1850 cmd[1] |= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 cmd[2] = blks >> 16;
1852 cmd[3] = blks >> 8;
1853 cmd[4] = blks;
1854
1855 SRpnt = *aSRpnt;
1856 SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06001857 STp->device->request_queue->rq_timeout,
1858 MAX_RETRIES, 1);
Kai Makisara787926b2005-11-13 10:04:44 +02001859 release_buffering(STp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 *aSRpnt = SRpnt;
1861 if (!SRpnt)
1862 return STbp->syscall_result;
1863
1864 STbp->read_pointer = 0;
1865 STps->at_sm = 0;
1866
1867 /* Something to check */
1868 if (STbp->syscall_result) {
1869 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1870
1871 retval = 1;
1872 DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1873 name,
Mike Christie8b05b772005-11-08 04:06:44 -06001874 SRpnt->sense[0], SRpnt->sense[1],
1875 SRpnt->sense[2], SRpnt->sense[3],
1876 SRpnt->sense[4], SRpnt->sense[5],
1877 SRpnt->sense[6], SRpnt->sense[7]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 if (cmdstatp->have_sense) {
1879
1880 if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
1881 cmdstatp->flags &= 0xcf; /* No need for EOM in this case */
1882
1883 if (cmdstatp->flags != 0) { /* EOF, EOM, or ILI */
1884 /* Compute the residual count */
1885 if (cmdstatp->remainder_valid)
1886 transfer = (int)cmdstatp->uremainder64;
1887 else
1888 transfer = 0;
1889 if (STp->block_size == 0 &&
1890 cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR)
1891 transfer = bytes;
1892
1893 if (cmdstatp->flags & SENSE_ILI) { /* ILI */
1894 if (STp->block_size == 0) {
1895 if (transfer <= 0) {
1896 if (transfer < 0)
1897 printk(KERN_NOTICE
1898 "%s: Failed to read %d byte block with %d byte transfer.\n",
1899 name, bytes - transfer, bytes);
1900 if (STps->drv_block >= 0)
1901 STps->drv_block += 1;
1902 STbp->buffer_bytes = 0;
1903 return (-ENOMEM);
1904 }
1905 STbp->buffer_bytes = bytes - transfer;
1906 } else {
Mike Christie8b05b772005-11-08 04:06:44 -06001907 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 SRpnt = *aSRpnt = NULL;
1909 if (transfer == blks) { /* We did not get anything, error */
1910 printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
1911 if (STps->drv_block >= 0)
1912 STps->drv_block += blks - transfer + 1;
1913 st_int_ioctl(STp, MTBSR, 1);
1914 return (-EIO);
1915 }
1916 /* We have some data, deliver it */
1917 STbp->buffer_bytes = (blks - transfer) *
1918 STp->block_size;
1919 DEBC(printk(ST_DEB_MSG
1920 "%s: ILI but enough data received %ld %d.\n",
1921 name, count, STbp->buffer_bytes));
1922 if (STps->drv_block >= 0)
1923 STps->drv_block += 1;
1924 if (st_int_ioctl(STp, MTBSR, 1))
1925 return (-EIO);
1926 }
1927 } else if (cmdstatp->flags & SENSE_FMK) { /* FM overrides EOM */
1928 if (STps->eof != ST_FM_HIT)
1929 STps->eof = ST_FM_HIT;
1930 else
1931 STps->eof = ST_EOD_2;
1932 if (STp->block_size == 0)
1933 STbp->buffer_bytes = 0;
1934 else
1935 STbp->buffer_bytes =
1936 bytes - transfer * STp->block_size;
1937 DEBC(printk(ST_DEB_MSG
1938 "%s: EOF detected (%d bytes read).\n",
1939 name, STbp->buffer_bytes));
1940 } else if (cmdstatp->flags & SENSE_EOM) {
1941 if (STps->eof == ST_FM)
1942 STps->eof = ST_EOD_1;
1943 else
1944 STps->eof = ST_EOM_OK;
1945 if (STp->block_size == 0)
1946 STbp->buffer_bytes = bytes - transfer;
1947 else
1948 STbp->buffer_bytes =
1949 bytes - transfer * STp->block_size;
1950
1951 DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n",
1952 name, STbp->buffer_bytes));
1953 }
1954 }
1955 /* end of EOF, EOM, ILI test */
1956 else { /* nonzero sense key */
1957 DEBC(printk(ST_DEB_MSG
1958 "%s: Tape error while reading.\n", name));
1959 STps->drv_block = (-1);
1960 if (STps->eof == ST_FM &&
1961 cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {
1962 DEBC(printk(ST_DEB_MSG
1963 "%s: Zero returned for first BLANK CHECK after EOF.\n",
1964 name));
1965 STps->eof = ST_EOD_2; /* First BLANK_CHECK after FM */
1966 } else /* Some other extended sense code */
1967 retval = (-EIO);
1968 }
1969
1970 if (STbp->buffer_bytes < 0) /* Caused by bogus sense data */
1971 STbp->buffer_bytes = 0;
1972 }
1973 /* End of extended sense test */
1974 else { /* Non-extended sense */
1975 retval = STbp->syscall_result;
1976 }
1977
1978 }
1979 /* End of error handling */
Kai Makisara40f6b362008-02-24 22:23:24 +02001980 else { /* Read successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 STbp->buffer_bytes = bytes;
Kai Makisara40f6b362008-02-24 22:23:24 +02001982 if (STp->sili) /* In fixed block mode residual is always zero here */
1983 STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
1984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985
1986 if (STps->drv_block >= 0) {
1987 if (STp->block_size == 0)
1988 STps->drv_block++;
1989 else
1990 STps->drv_block += STbp->buffer_bytes / STp->block_size;
1991 }
1992 return retval;
1993}
1994
1995
1996/* Read command */
1997static ssize_t
1998st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
1999{
2000 ssize_t total;
2001 ssize_t retval = 0;
2002 ssize_t i, transfer;
2003 int special, do_dio = 0;
Mike Christie8b05b772005-11-08 04:06:44 -06002004 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 struct scsi_tape *STp = filp->private_data;
2006 struct st_modedef *STm;
2007 struct st_partstat *STps;
2008 struct st_buffer *STbp = STp->buffer;
2009 DEB( char *name = tape_name(STp); )
2010
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02002011 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 return -ERESTARTSYS;
2013
2014 retval = rw_checks(STp, filp, count);
2015 if (retval || count == 0)
2016 goto out;
2017
2018 STm = &(STp->modes[STp->current_mode]);
Kai Makisara9abe16c2007-02-03 13:21:29 +02002019 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
2020 if (!STm->do_read_ahead) {
2021 retval = (-EINVAL); /* Read must be integral number of blocks */
2022 goto out;
2023 }
2024 STp->try_dio_now = 0; /* Direct i/o can't handle split blocks */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 }
2026
2027 STps = &(STp->ps[STp->partition]);
2028 if (STps->rw == ST_WRITING) {
2029 retval = flush_buffer(STp, 0);
2030 if (retval)
2031 goto out;
2032 STps->rw = ST_READING;
2033 }
2034 DEB(
2035 if (debugging && STps->eof != ST_NOEOF)
2036 printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name,
2037 STps->eof, STbp->buffer_bytes);
2038 ) /* end DEB */
2039
2040 retval = setup_buffering(STp, buf, count, 1);
2041 if (retval)
2042 goto out;
2043 do_dio = STbp->do_dio;
2044
2045 if (STbp->buffer_bytes == 0 &&
2046 STps->eof >= ST_EOD_1) {
2047 if (STps->eof < ST_EOD) {
2048 STps->eof += 1;
2049 retval = 0;
2050 goto out;
2051 }
2052 retval = (-EIO); /* EOM or Blank Check */
2053 goto out;
2054 }
2055
2056 if (do_dio) {
2057 /* Check the buffer writability before any tape movement. Don't alter
2058 buffer data. */
2059 if (copy_from_user(&i, buf, 1) != 0 ||
2060 copy_to_user(buf, &i, 1) != 0 ||
2061 copy_from_user(&i, buf + count - 1, 1) != 0 ||
2062 copy_to_user(buf + count - 1, &i, 1) != 0) {
2063 retval = (-EFAULT);
2064 goto out;
2065 }
2066 }
2067
2068 STps->rw = ST_READING;
2069
2070
2071 /* Loop until enough data in buffer or a special condition found */
2072 for (total = 0, special = 0; total < count && !special;) {
2073
2074 /* Get new data if the buffer is empty */
2075 if (STbp->buffer_bytes == 0) {
2076 special = read_tape(STp, count - total, &SRpnt);
2077 if (special < 0) { /* No need to continue read */
2078 retval = special;
2079 goto out;
2080 }
2081 }
2082
2083 /* Move the data from driver buffer to user buffer */
2084 if (STbp->buffer_bytes > 0) {
2085 DEB(
2086 if (debugging && STps->eof != ST_NOEOF)
2087 printk(ST_DEB_MSG
2088 "%s: EOF up (%d). Left %d, needed %d.\n", name,
2089 STps->eof, STbp->buffer_bytes,
2090 (int)(count - total));
2091 ) /* end DEB */
2092 transfer = STbp->buffer_bytes < count - total ?
2093 STbp->buffer_bytes : count - total;
2094 if (!do_dio) {
2095 i = from_buffer(STbp, buf, transfer);
2096 if (i) {
2097 retval = i;
2098 goto out;
2099 }
2100 }
2101 buf += transfer;
2102 total += transfer;
2103 }
2104
2105 if (STp->block_size == 0)
2106 break; /* Read only one variable length block */
2107
2108 } /* for (total = 0, special = 0;
2109 total < count && !special; ) */
2110
2111 /* Change the eof state if no data from tape or buffer */
2112 if (total == 0) {
2113 if (STps->eof == ST_FM_HIT) {
2114 STps->eof = ST_FM;
2115 STps->drv_block = 0;
2116 if (STps->drv_file >= 0)
2117 STps->drv_file++;
2118 } else if (STps->eof == ST_EOD_1) {
2119 STps->eof = ST_EOD_2;
2120 STps->drv_block = 0;
2121 if (STps->drv_file >= 0)
2122 STps->drv_file++;
2123 } else if (STps->eof == ST_EOD_2)
2124 STps->eof = ST_EOD;
2125 } else if (STps->eof == ST_FM)
2126 STps->eof = ST_NOEOF;
2127 retval = total;
2128
2129 out:
2130 if (SRpnt != NULL) {
Mike Christie8b05b772005-11-08 04:06:44 -06002131 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 SRpnt = NULL;
2133 }
2134 if (do_dio) {
Kai Makisara787926b2005-11-13 10:04:44 +02002135 release_buffering(STp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 STbp->buffer_bytes = 0;
2137 }
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02002138 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
2140 return retval;
2141}
2142
2143
2144
2145DEB(
2146/* Set the driver options */
2147static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name)
2148{
2149 if (debugging) {
2150 printk(KERN_INFO
2151 "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
2152 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
2153 STm->do_read_ahead);
2154 printk(KERN_INFO
2155 "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
2156 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
2157 printk(KERN_INFO
2158 "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
2159 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
2160 STp->scsi2_logical);
2161 printk(KERN_INFO
Kai Makisara40f6b362008-02-24 22:23:24 +02002162 "%s: sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate,
2163 STp->sili);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 printk(KERN_INFO "%s: debugging: %d\n",
2165 name, debugging);
2166 }
2167}
2168 )
2169
2170
2171static int st_set_options(struct scsi_tape *STp, long options)
2172{
2173 int value;
2174 long code;
2175 struct st_modedef *STm;
2176 char *name = tape_name(STp);
2177 struct cdev *cd0, *cd1;
2178
2179 STm = &(STp->modes[STp->current_mode]);
2180 if (!STm->defined) {
2181 cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1];
2182 memcpy(STm, &(STp->modes[0]), sizeof(struct st_modedef));
2183 STm->cdevs[0] = cd0; STm->cdevs[1] = cd1;
2184 modes_defined = 1;
2185 DEBC(printk(ST_DEB_MSG
2186 "%s: Initialized mode %d definition from mode 0\n",
2187 name, STp->current_mode));
2188 }
2189
2190 code = options & MT_ST_OPTIONS;
2191 if (code == MT_ST_BOOLEANS) {
2192 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
2193 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
2194 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
2195 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
2196 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
2197 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
2198 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
2199 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
2200 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
2201 if ((STp->device)->scsi_level >= SCSI_2)
2202 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
2203 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
2204 STp->immediate = (options & MT_ST_NOWAIT) != 0;
2205 STm->sysv = (options & MT_ST_SYSV) != 0;
Kai Makisara40f6b362008-02-24 22:23:24 +02002206 STp->sili = (options & MT_ST_SILI) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
2208 st_log_options(STp, STm, name); )
2209 } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
2210 value = (code == MT_ST_SETBOOLEANS);
2211 if ((options & MT_ST_BUFFER_WRITES) != 0)
2212 STm->do_buffer_writes = value;
2213 if ((options & MT_ST_ASYNC_WRITES) != 0)
2214 STm->do_async_writes = value;
2215 if ((options & MT_ST_DEF_WRITES) != 0)
2216 STm->defaults_for_writes = value;
2217 if ((options & MT_ST_READ_AHEAD) != 0)
2218 STm->do_read_ahead = value;
2219 if ((options & MT_ST_TWO_FM) != 0)
2220 STp->two_fm = value;
2221 if ((options & MT_ST_FAST_MTEOM) != 0)
2222 STp->fast_mteom = value;
2223 if ((options & MT_ST_AUTO_LOCK) != 0)
2224 STp->do_auto_lock = value;
2225 if ((options & MT_ST_CAN_BSR) != 0)
2226 STp->can_bsr = value;
2227 if ((options & MT_ST_NO_BLKLIMS) != 0)
2228 STp->omit_blklims = value;
2229 if ((STp->device)->scsi_level >= SCSI_2 &&
2230 (options & MT_ST_CAN_PARTITIONS) != 0)
2231 STp->can_partitions = value;
2232 if ((options & MT_ST_SCSI2LOGICAL) != 0)
2233 STp->scsi2_logical = value;
2234 if ((options & MT_ST_NOWAIT) != 0)
2235 STp->immediate = value;
2236 if ((options & MT_ST_SYSV) != 0)
2237 STm->sysv = value;
Kai Makisara40f6b362008-02-24 22:23:24 +02002238 if ((options & MT_ST_SILI) != 0)
2239 STp->sili = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 DEB(
2241 if ((options & MT_ST_DEBUGGING) != 0)
2242 debugging = value;
2243 st_log_options(STp, STm, name); )
2244 } else if (code == MT_ST_WRITE_THRESHOLD) {
2245 /* Retained for compatibility */
2246 } else if (code == MT_ST_DEF_BLKSIZE) {
2247 value = (options & ~MT_ST_OPTIONS);
2248 if (value == ~MT_ST_OPTIONS) {
2249 STm->default_blksize = (-1);
2250 DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name));
2251 } else {
2252 STm->default_blksize = value;
2253 DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n",
2254 name, STm->default_blksize));
2255 if (STp->ready == ST_READY) {
2256 STp->blksize_changed = 0;
2257 set_mode_densblk(STp, STm);
2258 }
2259 }
2260 } else if (code == MT_ST_TIMEOUTS) {
2261 value = (options & ~MT_ST_OPTIONS);
2262 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
2263 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
2264 DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name,
2265 (value & ~MT_ST_SET_LONG_TIMEOUT)));
2266 } else {
James Bottomleya02488e2008-11-30 10:36:26 -06002267 blk_queue_rq_timeout(STp->device->request_queue,
2268 value * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n",
2270 name, value) );
2271 }
2272 } else if (code == MT_ST_SET_CLN) {
2273 value = (options & ~MT_ST_OPTIONS) & 0xff;
2274 if (value != 0 &&
2275 value < EXTENDED_SENSE_START && value >= SCSI_SENSE_BUFFERSIZE)
2276 return (-EINVAL);
2277 STp->cln_mode = value;
2278 STp->cln_sense_mask = (options >> 8) & 0xff;
2279 STp->cln_sense_value = (options >> 16) & 0xff;
2280 printk(KERN_INFO
2281 "%s: Cleaning request mode %d, mask %02x, value %02x\n",
2282 name, value, STp->cln_sense_mask, STp->cln_sense_value);
2283 } else if (code == MT_ST_DEF_OPTIONS) {
2284 code = (options & ~MT_ST_CLEAR_DEFAULT);
2285 value = (options & MT_ST_CLEAR_DEFAULT);
2286 if (code == MT_ST_DEF_DENSITY) {
2287 if (value == MT_ST_CLEAR_DEFAULT) {
2288 STm->default_density = (-1);
2289 DEBC( printk(KERN_INFO "%s: Density default disabled.\n",
2290 name));
2291 } else {
2292 STm->default_density = value & 0xff;
2293 DEBC( printk(KERN_INFO "%s: Density default set to %x\n",
2294 name, STm->default_density));
2295 if (STp->ready == ST_READY) {
2296 STp->density_changed = 0;
2297 set_mode_densblk(STp, STm);
2298 }
2299 }
2300 } else if (code == MT_ST_DEF_DRVBUFFER) {
2301 if (value == MT_ST_CLEAR_DEFAULT) {
2302 STp->default_drvbuffer = 0xff;
2303 DEBC( printk(KERN_INFO
2304 "%s: Drive buffer default disabled.\n", name));
2305 } else {
2306 STp->default_drvbuffer = value & 7;
2307 DEBC( printk(KERN_INFO
2308 "%s: Drive buffer default set to %x\n",
2309 name, STp->default_drvbuffer));
2310 if (STp->ready == ST_READY)
2311 st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer);
2312 }
2313 } else if (code == MT_ST_DEF_COMPRESSION) {
2314 if (value == MT_ST_CLEAR_DEFAULT) {
2315 STm->default_compression = ST_DONT_TOUCH;
2316 DEBC( printk(KERN_INFO
2317 "%s: Compression default disabled.\n", name));
2318 } else {
2319 if ((value & 0xff00) != 0) {
2320 STp->c_algo = (value & 0xff00) >> 8;
2321 DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n",
2322 name, STp->c_algo));
2323 }
2324 if ((value & 0xff) != 0xff) {
2325 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
2326 DEBC( printk(KERN_INFO "%s: Compression default set to %x\n",
2327 name, (value & 1)));
2328 if (STp->ready == ST_READY) {
2329 STp->compression_changed = 0;
2330 st_compression(STp, (STm->default_compression == ST_YES));
2331 }
2332 }
2333 }
2334 }
2335 } else
2336 return (-EIO);
2337
2338 return 0;
2339}
2340
2341#define MODE_HEADER_LENGTH 4
2342
2343/* Mode header and page byte offsets */
2344#define MH_OFF_DATA_LENGTH 0
2345#define MH_OFF_MEDIUM_TYPE 1
2346#define MH_OFF_DEV_SPECIFIC 2
2347#define MH_OFF_BDESCS_LENGTH 3
2348#define MP_OFF_PAGE_NBR 0
2349#define MP_OFF_PAGE_LENGTH 1
2350
2351/* Mode header and page bit masks */
2352#define MH_BIT_WP 0x80
2353#define MP_MSK_PAGE_NBR 0x3f
2354
2355/* Don't return block descriptors */
2356#define MODE_SENSE_OMIT_BDESCS 0x08
2357
2358#define MODE_SELECT_PAGE_FORMAT 0x10
2359
2360/* Read a mode page into the tape buffer. The block descriptors are included
2361 if incl_block_descs is true. The page control is ored to the page number
2362 parameter, if necessary. */
2363static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
2364{
2365 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002366 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
2368 memset(cmd, 0, MAX_COMMAND_SIZE);
2369 cmd[0] = MODE_SENSE;
2370 if (omit_block_descs)
2371 cmd[1] = MODE_SENSE_OMIT_BDESCS;
2372 cmd[2] = page;
2373 cmd[4] = 255;
2374
2375 SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06002376 STp->device->request_queue->rq_timeout, 0, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 if (SRpnt == NULL)
2378 return (STp->buffer)->syscall_result;
2379
Mike Christie8b05b772005-11-08 04:06:44 -06002380 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
2382 return (STp->buffer)->syscall_result;
2383}
2384
2385
2386/* Send the mode page in the tape buffer to the drive. Assumes that the mode data
2387 in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */
2388static int write_mode_page(struct scsi_tape *STp, int page, int slow)
2389{
2390 int pgo;
2391 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002392 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393
2394 memset(cmd, 0, MAX_COMMAND_SIZE);
2395 cmd[0] = MODE_SELECT;
2396 cmd[1] = MODE_SELECT_PAGE_FORMAT;
2397 pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH];
2398 cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2;
2399
2400 /* Clear reserved fields */
2401 (STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0;
2402 (STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0;
2403 (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
2404 (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
2405
2406 SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06002407 (slow ? STp->long_timeout : STp->device->request_queue->rq_timeout), 0, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 if (SRpnt == NULL)
2409 return (STp->buffer)->syscall_result;
2410
Mike Christie8b05b772005-11-08 04:06:44 -06002411 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
2413 return (STp->buffer)->syscall_result;
2414}
2415
2416
2417#define COMPRESSION_PAGE 0x0f
2418#define COMPRESSION_PAGE_LENGTH 16
2419
2420#define CP_OFF_DCE_DCC 2
2421#define CP_OFF_C_ALGO 7
2422
2423#define DCE_MASK 0x80
2424#define DCC_MASK 0x40
2425#define RED_MASK 0x60
2426
2427
2428/* Control the compression with mode page 15. Algorithm not changed if zero.
2429
2430 The block descriptors are read and written because Sony SDT-7000 does not
2431 work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
2432 Including block descriptors should not cause any harm to other drives. */
2433
2434static int st_compression(struct scsi_tape * STp, int state)
2435{
2436 int retval;
2437 int mpoffs; /* Offset to mode page start */
2438 unsigned char *b_data = (STp->buffer)->b_data;
2439 DEB( char *name = tape_name(STp); )
2440
2441 if (STp->ready != ST_READY)
2442 return (-EIO);
2443
2444 /* Read the current page contents */
2445 retval = read_mode_page(STp, COMPRESSION_PAGE, 0);
2446 if (retval) {
2447 DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n",
2448 name));
2449 return (-EIO);
2450 }
2451
2452 mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH];
2453 DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name,
2454 (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
2455
2456 /* Check if compression can be changed */
2457 if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) {
2458 DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name));
2459 return (-EIO);
2460 }
2461
2462 /* Do the change */
2463 if (state) {
2464 b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK;
2465 if (STp->c_algo != 0)
2466 b_data[mpoffs + CP_OFF_C_ALGO] = STp->c_algo;
2467 }
2468 else {
2469 b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK;
2470 if (STp->c_algo != 0)
2471 b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */
2472 }
2473
2474 retval = write_mode_page(STp, COMPRESSION_PAGE, 0);
2475 if (retval) {
2476 DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name));
2477 return (-EIO);
2478 }
2479 DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n",
2480 name, state));
2481
2482 STp->compression_changed = 1;
2483 return 0;
2484}
2485
2486
2487/* Process the load and unload commands (does unload if the load code is zero) */
2488static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code)
2489{
2490 int retval = (-EIO), timeout;
2491 DEB( char *name = tape_name(STp); )
2492 unsigned char cmd[MAX_COMMAND_SIZE];
2493 struct st_partstat *STps;
Mike Christie8b05b772005-11-08 04:06:44 -06002494 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
2496 if (STp->ready != ST_READY && !load_code) {
2497 if (STp->ready == ST_NO_TAPE)
2498 return (-ENOMEDIUM);
2499 else
2500 return (-EIO);
2501 }
2502
2503 memset(cmd, 0, MAX_COMMAND_SIZE);
2504 cmd[0] = START_STOP;
2505 if (load_code)
2506 cmd[4] |= 1;
2507 /*
2508 * If arg >= 1 && arg <= 6 Enhanced load/unload in HP C1553A
2509 */
2510 if (load_code >= 1 + MT_ST_HPLOADER_OFFSET
2511 && load_code <= 6 + MT_ST_HPLOADER_OFFSET) {
2512 DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n",
2513 name, (cmd[4]) ? "" : "un",
2514 load_code - MT_ST_HPLOADER_OFFSET));
2515 cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
2516 }
2517 if (STp->immediate) {
2518 cmd[1] = 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002519 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 }
2521 else
2522 timeout = STp->long_timeout;
2523
2524 DEBC(
2525 if (!load_code)
2526 printk(ST_DEB_MSG "%s: Unloading tape.\n", name);
2527 else
2528 printk(ST_DEB_MSG "%s: Loading tape.\n", name);
2529 );
2530
FUJITA Tomonori15c920a2008-12-05 15:25:24 +09002531 SRpnt = st_allocate_request(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 if (!SRpnt)
FUJITA Tomonori15c920a2008-12-05 15:25:24 +09002533 return STp->buffer->syscall_result;
2534
2535 retval = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0, timeout,
2536 MAX_RETRIES);
2537 if (retval)
2538 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
2540 retval = (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
2542 if (!retval) { /* SCSI command successful */
2543
2544 if (!load_code) {
2545 STp->rew_at_close = 0;
2546 STp->ready = ST_NO_TAPE;
2547 }
2548 else {
2549 STp->rew_at_close = STp->autorew_dev;
2550 retval = check_tape(STp, filp);
2551 if (retval > 0)
2552 retval = 0;
2553 }
2554 }
2555 else {
2556 STps = &(STp->ps[STp->partition]);
2557 STps->drv_file = STps->drv_block = (-1);
2558 }
FUJITA Tomonori15c920a2008-12-05 15:25:24 +09002559out:
2560 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
2562 return retval;
2563}
2564
2565#if DEBUG
2566#define ST_DEB_FORWARD 0
2567#define ST_DEB_BACKWARD 1
2568static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd)
2569{
2570 s32 sc;
2571
2572 sc = cmd[2] & 0x80 ? 0xff000000 : 0;
2573 sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
2574 if (direction)
2575 sc = -sc;
2576 printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name,
2577 direction ? "backward" : "forward", sc, units);
2578}
2579#endif
2580
2581
2582/* Internal ioctl function */
2583static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned long arg)
2584{
2585 int timeout;
2586 long ltmp;
2587 int ioctl_result;
2588 int chg_eof = 1;
2589 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002590 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 struct st_partstat *STps;
2592 int fileno, blkno, at_sm, undone;
2593 int datalen = 0, direction = DMA_NONE;
2594 char *name = tape_name(STp);
2595
2596 WARN_ON(STp->buffer->do_dio != 0);
2597 if (STp->ready != ST_READY) {
2598 if (STp->ready == ST_NO_TAPE)
2599 return (-ENOMEDIUM);
2600 else
2601 return (-EIO);
2602 }
2603 timeout = STp->long_timeout;
2604 STps = &(STp->ps[STp->partition]);
2605 fileno = STps->drv_file;
2606 blkno = STps->drv_block;
2607 at_sm = STps->at_sm;
2608
2609 memset(cmd, 0, MAX_COMMAND_SIZE);
2610 switch (cmd_in) {
2611 case MTFSFM:
2612 chg_eof = 0; /* Changed from the FSF after this */
2613 case MTFSF:
2614 cmd[0] = SPACE;
2615 cmd[1] = 0x01; /* Space FileMarks */
2616 cmd[2] = (arg >> 16);
2617 cmd[3] = (arg >> 8);
2618 cmd[4] = arg;
2619 DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);)
2620 if (fileno >= 0)
2621 fileno += arg;
2622 blkno = 0;
2623 at_sm &= (arg == 0);
2624 break;
2625 case MTBSFM:
2626 chg_eof = 0; /* Changed from the FSF after this */
2627 case MTBSF:
2628 cmd[0] = SPACE;
2629 cmd[1] = 0x01; /* Space FileMarks */
2630 ltmp = (-arg);
2631 cmd[2] = (ltmp >> 16);
2632 cmd[3] = (ltmp >> 8);
2633 cmd[4] = ltmp;
2634 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);)
2635 if (fileno >= 0)
2636 fileno -= arg;
2637 blkno = (-1); /* We can't know the block number */
2638 at_sm &= (arg == 0);
2639 break;
2640 case MTFSR:
2641 cmd[0] = SPACE;
2642 cmd[1] = 0x00; /* Space Blocks */
2643 cmd[2] = (arg >> 16);
2644 cmd[3] = (arg >> 8);
2645 cmd[4] = arg;
2646 DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);)
2647 if (blkno >= 0)
2648 blkno += arg;
2649 at_sm &= (arg == 0);
2650 break;
2651 case MTBSR:
2652 cmd[0] = SPACE;
2653 cmd[1] = 0x00; /* Space Blocks */
2654 ltmp = (-arg);
2655 cmd[2] = (ltmp >> 16);
2656 cmd[3] = (ltmp >> 8);
2657 cmd[4] = ltmp;
2658 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);)
2659 if (blkno >= 0)
2660 blkno -= arg;
2661 at_sm &= (arg == 0);
2662 break;
2663 case MTFSS:
2664 cmd[0] = SPACE;
2665 cmd[1] = 0x04; /* Space Setmarks */
2666 cmd[2] = (arg >> 16);
2667 cmd[3] = (arg >> 8);
2668 cmd[4] = arg;
2669 DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);)
2670 if (arg != 0) {
2671 blkno = fileno = (-1);
2672 at_sm = 1;
2673 }
2674 break;
2675 case MTBSS:
2676 cmd[0] = SPACE;
2677 cmd[1] = 0x04; /* Space Setmarks */
2678 ltmp = (-arg);
2679 cmd[2] = (ltmp >> 16);
2680 cmd[3] = (ltmp >> 8);
2681 cmd[4] = ltmp;
2682 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);)
2683 if (arg != 0) {
2684 blkno = fileno = (-1);
2685 at_sm = 1;
2686 }
2687 break;
2688 case MTWEOF:
2689 case MTWSM:
2690 if (STp->write_prot)
2691 return (-EACCES);
2692 cmd[0] = WRITE_FILEMARKS;
2693 if (cmd_in == MTWSM)
2694 cmd[1] = 2;
2695 cmd[2] = (arg >> 16);
2696 cmd[3] = (arg >> 8);
2697 cmd[4] = arg;
James Bottomleya02488e2008-11-30 10:36:26 -06002698 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 DEBC(
2700 if (cmd_in == MTWEOF)
2701 printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
2702 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
2703 else
2704 printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name,
2705 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
2706 )
2707 if (fileno >= 0)
2708 fileno += arg;
2709 blkno = 0;
2710 at_sm = (cmd_in == MTWSM);
2711 break;
2712 case MTREW:
2713 cmd[0] = REZERO_UNIT;
2714 if (STp->immediate) {
2715 cmd[1] = 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002716 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
2718 DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name));
2719 fileno = blkno = at_sm = 0;
2720 break;
2721 case MTNOP:
2722 DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name));
2723 return 0; /* Should do something ? */
2724 break;
2725 case MTRETEN:
2726 cmd[0] = START_STOP;
2727 if (STp->immediate) {
2728 cmd[1] = 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002729 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 }
2731 cmd[4] = 3;
2732 DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name));
2733 fileno = blkno = at_sm = 0;
2734 break;
2735 case MTEOM:
2736 if (!STp->fast_mteom) {
2737 /* space to the end of tape */
2738 ioctl_result = st_int_ioctl(STp, MTFSF, 0x7fffff);
2739 fileno = STps->drv_file;
2740 if (STps->eof >= ST_EOD_1)
2741 return 0;
2742 /* The next lines would hide the number of spaced FileMarks
2743 That's why I inserted the previous lines. I had no luck
2744 with detecting EOM with FSF, so we go now to EOM.
2745 Joerg Weule */
2746 } else
2747 fileno = (-1);
2748 cmd[0] = SPACE;
2749 cmd[1] = 3;
2750 DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n",
2751 name));
2752 blkno = -1;
2753 at_sm = 0;
2754 break;
2755 case MTERASE:
2756 if (STp->write_prot)
2757 return (-EACCES);
2758 cmd[0] = ERASE;
2759 cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */
2760 if (STp->immediate) {
2761 cmd[1] |= 2; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002762 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 }
2764 else
2765 timeout = STp->long_timeout * 8;
2766
2767 DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name));
2768 fileno = blkno = at_sm = 0;
2769 break;
2770 case MTSETBLK: /* Set block length */
2771 case MTSETDENSITY: /* Set tape density */
2772 case MTSETDRVBUFFER: /* Set drive buffering */
2773 case SET_DENS_AND_BLK: /* Set density and block size */
2774 chg_eof = 0;
2775 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
2776 return (-EIO); /* Not allowed if data in buffer */
2777 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
2778 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
2779 STp->max_block > 0 &&
2780 ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
2781 (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) {
2782 printk(KERN_WARNING "%s: Illegal block size.\n", name);
2783 return (-EINVAL);
2784 }
2785 cmd[0] = MODE_SELECT;
2786 if ((STp->use_pf & USE_PF))
2787 cmd[1] = MODE_SELECT_PAGE_FORMAT;
2788 cmd[4] = datalen = 12;
2789 direction = DMA_TO_DEVICE;
2790
2791 memset((STp->buffer)->b_data, 0, 12);
2792 if (cmd_in == MTSETDRVBUFFER)
2793 (STp->buffer)->b_data[2] = (arg & 7) << 4;
2794 else
2795 (STp->buffer)->b_data[2] =
2796 STp->drv_buffer << 4;
2797 (STp->buffer)->b_data[3] = 8; /* block descriptor length */
2798 if (cmd_in == MTSETDENSITY) {
2799 (STp->buffer)->b_data[4] = arg;
2800 STp->density_changed = 1; /* At least we tried ;-) */
2801 } else if (cmd_in == SET_DENS_AND_BLK)
2802 (STp->buffer)->b_data[4] = arg >> 24;
2803 else
2804 (STp->buffer)->b_data[4] = STp->density;
2805 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
2806 ltmp = arg & MT_ST_BLKSIZE_MASK;
2807 if (cmd_in == MTSETBLK)
2808 STp->blksize_changed = 1; /* At least we tried ;-) */
2809 } else
2810 ltmp = STp->block_size;
2811 (STp->buffer)->b_data[9] = (ltmp >> 16);
2812 (STp->buffer)->b_data[10] = (ltmp >> 8);
2813 (STp->buffer)->b_data[11] = ltmp;
James Bottomleya02488e2008-11-30 10:36:26 -06002814 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 DEBC(
2816 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
2817 printk(ST_DEB_MSG
2818 "%s: Setting block size to %d bytes.\n", name,
2819 (STp->buffer)->b_data[9] * 65536 +
2820 (STp->buffer)->b_data[10] * 256 +
2821 (STp->buffer)->b_data[11]);
2822 if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK)
2823 printk(ST_DEB_MSG
2824 "%s: Setting density code to %x.\n", name,
2825 (STp->buffer)->b_data[4]);
2826 if (cmd_in == MTSETDRVBUFFER)
2827 printk(ST_DEB_MSG
2828 "%s: Setting drive buffer code to %d.\n", name,
2829 ((STp->buffer)->b_data[2] >> 4) & 7);
2830 )
2831 break;
2832 default:
2833 return (-ENOSYS);
2834 }
2835
2836 SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction,
2837 timeout, MAX_RETRIES, 1);
2838 if (!SRpnt)
2839 return (STp->buffer)->syscall_result;
2840
2841 ioctl_result = (STp->buffer)->syscall_result;
2842
2843 if (!ioctl_result) { /* SCSI command successful */
Mike Christie8b05b772005-11-08 04:06:44 -06002844 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 SRpnt = NULL;
2846 STps->drv_block = blkno;
2847 STps->drv_file = fileno;
2848 STps->at_sm = at_sm;
2849
2850 if (cmd_in == MTBSFM)
2851 ioctl_result = st_int_ioctl(STp, MTFSF, 1);
2852 else if (cmd_in == MTFSFM)
2853 ioctl_result = st_int_ioctl(STp, MTBSF, 1);
2854
2855 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
2856 int old_block_size = STp->block_size;
2857 STp->block_size = arg & MT_ST_BLKSIZE_MASK;
2858 if (STp->block_size != 0) {
2859 if (old_block_size == 0)
2860 normalize_buffer(STp->buffer);
2861 (STp->buffer)->buffer_blocks =
2862 (STp->buffer)->buffer_size / STp->block_size;
2863 }
2864 (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
2865 if (cmd_in == SET_DENS_AND_BLK)
2866 STp->density = arg >> MT_ST_DENSITY_SHIFT;
2867 } else if (cmd_in == MTSETDRVBUFFER)
2868 STp->drv_buffer = (arg & 7);
2869 else if (cmd_in == MTSETDENSITY)
2870 STp->density = arg;
2871
2872 if (cmd_in == MTEOM)
2873 STps->eof = ST_EOD;
2874 else if (cmd_in == MTFSF)
2875 STps->eof = ST_FM;
2876 else if (chg_eof)
2877 STps->eof = ST_NOEOF;
2878
2879 if (cmd_in == MTWEOF)
2880 STps->rw = ST_IDLE;
2881 } else { /* SCSI command was not completely successful. Don't return
2882 from this block without releasing the SCSI command block! */
2883 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
2884
2885 if (cmdstatp->flags & SENSE_EOM) {
2886 if (cmd_in != MTBSF && cmd_in != MTBSFM &&
2887 cmd_in != MTBSR && cmd_in != MTBSS)
2888 STps->eof = ST_EOM_OK;
2889 STps->drv_block = 0;
2890 }
2891
2892 if (cmdstatp->remainder_valid)
2893 undone = (int)cmdstatp->uremainder64;
2894 else
2895 undone = 0;
2896
2897 if (cmd_in == MTWEOF &&
2898 cmdstatp->have_sense &&
Kai Makisara91614c02007-01-26 00:38:39 +02002899 (cmdstatp->flags & SENSE_EOM)) {
2900 if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
2901 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
2902 ioctl_result = 0; /* EOF(s) written successfully at EOM */
2903 STps->eof = ST_NOEOF;
2904 } else { /* Writing EOF(s) failed */
2905 if (fileno >= 0)
2906 fileno -= undone;
2907 if (undone < arg)
2908 STps->eof = ST_NOEOF;
2909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 STps->drv_file = fileno;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 } else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
2912 if (fileno >= 0)
2913 STps->drv_file = fileno - undone;
2914 else
2915 STps->drv_file = fileno;
2916 STps->drv_block = -1;
2917 STps->eof = ST_NOEOF;
2918 } else if ((cmd_in == MTBSF) || (cmd_in == MTBSFM)) {
2919 if (arg > 0 && undone < 0) /* Some drives get this wrong */
2920 undone = (-undone);
2921 if (STps->drv_file >= 0)
2922 STps->drv_file = fileno + undone;
2923 STps->drv_block = 0;
2924 STps->eof = ST_NOEOF;
2925 } else if (cmd_in == MTFSR) {
2926 if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
2927 if (STps->drv_file >= 0)
2928 STps->drv_file++;
2929 STps->drv_block = 0;
2930 STps->eof = ST_FM;
2931 } else {
2932 if (blkno >= undone)
2933 STps->drv_block = blkno - undone;
2934 else
2935 STps->drv_block = (-1);
2936 STps->eof = ST_NOEOF;
2937 }
2938 } else if (cmd_in == MTBSR) {
2939 if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
2940 STps->drv_file--;
2941 STps->drv_block = (-1);
2942 } else {
2943 if (arg > 0 && undone < 0) /* Some drives get this wrong */
2944 undone = (-undone);
2945 if (STps->drv_block >= 0)
2946 STps->drv_block = blkno + undone;
2947 }
2948 STps->eof = ST_NOEOF;
2949 } else if (cmd_in == MTEOM) {
2950 STps->drv_file = (-1);
2951 STps->drv_block = (-1);
2952 STps->eof = ST_EOD;
2953 } else if (cmd_in == MTSETBLK ||
2954 cmd_in == MTSETDENSITY ||
2955 cmd_in == MTSETDRVBUFFER ||
2956 cmd_in == SET_DENS_AND_BLK) {
2957 if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST &&
2958 !(STp->use_pf & PF_TESTED)) {
2959 /* Try the other possible state of Page Format if not
2960 already tried */
2961 STp->use_pf = !STp->use_pf | PF_TESTED;
Mike Christie8b05b772005-11-08 04:06:44 -06002962 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 SRpnt = NULL;
2964 return st_int_ioctl(STp, cmd_in, arg);
2965 }
2966 } else if (chg_eof)
2967 STps->eof = ST_NOEOF;
2968
2969 if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
2970 STps->eof = ST_EOD;
2971
Mike Christie8b05b772005-11-08 04:06:44 -06002972 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 SRpnt = NULL;
2974 }
2975
2976 return ioctl_result;
2977}
2978
2979
2980/* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
2981 structure. */
2982
2983static int get_location(struct scsi_tape *STp, unsigned int *block, int *partition,
2984 int logical)
2985{
2986 int result;
2987 unsigned char scmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002988 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 DEB( char *name = tape_name(STp); )
2990
2991 if (STp->ready != ST_READY)
2992 return (-EIO);
2993
2994 memset(scmd, 0, MAX_COMMAND_SIZE);
2995 if ((STp->device)->scsi_level < SCSI_2) {
2996 scmd[0] = QFA_REQUEST_BLOCK;
2997 scmd[4] = 3;
2998 } else {
2999 scmd[0] = READ_POSITION;
3000 if (!logical && !STp->scsi2_logical)
3001 scmd[1] = 1;
3002 }
3003 SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06003004 STp->device->request_queue->rq_timeout,
3005 MAX_READY_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 if (!SRpnt)
3007 return (STp->buffer)->syscall_result;
3008
3009 if ((STp->buffer)->syscall_result != 0 ||
3010 (STp->device->scsi_level >= SCSI_2 &&
3011 ((STp->buffer)->b_data[0] & 4) != 0)) {
3012 *block = *partition = 0;
3013 DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name));
3014 result = (-EIO);
3015 } else {
3016 result = 0;
3017 if ((STp->device)->scsi_level < SCSI_2) {
3018 *block = ((STp->buffer)->b_data[0] << 16)
3019 + ((STp->buffer)->b_data[1] << 8)
3020 + (STp->buffer)->b_data[2];
3021 *partition = 0;
3022 } else {
3023 *block = ((STp->buffer)->b_data[4] << 24)
3024 + ((STp->buffer)->b_data[5] << 16)
3025 + ((STp->buffer)->b_data[6] << 8)
3026 + (STp->buffer)->b_data[7];
3027 *partition = (STp->buffer)->b_data[1];
3028 if (((STp->buffer)->b_data[0] & 0x80) &&
3029 (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */
3030 STp->ps[0].drv_block = STp->ps[0].drv_file = 0;
3031 }
3032 DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
3033 *block, *partition));
3034 }
Mike Christie8b05b772005-11-08 04:06:44 -06003035 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 SRpnt = NULL;
3037
3038 return result;
3039}
3040
3041
3042/* Set the tape block and partition. Negative partition means that only the
3043 block should be set in vendor specific way. */
3044static int set_location(struct scsi_tape *STp, unsigned int block, int partition,
3045 int logical)
3046{
3047 struct st_partstat *STps;
3048 int result, p;
3049 unsigned int blk;
3050 int timeout;
3051 unsigned char scmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06003052 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053 DEB( char *name = tape_name(STp); )
3054
3055 if (STp->ready != ST_READY)
3056 return (-EIO);
3057 timeout = STp->long_timeout;
3058 STps = &(STp->ps[STp->partition]);
3059
3060 DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n",
3061 name, block, partition));
3062 DEB(if (partition < 0)
3063 return (-EIO); )
3064
3065 /* Update the location at the partition we are leaving */
3066 if ((!STp->can_partitions && partition != 0) ||
3067 partition >= ST_NBR_PARTITIONS)
3068 return (-EINVAL);
3069 if (partition != STp->partition) {
3070 if (get_location(STp, &blk, &p, 1))
3071 STps->last_block_valid = 0;
3072 else {
3073 STps->last_block_valid = 1;
3074 STps->last_block_visited = blk;
3075 DEBC(printk(ST_DEB_MSG
3076 "%s: Visited block %d for partition %d saved.\n",
3077 name, blk, STp->partition));
3078 }
3079 }
3080
3081 memset(scmd, 0, MAX_COMMAND_SIZE);
3082 if ((STp->device)->scsi_level < SCSI_2) {
3083 scmd[0] = QFA_SEEK_BLOCK;
3084 scmd[2] = (block >> 16);
3085 scmd[3] = (block >> 8);
3086 scmd[4] = block;
3087 scmd[5] = 0;
3088 } else {
3089 scmd[0] = SEEK_10;
3090 scmd[3] = (block >> 24);
3091 scmd[4] = (block >> 16);
3092 scmd[5] = (block >> 8);
3093 scmd[6] = block;
3094 if (!logical && !STp->scsi2_logical)
3095 scmd[1] = 4;
3096 if (STp->partition != partition) {
3097 scmd[1] |= 2;
3098 scmd[8] = partition;
3099 DEBC(printk(ST_DEB_MSG
3100 "%s: Trying to change partition from %d to %d\n",
3101 name, STp->partition, partition));
3102 }
3103 }
3104 if (STp->immediate) {
3105 scmd[1] |= 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06003106 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 }
3108
FUJITA Tomonori3c0bf162008-12-05 15:25:23 +09003109 SRpnt = st_allocate_request(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 if (!SRpnt)
FUJITA Tomonori3c0bf162008-12-05 15:25:23 +09003111 return STp->buffer->syscall_result;
3112
3113 result = st_scsi_kern_execute(SRpnt, scmd, DMA_NONE, NULL, 0,
3114 timeout, MAX_READY_RETRIES);
3115 if (result)
3116 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117
3118 STps->drv_block = STps->drv_file = (-1);
3119 STps->eof = ST_NOEOF;
3120 if ((STp->buffer)->syscall_result != 0) {
3121 result = (-EIO);
3122 if (STp->can_partitions &&
3123 (STp->device)->scsi_level >= SCSI_2 &&
3124 (p = find_partition(STp)) >= 0)
3125 STp->partition = p;
3126 } else {
3127 if (STp->can_partitions) {
3128 STp->partition = partition;
3129 STps = &(STp->ps[partition]);
3130 if (!STps->last_block_valid ||
3131 STps->last_block_visited != block) {
3132 STps->at_sm = 0;
3133 STps->rw = ST_IDLE;
3134 }
3135 } else
3136 STps->at_sm = 0;
3137 if (block == 0)
3138 STps->drv_block = STps->drv_file = 0;
3139 result = 0;
3140 }
FUJITA Tomonori3c0bf162008-12-05 15:25:23 +09003141out:
Mike Christie8b05b772005-11-08 04:06:44 -06003142 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 SRpnt = NULL;
3144
3145 return result;
3146}
3147
3148
3149/* Find the current partition number for the drive status. Called from open and
3150 returns either partition number of negative error code. */
3151static int find_partition(struct scsi_tape *STp)
3152{
3153 int i, partition;
3154 unsigned int block;
3155
3156 if ((i = get_location(STp, &block, &partition, 1)) < 0)
3157 return i;
3158 if (partition >= ST_NBR_PARTITIONS)
3159 return (-EIO);
3160 return partition;
3161}
3162
3163
3164/* Change the partition if necessary */
3165static int switch_partition(struct scsi_tape *STp)
3166{
3167 struct st_partstat *STps;
3168
3169 if (STp->partition == STp->new_partition)
3170 return 0;
3171 STps = &(STp->ps[STp->new_partition]);
3172 if (!STps->last_block_valid)
3173 STps->last_block_visited = 0;
3174 return set_location(STp, STps->last_block_visited, STp->new_partition, 1);
3175}
3176
3177/* Functions for reading and writing the medium partition mode page. */
3178
3179#define PART_PAGE 0x11
3180#define PART_PAGE_FIXED_LENGTH 8
3181
3182#define PP_OFF_MAX_ADD_PARTS 2
3183#define PP_OFF_NBR_ADD_PARTS 3
3184#define PP_OFF_FLAGS 4
3185#define PP_OFF_PART_UNITS 6
3186#define PP_OFF_RESERVED 7
3187
3188#define PP_BIT_IDP 0x20
3189#define PP_MSK_PSUM_MB 0x10
3190
3191/* Get the number of partitions on the tape. As a side effect reads the
3192 mode page into the tape buffer. */
3193static int nbr_partitions(struct scsi_tape *STp)
3194{
3195 int result;
3196 DEB( char *name = tape_name(STp); )
3197
3198 if (STp->ready != ST_READY)
3199 return (-EIO);
3200
3201 result = read_mode_page(STp, PART_PAGE, 1);
3202
3203 if (result) {
3204 DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n",
3205 name));
3206 result = (-EIO);
3207 } else {
3208 result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
3209 PP_OFF_NBR_ADD_PARTS] + 1;
3210 DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result));
3211 }
3212
3213 return result;
3214}
3215
3216
3217/* Partition the tape into two partitions if size > 0 or one partition if
3218 size == 0.
3219
3220 The block descriptors are read and written because Sony SDT-7000 does not
3221 work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
3222
3223 My HP C1533A drive returns only one partition size field. This is used to
3224 set the size of partition 1. There is no size field for the default partition.
3225 Michael Schaefer's Sony SDT-7000 returns two descriptors and the second is
3226 used to set the size of partition 1 (this is what the SCSI-3 standard specifies).
3227 The following algorithm is used to accommodate both drives: if the number of
3228 partition size fields is greater than the maximum number of additional partitions
3229 in the mode page, the second field is used. Otherwise the first field is used.
3230
3231 For Seagate DDS drives the page length must be 8 when no partitions is defined
3232 and 10 when 1 partition is defined (information from Eric Lee Green). This is
3233 is acceptable also to some other old drives and enforced if the first partition
3234 size field is used for the first additional partition size.
3235 */
3236static int partition_tape(struct scsi_tape *STp, int size)
3237{
3238 char *name = tape_name(STp);
3239 int result;
3240 int pgo, psd_cnt, psdo;
3241 unsigned char *bp;
3242
3243 result = read_mode_page(STp, PART_PAGE, 0);
3244 if (result) {
3245 DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name));
3246 return result;
3247 }
3248 /* The mode page is in the buffer. Let's modify it and write it. */
3249 bp = (STp->buffer)->b_data;
3250 pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
3251 DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n",
3252 name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
3253
3254 psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
3255 psdo = pgo + PART_PAGE_FIXED_LENGTH;
3256 if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
3257 bp[psdo] = bp[psdo + 1] = 0xff; /* Rest of the tape */
3258 psdo += 2;
3259 }
3260 memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
3261
3262 DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name,
3263 psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
3264 bp[pgo + PP_OFF_NBR_ADD_PARTS]));
3265
3266 if (size <= 0) {
3267 bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
3268 if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
3269 bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
3270 DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n",
3271 name));
3272 } else {
3273 bp[psdo] = (size >> 8) & 0xff;
3274 bp[psdo + 1] = size & 0xff;
3275 bp[pgo + 3] = 1;
3276 if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8)
3277 bp[pgo + MP_OFF_PAGE_LENGTH] = 8;
3278 DEBC(printk(ST_DEB_MSG
3279 "%s: Formatting tape with two partitions (1 = %d MB).\n",
3280 name, size));
3281 }
3282 bp[pgo + PP_OFF_PART_UNITS] = 0;
3283 bp[pgo + PP_OFF_RESERVED] = 0;
3284 bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
3285
3286 result = write_mode_page(STp, PART_PAGE, 1);
3287 if (result) {
3288 printk(KERN_INFO "%s: Partitioning of tape failed.\n", name);
3289 result = (-EIO);
3290 }
3291
3292 return result;
3293}
3294
3295
3296
3297/* The ioctl command */
Kai Makisarafd66c1b2008-01-17 22:45:22 +02003298static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299{
3300 int i, cmd_nr, cmd_type, bt;
3301 int retval = 0;
3302 unsigned int blk;
3303 struct scsi_tape *STp = file->private_data;
3304 struct st_modedef *STm;
3305 struct st_partstat *STps;
3306 char *name = tape_name(STp);
3307 void __user *p = (void __user *)arg;
3308
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003309 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 return -ERESTARTSYS;
3311
3312 DEB(
3313 if (debugging && !STp->in_use) {
3314 printk(ST_DEB_MSG "%s: Incorrect device.\n", name);
3315 retval = (-EIO);
3316 goto out;
3317 } ) /* end DEB */
3318
3319 STm = &(STp->modes[STp->current_mode]);
3320 STps = &(STp->ps[STp->partition]);
3321
3322 /*
3323 * If we are in the middle of error recovery, don't let anyone
3324 * else try and use this device. Also, if error recovery fails, it
3325 * may try and take the device offline, in which case all further
3326 * access to the device is prohibited.
3327 */
Al Viro83ff6fe2008-03-02 08:15:49 -05003328 retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p,
3329 file->f_flags & O_NDELAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330 if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV)
3331 goto out;
3332 retval = 0;
3333
3334 cmd_type = _IOC_TYPE(cmd_in);
3335 cmd_nr = _IOC_NR(cmd_in);
3336
3337 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
3338 struct mtop mtc;
3339
3340 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
3341 retval = (-EINVAL);
3342 goto out;
3343 }
3344
3345 i = copy_from_user(&mtc, p, sizeof(struct mtop));
3346 if (i) {
3347 retval = (-EFAULT);
3348 goto out;
3349 }
3350
3351 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
3352 printk(KERN_WARNING
3353 "%s: MTSETDRVBUFFER only allowed for root.\n", name);
3354 retval = (-EPERM);
3355 goto out;
3356 }
3357 if (!STm->defined &&
3358 (mtc.mt_op != MTSETDRVBUFFER &&
3359 (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
3360 retval = (-ENXIO);
3361 goto out;
3362 }
3363
3364 if (!STp->pos_unknown) {
3365
3366 if (STps->eof == ST_FM_HIT) {
3367 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
3368 mtc.mt_op == MTEOM) {
3369 mtc.mt_count -= 1;
3370 if (STps->drv_file >= 0)
3371 STps->drv_file += 1;
3372 } else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
3373 mtc.mt_count += 1;
3374 if (STps->drv_file >= 0)
3375 STps->drv_file += 1;
3376 }
3377 }
3378
3379 if (mtc.mt_op == MTSEEK) {
3380 /* Old position must be restored if partition will be
3381 changed */
3382 i = !STp->can_partitions ||
3383 (STp->new_partition != STp->partition);
3384 } else {
3385 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
3386 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
3387 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
3388 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
3389 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
3390 mtc.mt_op == MTCOMPRESSION;
3391 }
3392 i = flush_buffer(STp, i);
3393 if (i < 0) {
3394 retval = i;
3395 goto out;
3396 }
3397 if (STps->rw == ST_WRITING &&
3398 (mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
3399 mtc.mt_op == MTSEEK ||
3400 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)) {
3401 i = st_int_ioctl(STp, MTWEOF, 1);
3402 if (i < 0) {
3403 retval = i;
3404 goto out;
3405 }
3406 if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)
3407 mtc.mt_count++;
3408 STps->rw = ST_IDLE;
3409 }
3410
3411 } else {
3412 /*
3413 * If there was a bus reset, block further access
3414 * to this device. If the user wants to rewind the tape,
3415 * then reset the flag and allow access again.
3416 */
3417 if (mtc.mt_op != MTREW &&
3418 mtc.mt_op != MTOFFL &&
3419 mtc.mt_op != MTRETEN &&
3420 mtc.mt_op != MTERASE &&
3421 mtc.mt_op != MTSEEK &&
3422 mtc.mt_op != MTEOM) {
3423 retval = (-EIO);
3424 goto out;
3425 }
3426 reset_state(STp);
3427 /* remove this when the midlevel properly clears was_reset */
3428 STp->device->was_reset = 0;
3429 }
3430
3431 if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
3432 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTWSM &&
3433 mtc.mt_op != MTSETDRVBUFFER && mtc.mt_op != MTSETPART)
3434 STps->rw = ST_IDLE; /* Prevent automatic WEOF and fsf */
3435
3436 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
3437 do_door_lock(STp, 0); /* Ignore result! */
3438
3439 if (mtc.mt_op == MTSETDRVBUFFER &&
3440 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
3441 retval = st_set_options(STp, mtc.mt_count);
3442 goto out;
3443 }
3444
3445 if (mtc.mt_op == MTSETPART) {
3446 if (!STp->can_partitions ||
3447 mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS) {
3448 retval = (-EINVAL);
3449 goto out;
3450 }
3451 if (mtc.mt_count >= STp->nbr_partitions &&
3452 (STp->nbr_partitions = nbr_partitions(STp)) < 0) {
3453 retval = (-EIO);
3454 goto out;
3455 }
3456 if (mtc.mt_count >= STp->nbr_partitions) {
3457 retval = (-EINVAL);
3458 goto out;
3459 }
3460 STp->new_partition = mtc.mt_count;
3461 retval = 0;
3462 goto out;
3463 }
3464
3465 if (mtc.mt_op == MTMKPART) {
3466 if (!STp->can_partitions) {
3467 retval = (-EINVAL);
3468 goto out;
3469 }
3470 if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
3471 (i = partition_tape(STp, mtc.mt_count)) < 0) {
3472 retval = i;
3473 goto out;
3474 }
3475 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3476 STp->ps[i].rw = ST_IDLE;
3477 STp->ps[i].at_sm = 0;
3478 STp->ps[i].last_block_valid = 0;
3479 }
3480 STp->partition = STp->new_partition = 0;
3481 STp->nbr_partitions = 1; /* Bad guess ?-) */
3482 STps->drv_block = STps->drv_file = 0;
3483 retval = 0;
3484 goto out;
3485 }
3486
3487 if (mtc.mt_op == MTSEEK) {
3488 i = set_location(STp, mtc.mt_count, STp->new_partition, 0);
3489 if (!STp->can_partitions)
3490 STp->ps[0].rw = ST_IDLE;
3491 retval = i;
3492 goto out;
3493 }
3494
3495 if (mtc.mt_op == MTUNLOAD || mtc.mt_op == MTOFFL) {
3496 retval = do_load_unload(STp, file, 0);
3497 goto out;
3498 }
3499
3500 if (mtc.mt_op == MTLOAD) {
3501 retval = do_load_unload(STp, file, max(1, mtc.mt_count));
3502 goto out;
3503 }
3504
3505 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
3506 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
3507 goto out;
3508 }
3509
3510 if (STp->can_partitions && STp->ready == ST_READY &&
3511 (i = switch_partition(STp)) < 0) {
3512 retval = i;
3513 goto out;
3514 }
3515
3516 if (mtc.mt_op == MTCOMPRESSION)
3517 retval = st_compression(STp, (mtc.mt_count & 1));
3518 else
3519 retval = st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
3520 goto out;
3521 }
3522 if (!STm->defined) {
3523 retval = (-ENXIO);
3524 goto out;
3525 }
3526
3527 if ((i = flush_buffer(STp, 0)) < 0) {
3528 retval = i;
3529 goto out;
3530 }
3531 if (STp->can_partitions &&
3532 (i = switch_partition(STp)) < 0) {
3533 retval = i;
3534 goto out;
3535 }
3536
3537 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
3538 struct mtget mt_status;
3539
3540 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
3541 retval = (-EINVAL);
3542 goto out;
3543 }
3544
3545 mt_status.mt_type = STp->tape_type;
3546 mt_status.mt_dsreg =
3547 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
3548 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
3549 mt_status.mt_blkno = STps->drv_block;
3550 mt_status.mt_fileno = STps->drv_file;
3551 if (STp->block_size != 0) {
3552 if (STps->rw == ST_WRITING)
3553 mt_status.mt_blkno +=
3554 (STp->buffer)->buffer_bytes / STp->block_size;
3555 else if (STps->rw == ST_READING)
3556 mt_status.mt_blkno -=
3557 ((STp->buffer)->buffer_bytes +
3558 STp->block_size - 1) / STp->block_size;
3559 }
3560
3561 mt_status.mt_gstat = 0;
3562 if (STp->drv_write_prot)
3563 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
3564 if (mt_status.mt_blkno == 0) {
3565 if (mt_status.mt_fileno == 0)
3566 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
3567 else
3568 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
3569 }
3570 mt_status.mt_erreg = (STp->recover_reg << MT_ST_SOFTERR_SHIFT);
3571 mt_status.mt_resid = STp->partition;
3572 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
3573 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
3574 else if (STps->eof >= ST_EOM_OK)
3575 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
3576 if (STp->density == 1)
3577 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
3578 else if (STp->density == 2)
3579 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
3580 else if (STp->density == 3)
3581 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
3582 if (STp->ready == ST_READY)
3583 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
3584 if (STp->ready == ST_NO_TAPE)
3585 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
3586 if (STps->at_sm)
3587 mt_status.mt_gstat |= GMT_SM(0xffffffff);
3588 if (STm->do_async_writes ||
3589 (STm->do_buffer_writes && STp->block_size != 0) ||
3590 STp->drv_buffer != 0)
3591 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
3592 if (STp->cleaning_req)
3593 mt_status.mt_gstat |= GMT_CLN(0xffffffff);
3594
3595 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
3596 if (i) {
3597 retval = (-EFAULT);
3598 goto out;
3599 }
3600
3601 STp->recover_reg = 0; /* Clear after read */
3602 retval = 0;
3603 goto out;
3604 } /* End of MTIOCGET */
3605 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
3606 struct mtpos mt_pos;
3607 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
3608 retval = (-EINVAL);
3609 goto out;
3610 }
3611 if ((i = get_location(STp, &blk, &bt, 0)) < 0) {
3612 retval = i;
3613 goto out;
3614 }
3615 mt_pos.mt_blkno = blk;
3616 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
3617 if (i)
3618 retval = (-EFAULT);
3619 goto out;
3620 }
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003621 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 switch (cmd_in) {
3623 case SCSI_IOCTL_GET_IDLUN:
3624 case SCSI_IOCTL_GET_BUS_NUMBER:
3625 break;
3626 default:
Kai Makisara 16c4b3e2005-05-01 18:11:55 +03003627 if ((cmd_in == SG_IO ||
3628 cmd_in == SCSI_IOCTL_SEND_COMMAND ||
3629 cmd_in == CDROM_SEND_PACKET) &&
3630 !capable(CAP_SYS_RAWIO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 i = -EPERM;
3632 else
Al Viro74f3c8a2007-08-27 15:38:10 -04003633 i = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
3634 file->f_mode, cmd_in, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 if (i != -ENOTTY)
3636 return i;
3637 break;
3638 }
Kai Makisara 16c4b3e2005-05-01 18:11:55 +03003639 retval = scsi_ioctl(STp->device, cmd_in, p);
3640 if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */
3641 STp->rew_at_close = 0;
3642 STp->ready = ST_NO_TAPE;
3643 }
3644 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
3646 out:
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003647 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 return retval;
3649}
3650
3651#ifdef CONFIG_COMPAT
3652static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3653{
3654 struct scsi_tape *STp = file->private_data;
3655 struct scsi_device *sdev = STp->device;
3656 int ret = -ENOIOCTLCMD;
3657 if (sdev->host->hostt->compat_ioctl) {
3658
3659 ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
3660
3661 }
3662 return ret;
3663}
3664#endif
3665
3666
3667
3668/* Try to allocate a new tape buffer. Calling function must not hold
3669 dev_arr_lock. */
3670static struct st_buffer *
3671 new_tape_buffer(int from_initialization, int need_dma, int max_sg)
3672{
Mike Christie8b05b772005-11-08 04:06:44 -06003673 int i, got = 0;
Al Viroc53033f2005-10-21 03:22:08 -04003674 gfp_t priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 struct st_buffer *tb;
3676
3677 if (from_initialization)
3678 priority = GFP_ATOMIC;
3679 else
3680 priority = GFP_KERNEL;
3681
3682 i = sizeof(struct st_buffer) + (max_sg - 1) * sizeof(struct scatterlist) +
3683 max_sg * sizeof(struct st_buf_fragment);
Jes Sorensen24669f752006-01-16 10:31:18 -05003684 tb = kzalloc(i, priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 if (!tb) {
3686 printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
3687 return NULL;
3688 }
Mike Christie8b05b772005-11-08 04:06:44 -06003689 tb->frp_segs = tb->orig_frp_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 tb->use_sg = max_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
3692
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 tb->dma = need_dma;
3694 tb->buffer_size = got;
FUJITA Tomonoricd816212007-12-15 15:51:55 +09003695 sg_init_table(tb->sg, max_sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
3697 return tb;
3698}
3699
3700
3701/* Try to allocate enough space in the tape buffer */
3702static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
3703{
Al Viroc53033f2005-10-21 03:22:08 -04003704 int segs, nbr, max_segs, b_size, order, got;
3705 gfp_t priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706
3707 if (new_size <= STbuffer->buffer_size)
3708 return 1;
3709
3710 if (STbuffer->buffer_size <= PAGE_SIZE)
3711 normalize_buffer(STbuffer); /* Avoid extra segment */
3712
3713 max_segs = STbuffer->use_sg;
3714 nbr = max_segs - STbuffer->frp_segs;
3715 if (nbr <= 0)
3716 return 0;
3717
3718 priority = GFP_KERNEL | __GFP_NOWARN;
3719 if (need_dma)
3720 priority |= GFP_DMA;
Mike Christie8b05b772005-11-08 04:06:44 -06003721 for (b_size = PAGE_SIZE, order=0; order <= 6 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 b_size < new_size - STbuffer->buffer_size;
3723 order++, b_size *= 2)
3724 ; /* empty */
3725
3726 for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size;
3727 segs < max_segs && got < new_size;) {
3728 STbuffer->frp[segs].page = alloc_pages(priority, order);
3729 if (STbuffer->frp[segs].page == NULL) {
3730 if (new_size - got <= (max_segs - segs) * b_size / 2) {
3731 b_size /= 2; /* Large enough for the rest of the buffers */
3732 order--;
3733 continue;
3734 }
3735 DEB(STbuffer->buffer_size = got);
3736 normalize_buffer(STbuffer);
3737 return 0;
3738 }
3739 STbuffer->frp[segs].length = b_size;
3740 STbuffer->frp_segs += 1;
3741 got += b_size;
3742 STbuffer->buffer_size = got;
Kai Makisara40f6b362008-02-24 22:23:24 +02003743 if (STbuffer->cleared)
3744 memset(page_address(STbuffer->frp[segs].page), 0, b_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 segs++;
3746 }
3747 STbuffer->b_data = page_address(STbuffer->frp[0].page);
3748
3749 return 1;
3750}
3751
3752
Kai Makisara40f6b362008-02-24 22:23:24 +02003753/* Make sure that no data from previous user is in the internal buffer */
3754static void clear_buffer(struct st_buffer * st_bp)
3755{
3756 int i;
3757
3758 for (i=0; i < st_bp->frp_segs; i++)
3759 memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
3760 st_bp->cleared = 1;
3761}
3762
3763
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764/* Release the extra buffer */
3765static void normalize_buffer(struct st_buffer * STbuffer)
3766{
3767 int i, order;
3768
3769 for (i = STbuffer->orig_frp_segs; i < STbuffer->frp_segs; i++) {
3770 order = get_order(STbuffer->frp[i].length);
3771 __free_pages(STbuffer->frp[i].page, order);
3772 STbuffer->buffer_size -= STbuffer->frp[i].length;
3773 }
3774 STbuffer->frp_segs = STbuffer->orig_frp_segs;
3775 STbuffer->frp_sg_current = 0;
Mike Christie8b05b772005-11-08 04:06:44 -06003776 STbuffer->sg_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777}
3778
3779
3780/* Move data from the user buffer to the tape buffer. Returns zero (success) or
3781 negative error code. */
3782static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
3783{
3784 int i, cnt, res, offset;
3785
3786 for (i = 0, offset = st_bp->buffer_bytes;
3787 i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
3788 offset -= st_bp->frp[i].length;
3789 if (i == st_bp->frp_segs) { /* Should never happen */
3790 printk(KERN_WARNING "st: append_to_buffer offset overflow.\n");
3791 return (-EIO);
3792 }
3793 for (; i < st_bp->frp_segs && do_count > 0; i++) {
3794 cnt = st_bp->frp[i].length - offset < do_count ?
3795 st_bp->frp[i].length - offset : do_count;
3796 res = copy_from_user(page_address(st_bp->frp[i].page) + offset, ubp, cnt);
3797 if (res)
3798 return (-EFAULT);
3799 do_count -= cnt;
3800 st_bp->buffer_bytes += cnt;
3801 ubp += cnt;
3802 offset = 0;
3803 }
3804 if (do_count) /* Should never happen */
3805 return (-EIO);
3806
3807 return 0;
3808}
3809
3810
3811/* Move data from the tape buffer to the user buffer. Returns zero (success) or
3812 negative error code. */
3813static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
3814{
3815 int i, cnt, res, offset;
3816
3817 for (i = 0, offset = st_bp->read_pointer;
3818 i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
3819 offset -= st_bp->frp[i].length;
3820 if (i == st_bp->frp_segs) { /* Should never happen */
3821 printk(KERN_WARNING "st: from_buffer offset overflow.\n");
3822 return (-EIO);
3823 }
3824 for (; i < st_bp->frp_segs && do_count > 0; i++) {
3825 cnt = st_bp->frp[i].length - offset < do_count ?
3826 st_bp->frp[i].length - offset : do_count;
3827 res = copy_to_user(ubp, page_address(st_bp->frp[i].page) + offset, cnt);
3828 if (res)
3829 return (-EFAULT);
3830 do_count -= cnt;
3831 st_bp->buffer_bytes -= cnt;
3832 st_bp->read_pointer += cnt;
3833 ubp += cnt;
3834 offset = 0;
3835 }
3836 if (do_count) /* Should never happen */
3837 return (-EIO);
3838
3839 return 0;
3840}
3841
3842
3843/* Move data towards start of buffer */
3844static void move_buffer_data(struct st_buffer * st_bp, int offset)
3845{
3846 int src_seg, dst_seg, src_offset = 0, dst_offset;
3847 int count, total;
3848
3849 if (offset == 0)
3850 return;
3851
3852 total=st_bp->buffer_bytes - offset;
3853 for (src_seg=0; src_seg < st_bp->frp_segs; src_seg++) {
3854 src_offset = offset;
3855 if (src_offset < st_bp->frp[src_seg].length)
3856 break;
3857 offset -= st_bp->frp[src_seg].length;
3858 }
3859
3860 st_bp->buffer_bytes = st_bp->read_pointer = total;
3861 for (dst_seg=dst_offset=0; total > 0; ) {
3862 count = min(st_bp->frp[dst_seg].length - dst_offset,
3863 st_bp->frp[src_seg].length - src_offset);
3864 memmove(page_address(st_bp->frp[dst_seg].page) + dst_offset,
3865 page_address(st_bp->frp[src_seg].page) + src_offset, count);
3866 src_offset += count;
3867 if (src_offset >= st_bp->frp[src_seg].length) {
3868 src_seg++;
3869 src_offset = 0;
3870 }
3871 dst_offset += count;
3872 if (dst_offset >= st_bp->frp[dst_seg].length) {
3873 dst_seg++;
3874 dst_offset = 0;
3875 }
3876 total -= count;
3877 }
3878}
3879
3880
3881/* Fill the s/g list up to the length required for this transfer */
3882static void buf_to_sg(struct st_buffer *STbp, unsigned int length)
3883{
3884 int i;
3885 unsigned int count;
3886 struct scatterlist *sg;
3887 struct st_buf_fragment *frp;
3888
3889 if (length == STbp->frp_sg_current)
3890 return; /* work already done */
3891
3892 sg = &(STbp->sg[0]);
3893 frp = STbp->frp;
3894 for (i=count=0; count < length; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 if (length - count > frp[i].length)
Jens Axboe642f1492007-10-24 11:20:47 +02003896 sg_set_page(&sg[i], frp[i].page, frp[i].length, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 else
Jens Axboe642f1492007-10-24 11:20:47 +02003898 sg_set_page(&sg[i], frp[i].page, length - count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 count += sg[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003900 }
3901 STbp->sg_segs = i;
3902 STbp->frp_sg_current = length;
3903}
3904
3905
3906/* Validate the options from command line or module parameters */
3907static void validate_options(void)
3908{
3909 if (buffer_kbs > 0)
3910 st_fixed_buffer_size = buffer_kbs * ST_KILOBYTE;
3911 if (max_sg_segs >= ST_FIRST_SG)
3912 st_max_sg_segs = max_sg_segs;
3913}
3914
3915#ifndef MODULE
3916/* Set the boot options. Syntax is defined in Documenation/scsi/st.txt.
3917 */
3918static int __init st_setup(char *str)
3919{
3920 int i, len, ints[5];
3921 char *stp;
3922
3923 stp = get_options(str, ARRAY_SIZE(ints), ints);
3924
3925 if (ints[0] > 0) {
3926 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
3927 if (parms[i].val)
3928 *parms[i].val = ints[i + 1];
3929 } else {
3930 while (stp != NULL) {
3931 for (i = 0; i < ARRAY_SIZE(parms); i++) {
3932 len = strlen(parms[i].name);
3933 if (!strncmp(stp, parms[i].name, len) &&
3934 (*(stp + len) == ':' || *(stp + len) == '=')) {
3935 if (parms[i].val)
3936 *parms[i].val =
3937 simple_strtoul(stp + len + 1, NULL, 0);
3938 else
3939 printk(KERN_WARNING "st: Obsolete parameter %s\n",
3940 parms[i].name);
3941 break;
3942 }
3943 }
Tobias Klauser6391a112006-06-08 22:23:48 -07003944 if (i >= ARRAY_SIZE(parms))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 printk(KERN_WARNING "st: invalid parameter in '%s'\n",
3946 stp);
3947 stp = strchr(stp, ',');
3948 if (stp)
3949 stp++;
3950 }
3951 }
3952
3953 validate_options();
3954
3955 return 1;
3956}
3957
3958__setup("st=", st_setup);
3959
3960#endif
3961
Arjan van de Ven00977a52007-02-12 00:55:34 -08003962static const struct file_operations st_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963{
3964 .owner = THIS_MODULE,
3965 .read = st_read,
3966 .write = st_write,
Kai Makisarafd66c1b2008-01-17 22:45:22 +02003967 .unlocked_ioctl = st_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968#ifdef CONFIG_COMPAT
3969 .compat_ioctl = st_compat_ioctl,
3970#endif
3971 .open = st_open,
3972 .flush = st_flush,
3973 .release = st_release,
3974};
3975
3976static int st_probe(struct device *dev)
3977{
3978 struct scsi_device *SDp = to_scsi_device(dev);
3979 struct gendisk *disk = NULL;
3980 struct cdev *cdev = NULL;
3981 struct scsi_tape *tpnt = NULL;
3982 struct st_modedef *STm;
3983 struct st_partstat *STps;
3984 struct st_buffer *buffer;
3985 int i, j, mode, dev_num, error;
3986 char *stp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
3988 if (SDp->type != TYPE_TAPE)
3989 return -ENODEV;
3990 if ((stp = st_incompatible(SDp))) {
Jeff Garzik3bf743e2005-10-24 18:04:06 -04003991 sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 printk(KERN_INFO "st: The suggested driver is %s.\n", stp);
3993 return -ENODEV;
3994 }
3995
Mike Christie8b05b772005-11-08 04:06:44 -06003996 i = min(SDp->request_queue->max_hw_segments,
3997 SDp->request_queue->max_phys_segments);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 if (st_max_sg_segs < i)
3999 i = st_max_sg_segs;
4000 buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i);
4001 if (buffer == NULL) {
4002 printk(KERN_ERR
4003 "st: Can't allocate new tape buffer. Device not attached.\n");
4004 goto out;
4005 }
4006
4007 disk = alloc_disk(1);
4008 if (!disk) {
4009 printk(KERN_ERR "st: out of memory. Device not attached.\n");
4010 goto out_buffer_free;
4011 }
4012
4013 write_lock(&st_dev_arr_lock);
4014 if (st_nr_dev >= st_dev_max) {
4015 struct scsi_tape **tmp_da;
4016 int tmp_dev_max;
4017
4018 tmp_dev_max = max(st_nr_dev * 2, 8);
4019 if (tmp_dev_max > ST_MAX_TAPES)
4020 tmp_dev_max = ST_MAX_TAPES;
4021 if (tmp_dev_max <= st_nr_dev) {
4022 write_unlock(&st_dev_arr_lock);
4023 printk(KERN_ERR "st: Too many tape devices (max. %d).\n",
4024 ST_MAX_TAPES);
4025 goto out_put_disk;
4026 }
4027
Jes Sorensen24669f752006-01-16 10:31:18 -05004028 tmp_da = kzalloc(tmp_dev_max * sizeof(struct scsi_tape *), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 if (tmp_da == NULL) {
4030 write_unlock(&st_dev_arr_lock);
4031 printk(KERN_ERR "st: Can't extend device array.\n");
4032 goto out_put_disk;
4033 }
4034
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 if (scsi_tapes != NULL) {
4036 memcpy(tmp_da, scsi_tapes,
4037 st_dev_max * sizeof(struct scsi_tape *));
4038 kfree(scsi_tapes);
4039 }
4040 scsi_tapes = tmp_da;
4041
4042 st_dev_max = tmp_dev_max;
4043 }
4044
4045 for (i = 0; i < st_dev_max; i++)
4046 if (scsi_tapes[i] == NULL)
4047 break;
4048 if (i >= st_dev_max)
4049 panic("scsi_devices corrupt (st)");
4050
Jes Sorensen24669f752006-01-16 10:31:18 -05004051 tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 if (tpnt == NULL) {
4053 write_unlock(&st_dev_arr_lock);
4054 printk(KERN_ERR "st: Can't allocate device descriptor.\n");
4055 goto out_put_disk;
4056 }
Kai Makisaraf03a5672005-08-02 13:40:47 +03004057 kref_init(&tpnt->kref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058 tpnt->disk = disk;
4059 sprintf(disk->disk_name, "st%d", i);
4060 disk->private_data = &tpnt->driver;
4061 disk->queue = SDp->request_queue;
4062 tpnt->driver = &st_template;
4063 scsi_tapes[i] = tpnt;
4064 dev_num = i;
4065
4066 tpnt->device = SDp;
4067 if (SDp->scsi_level <= 2)
4068 tpnt->tape_type = MT_ISSCSI1;
4069 else
4070 tpnt->tape_type = MT_ISSCSI2;
4071
4072 tpnt->buffer = buffer;
Kai Makisaraf03a5672005-08-02 13:40:47 +03004073 tpnt->buffer->last_SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
4075 tpnt->inited = 0;
4076 tpnt->dirty = 0;
4077 tpnt->in_use = 0;
4078 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
4079 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
4080 tpnt->use_pf = (SDp->scsi_level >= SCSI_2);
4081 tpnt->density = 0;
4082 tpnt->do_auto_lock = ST_AUTO_LOCK;
4083 tpnt->can_bsr = (SDp->scsi_level > 2 ? 1 : ST_IN_FILE_POS); /* BSR mandatory in SCSI3 */
4084 tpnt->can_partitions = 0;
4085 tpnt->two_fm = ST_TWO_FM;
4086 tpnt->fast_mteom = ST_FAST_MTEOM;
4087 tpnt->scsi2_logical = ST_SCSI2LOGICAL;
Kai Makisara40f6b362008-02-24 22:23:24 +02004088 tpnt->sili = ST_SILI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 tpnt->immediate = ST_NOWAIT;
4090 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
4091 tpnt->partition = 0;
4092 tpnt->new_partition = 0;
4093 tpnt->nbr_partitions = 0;
James Bottomleya02488e2008-11-30 10:36:26 -06004094 blk_queue_rq_timeout(tpnt->device->request_queue, ST_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 tpnt->long_timeout = ST_LONG_TIMEOUT;
4096 tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
4097
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 for (i = 0; i < ST_NBR_MODES; i++) {
4099 STm = &(tpnt->modes[i]);
4100 STm->defined = 0;
4101 STm->sysv = ST_SYSV;
4102 STm->defaults_for_writes = 0;
4103 STm->do_async_writes = ST_ASYNC_WRITES;
4104 STm->do_buffer_writes = ST_BUFFER_WRITES;
4105 STm->do_read_ahead = ST_READ_AHEAD;
4106 STm->default_compression = ST_DONT_TOUCH;
4107 STm->default_blksize = (-1); /* No forced size */
4108 STm->default_density = (-1); /* No forced density */
4109 }
4110
4111 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
4112 STps = &(tpnt->ps[i]);
4113 STps->rw = ST_IDLE;
4114 STps->eof = ST_NOEOF;
4115 STps->at_sm = 0;
4116 STps->last_block_valid = 0;
4117 STps->drv_block = (-1);
4118 STps->drv_file = (-1);
4119 }
4120
4121 tpnt->current_mode = 0;
4122 tpnt->modes[0].defined = 1;
4123
4124 tpnt->density_changed = tpnt->compression_changed =
4125 tpnt->blksize_changed = 0;
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02004126 mutex_init(&tpnt->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
4128 st_nr_dev++;
4129 write_unlock(&st_dev_arr_lock);
4130
4131 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
4132 STm = &(tpnt->modes[mode]);
4133 for (j=0; j < 2; j++) {
4134 cdev = cdev_alloc();
4135 if (!cdev) {
4136 printk(KERN_ERR
4137 "st%d: out of memory. Device not attached.\n",
4138 dev_num);
4139 goto out_free_tape;
4140 }
4141 cdev->owner = THIS_MODULE;
4142 cdev->ops = &st_fops;
4143
4144 error = cdev_add(cdev,
4145 MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, j)),
4146 1);
4147 if (error) {
4148 printk(KERN_ERR "st%d: Can't add %s-rewind mode %d\n",
4149 dev_num, j ? "non" : "auto", mode);
4150 printk(KERN_ERR "st%d: Device not attached.\n", dev_num);
4151 goto out_free_tape;
4152 }
4153 STm->cdevs[j] = cdev;
4154
4155 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004156 error = do_create_class_files(tpnt, dev_num, mode);
4157 if (error)
4158 goto out_free_tape;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 }
4160
Kai Makisara42252852006-11-07 21:56:38 +02004161 sdev_printk(KERN_NOTICE, SDp,
Rene Herman8b1ea242006-05-20 15:00:22 -07004162 "Attached scsi tape %s\n", tape_name(tpnt));
Kai Makisara42252852006-11-07 21:56:38 +02004163 sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n",
4164 tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
4165 queue_dma_alignment(SDp->request_queue) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166
4167 return 0;
4168
4169out_free_tape:
4170 for (mode=0; mode < ST_NBR_MODES; mode++) {
4171 STm = &(tpnt->modes[mode]);
4172 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
4173 "tape");
4174 for (j=0; j < 2; j++) {
4175 if (STm->cdevs[j]) {
4176 if (cdev == STm->cdevs[j])
4177 cdev = NULL;
Tony Jonesee959b02008-02-22 00:13:36 +01004178 device_destroy(st_sysfs_class,
4179 MKDEV(SCSI_TAPE_MAJOR,
4180 TAPE_MINOR(i, mode, j)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 cdev_del(STm->cdevs[j]);
4182 }
4183 }
4184 }
4185 if (cdev)
4186 cdev_del(cdev);
4187 write_lock(&st_dev_arr_lock);
4188 scsi_tapes[dev_num] = NULL;
4189 st_nr_dev--;
4190 write_unlock(&st_dev_arr_lock);
4191out_put_disk:
4192 put_disk(disk);
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004193 kfree(tpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194out_buffer_free:
4195 kfree(buffer);
4196out:
4197 return -ENODEV;
4198};
4199
4200
4201static int st_remove(struct device *dev)
4202{
4203 struct scsi_device *SDp = to_scsi_device(dev);
4204 struct scsi_tape *tpnt;
4205 int i, j, mode;
4206
4207 write_lock(&st_dev_arr_lock);
4208 for (i = 0; i < st_dev_max; i++) {
4209 tpnt = scsi_tapes[i];
4210 if (tpnt != NULL && tpnt->device == SDp) {
4211 scsi_tapes[i] = NULL;
4212 st_nr_dev--;
4213 write_unlock(&st_dev_arr_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 sysfs_remove_link(&tpnt->device->sdev_gendev.kobj,
4215 "tape");
4216 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 for (j=0; j < 2; j++) {
Tony Jonesee959b02008-02-22 00:13:36 +01004218 device_destroy(st_sysfs_class,
4219 MKDEV(SCSI_TAPE_MAJOR,
4220 TAPE_MINOR(i, mode, j)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 cdev_del(tpnt->modes[mode].cdevs[j]);
4222 tpnt->modes[mode].cdevs[j] = NULL;
4223 }
4224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Arjan van de Ven0b950672006-01-11 13:16:10 +01004226 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +03004227 kref_put(&tpnt->kref, scsi_tape_release);
Arjan van de Ven0b950672006-01-11 13:16:10 +01004228 mutex_unlock(&st_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 return 0;
4230 }
4231 }
4232
4233 write_unlock(&st_dev_arr_lock);
4234 return 0;
4235}
4236
Kai Makisaraf03a5672005-08-02 13:40:47 +03004237/**
4238 * scsi_tape_release - Called to free the Scsi_Tape structure
4239 * @kref: pointer to embedded kref
4240 *
Arjan van de Ven0b950672006-01-11 13:16:10 +01004241 * st_ref_mutex must be held entering this routine. Because it is
Kai Makisaraf03a5672005-08-02 13:40:47 +03004242 * called on last put, you should always use the scsi_tape_get()
4243 * scsi_tape_put() helpers which manipulate the semaphore directly
4244 * and never do a direct kref_put().
4245 **/
4246static void scsi_tape_release(struct kref *kref)
4247{
4248 struct scsi_tape *tpnt = to_scsi_tape(kref);
4249 struct gendisk *disk = tpnt->disk;
4250
4251 tpnt->device = NULL;
4252
4253 if (tpnt->buffer) {
4254 tpnt->buffer->orig_frp_segs = 0;
4255 normalize_buffer(tpnt->buffer);
4256 kfree(tpnt->buffer);
4257 }
4258
4259 disk->private_data = NULL;
4260 put_disk(disk);
4261 kfree(tpnt);
4262 return;
4263}
4264
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265static int __init init_st(void)
4266{
Jeff Garzik13026a62006-10-04 06:00:38 -04004267 int err;
4268
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 validate_options();
4270
Jeff Garzik13026a62006-10-04 06:00:38 -04004271 printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 verstr, st_fixed_buffer_size, st_max_sg_segs);
4273
gregkh@suse.ded2538782005-03-23 09:55:22 -08004274 st_sysfs_class = class_create(THIS_MODULE, "scsi_tape");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275 if (IS_ERR(st_sysfs_class)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276 printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n");
Jeff Garzik13026a62006-10-04 06:00:38 -04004277 return PTR_ERR(st_sysfs_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 }
4279
Jeff Garzik13026a62006-10-04 06:00:38 -04004280 err = register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4281 ST_MAX_TAPE_ENTRIES, "st");
4282 if (err) {
4283 printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
4284 SCSI_TAPE_MAJOR);
4285 goto err_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004287
4288 err = scsi_register_driver(&st_template.gendrv);
4289 if (err)
4290 goto err_chrdev;
4291
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004292 err = do_create_sysfs_files();
Jeff Garzik13026a62006-10-04 06:00:38 -04004293 if (err)
4294 goto err_scsidrv;
4295
4296 return 0;
4297
4298err_scsidrv:
4299 scsi_unregister_driver(&st_template.gendrv);
4300err_chrdev:
4301 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4302 ST_MAX_TAPE_ENTRIES);
4303err_class:
Kai Makisarac2c96f42005-08-02 12:21:51 +03004304 class_destroy(st_sysfs_class);
Jeff Garzik13026a62006-10-04 06:00:38 -04004305 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306}
4307
4308static void __exit exit_st(void)
4309{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004310 do_remove_sysfs_files();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 scsi_unregister_driver(&st_template.gendrv);
4312 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4313 ST_MAX_TAPE_ENTRIES);
Kai Makisarac2c96f42005-08-02 12:21:51 +03004314 class_destroy(st_sysfs_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315 kfree(scsi_tapes);
4316 printk(KERN_INFO "st: Unloaded.\n");
4317}
4318
4319module_init(init_st);
4320module_exit(exit_st);
4321
4322
4323/* The sysfs driver interface. Read-only at the moment */
4324static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
4325{
4326 return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
4327}
4328static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
4329
4330static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
4331{
4332 return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
4333}
4334static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
4335
4336static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
4337{
4338 return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
4339}
4340static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
4341
4342static ssize_t st_version_show(struct device_driver *ddd, char *buf)
4343{
4344 return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
4345}
4346static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
4347
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004348static int do_create_sysfs_files(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004350 struct device_driver *sysfs = &st_template.gendrv;
Jeff Garzik13026a62006-10-04 06:00:38 -04004351 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004353 err = driver_create_file(sysfs, &driver_attr_try_direct_io);
Jeff Garzik13026a62006-10-04 06:00:38 -04004354 if (err)
4355 return err;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004356 err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size);
Jeff Garzik13026a62006-10-04 06:00:38 -04004357 if (err)
4358 goto err_try_direct_io;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004359 err = driver_create_file(sysfs, &driver_attr_max_sg_segs);
Jeff Garzik13026a62006-10-04 06:00:38 -04004360 if (err)
4361 goto err_attr_fixed_buf;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004362 err = driver_create_file(sysfs, &driver_attr_version);
Jeff Garzik13026a62006-10-04 06:00:38 -04004363 if (err)
4364 goto err_attr_max_sg;
4365
4366 return 0;
4367
4368err_attr_max_sg:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004369 driver_remove_file(sysfs, &driver_attr_max_sg_segs);
Jeff Garzik13026a62006-10-04 06:00:38 -04004370err_attr_fixed_buf:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004371 driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
Jeff Garzik13026a62006-10-04 06:00:38 -04004372err_try_direct_io:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004373 driver_remove_file(sysfs, &driver_attr_try_direct_io);
Jeff Garzik13026a62006-10-04 06:00:38 -04004374 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375}
4376
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004377static void do_remove_sysfs_files(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004379 struct device_driver *sysfs = &st_template.gendrv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004381 driver_remove_file(sysfs, &driver_attr_version);
4382 driver_remove_file(sysfs, &driver_attr_max_sg_segs);
4383 driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
4384 driver_remove_file(sysfs, &driver_attr_try_direct_io);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385}
4386
4387
4388/* The sysfs simple class interface */
Tony Jonesee959b02008-02-22 00:13:36 +01004389static ssize_t
4390st_defined_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004392 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 ssize_t l = 0;
4394
4395 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
4396 return l;
4397}
4398
Tony Jonesee959b02008-02-22 00:13:36 +01004399DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
Tony Jonesee959b02008-02-22 00:13:36 +01004401static ssize_t
4402st_defblk_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004404 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 ssize_t l = 0;
4406
4407 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
4408 return l;
4409}
4410
Tony Jonesee959b02008-02-22 00:13:36 +01004411DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Tony Jonesee959b02008-02-22 00:13:36 +01004413static ssize_t
4414st_defdensity_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004416 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 ssize_t l = 0;
4418 char *fmt;
4419
4420 fmt = STm->default_density >= 0 ? "0x%02x\n" : "%d\n";
4421 l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density);
4422 return l;
4423}
4424
Tony Jonesee959b02008-02-22 00:13:36 +01004425DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426
Tony Jonesee959b02008-02-22 00:13:36 +01004427static ssize_t
4428st_defcompression_show(struct device *dev, struct device_attribute *attr,
4429 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004431 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 ssize_t l = 0;
4433
4434 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
4435 return l;
4436}
4437
Tony Jonesee959b02008-02-22 00:13:36 +01004438DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
Tony Jonesee959b02008-02-22 00:13:36 +01004440static ssize_t
4441st_options_show(struct device *dev, struct device_attribute *attr, char *buf)
Kai Makisarab174be02008-02-24 22:29:12 +02004442{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004443 struct st_modedef *STm = dev_get_drvdata(dev);
Kai Makisarab174be02008-02-24 22:29:12 +02004444 struct scsi_tape *STp;
4445 int i, j, options;
4446 ssize_t l = 0;
4447
4448 for (i=0; i < st_dev_max; i++) {
4449 for (j=0; j < ST_NBR_MODES; j++)
4450 if (&scsi_tapes[i]->modes[j] == STm)
4451 break;
4452 if (j < ST_NBR_MODES)
4453 break;
4454 }
4455 if (i == st_dev_max)
4456 return 0; /* should never happen */
4457
4458 STp = scsi_tapes[i];
4459
4460 options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
4461 options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
4462 options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
4463 DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
4464 options |= STp->two_fm ? MT_ST_TWO_FM : 0;
4465 options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
4466 options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
4467 options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
4468 options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
4469 options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
4470 options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
4471 options |= STm->sysv ? MT_ST_SYSV : 0;
4472 options |= STp->immediate ? MT_ST_NOWAIT : 0;
4473 options |= STp->sili ? MT_ST_SILI : 0;
4474
4475 l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
4476 return l;
4477}
4478
Tony Jonesee959b02008-02-22 00:13:36 +01004479DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL);
Kai Makisarab174be02008-02-24 22:29:12 +02004480
Jeff Garzik13026a62006-10-04 06:00:38 -04004481static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482{
4483 int i, rew, error;
4484 char name[10];
Tony Jonesee959b02008-02-22 00:13:36 +01004485 struct device *st_class_member;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 for (rew=0; rew < 2; rew++) {
4488 /* Make sure that the minor numbers corresponding to the four
4489 first modes always get the same names */
4490 i = mode << (4 - ST_NBR_MODE_BITS);
4491 snprintf(name, 10, "%s%s%s", rew ? "n" : "",
4492 STp->disk->disk_name, st_formats[i]);
4493 st_class_member =
Greg Kroah-Hartmand73a1a62008-07-21 20:03:34 -07004494 device_create(st_sysfs_class, &STp->device->sdev_gendev,
4495 MKDEV(SCSI_TAPE_MAJOR,
4496 TAPE_MINOR(dev_num, mode, rew)),
4497 &STp->modes[mode], "%s", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 if (IS_ERR(st_class_member)) {
Tony Jonesee959b02008-02-22 00:13:36 +01004499 printk(KERN_WARNING "st%d: device_create failed\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500 dev_num);
Jeff Garzik13026a62006-10-04 06:00:38 -04004501 error = PTR_ERR(st_class_member);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502 goto out;
4503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Tony Jonesee959b02008-02-22 00:13:36 +01004505 error = device_create_file(st_class_member,
4506 &dev_attr_defined);
Jeff Garzik13026a62006-10-04 06:00:38 -04004507 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004508 error = device_create_file(st_class_member,
4509 &dev_attr_default_blksize);
Jeff Garzik13026a62006-10-04 06:00:38 -04004510 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004511 error = device_create_file(st_class_member,
4512 &dev_attr_default_density);
Jeff Garzik13026a62006-10-04 06:00:38 -04004513 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004514 error = device_create_file(st_class_member,
4515 &dev_attr_default_compression);
Jeff Garzik13026a62006-10-04 06:00:38 -04004516 if (error) goto out;
Tony Jonesee959b02008-02-22 00:13:36 +01004517 error = device_create_file(st_class_member,
4518 &dev_attr_options);
Kai Makisarab174be02008-02-24 22:29:12 +02004519 if (error) goto out;
Jeff Garzik13026a62006-10-04 06:00:38 -04004520
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 if (mode == 0 && rew == 0) {
4522 error = sysfs_create_link(&STp->device->sdev_gendev.kobj,
4523 &st_class_member->kobj,
4524 "tape");
4525 if (error) {
4526 printk(KERN_ERR
4527 "st%d: Can't create sysfs link from SCSI device.\n",
4528 dev_num);
Jeff Garzik13026a62006-10-04 06:00:38 -04004529 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530 }
4531 }
4532 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004533
4534 return 0;
4535
4536out:
4537 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538}
4539
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540/* The following functions may be useful for a larger audience. */
4541static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
4542 unsigned long uaddr, size_t count, int rw)
4543{
James Bottomley07542b82005-08-31 20:27:22 -04004544 unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
4545 unsigned long start = uaddr >> PAGE_SHIFT;
4546 const int nr_pages = end - start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 int res, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548 struct page **pages;
4549
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 /* User attempted Overflow! */
4551 if ((uaddr + count) < uaddr)
4552 return -EINVAL;
4553
4554 /* Too big */
4555 if (nr_pages > max_pages)
4556 return -ENOMEM;
4557
4558 /* Hmm? */
4559 if (count == 0)
4560 return 0;
4561
4562 if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_KERNEL)) == NULL)
4563 return -ENOMEM;
4564
4565 /* Try to fault in all of the necessary pages */
4566 down_read(&current->mm->mmap_sem);
4567 /* rw==READ means read from drive, write into memory area */
4568 res = get_user_pages(
4569 current,
4570 current->mm,
4571 uaddr,
4572 nr_pages,
4573 rw == READ,
4574 0, /* don't force */
4575 pages,
4576 NULL);
4577 up_read(&current->mm->mmap_sem);
4578
4579 /* Errors and no page mapped should return here */
4580 if (res < nr_pages)
4581 goto out_unmap;
4582
4583 for (i=0; i < nr_pages; i++) {
4584 /* FIXME: flush superflous for rw==READ,
4585 * probably wrong function for rw==WRITE
4586 */
4587 flush_dcache_page(pages[i]);
4588 }
4589
4590 /* Populate the scatter/gather list */
Jens Axboe642f1492007-10-24 11:20:47 +02004591 sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 if (nr_pages > 1) {
4593 sgl[0].length = PAGE_SIZE - sgl[0].offset;
4594 count -= sgl[0].length;
4595 for (i=1; i < nr_pages ; i++) {
Jens Axboe642f1492007-10-24 11:20:47 +02004596 sg_set_page(&sgl[i], pages[i],
4597 count < PAGE_SIZE ? count : PAGE_SIZE, 0);;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004598 count -= PAGE_SIZE;
4599 }
4600 }
4601 else {
4602 sgl[0].length = count;
4603 }
4604
4605 kfree(pages);
4606 return nr_pages;
4607
4608 out_unmap:
4609 if (res > 0) {
4610 for (j=0; j < res; j++)
4611 page_cache_release(pages[j]);
Hugh Dickins6bc733e2005-12-01 20:21:57 +00004612 res = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613 }
4614 kfree(pages);
4615 return res;
4616}
4617
4618
4619/* And unmap them... */
4620static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
4621 int dirtied)
4622{
4623 int i;
4624
4625 for (i=0; i < nr_pages; i++) {
Jens Axboe45711f12007-10-22 21:19:53 +02004626 struct page *page = sg_page(&sgl[i]);
Nick Pigginb5810032005-10-29 18:16:12 -07004627
Nick Pigginb5810032005-10-29 18:16:12 -07004628 if (dirtied)
4629 SetPageDirty(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630 /* FIXME: cache flush missing for rw==READ
4631 * FIXME: call the correct reference counting function
4632 */
Nick Pigginb5810032005-10-29 18:16:12 -07004633 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634 }
4635
4636 return 0;
4637}