blob: ff44b3c2cff2b72662c7cda8e829ba433a108afa [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 Makisara3e51d3c2010-10-09 00:17:56 +030012 Copyright 1992 - 2010 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 Makisara373daac2010-12-20 18:43:39 +020020static const char *verstr = "20101219";
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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090030#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/errno.h>
32#include <linux/mtio.h>
Kai Makisara 16c4b3e2005-05-01 18:11:55 +030033#include <linux/cdrom.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/ioctl.h>
35#include <linux/fcntl.h>
36#include <linux/spinlock.h>
37#include <linux/blkdev.h>
38#include <linux/moduleparam.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/cdev.h>
Jeff Mahoney6c648d92012-08-18 15:20:39 -040040#include <linux/idr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/delay.h>
Arjan van de Ven0b950672006-01-11 13:16:10 +010042#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
44#include <asm/uaccess.h>
45#include <asm/dma.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
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
Jeff Mahoneyaf237822012-08-18 15:20:37 -040084static struct class st_sysfs_class;
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -070085static const struct attribute_group *st_dev_groups[];
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87MODULE_AUTHOR("Kai Makisara");
Rene Hermanf018fa52006-03-08 00:14:20 -080088MODULE_DESCRIPTION("SCSI tape (st) driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -070089MODULE_LICENSE("GPL");
Rene Hermanf018fa52006-03-08 00:14:20 -080090MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR);
Michael Tokarevd7b8bcb2006-10-27 16:02:37 +040091MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93/* Set 'perm' (4th argument) to 0 to disable module_param's definition
94 * of sysfs parameters (which module_param doesn't yet support).
95 * Sysfs parameters defined explicitly later.
96 */
97module_param_named(buffer_kbs, buffer_kbs, int, 0);
98MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size for fixed block mode (KB; 32)");
99module_param_named(max_sg_segs, max_sg_segs, int, 0);
100MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (256)");
101module_param_named(try_direct_io, try_direct_io, int, 0);
102MODULE_PARM_DESC(try_direct_io, "Try direct I/O between user buffer and tape drive (1)");
103
104/* Extra parameters for testing */
105module_param_named(try_rdio, try_rdio, int, 0);
106MODULE_PARM_DESC(try_rdio, "Try direct read i/o when possible");
107module_param_named(try_wdio, try_wdio, int, 0);
108MODULE_PARM_DESC(try_wdio, "Try direct write i/o when possible");
109
110#ifndef MODULE
111static int write_threshold_kbs; /* retained for compatibility */
112static struct st_dev_parm {
113 char *name;
114 int *val;
115} parms[] __initdata = {
116 {
117 "buffer_kbs", &buffer_kbs
118 },
119 { /* Retained for compatibility with 2.4 */
120 "write_threshold_kbs", &write_threshold_kbs
121 },
122 {
123 "max_sg_segs", NULL
124 },
125 {
126 "try_direct_io", &try_direct_io
127 }
128};
129#endif
130
131/* Restrict the number of modes so that names for all are assigned */
132#if ST_NBR_MODES > 16
133#error "Maximum number of modes is 16"
134#endif
135/* Bit reversed order to get same names for same minors with all
136 mode counts */
Arjan van de Ven0ad78202005-11-28 16:22:25 +0100137static const char *st_formats[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 "", "r", "k", "s", "l", "t", "o", "u",
139 "m", "v", "p", "x", "a", "y", "q", "z"};
140
141/* The default definitions have been moved to st_options.h */
142
143#define ST_FIXED_BUFFER_SIZE (ST_FIXED_BUFFER_BLOCKS * ST_KILOBYTE)
144
145/* The buffer size should fit into the 24 bits for length in the
146 6-byte SCSI read and write commands. */
147#if ST_FIXED_BUFFER_SIZE >= (2 << 24 - 1)
148#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
149#endif
150
151static int debugging = DEBUG;
152
153#define MAX_RETRIES 0
154#define MAX_WRITE_RETRIES 0
155#define MAX_READY_RETRIES 0
156#define NO_TAPE NOT_READY
157
158#define ST_TIMEOUT (900 * HZ)
159#define ST_LONG_TIMEOUT (14000 * HZ)
160
161/* Remove mode bits and auto-rewind bit (7) */
162#define TAPE_NR(x) ( ((iminor(x) & ~255) >> (ST_NBR_MODE_BITS + 1)) | \
163 (iminor(x) & ~(-1 << ST_MODE_SHIFT)) )
164#define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
165
166/* Construct the minor number from the device (d), mode (m), and non-rewind (n) data */
167#define TAPE_MINOR(d, m, n) (((d & ~(255 >> (ST_NBR_MODE_BITS + 1))) << (ST_NBR_MODE_BITS + 1)) | \
168 (d & (255 >> (ST_NBR_MODE_BITS + 1))) | (m << ST_MODE_SHIFT) | ((n != 0) << 7) )
169
170/* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
171 24 bits) */
172#define SET_DENS_AND_BLK 0x10001
173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE;
175static int st_max_sg_segs = ST_MAX_SG;
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177static int modes_defined;
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179static int enlarge_buffer(struct st_buffer *, int, int);
Kai Makisara40f6b362008-02-24 22:23:24 +0200180static void clear_buffer(struct st_buffer *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181static void normalize_buffer(struct st_buffer *);
182static int append_to_buffer(const char __user *, struct st_buffer *, int);
183static int from_buffer(struct st_buffer *, char __user *, int);
184static void move_buffer_data(struct st_buffer *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
FUJITA Tomonori66207422008-12-18 14:49:43 +0900186static int sgl_map_user_pages(struct st_buffer *, const unsigned int,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 unsigned long, size_t, int);
FUJITA Tomonori66207422008-12-18 14:49:43 +0900188static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190static int st_probe(struct device *);
191static int st_remove(struct device *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
Robert P. J. Day405ae7d2007-02-17 19:13:42 +0100193static int do_create_sysfs_files(void);
194static void do_remove_sysfs_files(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
196static struct scsi_driver st_template = {
197 .owner = THIS_MODULE,
198 .gendrv = {
199 .name = "st",
200 .probe = st_probe,
201 .remove = st_remove,
202 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203};
204
205static int st_compression(struct scsi_tape *, int);
206
207static int find_partition(struct scsi_tape *);
208static int switch_partition(struct scsi_tape *);
209
210static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
211
Kai Makisaraf03a5672005-08-02 13:40:47 +0300212static void scsi_tape_release(struct kref *);
213
214#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
215
Arjan van de Ven0b950672006-01-11 13:16:10 +0100216static DEFINE_MUTEX(st_ref_mutex);
Jeff Mahoney6c648d92012-08-18 15:20:39 -0400217static DEFINE_SPINLOCK(st_index_lock);
218static DEFINE_SPINLOCK(st_use_lock);
219static DEFINE_IDR(st_index_idr);
220
Kai Makisaraf03a5672005-08-02 13:40:47 +0300221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223#include "osst_detect.h"
224#ifndef SIGS_FROM_OSST
225#define SIGS_FROM_OSST \
226 {"OnStream", "SC-", "", "osst"}, \
227 {"OnStream", "DI-", "", "osst"}, \
228 {"OnStream", "DP-", "", "osst"}, \
229 {"OnStream", "USB", "", "osst"}, \
230 {"OnStream", "FW-", "", "osst"}
231#endif
232
Kai Makisaraf03a5672005-08-02 13:40:47 +0300233static struct scsi_tape *scsi_tape_get(int dev)
234{
235 struct scsi_tape *STp = NULL;
236
Arjan van de Ven0b950672006-01-11 13:16:10 +0100237 mutex_lock(&st_ref_mutex);
Jeff Mahoney6c648d92012-08-18 15:20:39 -0400238 spin_lock(&st_index_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300239
Jeff Mahoney6c648d92012-08-18 15:20:39 -0400240 STp = idr_find(&st_index_idr, dev);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300241 if (!STp) goto out;
242
243 kref_get(&STp->kref);
244
245 if (!STp->device)
246 goto out_put;
247
248 if (scsi_device_get(STp->device))
249 goto out_put;
250
251 goto out;
252
253out_put:
254 kref_put(&STp->kref, scsi_tape_release);
255 STp = NULL;
256out:
Jeff Mahoney6c648d92012-08-18 15:20:39 -0400257 spin_unlock(&st_index_lock);
Arjan van de Ven0b950672006-01-11 13:16:10 +0100258 mutex_unlock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300259 return STp;
260}
261
262static void scsi_tape_put(struct scsi_tape *STp)
263{
264 struct scsi_device *sdev = STp->device;
265
Arjan van de Ven0b950672006-01-11 13:16:10 +0100266 mutex_lock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300267 kref_put(&STp->kref, scsi_tape_release);
268 scsi_device_put(sdev);
Arjan van de Ven0b950672006-01-11 13:16:10 +0100269 mutex_unlock(&st_ref_mutex);
Kai Makisaraf03a5672005-08-02 13:40:47 +0300270}
271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272struct st_reject_data {
273 char *vendor;
274 char *model;
275 char *rev;
276 char *driver_hint; /* Name of the correct driver, NULL if unknown */
277};
278
279static struct st_reject_data reject_list[] = {
280 /* {"XXX", "Yy-", "", NULL}, example */
281 SIGS_FROM_OSST,
282 {NULL, }};
283
284/* If the device signature is on the list of incompatible drives, the
285 function returns a pointer to the name of the correct driver (if known) */
286static char * st_incompatible(struct scsi_device* SDp)
287{
288 struct st_reject_data *rp;
289
290 for (rp=&(reject_list[0]); rp->vendor != NULL; rp++)
291 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
292 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
293 !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) {
294 if (rp->driver_hint)
295 return rp->driver_hint;
296 else
297 return "unknown";
298 }
299 return NULL;
300}
301
302
303static inline char *tape_name(struct scsi_tape *tape)
304{
305 return tape->disk->disk_name;
306}
307
308
Mike Christie8b05b772005-11-08 04:06:44 -0600309static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310{
311 const u8 *ucp;
Mike Christie8b05b772005-11-08 04:06:44 -0600312 const u8 *sense = SRpnt->sense;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
Mike Christie8b05b772005-11-08 04:06:44 -0600314 s->have_sense = scsi_normalize_sense(SRpnt->sense,
315 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 s->flags = 0;
317
318 if (s->have_sense) {
319 s->deferred = 0;
320 s->remainder_valid =
321 scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
322 switch (sense[0] & 0x7f) {
323 case 0x71:
324 s->deferred = 1;
325 case 0x70:
326 s->fixed_format = 1;
327 s->flags = sense[2] & 0xe0;
328 break;
329 case 0x73:
330 s->deferred = 1;
331 case 0x72:
332 s->fixed_format = 0;
333 ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
334 s->flags = ucp ? (ucp[3] & 0xe0) : 0;
335 break;
336 }
337 }
338}
339
340
341/* Convert the result to success code */
Mike Christie8b05b772005-11-08 04:06:44 -0600342static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343{
Mike Christie8b05b772005-11-08 04:06:44 -0600344 int result = SRpnt->result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 u8 scode;
346 DEB(const char *stp;)
347 char *name = tape_name(STp);
348 struct st_cmdstatus *cmdstatp;
349
350 if (!result)
351 return 0;
352
353 cmdstatp = &STp->buffer->cmdstat;
Kai Makisaraf03a5672005-08-02 13:40:47 +0300354 st_analyze_sense(SRpnt, cmdstatp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
356 if (cmdstatp->have_sense)
357 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
358 else
359 scode = 0;
360
361 DEB(
362 if (debugging) {
Mike Christie8b05b772005-11-08 04:06:44 -0600363 printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 name, result,
Mike Christie8b05b772005-11-08 04:06:44 -0600365 SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
366 SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 if (cmdstatp->have_sense)
Luben Tuikov4e73ea72006-07-07 00:02:18 -0700368 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 } ) /* end DEB */
370 if (!debugging) { /* Abnormal conditions for tape */
371 if (!cmdstatp->have_sense)
372 printk(KERN_WARNING
Martin K. Petersen1c9fbaf2009-01-04 03:14:11 -0500373 "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n",
374 name, result, driver_byte(result),
375 host_byte(result));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 else if (cmdstatp->have_sense &&
377 scode != NO_SENSE &&
378 scode != RECOVERED_ERROR &&
379 /* scode != UNIT_ATTENTION && */
380 scode != BLANK_CHECK &&
381 scode != VOLUME_OVERFLOW &&
Mike Christie8b05b772005-11-08 04:06:44 -0600382 SRpnt->cmd[0] != MODE_SENSE &&
383 SRpnt->cmd[0] != TEST_UNIT_READY) {
Luben Tuikov4e73ea72006-07-07 00:02:18 -0700384
385 __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 }
387 }
388
389 if (cmdstatp->fixed_format &&
390 STp->cln_mode >= EXTENDED_SENSE_START) { /* Only fixed format sense */
391 if (STp->cln_sense_value)
Mike Christie8b05b772005-11-08 04:06:44 -0600392 STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 STp->cln_sense_mask) == STp->cln_sense_value);
394 else
Mike Christie8b05b772005-11-08 04:06:44 -0600395 STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 STp->cln_sense_mask) != 0);
397 }
398 if (cmdstatp->have_sense &&
399 cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
400 STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
401
402 STp->pos_unknown |= STp->device->was_reset;
403
404 if (cmdstatp->have_sense &&
405 scode == RECOVERED_ERROR
406#if ST_RECOVERED_WRITE_FATAL
Mike Christie8b05b772005-11-08 04:06:44 -0600407 && SRpnt->cmd[0] != WRITE_6
408 && SRpnt->cmd[0] != WRITE_FILEMARKS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409#endif
410 ) {
411 STp->recover_count++;
412 STp->recover_reg++;
413
414 DEB(
415 if (debugging) {
Mike Christie8b05b772005-11-08 04:06:44 -0600416 if (SRpnt->cmd[0] == READ_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 stp = "read";
Mike Christie8b05b772005-11-08 04:06:44 -0600418 else if (SRpnt->cmd[0] == WRITE_6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 stp = "write";
420 else
421 stp = "ioctl";
422 printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp,
423 STp->recover_count);
424 } ) /* end DEB */
425
426 if (cmdstatp->flags == 0)
427 return 0;
428 }
429 return (-EIO);
430}
431
FUJITA Tomonori4deba242008-12-05 15:25:20 +0900432static struct st_request *st_allocate_request(struct scsi_tape *stp)
Mike Christie8b05b772005-11-08 04:06:44 -0600433{
FUJITA Tomonori4deba242008-12-05 15:25:20 +0900434 struct st_request *streq;
435
436 streq = kzalloc(sizeof(*streq), GFP_KERNEL);
437 if (streq)
438 streq->stp = stp;
439 else {
440 DEBC(printk(KERN_ERR "%s: Can't get SCSI request.\n",
441 tape_name(stp)););
442 if (signal_pending(current))
443 stp->buffer->syscall_result = -EINTR;
444 else
445 stp->buffer->syscall_result = -EBUSY;
446 }
447
448 return streq;
Mike Christie8b05b772005-11-08 04:06:44 -0600449}
450
451static void st_release_request(struct st_request *streq)
452{
453 kfree(streq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454}
455
FUJITA Tomonori13b53b42008-12-18 14:49:41 +0900456static void st_scsi_execute_end(struct request *req, int uptodate)
457{
458 struct st_request *SRpnt = req->end_io_data;
459 struct scsi_tape *STp = SRpnt->stp;
Petr Uzelc68bf8e2011-10-21 13:31:09 +0200460 struct bio *tmp;
FUJITA Tomonori13b53b42008-12-18 14:49:41 +0900461
462 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
Tejun Heoc3a4d782009-05-07 22:24:37 +0900463 STp->buffer->cmdstat.residual = req->resid_len;
FUJITA Tomonori13b53b42008-12-18 14:49:41 +0900464
Petr Uzelc68bf8e2011-10-21 13:31:09 +0200465 tmp = SRpnt->bio;
FUJITA Tomonori13b53b42008-12-18 14:49:41 +0900466 if (SRpnt->waiting)
467 complete(SRpnt->waiting);
468
Petr Uzelc68bf8e2011-10-21 13:31:09 +0200469 blk_rq_unmap_user(tmp);
FUJITA Tomonori13b53b42008-12-18 14:49:41 +0900470 __blk_put_request(req->q, req);
471}
472
473static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
474 int data_direction, void *buffer, unsigned bufflen,
475 int timeout, int retries)
476{
477 struct request *req;
478 struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
479 int err = 0;
480 int write = (data_direction == DMA_TO_DEVICE);
481
482 req = blk_get_request(SRpnt->stp->device->request_queue, write,
483 GFP_KERNEL);
484 if (!req)
485 return DRIVER_ERROR << 24;
486
487 req->cmd_type = REQ_TYPE_BLOCK_PC;
488 req->cmd_flags |= REQ_QUIET;
489
490 mdata->null_mapped = 1;
491
Kai Makisara02ae2c02008-12-18 14:49:50 +0900492 if (bufflen) {
493 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen,
494 GFP_KERNEL);
495 if (err) {
496 blk_put_request(req);
497 return DRIVER_ERROR << 24;
498 }
FUJITA Tomonori13b53b42008-12-18 14:49:41 +0900499 }
500
501 SRpnt->bio = req->bio;
502 req->cmd_len = COMMAND_SIZE(cmd[0]);
503 memset(req->cmd, 0, BLK_MAX_CDB);
504 memcpy(req->cmd, cmd, req->cmd_len);
505 req->sense = SRpnt->sense;
506 req->sense_len = 0;
507 req->timeout = timeout;
508 req->retries = retries;
509 req->end_io_data = SRpnt;
510
511 blk_execute_rq_nowait(req->q, NULL, req, 1, st_scsi_execute_end);
512 return 0;
513}
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515/* Do the scsi command. Waits until command performed if do_wait is true.
516 Otherwise write_behind_check() is used to check that the command
517 has finished. */
Mike Christie8b05b772005-11-08 04:06:44 -0600518static struct st_request *
519st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 int bytes, int direction, int timeout, int retries, int do_wait)
521{
Kai Makisaraf03a5672005-08-02 13:40:47 +0300522 struct completion *waiting;
FUJITA Tomonori6d476262008-12-18 14:49:42 +0900523 struct rq_map_data *mdata = &STp->buffer->map_data;
524 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Kai Makisaraf03a5672005-08-02 13:40:47 +0300526 /* if async, make sure there's no command outstanding */
527 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
528 printk(KERN_ERR "%s: Async command already active.\n",
529 tape_name(STp));
530 if (signal_pending(current))
531 (STp->buffer)->syscall_result = (-EINTR);
532 else
533 (STp->buffer)->syscall_result = (-EBUSY);
534 return NULL;
535 }
536
FUJITA Tomonori4deba242008-12-05 15:25:20 +0900537 if (!SRpnt) {
538 SRpnt = st_allocate_request(STp);
539 if (!SRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
542
Kai Makisaraf03a5672005-08-02 13:40:47 +0300543 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
544 which IO is outstanding. It's nulled out when the IO completes. */
545 if (!do_wait)
546 (STp->buffer)->last_SRpnt = SRpnt;
547
548 waiting = &STp->wait;
549 init_completion(waiting);
Mike Christie8b05b772005-11-08 04:06:44 -0600550 SRpnt->waiting = waiting;
551
FUJITA Tomonori66207422008-12-18 14:49:43 +0900552 if (STp->buffer->do_dio) {
FUJITA Tomonoric982c362009-11-26 09:24:13 +0900553 mdata->page_order = 0;
FUJITA Tomonori66207422008-12-18 14:49:43 +0900554 mdata->nr_entries = STp->buffer->sg_segs;
555 mdata->pages = STp->buffer->mapped_pages;
556 } else {
FUJITA Tomonoric982c362009-11-26 09:24:13 +0900557 mdata->page_order = STp->buffer->reserved_page_order;
FUJITA Tomonori6d476262008-12-18 14:49:42 +0900558 mdata->nr_entries =
559 DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order);
FUJITA Tomonoric982c362009-11-26 09:24:13 +0900560 mdata->pages = STp->buffer->reserved_pages;
561 mdata->offset = 0;
FUJITA Tomonori6d476262008-12-18 14:49:42 +0900562 }
563
Mike Christie8b05b772005-11-08 04:06:44 -0600564 memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 STp->buffer->cmdstat.have_sense = 0;
Mike Christie8b05b772005-11-08 04:06:44 -0600566 STp->buffer->syscall_result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
FUJITA Tomonori66207422008-12-18 14:49:43 +0900568 ret = st_scsi_execute(SRpnt, cmd, direction, NULL, bytes, timeout,
569 retries);
FUJITA Tomonori6d476262008-12-18 14:49:42 +0900570 if (ret) {
Mike Christie8b05b772005-11-08 04:06:44 -0600571 /* could not allocate the buffer or request was too large */
572 (STp->buffer)->syscall_result = (-EBUSY);
Kai Makisara787926b2005-11-13 10:04:44 +0200573 (STp->buffer)->last_SRpnt = NULL;
FUJITA Tomonori6d476262008-12-18 14:49:42 +0900574 } else if (do_wait) {
Kai Makisaraf03a5672005-08-02 13:40:47 +0300575 wait_for_completion(waiting);
Mike Christie8b05b772005-11-08 04:06:44 -0600576 SRpnt->waiting = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
578 }
Mike Christie8b05b772005-11-08 04:06:44 -0600579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 return SRpnt;
581}
582
583
584/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
585 write has been correct but EOM early warning reached, -EIO if write ended in
586 error or zero if write successful. Asynchronous writes are used only in
587 variable block mode. */
588static int write_behind_check(struct scsi_tape * STp)
589{
590 int retval = 0;
591 struct st_buffer *STbuffer;
592 struct st_partstat *STps;
593 struct st_cmdstatus *cmdstatp;
Mike Christie8b05b772005-11-08 04:06:44 -0600594 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
596 STbuffer = STp->buffer;
597 if (!STbuffer->writing)
598 return 0;
599
600 DEB(
601 if (STp->write_pending)
602 STp->nbr_waits++;
603 else
604 STp->nbr_finished++;
605 ) /* end DEB */
606
607 wait_for_completion(&(STp->wait));
Kai Makisaraf03a5672005-08-02 13:40:47 +0300608 SRpnt = STbuffer->last_SRpnt;
609 STbuffer->last_SRpnt = NULL;
Mike Christie8b05b772005-11-08 04:06:44 -0600610 SRpnt->waiting = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Kai Makisaraf03a5672005-08-02 13:40:47 +0300612 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
Mike Christie8b05b772005-11-08 04:06:44 -0600613 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
615 STbuffer->buffer_bytes -= STbuffer->writing;
616 STps = &(STp->ps[STp->partition]);
617 if (STps->drv_block >= 0) {
618 if (STp->block_size == 0)
619 STps->drv_block++;
620 else
621 STps->drv_block += STbuffer->writing / STp->block_size;
622 }
623
624 cmdstatp = &STbuffer->cmdstat;
625 if (STbuffer->syscall_result) {
626 retval = -EIO;
627 if (cmdstatp->have_sense && !cmdstatp->deferred &&
628 (cmdstatp->flags & SENSE_EOM) &&
629 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
630 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR)) {
631 /* EOM at write-behind, has all data been written? */
632 if (!cmdstatp->remainder_valid ||
633 cmdstatp->uremainder64 == 0)
634 retval = -ENOSPC;
635 }
636 if (retval == -EIO)
637 STps->drv_block = -1;
638 }
639 STbuffer->writing = 0;
640
641 DEB(if (debugging && retval)
642 printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n",
643 tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
644
645 return retval;
646}
647
648
649/* Step over EOF if it has been inadvertently crossed (ioctl not used because
650 it messes up the block number). */
651static int cross_eof(struct scsi_tape * STp, int forward)
652{
Mike Christie8b05b772005-11-08 04:06:44 -0600653 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 unsigned char cmd[MAX_COMMAND_SIZE];
655
656 cmd[0] = SPACE;
657 cmd[1] = 0x01; /* Space FileMarks */
658 if (forward) {
659 cmd[2] = cmd[3] = 0;
660 cmd[4] = 1;
661 } else
662 cmd[2] = cmd[3] = cmd[4] = 0xff; /* -1 filemarks */
663 cmd[5] = 0;
664
665 DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",
666 tape_name(STp), forward ? "forward" : "backward"));
667
Kai Makisara02ae2c02008-12-18 14:49:50 +0900668 SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
669 STp->device->request_queue->rq_timeout,
670 MAX_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 if (!SRpnt)
Kai Makisara02ae2c02008-12-18 14:49:50 +0900672 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Kai Makisara02ae2c02008-12-18 14:49:50 +0900674 st_release_request(SRpnt);
675 SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
677 if ((STp->buffer)->cmdstat.midlevel_result != 0)
678 printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
679 tape_name(STp), forward ? "forward" : "backward");
680
Kai Makisara02ae2c02008-12-18 14:49:50 +0900681 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682}
683
684
685/* Flush the write buffer (never need to write if variable blocksize). */
Adrian Bunk8ef8d592008-04-14 17:17:16 +0300686static int st_flush_write_buffer(struct scsi_tape * STp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
Kai Makisara786231a2008-07-11 15:06:40 +0300688 int transfer, blks;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 int result;
690 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -0600691 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 struct st_partstat *STps;
693
694 result = write_behind_check(STp);
695 if (result)
696 return result;
697
698 result = 0;
699 if (STp->dirty == 1) {
700
Kai Makisara786231a2008-07-11 15:06:40 +0300701 transfer = STp->buffer->buffer_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",
703 tape_name(STp), transfer));
704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 memset(cmd, 0, MAX_COMMAND_SIZE);
706 cmd[0] = WRITE_6;
707 cmd[1] = 1;
708 blks = transfer / STp->block_size;
709 cmd[2] = blks >> 16;
710 cmd[3] = blks >> 8;
711 cmd[4] = blks;
712
713 SRpnt = st_do_scsi(NULL, STp, cmd, transfer, DMA_TO_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -0600714 STp->device->request_queue->rq_timeout,
715 MAX_WRITE_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 if (!SRpnt)
717 return (STp->buffer)->syscall_result;
718
719 STps = &(STp->ps[STp->partition]);
720 if ((STp->buffer)->syscall_result != 0) {
721 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
722
723 if (cmdstatp->have_sense && !cmdstatp->deferred &&
724 (cmdstatp->flags & SENSE_EOM) &&
725 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
726 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
727 (!cmdstatp->remainder_valid ||
728 cmdstatp->uremainder64 == 0)) { /* All written at EOM early warning */
729 STp->dirty = 0;
730 (STp->buffer)->buffer_bytes = 0;
731 if (STps->drv_block >= 0)
732 STps->drv_block += blks;
733 result = (-ENOSPC);
734 } else {
735 printk(KERN_ERR "%s: Error on flush.\n",
736 tape_name(STp));
737 STps->drv_block = (-1);
738 result = (-EIO);
739 }
740 } else {
741 if (STps->drv_block >= 0)
742 STps->drv_block += blks;
743 STp->dirty = 0;
744 (STp->buffer)->buffer_bytes = 0;
745 }
Mike Christie8b05b772005-11-08 04:06:44 -0600746 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 SRpnt = NULL;
748 }
749 return result;
750}
751
752
753/* Flush the tape buffer. The tape will be positioned correctly unless
754 seek_next is true. */
755static int flush_buffer(struct scsi_tape *STp, int seek_next)
756{
757 int backspace, result;
758 struct st_buffer *STbuffer;
759 struct st_partstat *STps;
760
761 STbuffer = STp->buffer;
762
763 /*
764 * If there was a bus reset, block further access
765 * to this device.
766 */
767 if (STp->pos_unknown)
768 return (-EIO);
769
770 if (STp->ready != ST_READY)
771 return 0;
772 STps = &(STp->ps[STp->partition]);
773 if (STps->rw == ST_WRITING) /* Writing */
Adrian Bunk8ef8d592008-04-14 17:17:16 +0300774 return st_flush_write_buffer(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 if (STp->block_size == 0)
777 return 0;
778
779 backspace = ((STp->buffer)->buffer_bytes +
780 (STp->buffer)->read_pointer) / STp->block_size -
781 ((STp->buffer)->read_pointer + STp->block_size - 1) /
782 STp->block_size;
783 (STp->buffer)->buffer_bytes = 0;
784 (STp->buffer)->read_pointer = 0;
785 result = 0;
786 if (!seek_next) {
787 if (STps->eof == ST_FM_HIT) {
788 result = cross_eof(STp, 0); /* Back over the EOF hit */
789 if (!result)
790 STps->eof = ST_NOEOF;
791 else {
792 if (STps->drv_file >= 0)
793 STps->drv_file++;
794 STps->drv_block = 0;
795 }
796 }
797 if (!result && backspace > 0)
798 result = st_int_ioctl(STp, MTBSR, backspace);
799 } else if (STps->eof == ST_FM_HIT) {
800 if (STps->drv_file >= 0)
801 STps->drv_file++;
802 STps->drv_block = 0;
803 STps->eof = ST_NOEOF;
804 }
805 return result;
806
807}
808
809/* Set the mode parameters */
810static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
811{
812 int set_it = 0;
813 unsigned long arg;
814 char *name = tape_name(STp);
815
816 if (!STp->density_changed &&
817 STm->default_density >= 0 &&
818 STm->default_density != STp->density) {
819 arg = STm->default_density;
820 set_it = 1;
821 } else
822 arg = STp->density;
823 arg <<= MT_ST_DENSITY_SHIFT;
824 if (!STp->blksize_changed &&
825 STm->default_blksize >= 0 &&
826 STm->default_blksize != STp->block_size) {
827 arg |= STm->default_blksize;
828 set_it = 1;
829 } else
830 arg |= STp->block_size;
831 if (set_it &&
832 st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {
833 printk(KERN_WARNING
834 "%s: Can't set default block size to %d bytes and density %x.\n",
835 name, STm->default_blksize, STm->default_density);
836 if (modes_defined)
837 return (-EINVAL);
838 }
839 return 0;
840}
841
842
Mike Christie8b05b772005-11-08 04:06:44 -0600843/* Lock or unlock the drive door. Don't use when st_request allocated. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844static int do_door_lock(struct scsi_tape * STp, int do_lock)
845{
846 int retval, cmd;
847 DEB(char *name = tape_name(STp);)
848
849
850 cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
851 DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name,
852 do_lock ? "L" : "Unl"));
853 retval = scsi_ioctl(STp->device, cmd, NULL);
854 if (!retval) {
855 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
856 }
857 else {
858 STp->door_locked = ST_LOCK_FAILS;
859 }
860 return retval;
861}
862
863
864/* Set the internal state after reset */
865static void reset_state(struct scsi_tape *STp)
866{
867 int i;
868 struct st_partstat *STps;
869
870 STp->pos_unknown = 0;
871 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
872 STps = &(STp->ps[i]);
873 STps->rw = ST_IDLE;
874 STps->eof = ST_NOEOF;
875 STps->at_sm = 0;
876 STps->last_block_valid = 0;
877 STps->drv_block = -1;
878 STps->drv_file = -1;
879 }
880 if (STp->can_partitions) {
881 STp->partition = find_partition(STp);
882 if (STp->partition < 0)
883 STp->partition = 0;
884 STp->new_partition = STp->partition;
885 }
886}
887
888/* Test if the drive is ready. Returns either one of the codes below or a negative system
889 error code. */
890#define CHKRES_READY 0
891#define CHKRES_NEW_SESSION 1
892#define CHKRES_NOT_READY 2
893#define CHKRES_NO_TAPE 3
894
895#define MAX_ATTENTIONS 10
896
897static int test_ready(struct scsi_tape *STp, int do_wait)
898{
899 int attentions, waits, max_wait, scode;
900 int retval = CHKRES_READY, new_session = 0;
901 unsigned char cmd[MAX_COMMAND_SIZE];
Kai Makisara02ae2c02008-12-18 14:49:50 +0900902 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
904
905 max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
906
907 for (attentions=waits=0; ; ) {
908 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
909 cmd[0] = TEST_UNIT_READY;
Kai Makisara02ae2c02008-12-18 14:49:50 +0900910 SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
911 STp->long_timeout, MAX_READY_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
Kai Makisara02ae2c02008-12-18 14:49:50 +0900913 if (!SRpnt) {
914 retval = (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 break;
Kai Makisara02ae2c02008-12-18 14:49:50 +0900916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
918 if (cmdstatp->have_sense) {
919
920 scode = cmdstatp->sense_hdr.sense_key;
921
922 if (scode == UNIT_ATTENTION) { /* New media? */
923 new_session = 1;
924 if (attentions < MAX_ATTENTIONS) {
925 attentions++;
926 continue;
927 }
928 else {
929 retval = (-EIO);
930 break;
931 }
932 }
933
934 if (scode == NOT_READY) {
935 if (waits < max_wait) {
936 if (msleep_interruptible(1000)) {
937 retval = (-EINTR);
938 break;
939 }
940 waits++;
941 continue;
942 }
943 else {
944 if ((STp->device)->scsi_level >= SCSI_2 &&
945 cmdstatp->sense_hdr.asc == 0x3a) /* Check ASC */
946 retval = CHKRES_NO_TAPE;
947 else
948 retval = CHKRES_NOT_READY;
949 break;
950 }
951 }
952 }
953
954 retval = (STp->buffer)->syscall_result;
955 if (!retval)
956 retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;
957 break;
958 }
959
Kai Makisara02ae2c02008-12-18 14:49:50 +0900960 if (SRpnt != NULL)
961 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 return retval;
963}
964
965
966/* See if the drive is ready and gather information about the tape. Return values:
967 < 0 negative error code from errno.h
968 0 drive ready
969 1 drive not ready (possibly no tape)
970*/
971static int check_tape(struct scsi_tape *STp, struct file *filp)
972{
973 int i, retval, new_session = 0, do_wait;
974 unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
975 unsigned short st_flags = filp->f_flags;
Mike Christie8b05b772005-11-08 04:06:44 -0600976 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 struct st_modedef *STm;
978 struct st_partstat *STps;
979 char *name = tape_name(STp);
Al Viro496ad9a2013-01-23 17:07:38 -0500980 struct inode *inode = file_inode(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 int mode = TAPE_MODE(inode);
982
983 STp->ready = ST_READY;
984
985 if (mode != STp->current_mode) {
986 DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n",
987 name, STp->current_mode, mode));
988 new_session = 1;
989 STp->current_mode = mode;
990 }
991 STm = &(STp->modes[STp->current_mode]);
992
993 saved_cleaning = STp->cleaning_req;
994 STp->cleaning_req = 0;
995
996 do_wait = ((filp->f_flags & O_NONBLOCK) == 0);
997 retval = test_ready(STp, do_wait);
998
999 if (retval < 0)
1000 goto err_out;
1001
1002 if (retval == CHKRES_NEW_SESSION) {
1003 STp->pos_unknown = 0;
1004 STp->partition = STp->new_partition = 0;
1005 if (STp->can_partitions)
1006 STp->nbr_partitions = 1; /* This guess will be updated later
1007 if necessary */
1008 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
1009 STps = &(STp->ps[i]);
1010 STps->rw = ST_IDLE;
1011 STps->eof = ST_NOEOF;
1012 STps->at_sm = 0;
1013 STps->last_block_valid = 0;
1014 STps->drv_block = 0;
1015 STps->drv_file = 0;
1016 }
1017 new_session = 1;
1018 }
1019 else {
1020 STp->cleaning_req |= saved_cleaning;
1021
1022 if (retval == CHKRES_NOT_READY || retval == CHKRES_NO_TAPE) {
1023 if (retval == CHKRES_NO_TAPE)
1024 STp->ready = ST_NO_TAPE;
1025 else
1026 STp->ready = ST_NOT_READY;
1027
1028 STp->density = 0; /* Clear the erroneous "residue" */
1029 STp->write_prot = 0;
1030 STp->block_size = 0;
1031 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
1032 STp->partition = STp->new_partition = 0;
1033 STp->door_locked = ST_UNLOCKED;
1034 return CHKRES_NOT_READY;
1035 }
1036 }
1037
1038 if (STp->omit_blklims)
1039 STp->min_block = STp->max_block = (-1);
1040 else {
1041 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
1042 cmd[0] = READ_BLOCK_LIMITS;
1043
Kai Makisara02ae2c02008-12-18 14:49:50 +09001044 SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE,
1045 STp->device->request_queue->rq_timeout,
1046 MAX_READY_RETRIES, 1);
1047 if (!SRpnt) {
1048 retval = (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 goto err_out;
1050 }
1051
Mike Christie8b05b772005-11-08 04:06:44 -06001052 if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 STp->max_block = ((STp->buffer)->b_data[1] << 16) |
1054 ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
1055 STp->min_block = ((STp->buffer)->b_data[4] << 8) |
1056 (STp->buffer)->b_data[5];
1057 if ( DEB( debugging || ) !STp->inited)
Kai Makisara422528542006-11-07 21:56:38 +02001058 printk(KERN_INFO
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 "%s: Block limits %d - %d bytes.\n", name,
1060 STp->min_block, STp->max_block);
1061 } else {
1062 STp->min_block = STp->max_block = (-1);
1063 DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",
1064 name));
1065 }
1066 }
1067
1068 memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
1069 cmd[0] = MODE_SENSE;
1070 cmd[4] = 12;
1071
Kai Makisara02ae2c02008-12-18 14:49:50 +09001072 SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE,
1073 STp->device->request_queue->rq_timeout,
1074 MAX_READY_RETRIES, 1);
1075 if (!SRpnt) {
1076 retval = (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 goto err_out;
1078 }
1079
1080 if ((STp->buffer)->syscall_result != 0) {
1081 DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name));
1082 STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */
1083 (STp->buffer)->syscall_result = 0; /* Prevent error propagation */
1084 STp->drv_write_prot = 0;
1085 } else {
1086 DEBC(printk(ST_DEB_MSG
1087 "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",
1088 name,
1089 (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
1090 (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]));
1091
1092 if ((STp->buffer)->b_data[3] >= 8) {
1093 STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
1094 STp->density = (STp->buffer)->b_data[4];
1095 STp->block_size = (STp->buffer)->b_data[9] * 65536 +
1096 (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
1097 DEBC(printk(ST_DEB_MSG
1098 "%s: Density %x, tape length: %x, drv buffer: %d\n",
1099 name, STp->density, (STp->buffer)->b_data[5] * 65536 +
1100 (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
1101 STp->drv_buffer));
1102 }
1103 STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
Lee Duncanc743e442012-03-01 12:41:01 -08001104 if (!STp->drv_buffer && STp->immediate_filemark) {
1105 printk(KERN_WARNING
1106 "%s: non-buffered tape: disabling writing immediate filemarks\n",
1107 name);
1108 STp->immediate_filemark = 0;
1109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 }
Mike Christie8b05b772005-11-08 04:06:44 -06001111 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 SRpnt = NULL;
1113 STp->inited = 1;
1114
1115 if (STp->block_size > 0)
1116 (STp->buffer)->buffer_blocks =
1117 (STp->buffer)->buffer_size / STp->block_size;
1118 else
1119 (STp->buffer)->buffer_blocks = 1;
1120 (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
1121
1122 DEBC(printk(ST_DEB_MSG
1123 "%s: Block size: %d, buffer size: %d (%d blocks).\n", name,
1124 STp->block_size, (STp->buffer)->buffer_size,
1125 (STp->buffer)->buffer_blocks));
1126
1127 if (STp->drv_write_prot) {
1128 STp->write_prot = 1;
1129
1130 DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name));
1131
1132 if (do_wait &&
1133 ((st_flags & O_ACCMODE) == O_WRONLY ||
1134 (st_flags & O_ACCMODE) == O_RDWR)) {
1135 retval = (-EROFS);
1136 goto err_out;
1137 }
1138 }
1139
1140 if (STp->can_partitions && STp->nbr_partitions < 1) {
1141 /* This code is reached when the device is opened for the first time
1142 after the driver has been initialized with tape in the drive and the
1143 partition support has been enabled. */
1144 DEBC(printk(ST_DEB_MSG
1145 "%s: Updating partition number in status.\n", name));
1146 if ((STp->partition = find_partition(STp)) < 0) {
1147 retval = STp->partition;
1148 goto err_out;
1149 }
1150 STp->new_partition = STp->partition;
1151 STp->nbr_partitions = 1; /* This guess will be updated when necessary */
1152 }
1153
1154 if (new_session) { /* Change the drive parameters for the new mode */
1155 STp->density_changed = STp->blksize_changed = 0;
1156 STp->compression_changed = 0;
1157 if (!(STm->defaults_for_writes) &&
1158 (retval = set_mode_densblk(STp, STm)) < 0)
1159 goto err_out;
1160
1161 if (STp->default_drvbuffer != 0xff) {
1162 if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))
1163 printk(KERN_WARNING
1164 "%s: Can't set default drive buffering to %d.\n",
1165 name, STp->default_drvbuffer);
1166 }
1167 }
1168
1169 return CHKRES_READY;
1170
1171 err_out:
1172 return retval;
1173}
1174
1175
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001176 /* Open the device. Needs to take the BKL only because of incrementing the SCSI host
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 module count. */
1178static int st_open(struct inode *inode, struct file *filp)
1179{
1180 int i, retval = (-EIO);
Oliver Neukum46a243f2012-01-15 00:16:51 +01001181 int resumed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 struct scsi_tape *STp;
1183 struct st_partstat *STps;
1184 int dev = TAPE_NR(inode);
1185 char *name;
1186
1187 /*
1188 * We really want to do nonseekable_open(inode, filp); here, but some
1189 * versions of tar incorrectly call lseek on tapes and bail out if that
1190 * fails. So we disallow pread() and pwrite(), but permit lseeks.
1191 */
1192 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
1193
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001194 if (!(STp = scsi_tape_get(dev))) {
Kai Makisaraf03a5672005-08-02 13:40:47 +03001195 return -ENXIO;
Jonathan Corbetb3369c62008-05-15 16:08:15 -06001196 }
Kai Makisaraf03a5672005-08-02 13:40:47 +03001197
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 filp->private_data = STp;
1199 name = tape_name(STp);
1200
Jeff Mahoney6c648d92012-08-18 15:20:39 -04001201 spin_lock(&st_use_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 if (STp->in_use) {
Jeff Mahoney6c648d92012-08-18 15:20:39 -04001203 spin_unlock(&st_use_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001204 scsi_tape_put(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
1206 return (-EBUSY);
1207 }
1208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 STp->in_use = 1;
Jeff Mahoney6c648d92012-08-18 15:20:39 -04001210 spin_unlock(&st_use_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
1212
Oliver Neukum46a243f2012-01-15 00:16:51 +01001213 if (scsi_autopm_get_device(STp->device) < 0) {
1214 retval = -EIO;
1215 goto err_out;
1216 }
1217 resumed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 if (!scsi_block_when_processing_errors(STp->device)) {
1219 retval = (-ENXIO);
1220 goto err_out;
1221 }
1222
1223 /* See that we have at least a one page buffer available */
1224 if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) {
1225 printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n",
1226 name);
1227 retval = (-EOVERFLOW);
1228 goto err_out;
1229 }
1230
Kai Makisara40f6b362008-02-24 22:23:24 +02001231 (STp->buffer)->cleared = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 (STp->buffer)->writing = 0;
1233 (STp->buffer)->syscall_result = 0;
1234
1235 STp->write_prot = ((filp->f_flags & O_ACCMODE) == O_RDONLY);
1236
1237 STp->dirty = 0;
1238 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
1239 STps = &(STp->ps[i]);
1240 STps->rw = ST_IDLE;
1241 }
Kai Makisara9abe16c2007-02-03 13:21:29 +02001242 STp->try_dio_now = STp->try_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 STp->recover_count = 0;
1244 DEB( STp->nbr_waits = STp->nbr_finished = 0;
Kai Makisaradeee13d2008-02-22 20:11:21 +02001245 STp->nbr_requests = STp->nbr_dio = STp->nbr_pages = 0; )
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 retval = check_tape(STp, filp);
1248 if (retval < 0)
1249 goto err_out;
1250 if ((filp->f_flags & O_NONBLOCK) == 0 &&
1251 retval != CHKRES_READY) {
Kai Makisara413f7322006-10-05 22:59:46 +03001252 if (STp->ready == NO_TAPE)
1253 retval = (-ENOMEDIUM);
1254 else
1255 retval = (-EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 goto err_out;
1257 }
1258 return 0;
1259
1260 err_out:
1261 normalize_buffer(STp->buffer);
Hannes Reinecke0644f532012-09-10 15:36:44 -07001262 spin_lock(&st_use_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 STp->in_use = 0;
Hannes Reinecke0644f532012-09-10 15:36:44 -07001264 spin_unlock(&st_use_lock);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001265 scsi_tape_put(STp);
Oliver Neukum46a243f2012-01-15 00:16:51 +01001266 if (resumed)
1267 scsi_autopm_put_device(STp->device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 return retval;
1269
1270}
1271
1272
1273/* Flush the tape buffer before close */
Miklos Szeredi75e1fcc2006-06-23 02:05:12 -07001274static int st_flush(struct file *filp, fl_owner_t id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275{
1276 int result = 0, result2;
1277 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06001278 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 struct scsi_tape *STp = filp->private_data;
1280 struct st_modedef *STm = &(STp->modes[STp->current_mode]);
1281 struct st_partstat *STps = &(STp->ps[STp->partition]);
1282 char *name = tape_name(STp);
1283
1284 if (file_count(filp) > 1)
1285 return 0;
1286
1287 if (STps->rw == ST_WRITING && !STp->pos_unknown) {
Adrian Bunk8ef8d592008-04-14 17:17:16 +03001288 result = st_flush_write_buffer(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 if (result != 0 && result != (-ENOSPC))
1290 goto out;
1291 }
1292
1293 if (STp->can_partitions &&
1294 (result2 = switch_partition(STp)) < 0) {
1295 DEBC(printk(ST_DEB_MSG
1296 "%s: switch_partition at close failed.\n", name));
1297 if (result == 0)
1298 result = result2;
1299 goto out;
1300 }
1301
1302 DEBC( if (STp->nbr_requests)
Kai Makisaradeee13d2008-02-22 20:11:21 +02001303 printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n",
1304 name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306 if (STps->rw == ST_WRITING && !STp->pos_unknown) {
1307 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1308
1309 DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n",
1310 name, STp->nbr_waits, STp->nbr_finished);
1311 )
1312
1313 memset(cmd, 0, MAX_COMMAND_SIZE);
1314 cmd[0] = WRITE_FILEMARKS;
Lee Duncanc743e442012-03-01 12:41:01 -08001315 if (STp->immediate_filemark)
1316 cmd[1] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 cmd[4] = 1 + STp->two_fm;
1318
Kai Makisara02ae2c02008-12-18 14:49:50 +09001319 SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
1320 STp->device->request_queue->rq_timeout,
1321 MAX_WRITE_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 if (!SRpnt) {
Kai Makisara02ae2c02008-12-18 14:49:50 +09001323 result = (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 goto out;
1325 }
1326
1327 if (STp->buffer->syscall_result == 0 ||
1328 (cmdstatp->have_sense && !cmdstatp->deferred &&
1329 (cmdstatp->flags & SENSE_EOM) &&
1330 (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
1331 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
1332 (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
1333 /* Write successful at EOM */
Mike Christie8b05b772005-11-08 04:06:44 -06001334 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 SRpnt = NULL;
1336 if (STps->drv_file >= 0)
1337 STps->drv_file++;
1338 STps->drv_block = 0;
1339 if (STp->two_fm)
1340 cross_eof(STp, 0);
1341 STps->eof = ST_FM;
1342 }
1343 else { /* Write error */
Mike Christie8b05b772005-11-08 04:06:44 -06001344 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 SRpnt = NULL;
1346 printk(KERN_ERR "%s: Error on write filemark.\n", name);
1347 if (result == 0)
1348 result = (-EIO);
1349 }
1350
1351 DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n",
1352 name, cmd[4]));
1353 } else if (!STp->rew_at_close) {
1354 STps = &(STp->ps[STp->partition]);
1355 if (!STm->sysv || STps->rw != ST_READING) {
1356 if (STp->can_bsr)
1357 result = flush_buffer(STp, 0);
1358 else if (STps->eof == ST_FM_HIT) {
1359 result = cross_eof(STp, 0);
1360 if (result) {
1361 if (STps->drv_file >= 0)
1362 STps->drv_file++;
1363 STps->drv_block = 0;
1364 STps->eof = ST_FM;
1365 } else
1366 STps->eof = ST_NOEOF;
1367 }
1368 } else if ((STps->eof == ST_NOEOF &&
1369 !(result = cross_eof(STp, 1))) ||
1370 STps->eof == ST_FM_HIT) {
1371 if (STps->drv_file >= 0)
1372 STps->drv_file++;
1373 STps->drv_block = 0;
1374 STps->eof = ST_FM;
1375 }
1376 }
1377
1378 out:
1379 if (STp->rew_at_close) {
1380 result2 = st_int_ioctl(STp, MTREW, 1);
1381 if (result == 0)
1382 result = result2;
1383 }
1384 return result;
1385}
1386
1387
1388/* Close the device and release it. BKL is not needed: this is the only thread
1389 accessing this tape. */
1390static int st_release(struct inode *inode, struct file *filp)
1391{
1392 int result = 0;
1393 struct scsi_tape *STp = filp->private_data;
1394
1395 if (STp->door_locked == ST_LOCKED_AUTO)
1396 do_door_lock(STp, 0);
1397
1398 normalize_buffer(STp->buffer);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04001399 spin_lock(&st_use_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 STp->in_use = 0;
Jeff Mahoney6c648d92012-08-18 15:20:39 -04001401 spin_unlock(&st_use_lock);
Oliver Neukum46a243f2012-01-15 00:16:51 +01001402 scsi_autopm_put_device(STp->device);
Kai Makisaraf03a5672005-08-02 13:40:47 +03001403 scsi_tape_put(STp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
1405 return result;
1406}
1407
1408/* The checks common to both reading and writing */
1409static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count)
1410{
1411 ssize_t retval = 0;
1412
1413 /*
1414 * If we are in the middle of error recovery, don't let anyone
1415 * else try and use this device. Also, if error recovery fails, it
1416 * may try and take the device offline, in which case all further
1417 * access to the device is prohibited.
1418 */
1419 if (!scsi_block_when_processing_errors(STp->device)) {
1420 retval = (-ENXIO);
1421 goto out;
1422 }
1423
1424 if (STp->ready != ST_READY) {
1425 if (STp->ready == ST_NO_TAPE)
1426 retval = (-ENOMEDIUM);
1427 else
1428 retval = (-EIO);
1429 goto out;
1430 }
1431
1432 if (! STp->modes[STp->current_mode].defined) {
1433 retval = (-ENXIO);
1434 goto out;
1435 }
1436
1437
1438 /*
1439 * If there was a bus reset, block further access
1440 * to this device.
1441 */
1442 if (STp->pos_unknown) {
1443 retval = (-EIO);
1444 goto out;
1445 }
1446
1447 if (count == 0)
1448 goto out;
1449
1450 DEB(
1451 if (!STp->in_use) {
1452 printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp));
1453 retval = (-EIO);
1454 goto out;
1455 } ) /* end DEB */
1456
1457 if (STp->can_partitions &&
1458 (retval = switch_partition(STp)) < 0)
1459 goto out;
1460
1461 if (STp->block_size == 0 && STp->max_block > 0 &&
1462 (count < STp->min_block || count > STp->max_block)) {
1463 retval = (-EINVAL);
1464 goto out;
1465 }
1466
1467 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
1468 !do_door_lock(STp, 1))
1469 STp->door_locked = ST_LOCKED_AUTO;
1470
1471 out:
1472 return retval;
1473}
1474
1475
1476static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
1477 size_t count, int is_read)
1478{
1479 int i, bufsize, retval = 0;
1480 struct st_buffer *STbp = STp->buffer;
1481
1482 if (is_read)
Kai Makisara9abe16c2007-02-03 13:21:29 +02001483 i = STp->try_dio_now && try_rdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 else
Kai Makisara9abe16c2007-02-03 13:21:29 +02001485 i = STp->try_dio_now && try_wdio;
Mike Christie8b05b772005-11-08 04:06:44 -06001486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 if (i && ((unsigned long)buf & queue_dma_alignment(
1488 STp->device->request_queue)) == 0) {
FUJITA Tomonori66207422008-12-18 14:49:43 +09001489 i = sgl_map_user_pages(STbp, STbp->use_sg, (unsigned long)buf,
1490 count, (is_read ? READ : WRITE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 if (i > 0) {
1492 STbp->do_dio = i;
1493 STbp->buffer_bytes = 0; /* can be used as transfer counter */
1494 }
1495 else
1496 STbp->do_dio = 0; /* fall back to buffering with any error */
1497 STbp->sg_segs = STbp->do_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 DEB(
1499 if (STbp->do_dio) {
1500 STp->nbr_dio++;
1501 STp->nbr_pages += STbp->do_dio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 }
1503 )
1504 } else
1505 STbp->do_dio = 0;
1506 DEB( STp->nbr_requests++; )
1507
1508 if (!STbp->do_dio) {
1509 if (STp->block_size)
1510 bufsize = STp->block_size > st_fixed_buffer_size ?
1511 STp->block_size : st_fixed_buffer_size;
Kai Makisara40f6b362008-02-24 22:23:24 +02001512 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 bufsize = count;
Kai Makisara40f6b362008-02-24 22:23:24 +02001514 /* Make sure that data from previous user is not leaked even if
1515 HBA does not return correct residual */
1516 if (is_read && STp->sili && !STbp->cleared)
1517 clear_buffer(STbp);
1518 }
1519
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 if (bufsize > STbp->buffer_size &&
1521 !enlarge_buffer(STbp, bufsize, STp->restr_dma)) {
1522 printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n",
1523 tape_name(STp), bufsize);
1524 retval = (-EOVERFLOW);
1525 goto out;
1526 }
1527 if (STp->block_size)
1528 STbp->buffer_blocks = bufsize / STp->block_size;
1529 }
1530
1531 out:
1532 return retval;
1533}
1534
1535
1536/* Can be called more than once after each setup_buffer() */
Kai Makisara787926b2005-11-13 10:04:44 +02001537static void release_buffering(struct scsi_tape *STp, int is_read)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538{
1539 struct st_buffer *STbp;
1540
1541 STbp = STp->buffer;
1542 if (STbp->do_dio) {
FUJITA Tomonori66207422008-12-18 14:49:43 +09001543 sgl_unmap_user_pages(STbp, STbp->do_dio, is_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 STbp->do_dio = 0;
Kai Makisara787926b2005-11-13 10:04:44 +02001545 STbp->sg_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 }
1547}
1548
1549
1550/* Write command */
1551static ssize_t
1552st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
1553{
1554 ssize_t total;
1555 ssize_t i, do_count, blks, transfer;
1556 ssize_t retval;
1557 int undone, retry_eot = 0, scode;
1558 int async_write;
1559 unsigned char cmd[MAX_COMMAND_SIZE];
1560 const char __user *b_point;
Mike Christie8b05b772005-11-08 04:06:44 -06001561 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 struct scsi_tape *STp = filp->private_data;
1563 struct st_modedef *STm;
1564 struct st_partstat *STps;
1565 struct st_buffer *STbp;
1566 char *name = tape_name(STp);
1567
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001568 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 return -ERESTARTSYS;
1570
1571 retval = rw_checks(STp, filp, count);
1572 if (retval || count == 0)
1573 goto out;
1574
1575 /* Write must be integral number of blocks */
1576 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
1577 printk(KERN_WARNING "%s: Write not multiple of tape block size.\n",
1578 name);
1579 retval = (-EINVAL);
1580 goto out;
1581 }
1582
1583 STm = &(STp->modes[STp->current_mode]);
1584 STps = &(STp->ps[STp->partition]);
1585
1586 if (STp->write_prot) {
1587 retval = (-EACCES);
1588 goto out;
1589 }
1590
1591
1592 if (STps->rw == ST_READING) {
1593 retval = flush_buffer(STp, 0);
1594 if (retval)
1595 goto out;
1596 STps->rw = ST_WRITING;
1597 } else if (STps->rw != ST_WRITING &&
1598 STps->drv_file == 0 && STps->drv_block == 0) {
1599 if ((retval = set_mode_densblk(STp, STm)) < 0)
1600 goto out;
1601 if (STm->default_compression != ST_DONT_TOUCH &&
1602 !(STp->compression_changed)) {
1603 if (st_compression(STp, (STm->default_compression == ST_YES))) {
1604 printk(KERN_WARNING "%s: Can't set default compression.\n",
1605 name);
1606 if (modes_defined) {
1607 retval = (-EINVAL);
1608 goto out;
1609 }
1610 }
1611 }
1612 }
1613
1614 STbp = STp->buffer;
1615 i = write_behind_check(STp);
1616 if (i) {
1617 if (i == -ENOSPC)
1618 STps->eof = ST_EOM_OK;
1619 else
1620 STps->eof = ST_EOM_ERROR;
1621 }
1622
1623 if (STps->eof == ST_EOM_OK) {
1624 STps->eof = ST_EOD_1; /* allow next write */
1625 retval = (-ENOSPC);
1626 goto out;
1627 }
1628 else if (STps->eof == ST_EOM_ERROR) {
1629 retval = (-EIO);
1630 goto out;
1631 }
1632
1633 /* Check the buffer readability in cases where copy_user might catch
1634 the problems after some tape movement. */
1635 if (STp->block_size != 0 &&
1636 !STbp->do_dio &&
1637 (copy_from_user(&i, buf, 1) != 0 ||
1638 copy_from_user(&i, buf + count - 1, 1) != 0)) {
1639 retval = (-EFAULT);
1640 goto out;
1641 }
1642
1643 retval = setup_buffering(STp, buf, count, 0);
1644 if (retval)
1645 goto out;
1646
1647 total = count;
1648
1649 memset(cmd, 0, MAX_COMMAND_SIZE);
1650 cmd[0] = WRITE_6;
1651 cmd[1] = (STp->block_size != 0);
1652
1653 STps->rw = ST_WRITING;
1654
1655 b_point = buf;
1656 while (count > 0 && !retry_eot) {
1657
1658 if (STbp->do_dio) {
1659 do_count = count;
1660 }
1661 else {
1662 if (STp->block_size == 0)
1663 do_count = count;
1664 else {
1665 do_count = STbp->buffer_blocks * STp->block_size -
1666 STbp->buffer_bytes;
1667 if (do_count > count)
1668 do_count = count;
1669 }
1670
1671 i = append_to_buffer(b_point, STbp, do_count);
1672 if (i) {
1673 retval = i;
1674 goto out;
1675 }
1676 }
1677 count -= do_count;
1678 b_point += do_count;
1679
1680 async_write = STp->block_size == 0 && !STbp->do_dio &&
1681 STm->do_async_writes && STps->eof < ST_EOM_OK;
1682
1683 if (STp->block_size != 0 && STm->do_buffer_writes &&
Kai Makisara9abe16c2007-02-03 13:21:29 +02001684 !(STp->try_dio_now && try_wdio) && STps->eof < ST_EOM_OK &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 STbp->buffer_bytes < STbp->buffer_size) {
1686 STp->dirty = 1;
1687 /* Don't write a buffer that is not full enough. */
1688 if (!async_write && count == 0)
1689 break;
1690 }
1691
1692 retry_write:
1693 if (STp->block_size == 0)
1694 blks = transfer = do_count;
1695 else {
1696 if (!STbp->do_dio)
1697 blks = STbp->buffer_bytes;
1698 else
1699 blks = do_count;
1700 blks /= STp->block_size;
1701 transfer = blks * STp->block_size;
1702 }
1703 cmd[2] = blks >> 16;
1704 cmd[3] = blks >> 8;
1705 cmd[4] = blks;
1706
1707 SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06001708 STp->device->request_queue->rq_timeout,
1709 MAX_WRITE_RETRIES, !async_write);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 if (!SRpnt) {
1711 retval = STbp->syscall_result;
1712 goto out;
1713 }
Mike Christie8b05b772005-11-08 04:06:44 -06001714 if (async_write && !STbp->syscall_result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 STbp->writing = transfer;
1716 STp->dirty = !(STbp->writing ==
1717 STbp->buffer_bytes);
1718 SRpnt = NULL; /* Prevent releasing this request! */
1719 DEB( STp->write_pending = 1; )
1720 break;
1721 }
1722
1723 if (STbp->syscall_result != 0) {
1724 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1725
1726 DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));
1727 if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) {
1728 scode = cmdstatp->sense_hdr.sense_key;
1729 if (cmdstatp->remainder_valid)
1730 undone = (int)cmdstatp->uremainder64;
1731 else if (STp->block_size == 0 &&
1732 scode == VOLUME_OVERFLOW)
1733 undone = transfer;
1734 else
1735 undone = 0;
1736 if (STp->block_size != 0)
1737 undone *= STp->block_size;
1738 if (undone <= do_count) {
1739 /* Only data from this write is not written */
1740 count += undone;
Kai Makisara626dcb12008-07-11 15:05:25 +03001741 b_point -= undone;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 do_count -= undone;
1743 if (STp->block_size)
1744 blks = (transfer - undone) / STp->block_size;
1745 STps->eof = ST_EOM_OK;
1746 /* Continue in fixed block mode if all written
1747 in this request but still something left to write
1748 (retval left to zero)
1749 */
1750 if (STp->block_size == 0 ||
1751 undone > 0 || count == 0)
1752 retval = (-ENOSPC); /* EOM within current request */
1753 DEBC(printk(ST_DEB_MSG
1754 "%s: EOM with %d bytes unwritten.\n",
1755 name, (int)count));
1756 } else {
1757 /* EOT within data buffered earlier (possible only
1758 in fixed block mode without direct i/o) */
1759 if (!retry_eot && !cmdstatp->deferred &&
1760 (scode == NO_SENSE || scode == RECOVERED_ERROR)) {
1761 move_buffer_data(STp->buffer, transfer - undone);
1762 retry_eot = 1;
1763 if (STps->drv_block >= 0) {
1764 STps->drv_block += (transfer - undone) /
1765 STp->block_size;
1766 }
1767 STps->eof = ST_EOM_OK;
1768 DEBC(printk(ST_DEB_MSG
1769 "%s: Retry write of %d bytes at EOM.\n",
1770 name, STp->buffer->buffer_bytes));
1771 goto retry_write;
1772 }
1773 else {
1774 /* Either error within data buffered by driver or
1775 failed retry */
1776 count -= do_count;
1777 blks = do_count = 0;
1778 STps->eof = ST_EOM_ERROR;
1779 STps->drv_block = (-1); /* Too cautious? */
1780 retval = (-EIO); /* EOM for old data */
1781 DEBC(printk(ST_DEB_MSG
1782 "%s: EOM with lost data.\n",
1783 name));
1784 }
1785 }
1786 } else {
1787 count += do_count;
1788 STps->drv_block = (-1); /* Too cautious? */
Mike Christie8b05b772005-11-08 04:06:44 -06001789 retval = STbp->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 }
1791
1792 }
1793
1794 if (STps->drv_block >= 0) {
1795 if (STp->block_size == 0)
1796 STps->drv_block += (do_count > 0);
1797 else
1798 STps->drv_block += blks;
1799 }
1800
1801 STbp->buffer_bytes = 0;
1802 STp->dirty = 0;
1803
1804 if (retval || retry_eot) {
1805 if (count < total)
1806 retval = total - count;
1807 goto out;
1808 }
1809 }
1810
1811 if (STps->eof == ST_EOD_1)
1812 STps->eof = ST_EOM_OK;
1813 else if (STps->eof != ST_EOM_OK)
1814 STps->eof = ST_NOEOF;
1815 retval = total - count;
1816
1817 out:
1818 if (SRpnt != NULL)
Mike Christie8b05b772005-11-08 04:06:44 -06001819 st_release_request(SRpnt);
Kai Makisara787926b2005-11-13 10:04:44 +02001820 release_buffering(STp, 0);
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02001821 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
1823 return retval;
1824}
1825
1826/* Read data from the tape. Returns zero in the normal case, one if the
1827 eof status has changed, and the negative error code in case of a
1828 fatal error. Otherwise updates the buffer and the eof state.
1829
1830 Does release user buffer mapping if it is set.
1831*/
1832static long read_tape(struct scsi_tape *STp, long count,
Mike Christie8b05b772005-11-08 04:06:44 -06001833 struct st_request ** aSRpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
1835 int transfer, blks, bytes;
1836 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06001837 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 struct st_modedef *STm;
1839 struct st_partstat *STps;
1840 struct st_buffer *STbp;
1841 int retval = 0;
1842 char *name = tape_name(STp);
1843
1844 if (count == 0)
1845 return 0;
1846
1847 STm = &(STp->modes[STp->current_mode]);
1848 STps = &(STp->ps[STp->partition]);
1849 if (STps->eof == ST_FM_HIT)
1850 return 1;
1851 STbp = STp->buffer;
1852
1853 if (STp->block_size == 0)
1854 blks = bytes = count;
1855 else {
Kai Makisara9abe16c2007-02-03 13:21:29 +02001856 if (!(STp->try_dio_now && try_rdio) && STm->do_read_ahead) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 blks = (STp->buffer)->buffer_blocks;
1858 bytes = blks * STp->block_size;
1859 } else {
1860 bytes = count;
1861 if (!STbp->do_dio && bytes > (STp->buffer)->buffer_size)
1862 bytes = (STp->buffer)->buffer_size;
1863 blks = bytes / STp->block_size;
1864 bytes = blks * STp->block_size;
1865 }
1866 }
1867
1868 memset(cmd, 0, MAX_COMMAND_SIZE);
1869 cmd[0] = READ_6;
1870 cmd[1] = (STp->block_size != 0);
Kai Makisara40f6b362008-02-24 22:23:24 +02001871 if (!cmd[1] && STp->sili)
1872 cmd[1] |= 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 cmd[2] = blks >> 16;
1874 cmd[3] = blks >> 8;
1875 cmd[4] = blks;
1876
1877 SRpnt = *aSRpnt;
1878 SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE,
James Bottomleya02488e2008-11-30 10:36:26 -06001879 STp->device->request_queue->rq_timeout,
1880 MAX_RETRIES, 1);
Kai Makisara787926b2005-11-13 10:04:44 +02001881 release_buffering(STp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 *aSRpnt = SRpnt;
1883 if (!SRpnt)
1884 return STbp->syscall_result;
1885
1886 STbp->read_pointer = 0;
1887 STps->at_sm = 0;
1888
1889 /* Something to check */
1890 if (STbp->syscall_result) {
1891 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
1892
1893 retval = 1;
1894 DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1895 name,
Mike Christie8b05b772005-11-08 04:06:44 -06001896 SRpnt->sense[0], SRpnt->sense[1],
1897 SRpnt->sense[2], SRpnt->sense[3],
1898 SRpnt->sense[4], SRpnt->sense[5],
1899 SRpnt->sense[6], SRpnt->sense[7]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 if (cmdstatp->have_sense) {
1901
1902 if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
1903 cmdstatp->flags &= 0xcf; /* No need for EOM in this case */
1904
1905 if (cmdstatp->flags != 0) { /* EOF, EOM, or ILI */
1906 /* Compute the residual count */
1907 if (cmdstatp->remainder_valid)
1908 transfer = (int)cmdstatp->uremainder64;
1909 else
1910 transfer = 0;
1911 if (STp->block_size == 0 &&
1912 cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR)
1913 transfer = bytes;
1914
1915 if (cmdstatp->flags & SENSE_ILI) { /* ILI */
1916 if (STp->block_size == 0) {
1917 if (transfer <= 0) {
1918 if (transfer < 0)
1919 printk(KERN_NOTICE
1920 "%s: Failed to read %d byte block with %d byte transfer.\n",
1921 name, bytes - transfer, bytes);
1922 if (STps->drv_block >= 0)
1923 STps->drv_block += 1;
1924 STbp->buffer_bytes = 0;
1925 return (-ENOMEM);
1926 }
1927 STbp->buffer_bytes = bytes - transfer;
1928 } else {
Mike Christie8b05b772005-11-08 04:06:44 -06001929 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 SRpnt = *aSRpnt = NULL;
1931 if (transfer == blks) { /* We did not get anything, error */
1932 printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
1933 if (STps->drv_block >= 0)
1934 STps->drv_block += blks - transfer + 1;
1935 st_int_ioctl(STp, MTBSR, 1);
1936 return (-EIO);
1937 }
1938 /* We have some data, deliver it */
1939 STbp->buffer_bytes = (blks - transfer) *
1940 STp->block_size;
1941 DEBC(printk(ST_DEB_MSG
1942 "%s: ILI but enough data received %ld %d.\n",
1943 name, count, STbp->buffer_bytes));
1944 if (STps->drv_block >= 0)
1945 STps->drv_block += 1;
1946 if (st_int_ioctl(STp, MTBSR, 1))
1947 return (-EIO);
1948 }
1949 } else if (cmdstatp->flags & SENSE_FMK) { /* FM overrides EOM */
1950 if (STps->eof != ST_FM_HIT)
1951 STps->eof = ST_FM_HIT;
1952 else
1953 STps->eof = ST_EOD_2;
1954 if (STp->block_size == 0)
1955 STbp->buffer_bytes = 0;
1956 else
1957 STbp->buffer_bytes =
1958 bytes - transfer * STp->block_size;
1959 DEBC(printk(ST_DEB_MSG
1960 "%s: EOF detected (%d bytes read).\n",
1961 name, STbp->buffer_bytes));
1962 } else if (cmdstatp->flags & SENSE_EOM) {
1963 if (STps->eof == ST_FM)
1964 STps->eof = ST_EOD_1;
1965 else
1966 STps->eof = ST_EOM_OK;
1967 if (STp->block_size == 0)
1968 STbp->buffer_bytes = bytes - transfer;
1969 else
1970 STbp->buffer_bytes =
1971 bytes - transfer * STp->block_size;
1972
1973 DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n",
1974 name, STbp->buffer_bytes));
1975 }
1976 }
1977 /* end of EOF, EOM, ILI test */
1978 else { /* nonzero sense key */
1979 DEBC(printk(ST_DEB_MSG
1980 "%s: Tape error while reading.\n", name));
1981 STps->drv_block = (-1);
1982 if (STps->eof == ST_FM &&
1983 cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {
1984 DEBC(printk(ST_DEB_MSG
1985 "%s: Zero returned for first BLANK CHECK after EOF.\n",
1986 name));
1987 STps->eof = ST_EOD_2; /* First BLANK_CHECK after FM */
1988 } else /* Some other extended sense code */
1989 retval = (-EIO);
1990 }
1991
1992 if (STbp->buffer_bytes < 0) /* Caused by bogus sense data */
1993 STbp->buffer_bytes = 0;
1994 }
1995 /* End of extended sense test */
1996 else { /* Non-extended sense */
1997 retval = STbp->syscall_result;
1998 }
1999
2000 }
2001 /* End of error handling */
Kai Makisara40f6b362008-02-24 22:23:24 +02002002 else { /* Read successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 STbp->buffer_bytes = bytes;
Kai Makisara40f6b362008-02-24 22:23:24 +02002004 if (STp->sili) /* In fixed block mode residual is always zero here */
2005 STbp->buffer_bytes -= STp->buffer->cmdstat.residual;
2006 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
2008 if (STps->drv_block >= 0) {
2009 if (STp->block_size == 0)
2010 STps->drv_block++;
2011 else
2012 STps->drv_block += STbp->buffer_bytes / STp->block_size;
2013 }
2014 return retval;
2015}
2016
2017
2018/* Read command */
2019static ssize_t
2020st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
2021{
2022 ssize_t total;
2023 ssize_t retval = 0;
2024 ssize_t i, transfer;
2025 int special, do_dio = 0;
Mike Christie8b05b772005-11-08 04:06:44 -06002026 struct st_request *SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 struct scsi_tape *STp = filp->private_data;
2028 struct st_modedef *STm;
2029 struct st_partstat *STps;
2030 struct st_buffer *STbp = STp->buffer;
2031 DEB( char *name = tape_name(STp); )
2032
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02002033 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 return -ERESTARTSYS;
2035
2036 retval = rw_checks(STp, filp, count);
2037 if (retval || count == 0)
2038 goto out;
2039
2040 STm = &(STp->modes[STp->current_mode]);
Kai Makisara9abe16c2007-02-03 13:21:29 +02002041 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
2042 if (!STm->do_read_ahead) {
2043 retval = (-EINVAL); /* Read must be integral number of blocks */
2044 goto out;
2045 }
2046 STp->try_dio_now = 0; /* Direct i/o can't handle split blocks */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 }
2048
2049 STps = &(STp->ps[STp->partition]);
2050 if (STps->rw == ST_WRITING) {
2051 retval = flush_buffer(STp, 0);
2052 if (retval)
2053 goto out;
2054 STps->rw = ST_READING;
2055 }
2056 DEB(
2057 if (debugging && STps->eof != ST_NOEOF)
2058 printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name,
2059 STps->eof, STbp->buffer_bytes);
2060 ) /* end DEB */
2061
2062 retval = setup_buffering(STp, buf, count, 1);
2063 if (retval)
2064 goto out;
2065 do_dio = STbp->do_dio;
2066
2067 if (STbp->buffer_bytes == 0 &&
2068 STps->eof >= ST_EOD_1) {
2069 if (STps->eof < ST_EOD) {
2070 STps->eof += 1;
2071 retval = 0;
2072 goto out;
2073 }
2074 retval = (-EIO); /* EOM or Blank Check */
2075 goto out;
2076 }
2077
2078 if (do_dio) {
2079 /* Check the buffer writability before any tape movement. Don't alter
2080 buffer data. */
2081 if (copy_from_user(&i, buf, 1) != 0 ||
2082 copy_to_user(buf, &i, 1) != 0 ||
2083 copy_from_user(&i, buf + count - 1, 1) != 0 ||
2084 copy_to_user(buf + count - 1, &i, 1) != 0) {
2085 retval = (-EFAULT);
2086 goto out;
2087 }
2088 }
2089
2090 STps->rw = ST_READING;
2091
2092
2093 /* Loop until enough data in buffer or a special condition found */
2094 for (total = 0, special = 0; total < count && !special;) {
2095
2096 /* Get new data if the buffer is empty */
2097 if (STbp->buffer_bytes == 0) {
2098 special = read_tape(STp, count - total, &SRpnt);
2099 if (special < 0) { /* No need to continue read */
2100 retval = special;
2101 goto out;
2102 }
2103 }
2104
2105 /* Move the data from driver buffer to user buffer */
2106 if (STbp->buffer_bytes > 0) {
2107 DEB(
2108 if (debugging && STps->eof != ST_NOEOF)
2109 printk(ST_DEB_MSG
2110 "%s: EOF up (%d). Left %d, needed %d.\n", name,
2111 STps->eof, STbp->buffer_bytes,
2112 (int)(count - total));
2113 ) /* end DEB */
2114 transfer = STbp->buffer_bytes < count - total ?
2115 STbp->buffer_bytes : count - total;
2116 if (!do_dio) {
2117 i = from_buffer(STbp, buf, transfer);
2118 if (i) {
2119 retval = i;
2120 goto out;
2121 }
2122 }
2123 buf += transfer;
2124 total += transfer;
2125 }
2126
2127 if (STp->block_size == 0)
2128 break; /* Read only one variable length block */
2129
2130 } /* for (total = 0, special = 0;
2131 total < count && !special; ) */
2132
2133 /* Change the eof state if no data from tape or buffer */
2134 if (total == 0) {
2135 if (STps->eof == ST_FM_HIT) {
2136 STps->eof = ST_FM;
2137 STps->drv_block = 0;
2138 if (STps->drv_file >= 0)
2139 STps->drv_file++;
2140 } else if (STps->eof == ST_EOD_1) {
2141 STps->eof = ST_EOD_2;
2142 STps->drv_block = 0;
2143 if (STps->drv_file >= 0)
2144 STps->drv_file++;
2145 } else if (STps->eof == ST_EOD_2)
2146 STps->eof = ST_EOD;
2147 } else if (STps->eof == ST_FM)
2148 STps->eof = ST_NOEOF;
2149 retval = total;
2150
2151 out:
2152 if (SRpnt != NULL) {
Mike Christie8b05b772005-11-08 04:06:44 -06002153 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 SRpnt = NULL;
2155 }
2156 if (do_dio) {
Kai Makisara787926b2005-11-13 10:04:44 +02002157 release_buffering(STp, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 STbp->buffer_bytes = 0;
2159 }
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02002160 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
2162 return retval;
2163}
2164
2165
2166
2167DEB(
2168/* Set the driver options */
2169static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name)
2170{
2171 if (debugging) {
2172 printk(KERN_INFO
2173 "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
2174 name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
2175 STm->do_read_ahead);
2176 printk(KERN_INFO
2177 "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
2178 name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
2179 printk(KERN_INFO
2180 "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
2181 name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
2182 STp->scsi2_logical);
2183 printk(KERN_INFO
Lee Duncanc743e442012-03-01 12:41:01 -08002184 "%s: sysv: %d nowait: %d sili: %d nowait_filemark: %d\n",
2185 name, STm->sysv, STp->immediate, STp->sili,
2186 STp->immediate_filemark);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 printk(KERN_INFO "%s: debugging: %d\n",
2188 name, debugging);
2189 }
2190}
2191 )
2192
2193
2194static int st_set_options(struct scsi_tape *STp, long options)
2195{
2196 int value;
2197 long code;
2198 struct st_modedef *STm;
2199 char *name = tape_name(STp);
2200 struct cdev *cd0, *cd1;
2201
2202 STm = &(STp->modes[STp->current_mode]);
2203 if (!STm->defined) {
2204 cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1];
2205 memcpy(STm, &(STp->modes[0]), sizeof(struct st_modedef));
2206 STm->cdevs[0] = cd0; STm->cdevs[1] = cd1;
2207 modes_defined = 1;
2208 DEBC(printk(ST_DEB_MSG
2209 "%s: Initialized mode %d definition from mode 0\n",
2210 name, STp->current_mode));
2211 }
2212
2213 code = options & MT_ST_OPTIONS;
2214 if (code == MT_ST_BOOLEANS) {
2215 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
2216 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
2217 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
2218 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
2219 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
2220 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
2221 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
2222 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
2223 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
2224 if ((STp->device)->scsi_level >= SCSI_2)
2225 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
2226 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
2227 STp->immediate = (options & MT_ST_NOWAIT) != 0;
Lee Duncanc743e442012-03-01 12:41:01 -08002228 STp->immediate_filemark = (options & MT_ST_NOWAIT_EOF) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 STm->sysv = (options & MT_ST_SYSV) != 0;
Kai Makisara40f6b362008-02-24 22:23:24 +02002230 STp->sili = (options & MT_ST_SILI) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 DEB( debugging = (options & MT_ST_DEBUGGING) != 0;
2232 st_log_options(STp, STm, name); )
2233 } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
2234 value = (code == MT_ST_SETBOOLEANS);
2235 if ((options & MT_ST_BUFFER_WRITES) != 0)
2236 STm->do_buffer_writes = value;
2237 if ((options & MT_ST_ASYNC_WRITES) != 0)
2238 STm->do_async_writes = value;
2239 if ((options & MT_ST_DEF_WRITES) != 0)
2240 STm->defaults_for_writes = value;
2241 if ((options & MT_ST_READ_AHEAD) != 0)
2242 STm->do_read_ahead = value;
2243 if ((options & MT_ST_TWO_FM) != 0)
2244 STp->two_fm = value;
2245 if ((options & MT_ST_FAST_MTEOM) != 0)
2246 STp->fast_mteom = value;
2247 if ((options & MT_ST_AUTO_LOCK) != 0)
2248 STp->do_auto_lock = value;
2249 if ((options & MT_ST_CAN_BSR) != 0)
2250 STp->can_bsr = value;
2251 if ((options & MT_ST_NO_BLKLIMS) != 0)
2252 STp->omit_blklims = value;
2253 if ((STp->device)->scsi_level >= SCSI_2 &&
2254 (options & MT_ST_CAN_PARTITIONS) != 0)
2255 STp->can_partitions = value;
2256 if ((options & MT_ST_SCSI2LOGICAL) != 0)
2257 STp->scsi2_logical = value;
2258 if ((options & MT_ST_NOWAIT) != 0)
2259 STp->immediate = value;
Lee Duncanc743e442012-03-01 12:41:01 -08002260 if ((options & MT_ST_NOWAIT_EOF) != 0)
2261 STp->immediate_filemark = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 if ((options & MT_ST_SYSV) != 0)
2263 STm->sysv = value;
Kai Makisara40f6b362008-02-24 22:23:24 +02002264 if ((options & MT_ST_SILI) != 0)
2265 STp->sili = value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 DEB(
2267 if ((options & MT_ST_DEBUGGING) != 0)
2268 debugging = value;
2269 st_log_options(STp, STm, name); )
2270 } else if (code == MT_ST_WRITE_THRESHOLD) {
2271 /* Retained for compatibility */
2272 } else if (code == MT_ST_DEF_BLKSIZE) {
2273 value = (options & ~MT_ST_OPTIONS);
2274 if (value == ~MT_ST_OPTIONS) {
2275 STm->default_blksize = (-1);
2276 DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name));
2277 } else {
2278 STm->default_blksize = value;
2279 DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n",
2280 name, STm->default_blksize));
2281 if (STp->ready == ST_READY) {
2282 STp->blksize_changed = 0;
2283 set_mode_densblk(STp, STm);
2284 }
2285 }
2286 } else if (code == MT_ST_TIMEOUTS) {
2287 value = (options & ~MT_ST_OPTIONS);
2288 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
2289 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
2290 DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name,
2291 (value & ~MT_ST_SET_LONG_TIMEOUT)));
2292 } else {
James Bottomleya02488e2008-11-30 10:36:26 -06002293 blk_queue_rq_timeout(STp->device->request_queue,
2294 value * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n",
2296 name, value) );
2297 }
2298 } else if (code == MT_ST_SET_CLN) {
2299 value = (options & ~MT_ST_OPTIONS) & 0xff;
2300 if (value != 0 &&
Roel Kluin832151f2009-11-17 14:53:22 -08002301 (value < EXTENDED_SENSE_START ||
2302 value >= SCSI_SENSE_BUFFERSIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 return (-EINVAL);
2304 STp->cln_mode = value;
2305 STp->cln_sense_mask = (options >> 8) & 0xff;
2306 STp->cln_sense_value = (options >> 16) & 0xff;
2307 printk(KERN_INFO
2308 "%s: Cleaning request mode %d, mask %02x, value %02x\n",
2309 name, value, STp->cln_sense_mask, STp->cln_sense_value);
2310 } else if (code == MT_ST_DEF_OPTIONS) {
2311 code = (options & ~MT_ST_CLEAR_DEFAULT);
2312 value = (options & MT_ST_CLEAR_DEFAULT);
2313 if (code == MT_ST_DEF_DENSITY) {
2314 if (value == MT_ST_CLEAR_DEFAULT) {
2315 STm->default_density = (-1);
2316 DEBC( printk(KERN_INFO "%s: Density default disabled.\n",
2317 name));
2318 } else {
2319 STm->default_density = value & 0xff;
2320 DEBC( printk(KERN_INFO "%s: Density default set to %x\n",
2321 name, STm->default_density));
2322 if (STp->ready == ST_READY) {
2323 STp->density_changed = 0;
2324 set_mode_densblk(STp, STm);
2325 }
2326 }
2327 } else if (code == MT_ST_DEF_DRVBUFFER) {
2328 if (value == MT_ST_CLEAR_DEFAULT) {
2329 STp->default_drvbuffer = 0xff;
2330 DEBC( printk(KERN_INFO
2331 "%s: Drive buffer default disabled.\n", name));
2332 } else {
2333 STp->default_drvbuffer = value & 7;
2334 DEBC( printk(KERN_INFO
2335 "%s: Drive buffer default set to %x\n",
2336 name, STp->default_drvbuffer));
2337 if (STp->ready == ST_READY)
2338 st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer);
2339 }
2340 } else if (code == MT_ST_DEF_COMPRESSION) {
2341 if (value == MT_ST_CLEAR_DEFAULT) {
2342 STm->default_compression = ST_DONT_TOUCH;
2343 DEBC( printk(KERN_INFO
2344 "%s: Compression default disabled.\n", name));
2345 } else {
2346 if ((value & 0xff00) != 0) {
2347 STp->c_algo = (value & 0xff00) >> 8;
2348 DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n",
2349 name, STp->c_algo));
2350 }
2351 if ((value & 0xff) != 0xff) {
2352 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
2353 DEBC( printk(KERN_INFO "%s: Compression default set to %x\n",
2354 name, (value & 1)));
2355 if (STp->ready == ST_READY) {
2356 STp->compression_changed = 0;
2357 st_compression(STp, (STm->default_compression == ST_YES));
2358 }
2359 }
2360 }
2361 }
2362 } else
2363 return (-EIO);
2364
2365 return 0;
2366}
2367
2368#define MODE_HEADER_LENGTH 4
2369
2370/* Mode header and page byte offsets */
2371#define MH_OFF_DATA_LENGTH 0
2372#define MH_OFF_MEDIUM_TYPE 1
2373#define MH_OFF_DEV_SPECIFIC 2
2374#define MH_OFF_BDESCS_LENGTH 3
2375#define MP_OFF_PAGE_NBR 0
2376#define MP_OFF_PAGE_LENGTH 1
2377
2378/* Mode header and page bit masks */
2379#define MH_BIT_WP 0x80
2380#define MP_MSK_PAGE_NBR 0x3f
2381
2382/* Don't return block descriptors */
2383#define MODE_SENSE_OMIT_BDESCS 0x08
2384
2385#define MODE_SELECT_PAGE_FORMAT 0x10
2386
2387/* Read a mode page into the tape buffer. The block descriptors are included
2388 if incl_block_descs is true. The page control is ored to the page number
2389 parameter, if necessary. */
2390static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
2391{
2392 unsigned char cmd[MAX_COMMAND_SIZE];
FUJITA Tomonori8ecf0d92008-12-05 15:25:28 +09002393 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394
2395 memset(cmd, 0, MAX_COMMAND_SIZE);
2396 cmd[0] = MODE_SENSE;
2397 if (omit_block_descs)
2398 cmd[1] = MODE_SENSE_OMIT_BDESCS;
2399 cmd[2] = page;
2400 cmd[4] = 255;
2401
Kai Makisara02ae2c02008-12-18 14:49:50 +09002402 SRpnt = st_do_scsi(NULL, STp, cmd, cmd[4], DMA_FROM_DEVICE,
2403 STp->device->request_queue->rq_timeout, 0, 1);
2404 if (SRpnt == NULL)
2405 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406
Mike Christie8b05b772005-11-08 04:06:44 -06002407 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Kai Makisara02ae2c02008-12-18 14:49:50 +09002409 return STp->buffer->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410}
2411
2412
2413/* Send the mode page in the tape buffer to the drive. Assumes that the mode data
2414 in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */
2415static int write_mode_page(struct scsi_tape *STp, int page, int slow)
2416{
Kai Makisara02ae2c02008-12-18 14:49:50 +09002417 int pgo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 unsigned char cmd[MAX_COMMAND_SIZE];
FUJITA Tomonori18c87012008-12-05 15:25:29 +09002419 struct st_request *SRpnt;
Kai Makisara02ae2c02008-12-18 14:49:50 +09002420 int timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
2422 memset(cmd, 0, MAX_COMMAND_SIZE);
2423 cmd[0] = MODE_SELECT;
2424 cmd[1] = MODE_SELECT_PAGE_FORMAT;
2425 pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH];
2426 cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2;
2427
2428 /* Clear reserved fields */
2429 (STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0;
2430 (STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0;
2431 (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
2432 (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
2433
Kai Makisara02ae2c02008-12-18 14:49:50 +09002434 timeout = slow ?
2435 STp->long_timeout : STp->device->request_queue->rq_timeout;
2436 SRpnt = st_do_scsi(NULL, STp, cmd, cmd[4], DMA_TO_DEVICE,
2437 timeout, 0, 1);
2438 if (SRpnt == NULL)
2439 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
Mike Christie8b05b772005-11-08 04:06:44 -06002441 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Kai Makisara02ae2c02008-12-18 14:49:50 +09002443 return STp->buffer->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444}
2445
2446
2447#define COMPRESSION_PAGE 0x0f
2448#define COMPRESSION_PAGE_LENGTH 16
2449
2450#define CP_OFF_DCE_DCC 2
2451#define CP_OFF_C_ALGO 7
2452
2453#define DCE_MASK 0x80
2454#define DCC_MASK 0x40
2455#define RED_MASK 0x60
2456
2457
2458/* Control the compression with mode page 15. Algorithm not changed if zero.
2459
2460 The block descriptors are read and written because Sony SDT-7000 does not
2461 work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
2462 Including block descriptors should not cause any harm to other drives. */
2463
2464static int st_compression(struct scsi_tape * STp, int state)
2465{
2466 int retval;
2467 int mpoffs; /* Offset to mode page start */
2468 unsigned char *b_data = (STp->buffer)->b_data;
2469 DEB( char *name = tape_name(STp); )
2470
2471 if (STp->ready != ST_READY)
2472 return (-EIO);
2473
2474 /* Read the current page contents */
2475 retval = read_mode_page(STp, COMPRESSION_PAGE, 0);
2476 if (retval) {
2477 DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n",
2478 name));
2479 return (-EIO);
2480 }
2481
2482 mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH];
2483 DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name,
2484 (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)));
2485
2486 /* Check if compression can be changed */
2487 if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) {
2488 DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name));
2489 return (-EIO);
2490 }
2491
2492 /* Do the change */
2493 if (state) {
2494 b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK;
2495 if (STp->c_algo != 0)
2496 b_data[mpoffs + CP_OFF_C_ALGO] = STp->c_algo;
2497 }
2498 else {
2499 b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK;
2500 if (STp->c_algo != 0)
2501 b_data[mpoffs + CP_OFF_C_ALGO] = 0; /* no compression */
2502 }
2503
2504 retval = write_mode_page(STp, COMPRESSION_PAGE, 0);
2505 if (retval) {
2506 DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name));
2507 return (-EIO);
2508 }
2509 DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n",
2510 name, state));
2511
2512 STp->compression_changed = 1;
2513 return 0;
2514}
2515
2516
2517/* Process the load and unload commands (does unload if the load code is zero) */
2518static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code)
2519{
2520 int retval = (-EIO), timeout;
2521 DEB( char *name = tape_name(STp); )
2522 unsigned char cmd[MAX_COMMAND_SIZE];
2523 struct st_partstat *STps;
Mike Christie8b05b772005-11-08 04:06:44 -06002524 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
2526 if (STp->ready != ST_READY && !load_code) {
2527 if (STp->ready == ST_NO_TAPE)
2528 return (-ENOMEDIUM);
2529 else
2530 return (-EIO);
2531 }
2532
2533 memset(cmd, 0, MAX_COMMAND_SIZE);
2534 cmd[0] = START_STOP;
2535 if (load_code)
2536 cmd[4] |= 1;
2537 /*
2538 * If arg >= 1 && arg <= 6 Enhanced load/unload in HP C1553A
2539 */
2540 if (load_code >= 1 + MT_ST_HPLOADER_OFFSET
2541 && load_code <= 6 + MT_ST_HPLOADER_OFFSET) {
2542 DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n",
2543 name, (cmd[4]) ? "" : "un",
2544 load_code - MT_ST_HPLOADER_OFFSET));
2545 cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */
2546 }
2547 if (STp->immediate) {
2548 cmd[1] = 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002549 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 }
2551 else
2552 timeout = STp->long_timeout;
2553
2554 DEBC(
2555 if (!load_code)
2556 printk(ST_DEB_MSG "%s: Unloading tape.\n", name);
2557 else
2558 printk(ST_DEB_MSG "%s: Loading tape.\n", name);
2559 );
2560
Kai Makisara02ae2c02008-12-18 14:49:50 +09002561 SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
2562 timeout, MAX_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 if (!SRpnt)
Kai Makisara02ae2c02008-12-18 14:49:50 +09002564 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
2566 retval = (STp->buffer)->syscall_result;
Kai Makisara02ae2c02008-12-18 14:49:50 +09002567 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 if (!retval) { /* SCSI command successful */
2570
2571 if (!load_code) {
2572 STp->rew_at_close = 0;
2573 STp->ready = ST_NO_TAPE;
2574 }
2575 else {
2576 STp->rew_at_close = STp->autorew_dev;
2577 retval = check_tape(STp, filp);
2578 if (retval > 0)
2579 retval = 0;
2580 }
2581 }
2582 else {
2583 STps = &(STp->ps[STp->partition]);
2584 STps->drv_file = STps->drv_block = (-1);
2585 }
2586
2587 return retval;
2588}
2589
2590#if DEBUG
2591#define ST_DEB_FORWARD 0
2592#define ST_DEB_BACKWARD 1
2593static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd)
2594{
2595 s32 sc;
2596
2597 sc = cmd[2] & 0x80 ? 0xff000000 : 0;
2598 sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
2599 if (direction)
2600 sc = -sc;
2601 printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name,
2602 direction ? "backward" : "forward", sc, units);
2603}
2604#endif
2605
2606
2607/* Internal ioctl function */
2608static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned long arg)
2609{
2610 int timeout;
2611 long ltmp;
2612 int ioctl_result;
2613 int chg_eof = 1;
2614 unsigned char cmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06002615 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 struct st_partstat *STps;
2617 int fileno, blkno, at_sm, undone;
2618 int datalen = 0, direction = DMA_NONE;
2619 char *name = tape_name(STp);
2620
2621 WARN_ON(STp->buffer->do_dio != 0);
2622 if (STp->ready != ST_READY) {
2623 if (STp->ready == ST_NO_TAPE)
2624 return (-ENOMEDIUM);
2625 else
2626 return (-EIO);
2627 }
2628 timeout = STp->long_timeout;
2629 STps = &(STp->ps[STp->partition]);
2630 fileno = STps->drv_file;
2631 blkno = STps->drv_block;
2632 at_sm = STps->at_sm;
2633
2634 memset(cmd, 0, MAX_COMMAND_SIZE);
2635 switch (cmd_in) {
2636 case MTFSFM:
2637 chg_eof = 0; /* Changed from the FSF after this */
2638 case MTFSF:
2639 cmd[0] = SPACE;
2640 cmd[1] = 0x01; /* Space FileMarks */
2641 cmd[2] = (arg >> 16);
2642 cmd[3] = (arg >> 8);
2643 cmd[4] = arg;
2644 DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);)
2645 if (fileno >= 0)
2646 fileno += arg;
2647 blkno = 0;
2648 at_sm &= (arg == 0);
2649 break;
2650 case MTBSFM:
2651 chg_eof = 0; /* Changed from the FSF after this */
2652 case MTBSF:
2653 cmd[0] = SPACE;
2654 cmd[1] = 0x01; /* Space FileMarks */
2655 ltmp = (-arg);
2656 cmd[2] = (ltmp >> 16);
2657 cmd[3] = (ltmp >> 8);
2658 cmd[4] = ltmp;
2659 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);)
2660 if (fileno >= 0)
2661 fileno -= arg;
2662 blkno = (-1); /* We can't know the block number */
2663 at_sm &= (arg == 0);
2664 break;
2665 case MTFSR:
2666 cmd[0] = SPACE;
2667 cmd[1] = 0x00; /* Space Blocks */
2668 cmd[2] = (arg >> 16);
2669 cmd[3] = (arg >> 8);
2670 cmd[4] = arg;
2671 DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);)
2672 if (blkno >= 0)
2673 blkno += arg;
2674 at_sm &= (arg == 0);
2675 break;
2676 case MTBSR:
2677 cmd[0] = SPACE;
2678 cmd[1] = 0x00; /* Space Blocks */
2679 ltmp = (-arg);
2680 cmd[2] = (ltmp >> 16);
2681 cmd[3] = (ltmp >> 8);
2682 cmd[4] = ltmp;
2683 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);)
2684 if (blkno >= 0)
2685 blkno -= arg;
2686 at_sm &= (arg == 0);
2687 break;
2688 case MTFSS:
2689 cmd[0] = SPACE;
2690 cmd[1] = 0x04; /* Space Setmarks */
2691 cmd[2] = (arg >> 16);
2692 cmd[3] = (arg >> 8);
2693 cmd[4] = arg;
2694 DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);)
2695 if (arg != 0) {
2696 blkno = fileno = (-1);
2697 at_sm = 1;
2698 }
2699 break;
2700 case MTBSS:
2701 cmd[0] = SPACE;
2702 cmd[1] = 0x04; /* Space Setmarks */
2703 ltmp = (-arg);
2704 cmd[2] = (ltmp >> 16);
2705 cmd[3] = (ltmp >> 8);
2706 cmd[4] = ltmp;
2707 DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);)
2708 if (arg != 0) {
2709 blkno = fileno = (-1);
2710 at_sm = 1;
2711 }
2712 break;
2713 case MTWEOF:
Kai Makisara3e51d3c2010-10-09 00:17:56 +03002714 case MTWEOFI:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 case MTWSM:
2716 if (STp->write_prot)
2717 return (-EACCES);
2718 cmd[0] = WRITE_FILEMARKS;
2719 if (cmd_in == MTWSM)
2720 cmd[1] = 2;
Lee Duncanc743e442012-03-01 12:41:01 -08002721 if (cmd_in == MTWEOFI ||
2722 (cmd_in == MTWEOF && STp->immediate_filemark))
Kai Makisara3e51d3c2010-10-09 00:17:56 +03002723 cmd[1] |= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 cmd[2] = (arg >> 16);
2725 cmd[3] = (arg >> 8);
2726 cmd[4] = arg;
James Bottomleya02488e2008-11-30 10:36:26 -06002727 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 DEBC(
Kai Makisara3e51d3c2010-10-09 00:17:56 +03002729 if (cmd_in != MTWSM)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name,
2731 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
2732 else
2733 printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name,
2734 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
2735 )
2736 if (fileno >= 0)
2737 fileno += arg;
2738 blkno = 0;
2739 at_sm = (cmd_in == MTWSM);
2740 break;
2741 case MTREW:
2742 cmd[0] = REZERO_UNIT;
2743 if (STp->immediate) {
2744 cmd[1] = 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002745 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 }
2747 DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name));
2748 fileno = blkno = at_sm = 0;
2749 break;
2750 case MTNOP:
2751 DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name));
2752 return 0; /* Should do something ? */
2753 break;
2754 case MTRETEN:
2755 cmd[0] = START_STOP;
2756 if (STp->immediate) {
2757 cmd[1] = 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002758 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 }
2760 cmd[4] = 3;
2761 DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name));
2762 fileno = blkno = at_sm = 0;
2763 break;
2764 case MTEOM:
2765 if (!STp->fast_mteom) {
2766 /* space to the end of tape */
2767 ioctl_result = st_int_ioctl(STp, MTFSF, 0x7fffff);
2768 fileno = STps->drv_file;
2769 if (STps->eof >= ST_EOD_1)
2770 return 0;
2771 /* The next lines would hide the number of spaced FileMarks
2772 That's why I inserted the previous lines. I had no luck
2773 with detecting EOM with FSF, so we go now to EOM.
2774 Joerg Weule */
2775 } else
2776 fileno = (-1);
2777 cmd[0] = SPACE;
2778 cmd[1] = 3;
2779 DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n",
2780 name));
2781 blkno = -1;
2782 at_sm = 0;
2783 break;
2784 case MTERASE:
2785 if (STp->write_prot)
2786 return (-EACCES);
2787 cmd[0] = ERASE;
2788 cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */
2789 if (STp->immediate) {
2790 cmd[1] |= 2; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06002791 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 }
2793 else
2794 timeout = STp->long_timeout * 8;
2795
2796 DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name));
2797 fileno = blkno = at_sm = 0;
2798 break;
2799 case MTSETBLK: /* Set block length */
2800 case MTSETDENSITY: /* Set tape density */
2801 case MTSETDRVBUFFER: /* Set drive buffering */
2802 case SET_DENS_AND_BLK: /* Set density and block size */
2803 chg_eof = 0;
2804 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
2805 return (-EIO); /* Not allowed if data in buffer */
2806 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
2807 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
2808 STp->max_block > 0 &&
2809 ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
2810 (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) {
2811 printk(KERN_WARNING "%s: Illegal block size.\n", name);
2812 return (-EINVAL);
2813 }
2814 cmd[0] = MODE_SELECT;
2815 if ((STp->use_pf & USE_PF))
2816 cmd[1] = MODE_SELECT_PAGE_FORMAT;
2817 cmd[4] = datalen = 12;
2818 direction = DMA_TO_DEVICE;
2819
2820 memset((STp->buffer)->b_data, 0, 12);
2821 if (cmd_in == MTSETDRVBUFFER)
2822 (STp->buffer)->b_data[2] = (arg & 7) << 4;
2823 else
2824 (STp->buffer)->b_data[2] =
2825 STp->drv_buffer << 4;
2826 (STp->buffer)->b_data[3] = 8; /* block descriptor length */
2827 if (cmd_in == MTSETDENSITY) {
2828 (STp->buffer)->b_data[4] = arg;
2829 STp->density_changed = 1; /* At least we tried ;-) */
2830 } else if (cmd_in == SET_DENS_AND_BLK)
2831 (STp->buffer)->b_data[4] = arg >> 24;
2832 else
2833 (STp->buffer)->b_data[4] = STp->density;
2834 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
2835 ltmp = arg & MT_ST_BLKSIZE_MASK;
2836 if (cmd_in == MTSETBLK)
2837 STp->blksize_changed = 1; /* At least we tried ;-) */
2838 } else
2839 ltmp = STp->block_size;
2840 (STp->buffer)->b_data[9] = (ltmp >> 16);
2841 (STp->buffer)->b_data[10] = (ltmp >> 8);
2842 (STp->buffer)->b_data[11] = ltmp;
James Bottomleya02488e2008-11-30 10:36:26 -06002843 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 DEBC(
2845 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK)
2846 printk(ST_DEB_MSG
2847 "%s: Setting block size to %d bytes.\n", name,
2848 (STp->buffer)->b_data[9] * 65536 +
2849 (STp->buffer)->b_data[10] * 256 +
2850 (STp->buffer)->b_data[11]);
2851 if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK)
2852 printk(ST_DEB_MSG
2853 "%s: Setting density code to %x.\n", name,
2854 (STp->buffer)->b_data[4]);
2855 if (cmd_in == MTSETDRVBUFFER)
2856 printk(ST_DEB_MSG
2857 "%s: Setting drive buffer code to %d.\n", name,
2858 ((STp->buffer)->b_data[2] >> 4) & 7);
2859 )
2860 break;
2861 default:
2862 return (-ENOSYS);
2863 }
2864
Kai Makisara02ae2c02008-12-18 14:49:50 +09002865 SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction,
2866 timeout, MAX_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 if (!SRpnt)
2868 return (STp->buffer)->syscall_result;
2869
Kai Makisara02ae2c02008-12-18 14:49:50 +09002870 ioctl_result = (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871
2872 if (!ioctl_result) { /* SCSI command successful */
Mike Christie8b05b772005-11-08 04:06:44 -06002873 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 SRpnt = NULL;
2875 STps->drv_block = blkno;
2876 STps->drv_file = fileno;
2877 STps->at_sm = at_sm;
2878
2879 if (cmd_in == MTBSFM)
2880 ioctl_result = st_int_ioctl(STp, MTFSF, 1);
2881 else if (cmd_in == MTFSFM)
2882 ioctl_result = st_int_ioctl(STp, MTBSF, 1);
2883
2884 if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 STp->block_size = arg & MT_ST_BLKSIZE_MASK;
2886 if (STp->block_size != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 (STp->buffer)->buffer_blocks =
2888 (STp->buffer)->buffer_size / STp->block_size;
2889 }
2890 (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
2891 if (cmd_in == SET_DENS_AND_BLK)
2892 STp->density = arg >> MT_ST_DENSITY_SHIFT;
2893 } else if (cmd_in == MTSETDRVBUFFER)
2894 STp->drv_buffer = (arg & 7);
2895 else if (cmd_in == MTSETDENSITY)
2896 STp->density = arg;
2897
2898 if (cmd_in == MTEOM)
2899 STps->eof = ST_EOD;
2900 else if (cmd_in == MTFSF)
2901 STps->eof = ST_FM;
2902 else if (chg_eof)
2903 STps->eof = ST_NOEOF;
2904
Kai Makisara3e51d3c2010-10-09 00:17:56 +03002905 if (cmd_in == MTWEOF || cmd_in == MTWEOFI)
2906 STps->rw = ST_IDLE; /* prevent automatic WEOF at close */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 } else { /* SCSI command was not completely successful. Don't return
2908 from this block without releasing the SCSI command block! */
2909 struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
2910
2911 if (cmdstatp->flags & SENSE_EOM) {
2912 if (cmd_in != MTBSF && cmd_in != MTBSFM &&
2913 cmd_in != MTBSR && cmd_in != MTBSS)
2914 STps->eof = ST_EOM_OK;
2915 STps->drv_block = 0;
2916 }
2917
2918 if (cmdstatp->remainder_valid)
2919 undone = (int)cmdstatp->uremainder64;
2920 else
2921 undone = 0;
2922
Kai Makisara3e51d3c2010-10-09 00:17:56 +03002923 if ((cmd_in == MTWEOF || cmd_in == MTWEOFI) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 cmdstatp->have_sense &&
Kai Makisara91614c02007-01-26 00:38:39 +02002925 (cmdstatp->flags & SENSE_EOM)) {
2926 if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
2927 cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
2928 ioctl_result = 0; /* EOF(s) written successfully at EOM */
2929 STps->eof = ST_NOEOF;
2930 } else { /* Writing EOF(s) failed */
2931 if (fileno >= 0)
2932 fileno -= undone;
2933 if (undone < arg)
2934 STps->eof = ST_NOEOF;
2935 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 STps->drv_file = fileno;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 } else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
2938 if (fileno >= 0)
2939 STps->drv_file = fileno - undone;
2940 else
2941 STps->drv_file = fileno;
2942 STps->drv_block = -1;
2943 STps->eof = ST_NOEOF;
2944 } else if ((cmd_in == MTBSF) || (cmd_in == MTBSFM)) {
2945 if (arg > 0 && undone < 0) /* Some drives get this wrong */
2946 undone = (-undone);
2947 if (STps->drv_file >= 0)
2948 STps->drv_file = fileno + undone;
2949 STps->drv_block = 0;
2950 STps->eof = ST_NOEOF;
2951 } else if (cmd_in == MTFSR) {
2952 if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
2953 if (STps->drv_file >= 0)
2954 STps->drv_file++;
2955 STps->drv_block = 0;
2956 STps->eof = ST_FM;
2957 } else {
2958 if (blkno >= undone)
2959 STps->drv_block = blkno - undone;
2960 else
2961 STps->drv_block = (-1);
2962 STps->eof = ST_NOEOF;
2963 }
2964 } else if (cmd_in == MTBSR) {
2965 if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
2966 STps->drv_file--;
2967 STps->drv_block = (-1);
2968 } else {
2969 if (arg > 0 && undone < 0) /* Some drives get this wrong */
2970 undone = (-undone);
2971 if (STps->drv_block >= 0)
2972 STps->drv_block = blkno + undone;
2973 }
2974 STps->eof = ST_NOEOF;
2975 } else if (cmd_in == MTEOM) {
2976 STps->drv_file = (-1);
2977 STps->drv_block = (-1);
2978 STps->eof = ST_EOD;
2979 } else if (cmd_in == MTSETBLK ||
2980 cmd_in == MTSETDENSITY ||
2981 cmd_in == MTSETDRVBUFFER ||
2982 cmd_in == SET_DENS_AND_BLK) {
2983 if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST &&
2984 !(STp->use_pf & PF_TESTED)) {
2985 /* Try the other possible state of Page Format if not
2986 already tried */
Kai Makisara1da20192009-05-02 08:49:34 +03002987 STp->use_pf = (STp->use_pf ^ USE_PF) | PF_TESTED;
Mike Christie8b05b772005-11-08 04:06:44 -06002988 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 SRpnt = NULL;
2990 return st_int_ioctl(STp, cmd_in, arg);
2991 }
2992 } else if (chg_eof)
2993 STps->eof = ST_NOEOF;
2994
2995 if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
2996 STps->eof = ST_EOD;
2997
Mike Christie8b05b772005-11-08 04:06:44 -06002998 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 SRpnt = NULL;
3000 }
3001
3002 return ioctl_result;
3003}
3004
3005
3006/* Get the tape position. If bt == 2, arg points into a kernel space mt_loc
3007 structure. */
3008
3009static int get_location(struct scsi_tape *STp, unsigned int *block, int *partition,
3010 int logical)
3011{
3012 int result;
3013 unsigned char scmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06003014 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 DEB( char *name = tape_name(STp); )
3016
3017 if (STp->ready != ST_READY)
3018 return (-EIO);
3019
3020 memset(scmd, 0, MAX_COMMAND_SIZE);
3021 if ((STp->device)->scsi_level < SCSI_2) {
3022 scmd[0] = QFA_REQUEST_BLOCK;
3023 scmd[4] = 3;
3024 } else {
3025 scmd[0] = READ_POSITION;
3026 if (!logical && !STp->scsi2_logical)
3027 scmd[1] = 1;
3028 }
Kai Makisara02ae2c02008-12-18 14:49:50 +09003029 SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE,
3030 STp->device->request_queue->rq_timeout,
3031 MAX_READY_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 if (!SRpnt)
Kai Makisara02ae2c02008-12-18 14:49:50 +09003033 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035 if ((STp->buffer)->syscall_result != 0 ||
3036 (STp->device->scsi_level >= SCSI_2 &&
3037 ((STp->buffer)->b_data[0] & 4) != 0)) {
3038 *block = *partition = 0;
3039 DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name));
3040 result = (-EIO);
3041 } else {
3042 result = 0;
3043 if ((STp->device)->scsi_level < SCSI_2) {
3044 *block = ((STp->buffer)->b_data[0] << 16)
3045 + ((STp->buffer)->b_data[1] << 8)
3046 + (STp->buffer)->b_data[2];
3047 *partition = 0;
3048 } else {
3049 *block = ((STp->buffer)->b_data[4] << 24)
3050 + ((STp->buffer)->b_data[5] << 16)
3051 + ((STp->buffer)->b_data[6] << 8)
3052 + (STp->buffer)->b_data[7];
3053 *partition = (STp->buffer)->b_data[1];
3054 if (((STp->buffer)->b_data[0] & 0x80) &&
3055 (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */
3056 STp->ps[0].drv_block = STp->ps[0].drv_file = 0;
3057 }
3058 DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
3059 *block, *partition));
3060 }
Mike Christie8b05b772005-11-08 04:06:44 -06003061 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 SRpnt = NULL;
3063
3064 return result;
3065}
3066
3067
3068/* Set the tape block and partition. Negative partition means that only the
3069 block should be set in vendor specific way. */
3070static int set_location(struct scsi_tape *STp, unsigned int block, int partition,
3071 int logical)
3072{
3073 struct st_partstat *STps;
3074 int result, p;
3075 unsigned int blk;
3076 int timeout;
3077 unsigned char scmd[MAX_COMMAND_SIZE];
Mike Christie8b05b772005-11-08 04:06:44 -06003078 struct st_request *SRpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 DEB( char *name = tape_name(STp); )
3080
3081 if (STp->ready != ST_READY)
3082 return (-EIO);
3083 timeout = STp->long_timeout;
3084 STps = &(STp->ps[STp->partition]);
3085
3086 DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n",
3087 name, block, partition));
3088 DEB(if (partition < 0)
3089 return (-EIO); )
3090
3091 /* Update the location at the partition we are leaving */
3092 if ((!STp->can_partitions && partition != 0) ||
3093 partition >= ST_NBR_PARTITIONS)
3094 return (-EINVAL);
3095 if (partition != STp->partition) {
3096 if (get_location(STp, &blk, &p, 1))
3097 STps->last_block_valid = 0;
3098 else {
3099 STps->last_block_valid = 1;
3100 STps->last_block_visited = blk;
3101 DEBC(printk(ST_DEB_MSG
3102 "%s: Visited block %d for partition %d saved.\n",
3103 name, blk, STp->partition));
3104 }
3105 }
3106
3107 memset(scmd, 0, MAX_COMMAND_SIZE);
3108 if ((STp->device)->scsi_level < SCSI_2) {
3109 scmd[0] = QFA_SEEK_BLOCK;
3110 scmd[2] = (block >> 16);
3111 scmd[3] = (block >> 8);
3112 scmd[4] = block;
3113 scmd[5] = 0;
3114 } else {
3115 scmd[0] = SEEK_10;
3116 scmd[3] = (block >> 24);
3117 scmd[4] = (block >> 16);
3118 scmd[5] = (block >> 8);
3119 scmd[6] = block;
3120 if (!logical && !STp->scsi2_logical)
3121 scmd[1] = 4;
3122 if (STp->partition != partition) {
3123 scmd[1] |= 2;
3124 scmd[8] = partition;
3125 DEBC(printk(ST_DEB_MSG
3126 "%s: Trying to change partition from %d to %d\n",
3127 name, STp->partition, partition));
3128 }
3129 }
3130 if (STp->immediate) {
3131 scmd[1] |= 1; /* Don't wait for completion */
James Bottomleya02488e2008-11-30 10:36:26 -06003132 timeout = STp->device->request_queue->rq_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 }
3134
Kai Makisara02ae2c02008-12-18 14:49:50 +09003135 SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE,
3136 timeout, MAX_READY_RETRIES, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 if (!SRpnt)
Kai Makisara02ae2c02008-12-18 14:49:50 +09003138 return (STp->buffer)->syscall_result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139
3140 STps->drv_block = STps->drv_file = (-1);
3141 STps->eof = ST_NOEOF;
3142 if ((STp->buffer)->syscall_result != 0) {
3143 result = (-EIO);
3144 if (STp->can_partitions &&
3145 (STp->device)->scsi_level >= SCSI_2 &&
3146 (p = find_partition(STp)) >= 0)
3147 STp->partition = p;
3148 } else {
3149 if (STp->can_partitions) {
3150 STp->partition = partition;
3151 STps = &(STp->ps[partition]);
3152 if (!STps->last_block_valid ||
3153 STps->last_block_visited != block) {
3154 STps->at_sm = 0;
3155 STps->rw = ST_IDLE;
3156 }
3157 } else
3158 STps->at_sm = 0;
3159 if (block == 0)
3160 STps->drv_block = STps->drv_file = 0;
3161 result = 0;
3162 }
Kai Makisara02ae2c02008-12-18 14:49:50 +09003163
Mike Christie8b05b772005-11-08 04:06:44 -06003164 st_release_request(SRpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 SRpnt = NULL;
3166
3167 return result;
3168}
3169
3170
3171/* Find the current partition number for the drive status. Called from open and
3172 returns either partition number of negative error code. */
3173static int find_partition(struct scsi_tape *STp)
3174{
3175 int i, partition;
3176 unsigned int block;
3177
3178 if ((i = get_location(STp, &block, &partition, 1)) < 0)
3179 return i;
3180 if (partition >= ST_NBR_PARTITIONS)
3181 return (-EIO);
3182 return partition;
3183}
3184
3185
3186/* Change the partition if necessary */
3187static int switch_partition(struct scsi_tape *STp)
3188{
3189 struct st_partstat *STps;
3190
3191 if (STp->partition == STp->new_partition)
3192 return 0;
3193 STps = &(STp->ps[STp->new_partition]);
3194 if (!STps->last_block_valid)
3195 STps->last_block_visited = 0;
3196 return set_location(STp, STps->last_block_visited, STp->new_partition, 1);
3197}
3198
3199/* Functions for reading and writing the medium partition mode page. */
3200
3201#define PART_PAGE 0x11
3202#define PART_PAGE_FIXED_LENGTH 8
3203
3204#define PP_OFF_MAX_ADD_PARTS 2
3205#define PP_OFF_NBR_ADD_PARTS 3
3206#define PP_OFF_FLAGS 4
3207#define PP_OFF_PART_UNITS 6
3208#define PP_OFF_RESERVED 7
3209
3210#define PP_BIT_IDP 0x20
3211#define PP_MSK_PSUM_MB 0x10
3212
3213/* Get the number of partitions on the tape. As a side effect reads the
3214 mode page into the tape buffer. */
3215static int nbr_partitions(struct scsi_tape *STp)
3216{
3217 int result;
3218 DEB( char *name = tape_name(STp); )
3219
3220 if (STp->ready != ST_READY)
3221 return (-EIO);
3222
3223 result = read_mode_page(STp, PART_PAGE, 1);
3224
3225 if (result) {
3226 DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n",
3227 name));
3228 result = (-EIO);
3229 } else {
3230 result = (STp->buffer)->b_data[MODE_HEADER_LENGTH +
3231 PP_OFF_NBR_ADD_PARTS] + 1;
3232 DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result));
3233 }
3234
3235 return result;
3236}
3237
3238
3239/* Partition the tape into two partitions if size > 0 or one partition if
3240 size == 0.
3241
3242 The block descriptors are read and written because Sony SDT-7000 does not
3243 work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>).
3244
3245 My HP C1533A drive returns only one partition size field. This is used to
3246 set the size of partition 1. There is no size field for the default partition.
3247 Michael Schaefer's Sony SDT-7000 returns two descriptors and the second is
3248 used to set the size of partition 1 (this is what the SCSI-3 standard specifies).
3249 The following algorithm is used to accommodate both drives: if the number of
3250 partition size fields is greater than the maximum number of additional partitions
3251 in the mode page, the second field is used. Otherwise the first field is used.
3252
3253 For Seagate DDS drives the page length must be 8 when no partitions is defined
3254 and 10 when 1 partition is defined (information from Eric Lee Green). This is
3255 is acceptable also to some other old drives and enforced if the first partition
3256 size field is used for the first additional partition size.
3257 */
3258static int partition_tape(struct scsi_tape *STp, int size)
3259{
3260 char *name = tape_name(STp);
3261 int result;
3262 int pgo, psd_cnt, psdo;
3263 unsigned char *bp;
3264
3265 result = read_mode_page(STp, PART_PAGE, 0);
3266 if (result) {
3267 DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name));
3268 return result;
3269 }
3270 /* The mode page is in the buffer. Let's modify it and write it. */
3271 bp = (STp->buffer)->b_data;
3272 pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH];
3273 DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n",
3274 name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2));
3275
3276 psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2;
3277 psdo = pgo + PART_PAGE_FIXED_LENGTH;
3278 if (psd_cnt > bp[pgo + PP_OFF_MAX_ADD_PARTS]) {
3279 bp[psdo] = bp[psdo + 1] = 0xff; /* Rest of the tape */
3280 psdo += 2;
3281 }
3282 memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2);
3283
3284 DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name,
3285 psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS],
3286 bp[pgo + PP_OFF_NBR_ADD_PARTS]));
3287
3288 if (size <= 0) {
3289 bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0;
3290 if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS])
3291 bp[pgo + MP_OFF_PAGE_LENGTH] = 6;
3292 DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n",
3293 name));
3294 } else {
3295 bp[psdo] = (size >> 8) & 0xff;
3296 bp[psdo + 1] = size & 0xff;
3297 bp[pgo + 3] = 1;
3298 if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8)
3299 bp[pgo + MP_OFF_PAGE_LENGTH] = 8;
3300 DEBC(printk(ST_DEB_MSG
3301 "%s: Formatting tape with two partitions (1 = %d MB).\n",
3302 name, size));
3303 }
3304 bp[pgo + PP_OFF_PART_UNITS] = 0;
3305 bp[pgo + PP_OFF_RESERVED] = 0;
3306 bp[pgo + PP_OFF_FLAGS] = PP_BIT_IDP | PP_MSK_PSUM_MB;
3307
3308 result = write_mode_page(STp, PART_PAGE, 1);
3309 if (result) {
3310 printk(KERN_INFO "%s: Partitioning of tape failed.\n", name);
3311 result = (-EIO);
3312 }
3313
3314 return result;
3315}
3316
3317
3318
3319/* The ioctl command */
Kai Makisarafd66c1b2008-01-17 22:45:22 +02003320static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321{
3322 int i, cmd_nr, cmd_type, bt;
3323 int retval = 0;
3324 unsigned int blk;
3325 struct scsi_tape *STp = file->private_data;
3326 struct st_modedef *STm;
3327 struct st_partstat *STps;
3328 char *name = tape_name(STp);
3329 void __user *p = (void __user *)arg;
3330
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003331 if (mutex_lock_interruptible(&STp->lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 return -ERESTARTSYS;
3333
3334 DEB(
3335 if (debugging && !STp->in_use) {
3336 printk(ST_DEB_MSG "%s: Incorrect device.\n", name);
3337 retval = (-EIO);
3338 goto out;
3339 } ) /* end DEB */
3340
3341 STm = &(STp->modes[STp->current_mode]);
3342 STps = &(STp->ps[STp->partition]);
3343
3344 /*
3345 * If we are in the middle of error recovery, don't let anyone
3346 * else try and use this device. Also, if error recovery fails, it
3347 * may try and take the device offline, in which case all further
3348 * access to the device is prohibited.
3349 */
Al Viro83ff6fe2008-03-02 08:15:49 -05003350 retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p,
3351 file->f_flags & O_NDELAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV)
3353 goto out;
3354 retval = 0;
3355
3356 cmd_type = _IOC_TYPE(cmd_in);
3357 cmd_nr = _IOC_NR(cmd_in);
3358
3359 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
3360 struct mtop mtc;
3361
3362 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
3363 retval = (-EINVAL);
3364 goto out;
3365 }
3366
3367 i = copy_from_user(&mtc, p, sizeof(struct mtop));
3368 if (i) {
3369 retval = (-EFAULT);
3370 goto out;
3371 }
3372
3373 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
3374 printk(KERN_WARNING
3375 "%s: MTSETDRVBUFFER only allowed for root.\n", name);
3376 retval = (-EPERM);
3377 goto out;
3378 }
3379 if (!STm->defined &&
3380 (mtc.mt_op != MTSETDRVBUFFER &&
3381 (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
3382 retval = (-ENXIO);
3383 goto out;
3384 }
3385
3386 if (!STp->pos_unknown) {
3387
3388 if (STps->eof == ST_FM_HIT) {
3389 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
3390 mtc.mt_op == MTEOM) {
3391 mtc.mt_count -= 1;
3392 if (STps->drv_file >= 0)
3393 STps->drv_file += 1;
3394 } else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
3395 mtc.mt_count += 1;
3396 if (STps->drv_file >= 0)
3397 STps->drv_file += 1;
3398 }
3399 }
3400
3401 if (mtc.mt_op == MTSEEK) {
3402 /* Old position must be restored if partition will be
3403 changed */
3404 i = !STp->can_partitions ||
3405 (STp->new_partition != STp->partition);
3406 } else {
3407 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
3408 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
3409 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
3410 mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM ||
3411 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM ||
3412 mtc.mt_op == MTCOMPRESSION;
3413 }
3414 i = flush_buffer(STp, i);
3415 if (i < 0) {
3416 retval = i;
3417 goto out;
3418 }
3419 if (STps->rw == ST_WRITING &&
3420 (mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
3421 mtc.mt_op == MTSEEK ||
3422 mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)) {
3423 i = st_int_ioctl(STp, MTWEOF, 1);
3424 if (i < 0) {
3425 retval = i;
3426 goto out;
3427 }
3428 if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)
3429 mtc.mt_count++;
3430 STps->rw = ST_IDLE;
3431 }
3432
3433 } else {
3434 /*
3435 * If there was a bus reset, block further access
3436 * to this device. If the user wants to rewind the tape,
3437 * then reset the flag and allow access again.
3438 */
3439 if (mtc.mt_op != MTREW &&
3440 mtc.mt_op != MTOFFL &&
3441 mtc.mt_op != MTRETEN &&
3442 mtc.mt_op != MTERASE &&
3443 mtc.mt_op != MTSEEK &&
3444 mtc.mt_op != MTEOM) {
3445 retval = (-EIO);
3446 goto out;
3447 }
3448 reset_state(STp);
3449 /* remove this when the midlevel properly clears was_reset */
3450 STp->device->was_reset = 0;
3451 }
3452
3453 if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
3454 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTWSM &&
3455 mtc.mt_op != MTSETDRVBUFFER && mtc.mt_op != MTSETPART)
3456 STps->rw = ST_IDLE; /* Prevent automatic WEOF and fsf */
3457
3458 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
3459 do_door_lock(STp, 0); /* Ignore result! */
3460
3461 if (mtc.mt_op == MTSETDRVBUFFER &&
3462 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
3463 retval = st_set_options(STp, mtc.mt_count);
3464 goto out;
3465 }
3466
3467 if (mtc.mt_op == MTSETPART) {
3468 if (!STp->can_partitions ||
3469 mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS) {
3470 retval = (-EINVAL);
3471 goto out;
3472 }
3473 if (mtc.mt_count >= STp->nbr_partitions &&
3474 (STp->nbr_partitions = nbr_partitions(STp)) < 0) {
3475 retval = (-EIO);
3476 goto out;
3477 }
3478 if (mtc.mt_count >= STp->nbr_partitions) {
3479 retval = (-EINVAL);
3480 goto out;
3481 }
3482 STp->new_partition = mtc.mt_count;
3483 retval = 0;
3484 goto out;
3485 }
3486
3487 if (mtc.mt_op == MTMKPART) {
3488 if (!STp->can_partitions) {
3489 retval = (-EINVAL);
3490 goto out;
3491 }
3492 if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
3493 (i = partition_tape(STp, mtc.mt_count)) < 0) {
3494 retval = i;
3495 goto out;
3496 }
3497 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3498 STp->ps[i].rw = ST_IDLE;
3499 STp->ps[i].at_sm = 0;
3500 STp->ps[i].last_block_valid = 0;
3501 }
3502 STp->partition = STp->new_partition = 0;
3503 STp->nbr_partitions = 1; /* Bad guess ?-) */
3504 STps->drv_block = STps->drv_file = 0;
3505 retval = 0;
3506 goto out;
3507 }
3508
3509 if (mtc.mt_op == MTSEEK) {
3510 i = set_location(STp, mtc.mt_count, STp->new_partition, 0);
3511 if (!STp->can_partitions)
3512 STp->ps[0].rw = ST_IDLE;
3513 retval = i;
3514 goto out;
3515 }
3516
3517 if (mtc.mt_op == MTUNLOAD || mtc.mt_op == MTOFFL) {
3518 retval = do_load_unload(STp, file, 0);
3519 goto out;
3520 }
3521
3522 if (mtc.mt_op == MTLOAD) {
3523 retval = do_load_unload(STp, file, max(1, mtc.mt_count));
3524 goto out;
3525 }
3526
3527 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
3528 retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
3529 goto out;
3530 }
3531
3532 if (STp->can_partitions && STp->ready == ST_READY &&
3533 (i = switch_partition(STp)) < 0) {
3534 retval = i;
3535 goto out;
3536 }
3537
3538 if (mtc.mt_op == MTCOMPRESSION)
3539 retval = st_compression(STp, (mtc.mt_count & 1));
3540 else
3541 retval = st_int_ioctl(STp, mtc.mt_op, mtc.mt_count);
3542 goto out;
3543 }
3544 if (!STm->defined) {
3545 retval = (-ENXIO);
3546 goto out;
3547 }
3548
3549 if ((i = flush_buffer(STp, 0)) < 0) {
3550 retval = i;
3551 goto out;
3552 }
3553 if (STp->can_partitions &&
3554 (i = switch_partition(STp)) < 0) {
3555 retval = i;
3556 goto out;
3557 }
3558
3559 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
3560 struct mtget mt_status;
3561
3562 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
3563 retval = (-EINVAL);
3564 goto out;
3565 }
3566
3567 mt_status.mt_type = STp->tape_type;
3568 mt_status.mt_dsreg =
3569 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
3570 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
3571 mt_status.mt_blkno = STps->drv_block;
3572 mt_status.mt_fileno = STps->drv_file;
3573 if (STp->block_size != 0) {
3574 if (STps->rw == ST_WRITING)
3575 mt_status.mt_blkno +=
3576 (STp->buffer)->buffer_bytes / STp->block_size;
3577 else if (STps->rw == ST_READING)
3578 mt_status.mt_blkno -=
3579 ((STp->buffer)->buffer_bytes +
3580 STp->block_size - 1) / STp->block_size;
3581 }
3582
3583 mt_status.mt_gstat = 0;
3584 if (STp->drv_write_prot)
3585 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
3586 if (mt_status.mt_blkno == 0) {
3587 if (mt_status.mt_fileno == 0)
3588 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
3589 else
3590 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
3591 }
3592 mt_status.mt_erreg = (STp->recover_reg << MT_ST_SOFTERR_SHIFT);
3593 mt_status.mt_resid = STp->partition;
3594 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
3595 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
3596 else if (STps->eof >= ST_EOM_OK)
3597 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
3598 if (STp->density == 1)
3599 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
3600 else if (STp->density == 2)
3601 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
3602 else if (STp->density == 3)
3603 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
3604 if (STp->ready == ST_READY)
3605 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
3606 if (STp->ready == ST_NO_TAPE)
3607 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
3608 if (STps->at_sm)
3609 mt_status.mt_gstat |= GMT_SM(0xffffffff);
3610 if (STm->do_async_writes ||
3611 (STm->do_buffer_writes && STp->block_size != 0) ||
3612 STp->drv_buffer != 0)
3613 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
3614 if (STp->cleaning_req)
3615 mt_status.mt_gstat |= GMT_CLN(0xffffffff);
3616
3617 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
3618 if (i) {
3619 retval = (-EFAULT);
3620 goto out;
3621 }
3622
3623 STp->recover_reg = 0; /* Clear after read */
3624 retval = 0;
3625 goto out;
3626 } /* End of MTIOCGET */
3627 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
3628 struct mtpos mt_pos;
3629 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
3630 retval = (-EINVAL);
3631 goto out;
3632 }
3633 if ((i = get_location(STp, &blk, &bt, 0)) < 0) {
3634 retval = i;
3635 goto out;
3636 }
3637 mt_pos.mt_blkno = blk;
3638 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
3639 if (i)
3640 retval = (-EFAULT);
3641 goto out;
3642 }
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003643 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 switch (cmd_in) {
3645 case SCSI_IOCTL_GET_IDLUN:
3646 case SCSI_IOCTL_GET_BUS_NUMBER:
3647 break;
3648 default:
Kai Makisara 16c4b3e2005-05-01 18:11:55 +03003649 if ((cmd_in == SG_IO ||
3650 cmd_in == SCSI_IOCTL_SEND_COMMAND ||
3651 cmd_in == CDROM_SEND_PACKET) &&
3652 !capable(CAP_SYS_RAWIO))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 i = -EPERM;
3654 else
Al Viro74f3c8a2007-08-27 15:38:10 -04003655 i = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
3656 file->f_mode, cmd_in, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 if (i != -ENOTTY)
3658 return i;
3659 break;
3660 }
Kai Makisara 16c4b3e2005-05-01 18:11:55 +03003661 retval = scsi_ioctl(STp->device, cmd_in, p);
3662 if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */
3663 STp->rew_at_close = 0;
3664 STp->ready = ST_NO_TAPE;
3665 }
3666 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667
3668 out:
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02003669 mutex_unlock(&STp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 return retval;
3671}
3672
3673#ifdef CONFIG_COMPAT
3674static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3675{
3676 struct scsi_tape *STp = file->private_data;
3677 struct scsi_device *sdev = STp->device;
3678 int ret = -ENOIOCTLCMD;
3679 if (sdev->host->hostt->compat_ioctl) {
3680
3681 ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
3682
3683 }
3684 return ret;
3685}
3686#endif
3687
3688
3689
3690/* Try to allocate a new tape buffer. Calling function must not hold
3691 dev_arr_lock. */
FUJITA Tomonorif409d6c2008-12-18 14:49:47 +09003692static struct st_buffer *new_tape_buffer(int need_dma, int max_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 struct st_buffer *tb;
3695
FUJITA Tomonorif409d6c2008-12-18 14:49:47 +09003696 tb = kzalloc(sizeof(struct st_buffer), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 if (!tb) {
3698 printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
3699 return NULL;
3700 }
FUJITA Tomonori1ac63cf2008-12-18 14:49:48 +09003701 tb->frp_segs = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 tb->use_sg = max_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 tb->dma = need_dma;
FUJITA Tomonorif409d6c2008-12-18 14:49:47 +09003704 tb->buffer_size = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
FUJITA Tomonorif409d6c2008-12-18 14:49:47 +09003706 tb->reserved_pages = kzalloc(max_sg * sizeof(struct page *),
3707 GFP_ATOMIC);
FUJITA Tomonorid0e1ae32008-12-18 14:49:40 +09003708 if (!tb->reserved_pages) {
3709 kfree(tb);
3710 return NULL;
3711 }
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 return tb;
3714}
3715
3716
3717/* Try to allocate enough space in the tape buffer */
Kai Makisara8f78fc52008-12-18 14:49:51 +09003718#define ST_MAX_ORDER 6
3719
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
3721{
Al Viroc53033f2005-10-21 03:22:08 -04003722 int segs, nbr, max_segs, b_size, order, got;
3723 gfp_t priority;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724
3725 if (new_size <= STbuffer->buffer_size)
3726 return 1;
3727
3728 if (STbuffer->buffer_size <= PAGE_SIZE)
3729 normalize_buffer(STbuffer); /* Avoid extra segment */
3730
3731 max_segs = STbuffer->use_sg;
3732 nbr = max_segs - STbuffer->frp_segs;
3733 if (nbr <= 0)
3734 return 0;
3735
3736 priority = GFP_KERNEL | __GFP_NOWARN;
3737 if (need_dma)
3738 priority |= GFP_DMA;
FUJITA Tomonori9c905962008-12-18 14:49:39 +09003739
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003740 if (STbuffer->cleared)
3741 priority |= __GFP_ZERO;
3742
FUJITA Tomonori9c905962008-12-18 14:49:39 +09003743 if (STbuffer->frp_segs) {
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003744 order = STbuffer->reserved_page_order;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003745 b_size = PAGE_SIZE << order;
FUJITA Tomonori9c905962008-12-18 14:49:39 +09003746 } else {
3747 for (b_size = PAGE_SIZE, order = 0;
FUJITA Tomonori46081b12010-12-20 18:44:45 +02003748 order < ST_MAX_ORDER &&
3749 max_segs * (PAGE_SIZE << order) < new_size;
Kai Makisara8f78fc52008-12-18 14:49:51 +09003750 order++, b_size *= 2)
FUJITA Tomonori9c905962008-12-18 14:49:39 +09003751 ; /* empty */
Kai Makisara373daac2010-12-20 18:43:39 +02003752 STbuffer->reserved_page_order = order;
FUJITA Tomonori9c905962008-12-18 14:49:39 +09003753 }
Kai Makisara8f78fc52008-12-18 14:49:51 +09003754 if (max_segs * (PAGE_SIZE << order) < new_size) {
3755 if (order == ST_MAX_ORDER)
3756 return 0;
3757 normalize_buffer(STbuffer);
3758 return enlarge_buffer(STbuffer, new_size, need_dma);
3759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
3761 for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size;
3762 segs < max_segs && got < new_size;) {
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003763 struct page *page;
3764
3765 page = alloc_pages(priority, order);
3766 if (!page) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 DEB(STbuffer->buffer_size = got);
3768 normalize_buffer(STbuffer);
3769 return 0;
3770 }
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003771
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 STbuffer->frp_segs += 1;
3773 got += b_size;
3774 STbuffer->buffer_size = got;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003775 STbuffer->reserved_pages[segs] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 segs++;
3777 }
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003778 STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
3780 return 1;
3781}
3782
3783
Kai Makisara40f6b362008-02-24 22:23:24 +02003784/* Make sure that no data from previous user is in the internal buffer */
3785static void clear_buffer(struct st_buffer * st_bp)
3786{
3787 int i;
3788
3789 for (i=0; i < st_bp->frp_segs; i++)
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003790 memset(page_address(st_bp->reserved_pages[i]), 0,
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003791 PAGE_SIZE << st_bp->reserved_page_order);
Kai Makisara40f6b362008-02-24 22:23:24 +02003792 st_bp->cleared = 1;
3793}
3794
3795
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796/* Release the extra buffer */
3797static void normalize_buffer(struct st_buffer * STbuffer)
3798{
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003799 int i, order = STbuffer->reserved_page_order;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800
FUJITA Tomonori1ac63cf2008-12-18 14:49:48 +09003801 for (i = 0; i < STbuffer->frp_segs; i++) {
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003802 __free_pages(STbuffer->reserved_pages[i], order);
3803 STbuffer->buffer_size -= (PAGE_SIZE << order);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 }
FUJITA Tomonori1ac63cf2008-12-18 14:49:48 +09003805 STbuffer->frp_segs = 0;
Mike Christie8b05b772005-11-08 04:06:44 -06003806 STbuffer->sg_segs = 0;
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003807 STbuffer->reserved_page_order = 0;
FUJITA Tomonorid0e1ae32008-12-18 14:49:40 +09003808 STbuffer->map_data.offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809}
3810
3811
3812/* Move data from the user buffer to the tape buffer. Returns zero (success) or
3813 negative error code. */
3814static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
3815{
3816 int i, cnt, res, offset;
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003817 int length = PAGE_SIZE << st_bp->reserved_page_order;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
3819 for (i = 0, offset = st_bp->buffer_bytes;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003820 i < st_bp->frp_segs && offset >= length; i++)
3821 offset -= length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 if (i == st_bp->frp_segs) { /* Should never happen */
3823 printk(KERN_WARNING "st: append_to_buffer offset overflow.\n");
3824 return (-EIO);
3825 }
3826 for (; i < st_bp->frp_segs && do_count > 0; i++) {
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003827 struct page *page = st_bp->reserved_pages[i];
3828 cnt = length - offset < do_count ? length - offset : do_count;
3829 res = copy_from_user(page_address(page) + offset, ubp, cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 if (res)
3831 return (-EFAULT);
3832 do_count -= cnt;
3833 st_bp->buffer_bytes += cnt;
3834 ubp += cnt;
3835 offset = 0;
3836 }
3837 if (do_count) /* Should never happen */
3838 return (-EIO);
3839
3840 return 0;
3841}
3842
3843
3844/* Move data from the tape buffer to the user buffer. Returns zero (success) or
3845 negative error code. */
3846static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
3847{
3848 int i, cnt, res, offset;
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003849 int length = PAGE_SIZE << st_bp->reserved_page_order;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
3851 for (i = 0, offset = st_bp->read_pointer;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003852 i < st_bp->frp_segs && offset >= length; i++)
3853 offset -= length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 if (i == st_bp->frp_segs) { /* Should never happen */
3855 printk(KERN_WARNING "st: from_buffer offset overflow.\n");
3856 return (-EIO);
3857 }
3858 for (; i < st_bp->frp_segs && do_count > 0; i++) {
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003859 struct page *page = st_bp->reserved_pages[i];
3860 cnt = length - offset < do_count ? length - offset : do_count;
3861 res = copy_to_user(ubp, page_address(page) + offset, cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 if (res)
3863 return (-EFAULT);
3864 do_count -= cnt;
3865 st_bp->buffer_bytes -= cnt;
3866 st_bp->read_pointer += cnt;
3867 ubp += cnt;
3868 offset = 0;
3869 }
3870 if (do_count) /* Should never happen */
3871 return (-EIO);
3872
3873 return 0;
3874}
3875
3876
3877/* Move data towards start of buffer */
3878static void move_buffer_data(struct st_buffer * st_bp, int offset)
3879{
3880 int src_seg, dst_seg, src_offset = 0, dst_offset;
3881 int count, total;
FUJITA Tomonoric982c362009-11-26 09:24:13 +09003882 int length = PAGE_SIZE << st_bp->reserved_page_order;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
3884 if (offset == 0)
3885 return;
3886
3887 total=st_bp->buffer_bytes - offset;
3888 for (src_seg=0; src_seg < st_bp->frp_segs; src_seg++) {
3889 src_offset = offset;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003890 if (src_offset < length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 break;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003892 offset -= length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893 }
3894
3895 st_bp->buffer_bytes = st_bp->read_pointer = total;
3896 for (dst_seg=dst_offset=0; total > 0; ) {
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003897 struct page *dpage = st_bp->reserved_pages[dst_seg];
3898 struct page *spage = st_bp->reserved_pages[src_seg];
3899
3900 count = min(length - dst_offset, length - src_offset);
3901 memmove(page_address(dpage) + dst_offset,
3902 page_address(spage) + src_offset, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 src_offset += count;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003904 if (src_offset >= length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 src_seg++;
3906 src_offset = 0;
3907 }
3908 dst_offset += count;
FUJITA Tomonori08c95832008-12-18 14:49:45 +09003909 if (dst_offset >= length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 dst_seg++;
3911 dst_offset = 0;
3912 }
3913 total -= count;
3914 }
3915}
3916
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917/* Validate the options from command line or module parameters */
3918static void validate_options(void)
3919{
3920 if (buffer_kbs > 0)
3921 st_fixed_buffer_size = buffer_kbs * ST_KILOBYTE;
3922 if (max_sg_segs >= ST_FIRST_SG)
3923 st_max_sg_segs = max_sg_segs;
3924}
3925
3926#ifndef MODULE
3927/* Set the boot options. Syntax is defined in Documenation/scsi/st.txt.
3928 */
3929static int __init st_setup(char *str)
3930{
3931 int i, len, ints[5];
3932 char *stp;
3933
3934 stp = get_options(str, ARRAY_SIZE(ints), ints);
3935
3936 if (ints[0] > 0) {
3937 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
3938 if (parms[i].val)
3939 *parms[i].val = ints[i + 1];
3940 } else {
3941 while (stp != NULL) {
3942 for (i = 0; i < ARRAY_SIZE(parms); i++) {
3943 len = strlen(parms[i].name);
3944 if (!strncmp(stp, parms[i].name, len) &&
3945 (*(stp + len) == ':' || *(stp + len) == '=')) {
3946 if (parms[i].val)
3947 *parms[i].val =
3948 simple_strtoul(stp + len + 1, NULL, 0);
3949 else
3950 printk(KERN_WARNING "st: Obsolete parameter %s\n",
3951 parms[i].name);
3952 break;
3953 }
3954 }
Tobias Klauser6391a112006-06-08 22:23:48 -07003955 if (i >= ARRAY_SIZE(parms))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 printk(KERN_WARNING "st: invalid parameter in '%s'\n",
3957 stp);
3958 stp = strchr(stp, ',');
3959 if (stp)
3960 stp++;
3961 }
3962 }
3963
3964 validate_options();
3965
3966 return 1;
3967}
3968
3969__setup("st=", st_setup);
3970
3971#endif
3972
Arjan van de Ven00977a52007-02-12 00:55:34 -08003973static const struct file_operations st_fops =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974{
3975 .owner = THIS_MODULE,
3976 .read = st_read,
3977 .write = st_write,
Kai Makisarafd66c1b2008-01-17 22:45:22 +02003978 .unlocked_ioctl = st_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979#ifdef CONFIG_COMPAT
3980 .compat_ioctl = st_compat_ioctl,
3981#endif
3982 .open = st_open,
3983 .flush = st_flush,
3984 .release = st_release,
Jan Blunckb4d878e2010-05-26 14:44:51 -07003985 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986};
3987
Jeff Mahoney26898af2012-08-18 15:20:40 -04003988static int create_one_cdev(struct scsi_tape *tape, int mode, int rew)
3989{
3990 int i, error;
3991 dev_t cdev_devno;
3992 struct cdev *cdev;
3993 struct device *dev;
3994 struct st_modedef *STm = &(tape->modes[mode]);
3995 char name[10];
3996 int dev_num = tape->index;
3997
3998 cdev_devno = MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, rew));
3999
4000 cdev = cdev_alloc();
4001 if (!cdev) {
4002 pr_err("st%d: out of memory. Device not attached.\n", dev_num);
4003 error = -ENOMEM;
4004 goto out;
4005 }
4006 cdev->owner = THIS_MODULE;
4007 cdev->ops = &st_fops;
4008
4009 error = cdev_add(cdev, cdev_devno, 1);
4010 if (error) {
4011 pr_err("st%d: Can't add %s-rewind mode %d\n", dev_num,
4012 rew ? "non" : "auto", mode);
4013 pr_err("st%d: Device not attached.\n", dev_num);
4014 goto out_free;
4015 }
4016 STm->cdevs[rew] = cdev;
4017
4018 i = mode << (4 - ST_NBR_MODE_BITS);
4019 snprintf(name, 10, "%s%s%s", rew ? "n" : "",
4020 tape->disk->disk_name, st_formats[i]);
4021
4022 dev = device_create(&st_sysfs_class, &tape->device->sdev_gendev,
4023 cdev_devno, &tape->modes[mode], "%s", name);
4024 if (IS_ERR(dev)) {
4025 pr_err("st%d: device_create failed\n", dev_num);
4026 error = PTR_ERR(dev);
4027 goto out_free;
4028 }
4029
4030 STm->devs[rew] = dev;
4031
4032 return 0;
4033out_free:
4034 cdev_del(STm->cdevs[rew]);
4035 STm->cdevs[rew] = NULL;
4036out:
4037 return error;
4038}
4039
4040static int create_cdevs(struct scsi_tape *tape)
4041{
4042 int mode, error;
4043 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
4044 error = create_one_cdev(tape, mode, 0);
4045 if (error)
4046 return error;
4047 error = create_one_cdev(tape, mode, 1);
4048 if (error)
4049 return error;
4050 }
4051
4052 return sysfs_create_link(&tape->device->sdev_gendev.kobj,
4053 &tape->modes[0].devs[0]->kobj, "tape");
4054}
4055
4056static void remove_cdevs(struct scsi_tape *tape)
4057{
4058 int mode, rew;
4059 sysfs_remove_link(&tape->device->sdev_gendev.kobj, "tape");
4060 for (mode = 0; mode < ST_NBR_MODES; mode++) {
4061 struct st_modedef *STm = &(tape->modes[mode]);
4062 for (rew = 0; rew < 2; rew++) {
4063 if (STm->cdevs[rew])
4064 cdev_del(STm->cdevs[rew]);
4065 if (STm->devs[rew])
4066 device_unregister(STm->devs[rew]);
4067 }
4068 }
4069}
4070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071static int st_probe(struct device *dev)
4072{
4073 struct scsi_device *SDp = to_scsi_device(dev);
4074 struct gendisk *disk = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 struct scsi_tape *tpnt = NULL;
4076 struct st_modedef *STm;
4077 struct st_partstat *STps;
4078 struct st_buffer *buffer;
Tejun Heob98c52b2013-02-27 17:04:42 -08004079 int i, error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 char *stp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
4082 if (SDp->type != TYPE_TAPE)
4083 return -ENODEV;
4084 if ((stp = st_incompatible(SDp))) {
Jeff Garzik3bf743e2005-10-24 18:04:06 -04004085 sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 printk(KERN_INFO "st: The suggested driver is %s.\n", stp);
4087 return -ENODEV;
4088 }
4089
Martin K. Petersen8a783622010-02-26 00:20:39 -05004090 i = queue_max_segments(SDp->request_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 if (st_max_sg_segs < i)
4092 i = st_max_sg_segs;
FUJITA Tomonorif409d6c2008-12-18 14:49:47 +09004093 buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 if (buffer == NULL) {
4095 printk(KERN_ERR
4096 "st: Can't allocate new tape buffer. Device not attached.\n");
4097 goto out;
4098 }
4099
4100 disk = alloc_disk(1);
4101 if (!disk) {
4102 printk(KERN_ERR "st: out of memory. Device not attached.\n");
4103 goto out_buffer_free;
4104 }
4105
Jes Sorensen24669f752006-01-16 10:31:18 -05004106 tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107 if (tpnt == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 printk(KERN_ERR "st: Can't allocate device descriptor.\n");
4109 goto out_put_disk;
4110 }
Kai Makisaraf03a5672005-08-02 13:40:47 +03004111 kref_init(&tpnt->kref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 tpnt->disk = disk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 disk->private_data = &tpnt->driver;
4114 disk->queue = SDp->request_queue;
Joe Lawrence2b5bebc2013-03-05 10:57:56 -05004115 /* SCSI tape doesn't register this gendisk via add_disk(). Manually
4116 * take queue reference that release_disk() expects. */
4117 if (!blk_get_queue(disk->queue))
4118 goto out_put_disk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 tpnt->driver = &st_template;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120
4121 tpnt->device = SDp;
4122 if (SDp->scsi_level <= 2)
4123 tpnt->tape_type = MT_ISSCSI1;
4124 else
4125 tpnt->tape_type = MT_ISSCSI2;
4126
4127 tpnt->buffer = buffer;
Kai Makisaraf03a5672005-08-02 13:40:47 +03004128 tpnt->buffer->last_SRpnt = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
4130 tpnt->inited = 0;
4131 tpnt->dirty = 0;
4132 tpnt->in_use = 0;
4133 tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
4134 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
4135 tpnt->use_pf = (SDp->scsi_level >= SCSI_2);
4136 tpnt->density = 0;
4137 tpnt->do_auto_lock = ST_AUTO_LOCK;
4138 tpnt->can_bsr = (SDp->scsi_level > 2 ? 1 : ST_IN_FILE_POS); /* BSR mandatory in SCSI3 */
4139 tpnt->can_partitions = 0;
4140 tpnt->two_fm = ST_TWO_FM;
4141 tpnt->fast_mteom = ST_FAST_MTEOM;
4142 tpnt->scsi2_logical = ST_SCSI2LOGICAL;
Kai Makisara40f6b362008-02-24 22:23:24 +02004143 tpnt->sili = ST_SILI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 tpnt->immediate = ST_NOWAIT;
Lee Duncanc743e442012-03-01 12:41:01 -08004145 tpnt->immediate_filemark = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 tpnt->default_drvbuffer = 0xff; /* No forced buffering */
4147 tpnt->partition = 0;
4148 tpnt->new_partition = 0;
4149 tpnt->nbr_partitions = 0;
James Bottomleya02488e2008-11-30 10:36:26 -06004150 blk_queue_rq_timeout(tpnt->device->request_queue, ST_TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 tpnt->long_timeout = ST_LONG_TIMEOUT;
4152 tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
4153
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 for (i = 0; i < ST_NBR_MODES; i++) {
4155 STm = &(tpnt->modes[i]);
4156 STm->defined = 0;
4157 STm->sysv = ST_SYSV;
4158 STm->defaults_for_writes = 0;
4159 STm->do_async_writes = ST_ASYNC_WRITES;
4160 STm->do_buffer_writes = ST_BUFFER_WRITES;
4161 STm->do_read_ahead = ST_READ_AHEAD;
4162 STm->default_compression = ST_DONT_TOUCH;
4163 STm->default_blksize = (-1); /* No forced size */
4164 STm->default_density = (-1); /* No forced density */
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004165 STm->tape = tpnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 }
4167
4168 for (i = 0; i < ST_NBR_PARTITIONS; i++) {
4169 STps = &(tpnt->ps[i]);
4170 STps->rw = ST_IDLE;
4171 STps->eof = ST_NOEOF;
4172 STps->at_sm = 0;
4173 STps->last_block_valid = 0;
4174 STps->drv_block = (-1);
4175 STps->drv_file = (-1);
4176 }
4177
4178 tpnt->current_mode = 0;
4179 tpnt->modes[0].defined = 1;
4180
4181 tpnt->density_changed = tpnt->compression_changed =
4182 tpnt->blksize_changed = 0;
Matthias Kaehlcke28f85002007-07-29 23:38:15 +02004183 mutex_init(&tpnt->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Tejun Heob98c52b2013-02-27 17:04:42 -08004185 idr_preload(GFP_KERNEL);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004186 spin_lock(&st_index_lock);
Tejun Heob98c52b2013-02-27 17:04:42 -08004187 error = idr_alloc(&st_index_idr, tpnt, 0, ST_MAX_TAPES + 1, GFP_NOWAIT);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004188 spin_unlock(&st_index_lock);
Tejun Heob98c52b2013-02-27 17:04:42 -08004189 idr_preload_end();
4190 if (error < 0) {
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004191 pr_warn("st: idr allocation failed: %d\n", error);
Joe Lawrence2b5bebc2013-03-05 10:57:56 -05004192 goto out_put_queue;
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004193 }
Tejun Heob98c52b2013-02-27 17:04:42 -08004194 tpnt->index = error;
4195 sprintf(disk->disk_name, "st%d", tpnt->index);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004196
4197 dev_set_drvdata(dev, tpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Jeff Mahoney26898af2012-08-18 15:20:40 -04004200 error = create_cdevs(tpnt);
4201 if (error)
4202 goto out_remove_devs;
Oliver Neukum46a243f2012-01-15 00:16:51 +01004203 scsi_autopm_put_device(SDp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204
Kai Makisara422528542006-11-07 21:56:38 +02004205 sdev_printk(KERN_NOTICE, SDp,
Rene Herman8b1ea242006-05-20 15:00:22 -07004206 "Attached scsi tape %s\n", tape_name(tpnt));
Kai Makisara422528542006-11-07 21:56:38 +02004207 sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n",
4208 tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
4209 queue_dma_alignment(SDp->request_queue) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210
4211 return 0;
4212
Jeff Mahoney26898af2012-08-18 15:20:40 -04004213out_remove_devs:
4214 remove_cdevs(tpnt);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004215 spin_lock(&st_index_lock);
Tejun Heob98c52b2013-02-27 17:04:42 -08004216 idr_remove(&st_index_idr, tpnt->index);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004217 spin_unlock(&st_index_lock);
Joe Lawrence2b5bebc2013-03-05 10:57:56 -05004218out_put_queue:
4219 blk_put_queue(disk->queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220out_put_disk:
4221 put_disk(disk);
Jesper Juhlc9475cb2005-11-07 01:01:26 -08004222 kfree(tpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223out_buffer_free:
4224 kfree(buffer);
4225out:
4226 return -ENODEV;
4227};
4228
4229
4230static int st_remove(struct device *dev)
4231{
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004232 struct scsi_tape *tpnt = dev_get_drvdata(dev);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004233 int index = tpnt->index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004235 scsi_autopm_get_device(to_scsi_device(dev));
Jeff Mahoney26898af2012-08-18 15:20:40 -04004236 remove_cdevs(tpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004238 mutex_lock(&st_ref_mutex);
4239 kref_put(&tpnt->kref, scsi_tape_release);
4240 mutex_unlock(&st_ref_mutex);
4241 spin_lock(&st_index_lock);
4242 idr_remove(&st_index_idr, index);
4243 spin_unlock(&st_index_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 return 0;
4245}
4246
Kai Makisaraf03a5672005-08-02 13:40:47 +03004247/**
4248 * scsi_tape_release - Called to free the Scsi_Tape structure
4249 * @kref: pointer to embedded kref
4250 *
Arjan van de Ven0b950672006-01-11 13:16:10 +01004251 * st_ref_mutex must be held entering this routine. Because it is
Kai Makisaraf03a5672005-08-02 13:40:47 +03004252 * called on last put, you should always use the scsi_tape_get()
4253 * scsi_tape_put() helpers which manipulate the semaphore directly
4254 * and never do a direct kref_put().
4255 **/
4256static void scsi_tape_release(struct kref *kref)
4257{
4258 struct scsi_tape *tpnt = to_scsi_tape(kref);
4259 struct gendisk *disk = tpnt->disk;
4260
4261 tpnt->device = NULL;
4262
4263 if (tpnt->buffer) {
Kai Makisaraf03a5672005-08-02 13:40:47 +03004264 normalize_buffer(tpnt->buffer);
FUJITA Tomonorid0e1ae32008-12-18 14:49:40 +09004265 kfree(tpnt->buffer->reserved_pages);
Kai Makisaraf03a5672005-08-02 13:40:47 +03004266 kfree(tpnt->buffer);
4267 }
4268
4269 disk->private_data = NULL;
4270 put_disk(disk);
4271 kfree(tpnt);
4272 return;
4273}
4274
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004275static struct class st_sysfs_class = {
4276 .name = "scsi_tape",
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004277 .dev_groups = st_dev_groups,
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004278};
4279
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280static int __init init_st(void)
4281{
Jeff Garzik13026a62006-10-04 06:00:38 -04004282 int err;
4283
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 validate_options();
4285
Jeff Garzik13026a62006-10-04 06:00:38 -04004286 printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 verstr, st_fixed_buffer_size, st_max_sg_segs);
4288
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004289 err = class_register(&st_sysfs_class);
4290 if (err) {
4291 pr_err("Unable register sysfs class for SCSI tapes\n");
4292 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293 }
4294
Jeff Garzik13026a62006-10-04 06:00:38 -04004295 err = register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4296 ST_MAX_TAPE_ENTRIES, "st");
4297 if (err) {
4298 printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",
4299 SCSI_TAPE_MAJOR);
4300 goto err_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 }
Jeff Garzik13026a62006-10-04 06:00:38 -04004302
4303 err = scsi_register_driver(&st_template.gendrv);
4304 if (err)
4305 goto err_chrdev;
4306
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004307 err = do_create_sysfs_files();
Jeff Garzik13026a62006-10-04 06:00:38 -04004308 if (err)
4309 goto err_scsidrv;
4310
4311 return 0;
4312
4313err_scsidrv:
4314 scsi_unregister_driver(&st_template.gendrv);
4315err_chrdev:
4316 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4317 ST_MAX_TAPE_ENTRIES);
4318err_class:
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004319 class_unregister(&st_sysfs_class);
Jeff Garzik13026a62006-10-04 06:00:38 -04004320 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321}
4322
4323static void __exit exit_st(void)
4324{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004325 do_remove_sysfs_files();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 scsi_unregister_driver(&st_template.gendrv);
4327 unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
4328 ST_MAX_TAPE_ENTRIES);
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004329 class_unregister(&st_sysfs_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 printk(KERN_INFO "st: Unloaded.\n");
4331}
4332
4333module_init(init_st);
4334module_exit(exit_st);
4335
4336
4337/* The sysfs driver interface. Read-only at the moment */
4338static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf)
4339{
4340 return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io);
4341}
4342static DRIVER_ATTR(try_direct_io, S_IRUGO, st_try_direct_io_show, NULL);
4343
4344static ssize_t st_fixed_buffer_size_show(struct device_driver *ddp, char *buf)
4345{
4346 return snprintf(buf, PAGE_SIZE, "%d\n", st_fixed_buffer_size);
4347}
4348static DRIVER_ATTR(fixed_buffer_size, S_IRUGO, st_fixed_buffer_size_show, NULL);
4349
4350static ssize_t st_max_sg_segs_show(struct device_driver *ddp, char *buf)
4351{
4352 return snprintf(buf, PAGE_SIZE, "%d\n", st_max_sg_segs);
4353}
4354static DRIVER_ATTR(max_sg_segs, S_IRUGO, st_max_sg_segs_show, NULL);
4355
4356static ssize_t st_version_show(struct device_driver *ddd, char *buf)
4357{
4358 return snprintf(buf, PAGE_SIZE, "[%s]\n", verstr);
4359}
4360static DRIVER_ATTR(version, S_IRUGO, st_version_show, NULL);
4361
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004362static int do_create_sysfs_files(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004364 struct device_driver *sysfs = &st_template.gendrv;
Jeff Garzik13026a62006-10-04 06:00:38 -04004365 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004367 err = driver_create_file(sysfs, &driver_attr_try_direct_io);
Jeff Garzik13026a62006-10-04 06:00:38 -04004368 if (err)
4369 return err;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004370 err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size);
Jeff Garzik13026a62006-10-04 06:00:38 -04004371 if (err)
4372 goto err_try_direct_io;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004373 err = driver_create_file(sysfs, &driver_attr_max_sg_segs);
Jeff Garzik13026a62006-10-04 06:00:38 -04004374 if (err)
4375 goto err_attr_fixed_buf;
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004376 err = driver_create_file(sysfs, &driver_attr_version);
Jeff Garzik13026a62006-10-04 06:00:38 -04004377 if (err)
4378 goto err_attr_max_sg;
4379
4380 return 0;
4381
4382err_attr_max_sg:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004383 driver_remove_file(sysfs, &driver_attr_max_sg_segs);
Jeff Garzik13026a62006-10-04 06:00:38 -04004384err_attr_fixed_buf:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004385 driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
Jeff Garzik13026a62006-10-04 06:00:38 -04004386err_try_direct_io:
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004387 driver_remove_file(sysfs, &driver_attr_try_direct_io);
Jeff Garzik13026a62006-10-04 06:00:38 -04004388 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389}
4390
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004391static void do_remove_sysfs_files(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392{
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004393 struct device_driver *sysfs = &st_template.gendrv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394
Robert P. J. Day405ae7d2007-02-17 19:13:42 +01004395 driver_remove_file(sysfs, &driver_attr_version);
4396 driver_remove_file(sysfs, &driver_attr_max_sg_segs);
4397 driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
4398 driver_remove_file(sysfs, &driver_attr_try_direct_io);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399}
4400
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401/* The sysfs simple class interface */
Tony Jonesee959b02008-02-22 00:13:36 +01004402static ssize_t
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004403defined_show(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004405 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406 ssize_t l = 0;
4407
4408 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
4409 return l;
4410}
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004411static DEVICE_ATTR_RO(defined);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Tony Jonesee959b02008-02-22 00:13:36 +01004413static ssize_t
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004414default_blksize_show(struct device *dev, struct device_attribute *attr,
4415 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004417 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 ssize_t l = 0;
4419
4420 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
4421 return l;
4422}
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004423static DEVICE_ATTR_RO(default_blksize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
Tony Jonesee959b02008-02-22 00:13:36 +01004425static ssize_t
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004426default_density_show(struct device *dev, struct device_attribute *attr,
4427 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004429 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 ssize_t l = 0;
4431 char *fmt;
4432
4433 fmt = STm->default_density >= 0 ? "0x%02x\n" : "%d\n";
4434 l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density);
4435 return l;
4436}
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004437static DEVICE_ATTR_RO(default_density);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Tony Jonesee959b02008-02-22 00:13:36 +01004439static ssize_t
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004440default_compression_show(struct device *dev, struct device_attribute *attr,
4441 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004443 struct st_modedef *STm = dev_get_drvdata(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444 ssize_t l = 0;
4445
4446 l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
4447 return l;
4448}
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004449static DEVICE_ATTR_RO(default_compression);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Tony Jonesee959b02008-02-22 00:13:36 +01004451static ssize_t
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004452options_show(struct device *dev, struct device_attribute *attr, char *buf)
Kai Makisarab174be02008-02-24 22:29:12 +02004453{
James Bottomley7d15d6a2008-03-14 14:12:43 -07004454 struct st_modedef *STm = dev_get_drvdata(dev);
Jeff Mahoney6c648d92012-08-18 15:20:39 -04004455 struct scsi_tape *STp = STm->tape;
4456 int options;
Kai Makisarab174be02008-02-24 22:29:12 +02004457 ssize_t l = 0;
4458
Kai Makisarab174be02008-02-24 22:29:12 +02004459 options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0;
4460 options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0;
4461 options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0;
4462 DEB( options |= debugging ? MT_ST_DEBUGGING : 0 );
4463 options |= STp->two_fm ? MT_ST_TWO_FM : 0;
4464 options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0;
4465 options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0;
4466 options |= STp->can_bsr ? MT_ST_CAN_BSR : 0;
4467 options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0;
4468 options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0;
4469 options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0;
4470 options |= STm->sysv ? MT_ST_SYSV : 0;
4471 options |= STp->immediate ? MT_ST_NOWAIT : 0;
Lee Duncanc743e442012-03-01 12:41:01 -08004472 options |= STp->immediate_filemark ? MT_ST_NOWAIT_EOF : 0;
Kai Makisarab174be02008-02-24 22:29:12 +02004473 options |= STp->sili ? MT_ST_SILI : 0;
4474
4475 l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options);
4476 return l;
4477}
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004478static DEVICE_ATTR_RO(options);
Kai Makisarab174be02008-02-24 22:29:12 +02004479
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004480static struct attribute *st_dev_attrs[] = {
4481 &dev_attr_defined.attr,
4482 &dev_attr_default_blksize.attr,
4483 &dev_attr_default_density.attr,
4484 &dev_attr_default_compression.attr,
4485 &dev_attr_options.attr,
4486 NULL,
Jeff Mahoneyaf237822012-08-18 15:20:37 -04004487};
Greg Kroah-Hartmanc69c6be2013-07-24 15:05:29 -07004488ATTRIBUTE_GROUPS(st_dev);
Kai Makisarab174be02008-02-24 22:29:12 +02004489
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490/* The following functions may be useful for a larger audience. */
FUJITA Tomonori66207422008-12-18 14:49:43 +09004491static int sgl_map_user_pages(struct st_buffer *STbp,
4492 const unsigned int max_pages, unsigned long uaddr,
4493 size_t count, int rw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494{
James Bottomley07542b82005-08-31 20:27:22 -04004495 unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
4496 unsigned long start = uaddr >> PAGE_SHIFT;
4497 const int nr_pages = end - start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 int res, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499 struct page **pages;
FUJITA Tomonori66207422008-12-18 14:49:43 +09004500 struct rq_map_data *mdata = &STbp->map_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502 /* User attempted Overflow! */
4503 if ((uaddr + count) < uaddr)
4504 return -EINVAL;
4505
4506 /* Too big */
4507 if (nr_pages > max_pages)
4508 return -ENOMEM;
4509
4510 /* Hmm? */
4511 if (count == 0)
4512 return 0;
4513
4514 if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_KERNEL)) == NULL)
4515 return -ENOMEM;
4516
4517 /* Try to fault in all of the necessary pages */
4518 down_read(&current->mm->mmap_sem);
4519 /* rw==READ means read from drive, write into memory area */
4520 res = get_user_pages(
4521 current,
4522 current->mm,
4523 uaddr,
4524 nr_pages,
4525 rw == READ,
4526 0, /* don't force */
4527 pages,
4528 NULL);
4529 up_read(&current->mm->mmap_sem);
4530
4531 /* Errors and no page mapped should return here */
4532 if (res < nr_pages)
4533 goto out_unmap;
4534
4535 for (i=0; i < nr_pages; i++) {
4536 /* FIXME: flush superflous for rw==READ,
4537 * probably wrong function for rw==WRITE
4538 */
4539 flush_dcache_page(pages[i]);
4540 }
4541
FUJITA Tomonori66207422008-12-18 14:49:43 +09004542 mdata->offset = uaddr & ~PAGE_MASK;
FUJITA Tomonori66207422008-12-18 14:49:43 +09004543 STbp->mapped_pages = pages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 return nr_pages;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546 out_unmap:
4547 if (res > 0) {
4548 for (j=0; j < res; j++)
4549 page_cache_release(pages[j]);
Hugh Dickins6bc733e2005-12-01 20:21:57 +00004550 res = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 }
4552 kfree(pages);
4553 return res;
4554}
4555
4556
4557/* And unmap them... */
FUJITA Tomonori66207422008-12-18 14:49:43 +09004558static int sgl_unmap_user_pages(struct st_buffer *STbp,
4559 const unsigned int nr_pages, int dirtied)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560{
4561 int i;
4562
4563 for (i=0; i < nr_pages; i++) {
FUJITA Tomonori66207422008-12-18 14:49:43 +09004564 struct page *page = STbp->mapped_pages[i];
Nick Pigginb5810032005-10-29 18:16:12 -07004565
Nick Pigginb5810032005-10-29 18:16:12 -07004566 if (dirtied)
4567 SetPageDirty(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 /* FIXME: cache flush missing for rw==READ
4569 * FIXME: call the correct reference counting function
4570 */
Nick Pigginb5810032005-10-29 18:16:12 -07004571 page_cache_release(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572 }
FUJITA Tomonori66207422008-12-18 14:49:43 +09004573 kfree(STbp->mapped_pages);
4574 STbp->mapped_pages = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575
4576 return 0;
4577}