ide-tape.c 55.2 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2 3
 * IDE ATAPI streaming tape driver.
 *
4 5
 * Copyright (C) 1995-1999  Gadi Oxman <gadio@netvision.net.il>
 * Copyright (C) 2003-2005  Bartlomiej Zolnierkiewicz
Linus Torvalds's avatar
Linus Torvalds committed
6 7 8 9 10 11 12 13
 *
 * This driver was constructed as a student project in the software laboratory
 * of the faculty of electrical engineering in the Technion - Israel's
 * Institute Of Technology, with the guide of Avner Lottem and Dr. Ilana David.
 *
 * It is hereby placed under the terms of the GNU general public license.
 * (See linux/COPYING).
 *
14 15
 * For a historical changelog see
 * Documentation/ide/ChangeLog.ide-tape.1995-2002
Linus Torvalds's avatar
Linus Torvalds committed
16 17
 */

18 19
#define DRV_NAME "ide-tape"

20
#define IDETAPE_VERSION "1.20"
Linus Torvalds's avatar
Linus Torvalds committed
21 22 23 24 25 26 27 28 29

#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
30
#include <linux/jiffies.h>
Linus Torvalds's avatar
Linus Torvalds committed
31 32 33
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
34
#include <linux/seq_file.h>
Linus Torvalds's avatar
Linus Torvalds committed
35 36 37 38 39
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/completion.h>
#include <linux/bitops.h>
40
#include <linux/mutex.h>
41
#include <scsi/scsi.h>
Linus Torvalds's avatar
Linus Torvalds committed
42 43

#include <asm/byteorder.h>
44 45
#include <linux/uaccess.h>
#include <linux/io.h>
Linus Torvalds's avatar
Linus Torvalds committed
46 47 48
#include <asm/unaligned.h>
#include <linux/mtio.h>

49
/* define to see debug info */
50
#undef IDETAPE_DEBUG_LOG
51

52 53
#ifdef IDETAPE_DEBUG_LOG
#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, ## args)
54
#else
55
#define ide_debug_log(lvl, fmt, args...) do {} while (0)
56 57
#endif

Linus Torvalds's avatar
Linus Torvalds committed
58 59
/**************************** Tunable parameters *****************************/
/*
60 61
 * After each failed packet command we issue a request sense command and retry
 * the packet command IDETAPE_MAX_PC_RETRIES times.
Linus Torvalds's avatar
Linus Torvalds committed
62
 *
63
 * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
Linus Torvalds's avatar
Linus Torvalds committed
64 65 66 67
 */
#define IDETAPE_MAX_PC_RETRIES		3

/*
68 69 70 71
 * The following parameter is used to select the point in the internal tape fifo
 * in which we will start to refill the buffer. Decreasing the following
 * parameter will improve the system's latency and interactive response, while
 * using a high value might improve system throughput.
Linus Torvalds's avatar
Linus Torvalds committed
72
 */
73
#define IDETAPE_FIFO_THRESHOLD		2
Linus Torvalds's avatar
Linus Torvalds committed
74 75

/*
76
 * DSC polling parameters.
Linus Torvalds's avatar
Linus Torvalds committed
77
 *
78 79
 * Polling for DSC (a single bit in the status register) is a very important
 * function in ide-tape. There are two cases in which we poll for DSC:
Linus Torvalds's avatar
Linus Torvalds committed
80
 *
81 82 83 84 85
 * 1. Before a read/write packet command, to ensure that we can transfer data
 * from/to the tape's data buffers, without causing an actual media access.
 * In case the tape is not ready yet, we take out our request from the device
 * request queue, so that ide.c could service requests from the other device
 * on the same interface in the meantime.
Linus Torvalds's avatar
Linus Torvalds committed
86
 *
87 88 89 90 91 92 93 94
 * 2. After the successful initialization of a "media access packet command",
 * which is a command that can take a long time to complete (the interval can
 * range from several seconds to even an hour). Again, we postpone our request
 * in the middle to free the bus for the other device. The polling frequency
 * here should be lower than the read/write frequency since those media access
 * commands are slow. We start from a "fast" frequency - IDETAPE_DSC_MA_FAST
 * (1 second), and if we don't receive DSC after IDETAPE_DSC_MA_THRESHOLD
 * (5 min), we switch it to a lower frequency - IDETAPE_DSC_MA_SLOW (1 min).
Linus Torvalds's avatar
Linus Torvalds committed
95
 *
96 97
 * We also set a timeout for the timer, in case something goes wrong. The
 * timeout should be longer then the maximum execution time of a tape operation.
Linus Torvalds's avatar
Linus Torvalds committed
98
 */
99 100

/* DSC timings. */
Linus Torvalds's avatar
Linus Torvalds committed
101 102 103 104 105 106 107 108 109 110
#define IDETAPE_DSC_RW_MIN		5*HZ/100	/* 50 msec */
#define IDETAPE_DSC_RW_MAX		40*HZ/100	/* 400 msec */
#define IDETAPE_DSC_RW_TIMEOUT		2*60*HZ		/* 2 minutes */
#define IDETAPE_DSC_MA_FAST		2*HZ		/* 2 seconds */
#define IDETAPE_DSC_MA_THRESHOLD	5*60*HZ		/* 5 minutes */
#define IDETAPE_DSC_MA_SLOW		30*HZ		/* 30 seconds */
#define IDETAPE_DSC_MA_TIMEOUT		2*60*60*HZ	/* 2 hours */

/*************************** End of tunable parameters ***********************/

111 112 113 114 115 116
/* tape directions */
enum {
	IDETAPE_DIR_NONE  = (1 << 0),
	IDETAPE_DIR_READ  = (1 << 1),
	IDETAPE_DIR_WRITE = (1 << 2),
};
Linus Torvalds's avatar
Linus Torvalds committed
117

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/* Tape door status */
#define DOOR_UNLOCKED			0
#define DOOR_LOCKED			1
#define DOOR_EXPLICITLY_LOCKED		2

/* Some defines for the SPACE command */
#define IDETAPE_SPACE_OVER_FILEMARK	1
#define IDETAPE_SPACE_TO_EOD		3

/* Some defines for the LOAD UNLOAD command */
#define IDETAPE_LU_LOAD_MASK		1
#define IDETAPE_LU_RETENSION_MASK	2
#define IDETAPE_LU_EOT_MASK		4

/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
#define IDETAPE_BLOCK_DESCRIPTOR	0
#define IDETAPE_CAPABILITIES_PAGE	0x2a

Linus Torvalds's avatar
Linus Torvalds committed
136
/*
137 138
 * Most of our global data which we need to save even as we leave the driver due
 * to an interrupt or a timer event is stored in the struct defined below.
Linus Torvalds's avatar
Linus Torvalds committed
139 140
 */
typedef struct ide_tape_obj {
141 142 143
	ide_drive_t		*drive;
	struct ide_driver	*driver;
	struct gendisk		*disk;
144
	struct device		dev;
Linus Torvalds's avatar
Linus Torvalds committed
145

146 147
	/* used by REQ_IDETAPE_{READ,WRITE} requests */
	struct ide_atapi_pc queued_pc;
148

Linus Torvalds's avatar
Linus Torvalds committed
149
	/*
150
	 * DSC polling variables.
Linus Torvalds's avatar
Linus Torvalds committed
151
	 *
152 153 154
	 * While polling for DSC we use postponed_rq to postpone the current
	 * request so that ide.c will be able to service pending requests on the
	 * other device. Note that at most we will have only one DSC (usually
155
	 * data transfer) request in the device request queue.
Linus Torvalds's avatar
Linus Torvalds committed
156
	 */
157 158
	bool postponed_rq;

Linus Torvalds's avatar
Linus Torvalds committed
159 160 161 162 163
	/* The time in which we started polling for DSC */
	unsigned long dsc_polling_start;
	/* Timer used to poll for dsc */
	struct timer_list dsc_timer;
	/* Read/Write dsc polling frequency */
164 165
	unsigned long best_dsc_rw_freq;
	unsigned long dsc_poll_freq;
Linus Torvalds's avatar
Linus Torvalds committed
166 167
	unsigned long dsc_timeout;

168
	/* Read position information */
Linus Torvalds's avatar
Linus Torvalds committed
169 170
	u8 partition;
	/* Current block */
171
	unsigned int first_frame;
Linus Torvalds's avatar
Linus Torvalds committed
172

173
	/* Last error information */
Linus Torvalds's avatar
Linus Torvalds committed
174 175
	u8 sense_key, asc, ascq;

176
	/* Character device operation */
Linus Torvalds's avatar
Linus Torvalds committed
177 178 179 180
	unsigned int minor;
	/* device name */
	char name[4];
	/* Current character device data transfer direction */
181
	u8 chrdev_dir;
Linus Torvalds's avatar
Linus Torvalds committed
182

183 184
	/* tape block size, usually 512 or 1024 bytes */
	unsigned short blk_size;
Linus Torvalds's avatar
Linus Torvalds committed
185
	int user_bs_factor;
186

Linus Torvalds's avatar
Linus Torvalds committed
187
	/* Copy of the tape's Capabilities and Mechanical Page */
188
	u8 caps[20];
Linus Torvalds's avatar
Linus Torvalds committed
189 190

	/*
191
	 * Active data transfer request parameters.
Linus Torvalds's avatar
Linus Torvalds committed
192
	 *
193 194 195
	 * At most, there is only one ide-tape originated data transfer request
	 * in the device request queue. This allows ide.c to easily service
	 * requests from the other device when we postpone our active request.
Linus Torvalds's avatar
Linus Torvalds committed
196
	 */
197

198
	/* Data buffer size chosen based on the tape's recommendation */
199
	int buffer_size;
Tejun Heo's avatar
Tejun Heo committed
200 201 202 203 204 205
	/* Staging buffer of buffer_size bytes */
	void *buf;
	/* The read/write cursor */
	void *cur;
	/* The number of valid bytes in buf */
	size_t valid;
206 207

	/* Measures average tape speed */
Linus Torvalds's avatar
Linus Torvalds committed
208 209 210 211 212 213 214 215 216 217 218 219
	unsigned long avg_time;
	int avg_size;
	int avg_speed;

	/* the door is currently locked */
	int door_locked;
	/* the tape hardware is write protected */
	char drv_write_prot;
	/* the tape is write protected (hardware or opened as read-only) */
	char write_prot;
} idetape_tape_t;

220
static DEFINE_MUTEX(ide_tape_mutex);
221
static DEFINE_MUTEX(idetape_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
222

223 224
static DEFINE_MUTEX(idetape_chrdev_mutex);

225 226
static struct class *idetape_sysfs_class;

227
static void ide_tape_release(struct device *);
228

229 230 231 232
static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];

static struct ide_tape_obj *ide_tape_get(struct gendisk *disk, bool cdev,
					 unsigned int i)
Linus Torvalds's avatar
Linus Torvalds committed
233 234 235
{
	struct ide_tape_obj *tape = NULL;

236
	mutex_lock(&idetape_ref_mutex);
237 238 239 240 241 242

	if (cdev)
		tape = idetape_devs[i];
	else
		tape = ide_drv_g(disk, ide_tape_obj);

243
	if (tape) {
244
		if (ide_device_get(tape->drive))
245
			tape = NULL;
246
		else
247
			get_device(&tape->dev);
248
	}
249

250
	mutex_unlock(&idetape_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
251 252 253 254 255
	return tape;
}

static void ide_tape_put(struct ide_tape_obj *tape)
{
256 257
	ide_drive_t *drive = tape->drive;

258
	mutex_lock(&idetape_ref_mutex);
259
	put_device(&tape->dev);
260
	ide_device_put(drive);
261
	mutex_unlock(&idetape_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
262 263 264
}

/*
265 266
 * called on each failed packet command retry to analyze the request sense. We
 * currently do not utilize this information.
Linus Torvalds's avatar
Linus Torvalds committed
267
 */
268
static void idetape_analyze_error(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
269 270
{
	idetape_tape_t *tape = drive->driver_data;
271
	struct ide_atapi_pc *pc = drive->failed_pc;
272
	struct request *rq = drive->hwif->rq;
273
	u8 *sense = bio_data(rq->bio);
Linus Torvalds's avatar
Linus Torvalds committed
274

275 276 277
	tape->sense_key = sense[2] & 0xF;
	tape->asc       = sense[12];
	tape->ascq      = sense[13];
278

279 280 281
	ide_debug_log(IDE_DBG_FUNC,
		      "cmd: 0x%x, sense key = %x, asc = %x, ascq = %x",
		      rq->cmd[0], tape->sense_key, tape->asc, tape->ascq);
Linus Torvalds's avatar
Linus Torvalds committed
282

283
	/* correct remaining bytes to transfer */
284
	if (pc->flags & PC_FLAG_DMA_ERROR)
285
		rq->resid_len = tape->blk_size * get_unaligned_be32(&sense[3]);
Linus Torvalds's avatar
Linus Torvalds committed
286 287 288 289 290 291

	/*
	 * If error was the result of a zero-length read or write command,
	 * with sense key=5, asc=0x22, ascq=0, let it slide.  Some drives
	 * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes.
	 */
292
	if ((pc->c[0] == READ_6 || pc->c[0] == WRITE_6)
293 294 295
	    /* length == 0 */
	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) {
		if (tape->sense_key == 5) {
Linus Torvalds's avatar
Linus Torvalds committed
296 297 298
			/* don't report an error, everything's ok */
			pc->error = 0;
			/* don't retry read/write */
299
			pc->flags |= PC_FLAG_ABORT;
Linus Torvalds's avatar
Linus Torvalds committed
300 301
		}
	}
302
	if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
303
		pc->error = IDE_DRV_ERROR_FILEMARK;
304
		pc->flags |= PC_FLAG_ABORT;
Linus Torvalds's avatar
Linus Torvalds committed
305
	}
306
	if (pc->c[0] == WRITE_6) {
307 308
		if ((sense[2] & 0x40) || (tape->sense_key == 0xd
		     && tape->asc == 0x0 && tape->ascq == 0x2)) {
309
			pc->error = IDE_DRV_ERROR_EOD;
310
			pc->flags |= PC_FLAG_ABORT;
Linus Torvalds's avatar
Linus Torvalds committed
311 312
		}
	}
313
	if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
314
		if (tape->sense_key == 8) {
315
			pc->error = IDE_DRV_ERROR_EOD;
316
			pc->flags |= PC_FLAG_ABORT;
Linus Torvalds's avatar
Linus Torvalds committed
317
		}
318
		if (!(pc->flags & PC_FLAG_ABORT) &&
319
		    (blk_rq_bytes(rq) - rq->resid_len))
Linus Torvalds's avatar
Linus Torvalds committed
320 321 322 323
			pc->retries = IDETAPE_MAX_PC_RETRIES + 1;
	}
}

324 325
static void ide_tape_handle_dsc(ide_drive_t *);

326
static int ide_tape_callback(ide_drive_t *drive, int dsc)
Linus Torvalds's avatar
Linus Torvalds committed
327 328
{
	idetape_tape_t *tape = drive->driver_data;
329
	struct ide_atapi_pc *pc = drive->pc;
330
	struct request *rq = drive->hwif->rq;
331
	int uptodate = pc->error ? 0 : 1;
332
	int err = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;
Linus Torvalds's avatar
Linus Torvalds committed
333

334 335
	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc: %d, err: %d", rq->cmd[0],
		      dsc, err);
336

337 338 339
	if (dsc)
		ide_tape_handle_dsc(drive);

340 341
	if (drive->failed_pc == pc)
		drive->failed_pc = NULL;
342

343 344
	if (pc->c[0] == REQUEST_SENSE) {
		if (uptodate)
345
			idetape_analyze_error(drive);
346 347 348 349
		else
			printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
					"itself - Aborting request!\n");
	} else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
350 351
		unsigned int blocks =
			(blk_rq_bytes(rq) - rq->resid_len) / tape->blk_size;
352 353 354 355 356 357 358 359 360 361 362 363

		tape->avg_size += blocks * tape->blk_size;

		if (time_after_eq(jiffies, tape->avg_time + HZ)) {
			tape->avg_speed = tape->avg_size * HZ /
				(jiffies - tape->avg_time) / 1024;
			tape->avg_size = 0;
			tape->avg_time = jiffies;
		}

		tape->first_frame += blocks;

364 365 366 367
		if (pc->error) {
			uptodate = 0;
			err = pc->error;
		}
Linus Torvalds's avatar
Linus Torvalds committed
368
	}
369 370
	rq->errors = err;

371
	return uptodate;
Linus Torvalds's avatar
Linus Torvalds committed
372 373 374
}

/*
375
 * Postpone the current request so that ide.c will be able to service requests
376
 * from another device on the same port while we are polling for DSC.
Linus Torvalds's avatar
Linus Torvalds committed
377
 */
378
static void ide_tape_stall_queue(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
379 380 381
{
	idetape_tape_t *tape = drive->driver_data;

382
	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, dsc_poll_freq: %lu",
383
		      drive->hwif->rq->cmd[0], tape->dsc_poll_freq);
384

385
	tape->postponed_rq = true;
386

387
	ide_stall_queue(drive, tape->dsc_poll_freq);
Linus Torvalds's avatar
Linus Torvalds committed
388 389
}

390 391 392 393 394 395 396 397 398
static void ide_tape_handle_dsc(ide_drive_t *drive)
{
	idetape_tape_t *tape = drive->driver_data;

	/* Media access command */
	tape->dsc_polling_start = jiffies;
	tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
	tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
	/* Allow ide.c to handle other requests */
399
	ide_tape_stall_queue(drive);
400 401
}

Linus Torvalds's avatar
Linus Torvalds committed
402
/*
403
 * Packet Command Interface
Linus Torvalds's avatar
Linus Torvalds committed
404
 *
405
 * The current Packet Command is available in drive->pc, and will not change
406 407
 * until we finish handling it. Each packet command is associated with a
 * callback function that will be called when the command is finished.
Linus Torvalds's avatar
Linus Torvalds committed
408
 *
409
 * The handling will be done in three stages:
Linus Torvalds's avatar
Linus Torvalds committed
410
 *
411
 * 1. ide_tape_issue_pc will send the packet command to the drive, and will set
412
 * the interrupt handler to ide_pc_intr.
Linus Torvalds's avatar
Linus Torvalds committed
413
 *
414
 * 2. On each interrupt, ide_pc_intr will be called. This step will be
415
 * repeated until the device signals us that no more interrupts will be issued.
Linus Torvalds's avatar
Linus Torvalds committed
416
 *
417 418 419 420 421 422 423
 * 3. ATAPI Tape media access commands have immediate status with a delayed
 * process. In case of a successful initiation of a media access packet command,
 * the DSC bit will be set when the actual execution of the command is finished.
 * Since the tape drive will not issue an interrupt, we have to poll for this
 * event. In this case, we define the request as "low priority request" by
 * setting rq_status to IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and
 * exit the driver.
Linus Torvalds's avatar
Linus Torvalds committed
424
 *
425 426
 * ide.c will then give higher priority to requests which originate from the
 * other device, until will change rq_status to RQ_ACTIVE.
Linus Torvalds's avatar
Linus Torvalds committed
427
 *
428
 * 4. When the packet command is finished, it will be checked for errors.
Linus Torvalds's avatar
Linus Torvalds committed
429
 *
430 431 432
 * 5. In case an error was found, we queue a request sense packet command in
 * front of the request queue and retry the operation up to
 * IDETAPE_MAX_PC_RETRIES times.
Linus Torvalds's avatar
Linus Torvalds committed
433
 *
434 435 436
 * 6. In case no error was found, or we decided to give up and not to retry
 * again, the callback function will be called and then we will handle the next
 * request.
Linus Torvalds's avatar
Linus Torvalds committed
437 438
 */

439 440 441
static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
					 struct ide_cmd *cmd,
					 struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
442 443
{
	idetape_tape_t *tape = drive->driver_data;
444
	struct request *rq = drive->hwif->rq;
Linus Torvalds's avatar
Linus Torvalds committed
445

446 447
	if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
		drive->failed_pc = pc;
448

Linus Torvalds's avatar
Linus Torvalds committed
449
	/* Set the current packet command */
450
	drive->pc = pc;
Linus Torvalds's avatar
Linus Torvalds committed
451 452

	if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
453
		(pc->flags & PC_FLAG_ABORT)) {
454

Linus Torvalds's avatar
Linus Torvalds committed
455
		/*
456 457 458
		 * We will "abort" retrying a packet command in case legitimate
		 * error code was received (crossing a filemark, or end of the
		 * media, for example).
Linus Torvalds's avatar
Linus Torvalds committed
459
		 */
460
		if (!(pc->flags & PC_FLAG_ABORT)) {
461
			if (!(pc->c[0] == TEST_UNIT_READY &&
Linus Torvalds's avatar
Linus Torvalds committed
462 463 464 465 466 467 468 469 470 471
			      tape->sense_key == 2 && tape->asc == 4 &&
			     (tape->ascq == 1 || tape->ascq == 8))) {
				printk(KERN_ERR "ide-tape: %s: I/O error, "
						"pc = %2x, key = %2x, "
						"asc = %2x, ascq = %2x\n",
						tape->name, pc->c[0],
						tape->sense_key, tape->asc,
						tape->ascq);
			}
			/* Giving up */
472
			pc->error = IDE_DRV_ERROR_GENERAL;
Linus Torvalds's avatar
Linus Torvalds committed
473
		}
474

475
		drive->failed_pc = NULL;
476
		drive->pc_callback(drive, 0);
477
		ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
478
		return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
479
	}
480 481
	ide_debug_log(IDE_DBG_SENSE, "retry #%d, cmd: 0x%02x", pc->retries,
		      pc->c[0]);
Linus Torvalds's avatar
Linus Torvalds committed
482 483 484

	pc->retries++;

485
	return ide_issue_pc(drive, cmd);
Linus Torvalds's avatar
Linus Torvalds committed
486 487
}

488
/* A mode sense command is used to "sense" tape parameters. */
489
static void idetape_create_mode_sense_cmd(struct ide_atapi_pc *pc, u8 page_code)
Linus Torvalds's avatar
Linus Torvalds committed
490
{
491
	ide_init_pc(pc);
492
	pc->c[0] = MODE_SENSE;
Linus Torvalds's avatar
Linus Torvalds committed
493
	if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
494 495
		/* DBD = 1 - Don't return block descriptors */
		pc->c[1] = 8;
Linus Torvalds's avatar
Linus Torvalds committed
496 497 498 499 500 501 502 503 504
	pc->c[2] = page_code;
	/*
	 * Changed pc->c[3] to 0 (255 will at best return unused info).
	 *
	 * For SCSI this byte is defined as subpage instead of high byte
	 * of length and some IDE drives seem to interpret it this way
	 * and return an error when 255 is used.
	 */
	pc->c[3] = 0;
505 506
	/* We will just discard data in that case */
	pc->c[4] = 255;
Linus Torvalds's avatar
Linus Torvalds committed
507
	if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
508
		pc->req_xfer = 12;
Linus Torvalds's avatar
Linus Torvalds committed
509
	else if (page_code == IDETAPE_CAPABILITIES_PAGE)
510
		pc->req_xfer = 24;
Linus Torvalds's avatar
Linus Torvalds committed
511
	else
512
		pc->req_xfer = 50;
Linus Torvalds's avatar
Linus Torvalds committed
513 514
}

515
static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
516
{
517
	ide_hwif_t *hwif = drive->hwif;
Linus Torvalds's avatar
Linus Torvalds committed
518
	idetape_tape_t *tape = drive->driver_data;
519
	struct ide_atapi_pc *pc = drive->pc;
520
	u8 stat;
Linus Torvalds's avatar
Linus Torvalds committed
521

522
	stat = hwif->tp_ops->read_status(hwif);
523

524 525
	if (stat & ATA_DSC) {
		if (stat & ATA_ERR) {
Linus Torvalds's avatar
Linus Torvalds committed
526
			/* Error detected */
527
			if (pc->c[0] != TEST_UNIT_READY)
Linus Torvalds's avatar
Linus Torvalds committed
528 529 530
				printk(KERN_ERR "ide-tape: %s: I/O error, ",
						tape->name);
			/* Retry operation */
531
			ide_retry_pc(drive);
532
			return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
533 534 535
		}
		pc->error = 0;
	} else {
536
		pc->error = IDE_DRV_ERROR_GENERAL;
537
		drive->failed_pc = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
538
	}
539
	drive->pc_callback(drive, 0);
Linus Torvalds's avatar
Linus Torvalds committed
540 541 542
	return ide_stopped;
}

543
static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
544 545
				   struct ide_atapi_pc *pc, struct request *rq,
				   u8 opcode)
Linus Torvalds's avatar
Linus Torvalds committed
546
{
547
	unsigned int length = blk_rq_sectors(rq) / (tape->blk_size >> 9);
548

549
	ide_init_pc(pc);
550
	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
Linus Torvalds's avatar
Linus Torvalds committed
551
	pc->c[1] = 1;
552 553

	if (blk_rq_bytes(rq) == tape->buffer_size)
554
		pc->flags |= PC_FLAG_DMA_OK;
Linus Torvalds's avatar
Linus Torvalds committed
555

Tejun Heo's avatar
Tejun Heo committed
556
	if (opcode == READ_6)
557
		pc->c[0] = READ_6;
Tejun Heo's avatar
Tejun Heo committed
558
	else if (opcode == WRITE_6) {
559 560 561
		pc->c[0] = WRITE_6;
		pc->flags |= PC_FLAG_WRITING;
	}
562 563

	memcpy(rq->cmd, pc->c, 12);
Linus Torvalds's avatar
Linus Torvalds committed
564 565 566 567 568
}

static ide_startstop_t idetape_do_request(ide_drive_t *drive,
					  struct request *rq, sector_t block)
{
569
	ide_hwif_t *hwif = drive->hwif;
Linus Torvalds's avatar
Linus Torvalds committed
570
	idetape_tape_t *tape = drive->driver_data;
571
	struct ide_atapi_pc *pc = NULL;
572
	struct ide_cmd cmd;
573
	u8 stat;
Linus Torvalds's avatar
Linus Torvalds committed
574

575 576 577
	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, sector: %llu, nr_sectors: %u",
		      rq->cmd[0], (unsigned long long)blk_rq_pos(rq),
		      blk_rq_sectors(rq));
Linus Torvalds's avatar
Linus Torvalds committed
578

579
	BUG_ON(!(rq->cmd_type == REQ_TYPE_DRV_PRIV ||
580
		 rq->cmd_type == REQ_TYPE_ATA_SENSE));
Linus Torvalds's avatar
Linus Torvalds committed
581

582
	/* Retry a failed packet command */
583 584
	if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) {
		pc = drive->failed_pc;
585 586
		goto out;
	}
587

Linus Torvalds's avatar
Linus Torvalds committed
588 589 590 591
	/*
	 * If the tape is still busy, postpone our request and service
	 * the other device meanwhile.
	 */
592
	stat = hwif->tp_ops->read_status(hwif);
Linus Torvalds's avatar
Linus Torvalds committed
593

594 595
	if ((drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) == 0 &&
	    (rq->cmd[13] & REQ_IDETAPE_PC2) == 0)
596
		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
Linus Torvalds's avatar
Linus Torvalds committed
597

598
	if (drive->dev_flags & IDE_DFLAG_POST_RESET) {
599
		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
600
		drive->dev_flags &= ~IDE_DFLAG_POST_RESET;
Linus Torvalds's avatar
Linus Torvalds committed
601 602
	}

603 604
	if (!(drive->atapi_flags & IDE_AFLAG_IGNORE_DSC) &&
	    !(stat & ATA_DSC)) {
605
		if (!tape->postponed_rq) {
Linus Torvalds's avatar
Linus Torvalds committed
606
			tape->dsc_polling_start = jiffies;
607
			tape->dsc_poll_freq = tape->best_dsc_rw_freq;
Linus Torvalds's avatar
Linus Torvalds committed
608 609 610 611
			tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
		} else if (time_after(jiffies, tape->dsc_timeout)) {
			printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
				tape->name);
612
			if (rq->cmd[13] & REQ_IDETAPE_PC2) {
Linus Torvalds's avatar
Linus Torvalds committed
613 614 615 616 617
				idetape_media_access_finished(drive);
				return ide_stopped;
			} else {
				return ide_do_reset(drive);
			}
618 619 620
		} else if (time_after(jiffies,
					tape->dsc_polling_start +
					IDETAPE_DSC_MA_THRESHOLD))
621
			tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW;
622
		ide_tape_stall_queue(drive);
Linus Torvalds's avatar
Linus Torvalds committed
623
		return ide_stopped;
624
	} else {
625
		drive->atapi_flags &= ~IDE_AFLAG_IGNORE_DSC;
626 627
		tape->postponed_rq = false;
	}
628

629
	if (rq->cmd[13] & REQ_IDETAPE_READ) {
630
		pc = &tape->queued_pc;
631
		ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
Linus Torvalds's avatar
Linus Torvalds committed
632 633
		goto out;
	}
634
	if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
635
		pc = &tape->queued_pc;
636
		ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
Linus Torvalds's avatar
Linus Torvalds committed
637 638
		goto out;
	}
639
	if (rq->cmd[13] & REQ_IDETAPE_PC1) {
640
		pc = (struct ide_atapi_pc *)rq->special;
641 642
		rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
		rq->cmd[13] |= REQ_IDETAPE_PC2;
Linus Torvalds's avatar
Linus Torvalds committed
643 644
		goto out;
	}
645
	if (rq->cmd[13] & REQ_IDETAPE_PC2) {
Linus Torvalds's avatar
Linus Torvalds committed
646 647 648 649
		idetape_media_access_finished(drive);
		return ide_stopped;
	}
	BUG();
650

651
out:
652 653 654
	/* prepare sense request for this command */
	ide_prep_sense(drive, rq);

655 656 657 658 659 660 661
	memset(&cmd, 0, sizeof(cmd));

	if (rq_data_dir(rq))
		cmd.tf_flags |= IDE_TFLAG_WRITE;

	cmd.rq = rq;

662
	ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
663 664
	ide_map_sg(drive, &cmd);

665
	return ide_tape_issue_pc(drive, &cmd, pc);
Linus Torvalds's avatar
Linus Torvalds committed
666 667 668
}

/*
669 670
 * Write a filemark if write_filemark=1. Flush the device buffers without
 * writing a filemark otherwise.
Linus Torvalds's avatar
Linus Torvalds committed
671
 */
672
static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
673
		struct ide_atapi_pc *pc, int write_filemark)
Linus Torvalds's avatar
Linus Torvalds committed
674
{
675
	ide_init_pc(pc);
676
	pc->c[0] = WRITE_FILEMARKS;
Linus Torvalds's avatar
Linus Torvalds committed
677
	pc->c[4] = write_filemark;
678
	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
Linus Torvalds's avatar
Linus Torvalds committed
679 680 681 682 683
}

static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
{
	idetape_tape_t *tape = drive->driver_data;
684
	struct gendisk *disk = tape->disk;
Linus Torvalds's avatar
Linus Torvalds committed
685 686
	int load_attempted = 0;

687
	/* Wait for the tape to become ready */
688
	set_bit(ilog2(IDE_AFLAG_MEDIUM_PRESENT), &drive->atapi_flags);
Linus Torvalds's avatar
Linus Torvalds committed
689 690
	timeout += jiffies;
	while (time_before(jiffies, timeout)) {
691
		if (ide_do_test_unit_ready(drive, disk) == 0)
Linus Torvalds's avatar
Linus Torvalds committed
692 693
			return 0;
		if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
694 695
		    || (tape->asc == 0x3A)) {
			/* no media */
Linus Torvalds's avatar
Linus Torvalds committed
696 697
			if (load_attempted)
				return -ENOMEDIUM;
698
			ide_do_start_stop(drive, disk, IDETAPE_LU_LOAD_MASK);
Linus Torvalds's avatar
Linus Torvalds committed
699 700 701 702 703
			load_attempted = 1;
		/* not about to be ready */
		} else if (!(tape->sense_key == 2 && tape->asc == 4 &&
			     (tape->ascq == 1 || tape->ascq == 8)))
			return -EIO;
704
		msleep(100);
Linus Torvalds's avatar
Linus Torvalds committed
705 706 707 708
	}
	return -EIO;
}

709
static int idetape_flush_tape_buffers(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
710
{
711
	struct ide_tape_obj *tape = drive->driver_data;
712
	struct ide_atapi_pc pc;
Linus Torvalds's avatar
Linus Torvalds committed
713 714 715
	int rc;

	idetape_create_write_filemark_cmd(drive, &pc, 0);
716
	rc = ide_queue_pc_tail(drive, tape->disk, &pc, NULL, 0);
717
	if (rc)
Linus Torvalds's avatar
Linus Torvalds committed
718 719 720 721 722
		return rc;
	idetape_wait_ready(drive, 60 * 5 * HZ);
	return 0;
}

723
static int ide_tape_read_position(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
724 725
{
	idetape_tape_t *tape = drive->driver_data;
726
	struct ide_atapi_pc pc;
727
	u8 buf[20];
Linus Torvalds's avatar
Linus Torvalds committed
728

729
	ide_debug_log(IDE_DBG_FUNC, "enter");
Linus Torvalds's avatar
Linus Torvalds committed
730

731 732 733 734 735 736
	/* prep cmd */
	ide_init_pc(&pc);
	pc.c[0] = READ_POSITION;
	pc.req_xfer = 20;

	if (ide_queue_pc_tail(drive, tape->disk, &pc, buf, pc.req_xfer))
Linus Torvalds's avatar
Linus Torvalds committed
737
		return -1;
738 739

	if (!pc.error) {
740
		ide_debug_log(IDE_DBG_FUNC, "BOP - %s",
741
				(buf[0] & 0x80) ? "Yes" : "No");
742
		ide_debug_log(IDE_DBG_FUNC, "EOP - %s",
743 744 745 746 747
				(buf[0] & 0x40) ? "Yes" : "No");

		if (buf[0] & 0x4) {
			printk(KERN_INFO "ide-tape: Block location is unknown"
					 "to the tape\n");
748 749
			clear_bit(ilog2(IDE_AFLAG_ADDRESS_VALID),
				  &drive->atapi_flags);
750 751
			return -1;
		} else {
752 753
			ide_debug_log(IDE_DBG_FUNC, "Block Location: %u",
				      be32_to_cpup((__be32 *)&buf[4]));
754 755 756

			tape->partition = buf[1];
			tape->first_frame = be32_to_cpup((__be32 *)&buf[4]);
757 758
			set_bit(ilog2(IDE_AFLAG_ADDRESS_VALID),
				&drive->atapi_flags);
759 760 761 762
		}
	}

	return tape->first_frame;
Linus Torvalds's avatar
Linus Torvalds committed
763 764
}

765 766
static void idetape_create_locate_cmd(ide_drive_t *drive,
		struct ide_atapi_pc *pc,
767
		unsigned int block, u8 partition, int skip)
Linus Torvalds's avatar
Linus Torvalds committed
768
{
769
	ide_init_pc(pc);
770
	pc->c[0] = POSITION_TO_ELEMENT;
Linus Torvalds's avatar
Linus Torvalds committed
771
	pc->c[1] = 2;
772
	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
Linus Torvalds's avatar
Linus Torvalds committed
773
	pc->c[8] = partition;
774
	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
Linus Torvalds's avatar
Linus Torvalds committed
775 776
}

777
static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
778 779 780
{
	idetape_tape_t *tape = drive->driver_data;

781
	if (tape->chrdev_dir != IDETAPE_DIR_READ)
782
		return;
Linus Torvalds's avatar
Linus Torvalds committed
783

784
	clear_bit(ilog2(IDE_AFLAG_FILEMARK), &drive->atapi_flags);
Tejun Heo's avatar
Tejun Heo committed
785 786 787 788
	tape->valid = 0;
	if (tape->buf != NULL) {
		kfree(tape->buf);
		tape->buf = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
789 790
	}

791
	tape->chrdev_dir = IDETAPE_DIR_NONE;
Linus Torvalds's avatar
Linus Torvalds committed
792 793 794
}

/*
795 796 797 798
 * Position the tape to the requested block using the LOCATE packet command.
 * A READ POSITION command is then issued to check where we are positioned. Like
 * all higher level operations, we queue the commands at the tail of the request
 * queue and wait for their completion.
Linus Torvalds's avatar
Linus Torvalds committed
799
 */
800 801
static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
		u8 partition, int skip)
Linus Torvalds's avatar
Linus Torvalds committed
802 803
{
	idetape_tape_t *tape = drive->driver_data;
804
	struct gendisk *disk = tape->disk;
805
	int ret;
806
	struct ide_atapi_pc pc;
Linus Torvalds's avatar
Linus Torvalds committed
807

808
	if (tape->chrdev_dir == IDETAPE_DIR_READ)
809
		__ide_tape_discard_merge_buffer(drive);
Linus Torvalds's avatar
Linus Torvalds committed
810 811
	idetape_wait_ready(drive, 60 * 5 * HZ);
	idetape_create_locate_cmd(drive, &pc, block, partition, skip);
812 813 814
	ret = ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
	if (ret)
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
815

816 817 818 819
	ret = ide_tape_read_position(drive);
	if (ret < 0)
		return ret;
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
820 821
}

822
static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
823
					  int restore_position)
Linus Torvalds's avatar
Linus Torvalds committed
824 825 826 827
{
	idetape_tape_t *tape = drive->driver_data;
	int seek, position;

828
	__ide_tape_discard_merge_buffer(drive);
Linus Torvalds's avatar
Linus Torvalds committed
829
	if (restore_position) {
830
		position = ide_tape_read_position(drive);
831
		seek = position > 0 ? position : 0;
Linus Torvalds's avatar
Linus Torvalds committed
832
		if (idetape_position_tape(drive, seek, 0, 0)) {
833
			printk(KERN_INFO "ide-tape: %s: position_tape failed in"
834
					 " %s\n", tape->name, __func__);
Linus Torvalds's avatar
Linus Torvalds committed
835 836 837 838 839 840
			return;
		}
	}
}

/*
841 842
 * Generate a read/write request for the block device interface and wait for it
 * to be serviced.
Linus Torvalds's avatar
Linus Torvalds committed
843
 */
844
static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
Linus Torvalds's avatar
Linus Torvalds committed
845 846
{
	idetape_tape_t *tape = drive->driver_data;
847
	struct request *rq;
848
	int ret;
Linus Torvalds's avatar
Linus Torvalds committed
849

850 851
	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, size: %d", cmd, size);

852
	BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE);
853
	BUG_ON(size < 0 || size % tape->blk_size);
854

855
	rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
856
	rq->cmd_type = REQ_TYPE_DRV_PRIV;
857
	rq->cmd[13] = cmd;
858
	rq->rq_disk = tape->disk;
859
	rq->__sector = tape->first_frame;
860 861

	if (size) {
Tejun Heo's avatar
Tejun Heo committed
862
		ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
863
				      __GFP_RECLAIM);
864 865 866 867
		if (ret)
			goto out_put;
	}

868 869
	blk_execute_rq(drive->queue, tape->disk, rq, 0);

Tejun Heo's avatar
Tejun Heo committed
870
	/* calculate the number of transferred bytes and update buffer state */
Tejun Heo's avatar
Tejun Heo committed
871
	size -= rq->resid_len;
Tejun Heo's avatar
Tejun Heo committed
872
	tape->cur = tape->buf;
873
	if (cmd == REQ_IDETAPE_READ)
Tejun Heo's avatar
Tejun Heo committed
874 875 876
		tape->valid = size;
	else
		tape->valid = 0;
Linus Torvalds's avatar
Linus Torvalds committed
877

878 879 880 881 882
	ret = size;
	if (rq->errors == IDE_DRV_ERROR_GENERAL)
		ret = -EIO;
out_put:
	blk_put_request(rq);
883
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
884 885
}

886
static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
887
{
888
	ide_init_pc(pc);
889
	pc->c[0] = INQUIRY;
890
	pc->c[4] = 254;
891
	pc->req_xfer = 254;
Linus Torvalds's avatar
Linus Torvalds committed
892 893
}

894 895
static void idetape_create_rewind_cmd(ide_drive_t *drive,
		struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
896
{
897
	ide_init_pc(pc);
898
	pc->c[0] = REZERO_UNIT;
899
	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
Linus Torvalds's avatar
Linus Torvalds committed
900 901
}

902
static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
Linus Torvalds's avatar
Linus Torvalds committed
903
{
904
	ide_init_pc(pc);
905
	pc->c[0] = ERASE;
Linus Torvalds's avatar
Linus Torvalds committed
906
	pc->c[1] = 1;
907
	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
Linus Torvalds's avatar
Linus Torvalds committed
908 909
}

910
static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
Linus Torvalds's avatar
Linus Torvalds committed
911
{
912
	ide_init_pc(pc);
913
	pc->c[0] = SPACE;
914
	put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
Linus Torvalds's avatar
Linus Torvalds committed
915
	pc->c[1] = cmd;
916
	pc->flags |= PC_FLAG_WAIT_FOR_DSC;
Linus Torvalds's avatar
Linus Torvalds committed
917 918
}

919
static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
920 921
{
	idetape_tape_t *tape = drive->driver_data;
922

923
	if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
924
		printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
925
				" but we are not writing.\n");
Linus Torvalds's avatar
Linus Torvalds committed
926 927
		return;
	}
Tejun Heo's avatar
Tejun Heo committed
928
	if (tape->buf) {
929 930 931
		size_t aligned = roundup(tape->valid, tape->blk_size);

		memset(tape->cur, 0, aligned - tape->valid);
932
		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned);
Tejun Heo's avatar
Tejun Heo committed
933 934
		kfree(tape->buf);
		tape->buf = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
935
	}
936
	tape->chrdev_dir = IDETAPE_DIR_NONE;
Linus Torvalds's avatar
Linus Torvalds committed
937 938
}

939
static int idetape_init_rw(ide_drive_t *drive, int dir)
Linus Torvalds's avatar
Linus Torvalds committed
940 941
{
	idetape_tape_t *tape = drive->driver_data;
942
	int rc;
Linus Torvalds's avatar
Linus Torvalds committed
943

944
	BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE);
Linus Torvalds's avatar
Linus Torvalds committed
945

946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
	if (tape->chrdev_dir == dir)
		return 0;

	if (tape->chrdev_dir == IDETAPE_DIR_READ)
		ide_tape_discard_merge_buffer(drive, 1);
	else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
		ide_tape_flush_merge_buffer(drive);
		idetape_flush_tape_buffers(drive);
	}

	if (tape->buf || tape->valid) {
		printk(KERN_ERR "ide-tape: valid should be 0 now\n");
		tape->valid = 0;
	}

	tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
	if (!tape->buf)
		return -ENOMEM;
	tape->chrdev_dir = dir;
	tape->cur = tape->buf;

	/*
	 * Issue a 0 rw command to ensure that DSC handshake is
	 * switched from completion mode to buffer available mode.  No
	 * point in issuing this if DSC overlap isn't supported, some
	 * drives (Seagate STT3401A) will return an error.
	 */
	if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
		int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ
						  : REQ_IDETAPE_WRITE;

		rc = idetape_queue_rw_tail(drive, cmd, 0);
		if (rc < 0) {
			kfree(tape->buf);
			tape->buf = NULL;
			tape->chrdev_dir = IDETAPE_DIR_NONE;
			return rc;
Linus Torvalds's avatar
Linus Torvalds committed
983 984
		}
	}
985

Linus Torvalds's avatar
Linus Torvalds committed
986 987 988
	return 0;
}

989
static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
Linus Torvalds's avatar
Linus Torvalds committed
990 991
{
	idetape_tape_t *tape = drive->driver_data;
Tejun Heo's avatar
Tejun Heo committed
992 993

	memset(tape->buf, 0, tape->buffer_size);
994

Linus Torvalds's avatar
Linus Torvalds committed
995
	while (bcount) {
Tejun Heo's avatar
Tejun Heo committed
996
		unsigned int count = min(tape->buffer_size, bcount);
Linus Torvalds's avatar
Linus Torvalds committed
997

998
		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count);
Linus Torvalds's avatar
Linus Torvalds committed
999 1000 1001 1002 1003
		bcount -= count;
	}
}

/*
1004 1005 1006
 * Rewinds the tape to the Beginning Of the current Partition (BOP). We
 * currently support only one partition.
 */
1007
static int idetape_rewind_tape(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
1008
{
1009 1010
	struct ide_tape_obj *tape = drive->driver_data;
	struct gendisk *disk = tape->disk;
1011
	struct ide_atapi_pc pc;
1012
	int ret;
1013

1014
	ide_debug_log(IDE_DBG_FUNC, "enter");
1015

Linus Torvalds's avatar
Linus Torvalds committed
1016
	idetape_create_rewind_cmd(drive, &pc);
1017 1018 1019
	ret = ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
	if (ret)
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1020

1021 1022 1023
	ret = ide_tape_read_position(drive);
	if (ret < 0)
		return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1024 1025 1026
	return 0;
}

1027
/* mtio.h compatible commands should be issued to the chrdev interface. */
1028 1029
static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
				unsigned long arg)
Linus Torvalds's avatar
Linus Torvalds committed
1030 1031 1032 1033
{
	idetape_tape_t *tape = drive->driver_data;
	void __user *argp = (void __user *)arg;

1034 1035 1036 1037 1038 1039
	struct idetape_config {
		int dsc_rw_frequency;
		int dsc_media_access_frequency;
		int nr_stages;
	} config;

1040
	ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%04x", cmd);
1041

Linus Torvalds's avatar
Linus Torvalds committed
1042
	switch (cmd) {
1043 1044 1045 1046 1047 1048
	case 0x0340:
		if (copy_from_user(&config, argp, sizeof(config)))
			return -EFAULT;
		tape->best_dsc_rw_freq = config.dsc_rw_frequency;
		break;
	case 0x0350:
1049
		memset(&config, 0, sizeof(config));
1050
		config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
1051
		config.nr_stages = 1;
1052 1053 1054 1055 1056
		if (copy_to_user(argp, &config, sizeof(config)))
			return -EFAULT;
		break;
	default:
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
1057 1058 1059 1060
	}
	return 0;
}

1061 1062
static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
					int mt_count)
Linus Torvalds's avatar
Linus Torvalds committed
1063 1064
{
	idetape_tape_t *tape = drive->driver_data;
1065
	struct gendisk *disk = tape->disk;
1066
	struct ide_atapi_pc pc;