ide-cd.c 46.2 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 * ATAPI CD-ROM driver.
Linus Torvalds's avatar
Linus Torvalds committed
3
 *
4 5 6
 * Copyright (C) 1994-1996   Scott Snyder <snyder@fnald0.fnal.gov>
 * Copyright (C) 1996-1998   Erik Andersen <andersee@debian.org>
 * Copyright (C) 1998-2000   Jens Axboe <axboe@suse.de>
7
 * Copyright (C) 2005, 2007-2009  Bartlomiej Zolnierkiewicz
Linus Torvalds's avatar
Linus Torvalds committed
8 9 10 11 12 13 14
 *
 * May be copied or modified under the terms of the GNU General Public
 * License.  See linux/COPYING for more information.
 *
 * See Documentation/cdrom/ide-cd for usage information.
 *
 * Suggestions are welcome. Patches that work are more welcome though. ;-)
15 16 17
 *
 * Documentation:
 *	Mt. Fuji (SFF8090 version 4) and ATAPI (SFF-8020i rev 2.6) standards.
Linus Torvalds's avatar
Linus Torvalds committed
18
 *
19 20 21 22
 * For historical changelog please see:
 *	Documentation/ide/ChangeLog.ide-cd.1994-2004
 */

23 24 25
#define DRV_NAME "ide-cd"
#define PFX DRV_NAME ": "

26
#define IDECD_VERSION "5.00"
Linus Torvalds's avatar
Linus Torvalds committed
27 28 29 30 31 32 33 34 35 36 37 38

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
#include <linux/completion.h>
39
#include <linux/mutex.h>
40
#include <linux/bcd.h>
Linus Torvalds's avatar
Linus Torvalds committed
41

Borislav Petkov's avatar
Borislav Petkov committed
42 43
/* For SCSI -> ATAPI command conversion */
#include <scsi/scsi.h>
Linus Torvalds's avatar
Linus Torvalds committed
44

45 46
#include <linux/irq.h>
#include <linux/io.h>
Linus Torvalds's avatar
Linus Torvalds committed
47
#include <asm/byteorder.h>
48
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
49 50 51 52
#include <asm/unaligned.h>

#include "ide-cd.h"

53
static DEFINE_MUTEX(idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
54

55
static void ide_cd_release(struct device *);
56

Linus Torvalds's avatar
Linus Torvalds committed
57 58 59 60
static struct cdrom_info *ide_cd_get(struct gendisk *disk)
{
	struct cdrom_info *cd = NULL;

61
	mutex_lock(&idecd_ref_mutex);
Borislav Petkov's avatar
Borislav Petkov committed
62
	cd = ide_drv_g(disk, cdrom_info);
63
	if (cd) {
64
		if (ide_device_get(cd->drive))
65
			cd = NULL;
66
		else
67
			get_device(&cd->dev);
68

69
	}
70
	mutex_unlock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
71 72 73 74 75
	return cd;
}

static void ide_cd_put(struct cdrom_info *cd)
{
76 77
	ide_drive_t *drive = cd->drive;

78
	mutex_lock(&idecd_ref_mutex);
79
	put_device(&cd->dev);
80
	ide_device_put(drive);
81
	mutex_unlock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
82 83
}

Borislav Petkov's avatar
Borislav Petkov committed
84
/*
Linus Torvalds's avatar
Linus Torvalds committed
85 86 87
 * Generic packet command support and error handling routines.
 */

Borislav Petkov's avatar
Borislav Petkov committed
88
/* Mark that we've seen a media change and invalidate our internal buffers. */
89
static void cdrom_saw_media_change(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
90
{
91
	drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
92
	drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
Linus Torvalds's avatar
Linus Torvalds committed
93 94 95 96 97 98 99
}

static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
			   struct request_sense *sense)
{
	int log = 0;

100
	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
101

102
	if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
Linus Torvalds's avatar
Linus Torvalds committed
103 104 105
		return 0;

	switch (sense->sense_key) {
106 107 108 109 110
	case NO_SENSE:
	case RECOVERED_ERROR:
		break;
	case NOT_READY:
		/*
Borislav Petkov's avatar
Borislav Petkov committed
111 112
		 * don't care about tray state messages for e.g. capacity
		 * commands or in-progress or becoming ready
113 114
		 */
		if (sense->asc == 0x3a || sense->asc == 0x04)
Linus Torvalds's avatar
Linus Torvalds committed
115
			break;
116 117 118 119
		log = 1;
		break;
	case ILLEGAL_REQUEST:
		/*
Borislav Petkov's avatar
Borislav Petkov committed
120 121
		 * don't log START_STOP unit with LoEj set, since we cannot
		 * reliably check if drive can auto-close
122 123
		 */
		if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
Linus Torvalds's avatar
Linus Torvalds committed
124
			break;
125 126 127 128
		log = 1;
		break;
	case UNIT_ATTENTION:
		/*
Borislav Petkov's avatar
Borislav Petkov committed
129 130 131
		 * Make good and sure we've seen this potential media change.
		 * Some drives (i.e. Creative) fail to present the correct sense
		 * key in the error register.
132 133 134 135 136 137
		 */
		cdrom_saw_media_change(drive);
		break;
	default:
		log = 1;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
138 139 140 141
	}
	return log;
}

142
static void cdrom_analyze_sense_data(ide_drive_t *drive,
Linus Torvalds's avatar
Linus Torvalds committed
143 144 145
			      struct request *failed_command,
			      struct request_sense *sense)
{
146 147 148 149
	unsigned long sector;
	unsigned long bio_sectors;
	struct cdrom_info *info = drive->driver_data;

150 151
	ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x",
				     sense->error_code, sense->sense_key);
152 153

	if (failed_command)
154 155
		ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x",
					     failed_command->cmd[0]);
156

Linus Torvalds's avatar
Linus Torvalds committed
157 158 159 160
	if (!cdrom_log_sense(drive, failed_command, sense))
		return;

	/*
Borislav Petkov's avatar
Borislav Petkov committed
161 162 163
	 * If a read toc is executed for a CD-R or CD-RW medium where the first
	 * toc has not been recorded yet, it will fail with 05/24/00 (which is a
	 * confusing error)
Linus Torvalds's avatar
Linus Torvalds committed
164 165 166 167 168
	 */
	if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
		if (sense->sense_key == 0x05 && sense->asc == 0x24)
			return;

Borislav Petkov's avatar
Borislav Petkov committed
169 170
	/* current error */
	if (sense->error_code == 0x70) {
171
		switch (sense->sense_key) {
172 173 174 175 176 177 178 179 180 181 182 183 184 185
		case MEDIUM_ERROR:
		case VOLUME_OVERFLOW:
		case ILLEGAL_REQUEST:
			if (!sense->valid)
				break;
			if (failed_command == NULL ||
					!blk_fs_request(failed_command))
				break;
			sector = (sense->information[0] << 24) |
				 (sense->information[1] << 16) |
				 (sense->information[2] <<  8) |
				 (sense->information[3]);

			if (drive->queue->hardsect_size == 2048)
Borislav Petkov's avatar
Borislav Petkov committed
186 187
				/* device sector size is 2K */
				sector <<= 2;
188 189

			bio_sectors = max(bio_sectors(failed_command->bio), 4U);
190
			sector &= ~(bio_sectors - 1);
191

192 193 194 195 196 197 198 199
			/*
			 * The SCSI specification allows for the value
			 * returned by READ CAPACITY to be up to 75 2K
			 * sectors past the last readable block.
			 * Therefore, if we hit a medium error within the
			 * last 75 2K sectors, we decrease the saved size
			 * value.
			 */
200
			if (sector < get_capacity(info->disk) &&
201
			    drive->probed_capacity - sector < 4 * 75)
202
				set_capacity(info->disk, sector);
203 204
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
205

206
	ide_cd_log_error(drive->name, failed_command, sense);
Linus Torvalds's avatar
Linus Torvalds committed
207 208
}

209 210 211
static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
{
	/*
Tejun Heo's avatar
Tejun Heo committed
212
	 * For REQ_TYPE_SENSE, "rq->special" points to the original
213 214 215
	 * failed request.  Also, the sense data should be read
	 * directly from rq which might be different from the original
	 * sense buffer if it got copied during mapping.
216
	 */
Tejun Heo's avatar
Tejun Heo committed
217
	struct request *failed = (struct request *)rq->special;
218
	void *sense = bio_data(rq->bio);
219 220 221

	if (failed) {
		if (failed->sense) {
222 223 224 225 226 227
			/*
			 * Sense is always read into drive->sense_data.
			 * Copy back if the failed request has its
			 * sense pointer set.
			 */
			memcpy(failed->sense, sense, 18);
228 229 230 231 232 233 234 235 236 237 238
			sense = failed->sense;
			failed->sense_len = rq->sense_len;
		}
		cdrom_analyze_sense_data(drive, failed, sense);

		if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed)))
			BUG();
	} else
		cdrom_analyze_sense_data(drive, NULL, sense);
}

239

Borislav Petkov's avatar
Borislav Petkov committed
240
/*
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
 * Allow the drive 5 seconds to recover; some devices will return NOT_READY
 * while flushing data from cache.
 *
 * returns: 0 failed (write timeout expired)
 *	    1 success
 */
static int ide_cd_breathe(ide_drive_t *drive, struct request *rq)
{

	struct cdrom_info *info = drive->driver_data;

	if (!rq->errors)
		info->write_timeout = jiffies +	ATAPI_WAIT_WRITE_BUSY;

	rq->errors = 1;

	if (time_after(jiffies, info->write_timeout))
		return 0;
	else {
		struct request_queue *q = drive->queue;
		unsigned long flags;

		/*
		 * take a breather relying on the unplug timer to kick us again
		 */

		spin_lock_irqsave(q->queue_lock, flags);
		blk_plug_device(q);
		spin_unlock_irqrestore(q->queue_lock, flags);

		return 1;
	}
}

/**
Borislav Petkov's avatar
Borislav Petkov committed
276 277
 * Returns:
 * 0: if the request should be continued.
278 279
 * 1: if the request will be going through error recovery.
 * 2: if the request should be ended.
Borislav Petkov's avatar
Borislav Petkov committed
280
 */
281
static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
Linus Torvalds's avatar
Linus Torvalds committed
282
{
283
	ide_hwif_t *hwif = drive->hwif;
284
	struct request *rq = hwif->rq;
285
	int err, sense_key, do_end_request = 0;
286
	u8 quiet = rq->cmd_flags & REQ_QUIET;
Linus Torvalds's avatar
Linus Torvalds committed
287

Borislav Petkov's avatar
Borislav Petkov committed
288
	/* get the IDE error register */
289
	err = ide_read_error(drive);
Linus Torvalds's avatar
Linus Torvalds committed
290 291
	sense_key = err >> 4;

292 293 294
	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, rq->cmd_type: 0x%x, err: 0x%x, "
				  "stat 0x%x",
				  rq->cmd[0], rq->cmd_type, err, stat);
295

296
	if (blk_sense_request(rq)) {
Borislav Petkov's avatar
Borislav Petkov committed
297 298 299 300 301
		/*
		 * We got an error trying to get sense info from the drive
		 * (probably while trying to recover from a former error).
		 * Just give up.
		 */
302
		rq->cmd_flags |= REQ_FAILED;
303
		return 2;
304
	}
Linus Torvalds's avatar
Linus Torvalds committed
305

306 307 308
	/* if we have an error, pass CHECK_CONDITION as the SCSI status byte */
	if (blk_pc_request(rq) && !rq->errors)
		rq->errors = SAM_STAT_CHECK_CONDITION;
Linus Torvalds's avatar
Linus Torvalds committed
309

310 311
	if (blk_noretry_request(rq))
		do_end_request = 1;
Linus Torvalds's avatar
Linus Torvalds committed
312

313 314
	switch (sense_key) {
	case NOT_READY:
315 316 317 318
		if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) {
			if (ide_cd_breathe(drive, rq))
				return 1;
		} else {
319
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
320

321 322 323
			if (blk_fs_request(rq) && !quiet)
				printk(KERN_ERR PFX "%s: tray open\n",
					drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
324
		}
325 326 327 328
		do_end_request = 1;
		break;
	case UNIT_ATTENTION:
		cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
329

330 331
		if (blk_fs_request(rq) == 0)
			return 0;
332

Borislav Petkov's avatar
Borislav Petkov committed
333
		/*
334 335
		 * Arrange to retry the request but be sure to give up if we've
		 * retried too many times.
Borislav Petkov's avatar
Borislav Petkov committed
336
		 */
337 338 339 340
		if (++rq->errors > ERROR_MAX)
			do_end_request = 1;
		break;
	case ILLEGAL_REQUEST:
341
		/*
342 343 344 345 346
		 * Don't print error message for this condition -- SFF8090i
		 * indicates that 5/24/00 is the correct response to a request
		 * to close the tray if the drive doesn't have that capability.
		 *
		 * cdrom_log_sense() knows this!
347
		 */
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
		if (rq->cmd[0] == GPCMD_START_STOP_UNIT)
			break;
		/* fall-through */
	case DATA_PROTECT:
		/*
		 * No point in retrying after an illegal request or data
		 * protect error.
		 */
		if (!quiet)
			ide_dump_status(drive, "command error", stat);
		do_end_request = 1;
		break;
	case MEDIUM_ERROR:
		/*
		 * No point in re-trying a zillion times on a bad sector.
		 * If we got here the error is not correctable.
		 */
		if (!quiet)
			ide_dump_status(drive, "media error "
					"(bad sector)", stat);
		do_end_request = 1;
		break;
	case BLANK_CHECK:
		/* disk appears blank? */
		if (!quiet)
			ide_dump_status(drive, "media error (blank)",
					stat);
		do_end_request = 1;
		break;
	default:
		if (blk_fs_request(rq) == 0)
			break;
		if (err & ~ATA_ABORTED) {
			/* go to the default handler for other errors */
			ide_error(drive, "cdrom_decode_status", stat);
			return 1;
		} else if (++rq->errors > ERROR_MAX)
			/* we've racked up too many retries, abort */
			do_end_request = 1;
Linus Torvalds's avatar
Linus Torvalds committed
387 388
	}

389 390 391 392 393 394 395 396 397 398 399 400 401 402
	if (blk_fs_request(rq) == 0) {
		rq->cmd_flags |= REQ_FAILED;
		do_end_request = 1;
	}

	/*
	 * End a request through request sense analysis when we have sense data.
	 * We need this in order to perform end of media processing.
	 */
	if (do_end_request)
		goto end_request;

	/* if we got a CHECK_CONDITION status, queue a request sense command */
	if (stat & ATA_ERR)
403
		return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
404 405
	return 1;

406
end_request:
407
	if (stat & ATA_ERR) {
408
		struct request_queue *q = drive->queue;
409 410
		unsigned long flags;

411
		spin_lock_irqsave(q->queue_lock, flags);
412
		blkdev_dequeue_request(rq);
413
		spin_unlock_irqrestore(q->queue_lock, flags);
414

415
		hwif->rq = NULL;
416

417
		return ide_queue_sense_rq(drive, rq) ? 2 : 1;
418
	} else
419
		return 2;
Linus Torvalds's avatar
Linus Torvalds committed
420 421 422 423 424 425 426
}

/*
 * Check the contents of the interrupt reason register from the cdrom
 * and attempt to recover if there are problems.  Returns  0 if everything's
 * ok; nonzero if the request has been terminated.
 */
427 428
static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
				int len, int ireason, int rw)
Linus Torvalds's avatar
Linus Torvalds committed
429
{
430 431
	ide_hwif_t *hwif = drive->hwif;

432
	ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw);
433

434 435 436 437 438
	/*
	 * ireason == 0: the drive wants to receive data from us
	 * ireason == 2: the drive is expecting to transfer data to us
	 */
	if (ireason == (!rw << 1))
Linus Torvalds's avatar
Linus Torvalds committed
439
		return 0;
440
	else if (ireason == (rw << 1)) {
441

Borislav Petkov's avatar
Borislav Petkov committed
442
		/* whoops... */
443
		printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
444
				drive->name, __func__);
Linus Torvalds's avatar
Linus Torvalds committed
445

446
		ide_pad_transfer(drive, rw, len);
447
	} else  if (rw == 0 && ireason == 1) {
Borislav Petkov's avatar
Borislav Petkov committed
448 449 450
		/*
		 * Some drives (ASUS) seem to tell us that status info is
		 * available.  Just get it and ignore.
Linus Torvalds's avatar
Linus Torvalds committed
451
		 */
452
		(void)hwif->tp_ops->read_status(hwif);
Linus Torvalds's avatar
Linus Torvalds committed
453 454
		return 0;
	} else {
Borislav Petkov's avatar
Borislav Petkov committed
455
		/* drive wants a command packet, or invalid ireason... */
456
		printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
457
				drive->name, __func__, ireason);
Linus Torvalds's avatar
Linus Torvalds committed
458 459
	}

460 461 462
	if (rq->cmd_type == REQ_TYPE_ATA_PC)
		rq->cmd_flags |= REQ_FAILED;

Linus Torvalds's avatar
Linus Torvalds committed
463 464 465
	return -1;
}

466
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
467
{
468 469
	struct request *rq = cmd->rq;

470
	ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]);
471

472 473 474 475 476
	/*
	 * Some of the trailing request sense fields are optional,
	 * and some drives don't send them.  Sigh.
	 */
	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
477 478
	    cmd->nleft > 0 && cmd->nleft <= 5)
		cmd->nleft = 0;
479 480
}

481 482 483 484
int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
		    int write, void *buffer, unsigned *bufflen,
		    struct request_sense *sense, int timeout,
		    unsigned int cmd_flags)
Linus Torvalds's avatar
Linus Torvalds committed
485
{
486 487
	struct cdrom_info *info = drive->driver_data;
	struct request_sense local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
488
	int retries = 10;
489
	unsigned int flags = 0;
Linus Torvalds's avatar
Linus Torvalds committed
490

491 492
	if (!sense)
		sense = &local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
493

494 495 496
	ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, "
				  "cmd_flags: 0x%x",
				  cmd[0], write, timeout, cmd_flags);
497

Borislav Petkov's avatar
Borislav Petkov committed
498
	/* start of retry loop */
Linus Torvalds's avatar
Linus Torvalds committed
499
	do {
500
		struct request *rq;
Linus Torvalds's avatar
Linus Torvalds committed
501 502
		int error;

503 504 505 506 507 508 509 510
		rq = blk_get_request(drive->queue, write, __GFP_WAIT);

		memcpy(rq->cmd, cmd, BLK_MAX_CDB);
		rq->cmd_type = REQ_TYPE_ATA_PC;
		rq->sense = sense;
		rq->cmd_flags |= cmd_flags;
		rq->timeout = timeout;
		if (buffer) {
511 512 513 514 515 516
			error = blk_rq_map_kern(drive->queue, rq, buffer,
						*bufflen, GFP_NOIO);
			if (error) {
				blk_put_request(rq);
				return error;
			}
517 518 519 520 521
		}

		error = blk_execute_rq(drive->queue, info->disk, rq, 0);

		if (buffer)
Tejun Heo's avatar
Tejun Heo committed
522
			*bufflen = rq->resid_len;
523 524 525

		flags = rq->cmd_flags;
		blk_put_request(rq);
Linus Torvalds's avatar
Linus Torvalds committed
526

Borislav Petkov's avatar
Borislav Petkov committed
527 528 529 530
		/*
		 * FIXME: we should probably abort/retry or something in case of
		 * failure.
		 */
531
		if (flags & REQ_FAILED) {
Borislav Petkov's avatar
Borislav Petkov committed
532 533 534 535
			/*
			 * The request failed.  Retry if it was due to a unit
			 * attention status (usually means media was changed).
			 */
536
			struct request_sense *reqbuf = sense;
Linus Torvalds's avatar
Linus Torvalds committed
537 538 539 540 541

			if (reqbuf->sense_key == UNIT_ATTENTION)
				cdrom_saw_media_change(drive);
			else if (reqbuf->sense_key == NOT_READY &&
				 reqbuf->asc == 4 && reqbuf->ascq != 4) {
Borislav Petkov's avatar
Borislav Petkov committed
542 543 544 545 546
				/*
				 * The drive is in the process of loading
				 * a disk.  Retry, but wait a little to give
				 * the drive time to complete the load.
				 */
Linus Torvalds's avatar
Linus Torvalds committed
547 548
				ssleep(2);
			} else {
Borislav Petkov's avatar
Borislav Petkov committed
549
				/* otherwise, don't retry */
Linus Torvalds's avatar
Linus Torvalds committed
550 551 552 553 554
				retries = 0;
			}
			--retries;
		}

Borislav Petkov's avatar
Borislav Petkov committed
555
		/* end of retry loop */
556
	} while ((flags & REQ_FAILED) && retries >= 0);
Linus Torvalds's avatar
Linus Torvalds committed
557

Borislav Petkov's avatar
Borislav Petkov committed
558
	/* return an error if the command failed */
559
	return (flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds's avatar
Linus Torvalds committed
560 561
}

562 563 564 565 566 567 568 569 570 571 572
static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
{
	unsigned int nr_bytes = cmd->nbytes - cmd->nleft;

	if (cmd->tf_flags & IDE_TFLAG_WRITE)
		nr_bytes -= cmd->last_xfer_len;

	if (nr_bytes > 0)
		ide_complete_rq(drive, 0, nr_bytes);
}

Linus Torvalds's avatar
Linus Torvalds committed
573 574
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
575
	ide_hwif_t *hwif = drive->hwif;
576
	struct ide_cmd *cmd = &hwif->cmd;
577
	struct request *rq = hwif->rq;
578
	ide_expiry_t *expiry = NULL;
579
	int dma_error = 0, dma, thislen, uptodate = 0;
Tejun Heo's avatar
Tejun Heo committed
580
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0;
581
	int sense = blk_sense_request(rq);
582
	unsigned int timeout;
583
	u16 len;
584
	u8 ireason, stat;
Linus Torvalds's avatar
Linus Torvalds committed
585

586
	ide_debug_log(IDE_DBG_PC, "cmd: 0x%x, write: 0x%x", rq->cmd[0], write);
587

Borislav Petkov's avatar
Borislav Petkov committed
588
	/* check for errors */
589
	dma = drive->dma;
Linus Torvalds's avatar
Linus Torvalds committed
590
	if (dma) {
591
		drive->dma = 0;
592
		drive->waiting_for_dma = 0;
593
		dma_error = hwif->dma_ops->dma_end(drive);
594
		ide_dma_unmap_sg(drive, cmd);
595
		if (dma_error) {
596
			printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
597
					write ? "write" : "read");
598 599
			ide_dma_off(drive);
		}
Linus Torvalds's avatar
Linus Torvalds committed
600 601
	}

602 603 604 605 606 607 608 609 610 611
	/* check status */
	stat = hwif->tp_ops->read_status(hwif);

	if (!OK_STAT(stat, 0, BAD_R_STAT)) {
		rc = cdrom_decode_status(drive, stat);
		if (rc) {
			if (rc == 2)
				goto out_end;
			return ide_stopped;
		}
612
	}
Linus Torvalds's avatar
Linus Torvalds committed
613

Borislav Petkov's avatar
Borislav Petkov committed
614
	/* using dma, transfer is complete now */
Linus Torvalds's avatar
Linus Torvalds committed
615
	if (dma) {
616
		if (dma_error)
Linus Torvalds's avatar
Linus Torvalds committed
617
			return ide_error(drive, "dma error", stat);
618
		uptodate = 1;
619
		goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
620 621
	}

622
	ide_read_bcount_and_ireason(drive, &len, &ireason);
623

624
	thislen = blk_fs_request(rq) ? len : cmd->nleft;
Linus Torvalds's avatar
Linus Torvalds committed
625 626 627
	if (thislen > len)
		thislen = len;

628 629
	ide_debug_log(IDE_DBG_PC, "DRQ: stat: 0x%x, thislen: %d",
				  stat, thislen);
630

Borislav Petkov's avatar
Borislav Petkov committed
631
	/* If DRQ is clear, the command has completed. */
632
	if ((stat & ATA_DRQ) == 0) {
633 634 635 636 637 638
		if (blk_fs_request(rq)) {
			/*
			 * If we're not done reading/writing, complain.
			 * Otherwise, complete the command normally.
			 */
			uptodate = 1;
639
			if (cmd->nleft > 0) {
640
				printk(KERN_ERR PFX "%s: %s: data underrun "
641 642
					"(%u bytes)\n", drive->name, __func__,
					cmd->nleft);
643 644 645 646 647
				if (!write)
					rq->cmd_flags |= REQ_FAILED;
				uptodate = 0;
			}
		} else if (!blk_pc_request(rq)) {
648
			ide_cd_request_sense_fixup(drive, cmd);
Borislav Petkov's avatar
Borislav Petkov committed
649
			/* complain if we still have data left to transfer */
650
			uptodate = cmd->nleft ? 0 : 1;
651 652
			if (uptodate == 0)
				rq->cmd_flags |= REQ_FAILED;
653
		}
654
		goto out_end;
655
	}
Linus Torvalds's avatar
Linus Torvalds committed
656

Borislav Petkov's avatar
Borislav Petkov committed
657
	/* check which way to transfer data */
658 659 660
	rc = ide_cd_check_ireason(drive, rq, len, ireason, write);
	if (rc)
		goto out_end;
661

662
	cmd->last_xfer_len = 0;
Linus Torvalds's avatar
Linus Torvalds committed
663

664 665 666
	ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, "
				  "ireason: 0x%x",
				  rq->cmd_type, ireason);
667

Borislav Petkov's avatar
Borislav Petkov committed
668
	/* transfer data */
Linus Torvalds's avatar
Linus Torvalds committed
669
	while (thislen > 0) {
670
		int blen = min_t(int, thislen, cmd->nleft);
Linus Torvalds's avatar
Linus Torvalds committed
671

672
		if (cmd->nleft == 0)
Linus Torvalds's avatar
Linus Torvalds committed
673 674
			break;

675 676
		ide_pio_bytes(drive, cmd, write, blen);
		cmd->last_xfer_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
677 678 679 680

		thislen -= blen;
		len -= blen;

681
		if (sense && write == 0)
Andreas Schwab's avatar
Andreas Schwab committed
682
			rq->sense_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
683 684
	}

Borislav Petkov's avatar
Borislav Petkov committed
685
	/* pad, if necessary */
686 687 688 689 690 691 692 693 694
	if (len > 0) {
		if (blk_fs_request(rq) == 0 || write == 0)
			ide_pad_transfer(drive, write, len);
		else {
			printk(KERN_ERR PFX "%s: confused, missing data\n",
				drive->name);
			blk_dump_rq_flags(rq, "cdrom_newpc_intr");
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
695

696 697 698 699
	if (blk_pc_request(rq)) {
		timeout = rq->timeout;
	} else {
		timeout = ATAPI_WAIT_PC;
700
		if (!blk_fs_request(rq))
701
			expiry = ide_cd_expiry;
702 703
	}

704 705
	hwif->expiry = expiry;
	ide_set_handler(drive, cdrom_newpc_intr, timeout);
Linus Torvalds's avatar
Linus Torvalds committed
706
	return ide_started;
707

708
out_end:
709
	if (blk_pc_request(rq) && rc == 0) {
Tejun Heo's avatar
Tejun Heo committed
710
		blk_end_request_all(rq, 0);
711
		hwif->rq = NULL;
712
	} else {
713 714 715 716
		if (sense && uptodate)
			ide_cd_complete_failed_rq(drive, rq);

		if (blk_fs_request(rq)) {
717
			if (cmd->nleft == 0)
718 719 720 721 722 723
				uptodate = 1;
		} else {
			if (uptodate <= 0 && rq->errors == 0)
				rq->errors = -EIO;
		}

724 725 726
		if (uptodate == 0)
			ide_cd_error_cmd(drive, cmd);

727
		/* make sure it's fully ended */
728
		if (blk_fs_request(rq) == 0) {
Tejun Heo's avatar
Tejun Heo committed
729
			rq->resid_len = blk_rq_bytes(rq) -
Tejun Heo's avatar
Tejun Heo committed
730
				(cmd->nbytes - cmd->nleft);
731
			if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
Tejun Heo's avatar
Tejun Heo committed
732
				rq->resid_len += cmd->last_xfer_len;
733 734
		}

Tejun Heo's avatar
Tejun Heo committed
735
		ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq));
736

737 738
		if (sense && rc == 2)
			ide_error(drive, "request sense failure", stat);
739 740
	}
	return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
741 742
}

743
static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
744
{
745
	struct cdrom_info *cd = drive->driver_data;
746
	struct request_queue *q = drive->queue;
747 748
	int write = rq_data_dir(rq) == WRITE;
	unsigned short sectors_per_frame =
749
		queue_hardsect_size(q) >> SECTOR_BITS;
Linus Torvalds's avatar
Linus Torvalds committed
750

751
	ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, "
752
				  "secs_per_frame: %u",
753
				  rq->cmd[0], rq->cmd_flags, sectors_per_frame);
754

755
	if (write) {
Borislav Petkov's avatar
Borislav Petkov committed
756
		/* disk has become write protected */
757
		if (get_disk_ro(cd->disk))
758 759 760 761 762 763
			return ide_stopped;
	} else {
		/*
		 * We may be retrying this request after an error.  Fix up any
		 * weirdness which might be present in the request packet.
		 */
764
		q->prep_rq_fn(q, rq);
Linus Torvalds's avatar
Linus Torvalds committed
765 766
	}

767
	/* fs requests *must* be hardware frame aligned */
768 769
	if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) ||
	    (blk_rq_pos(rq) & (sectors_per_frame - 1)))
770 771 772 773
		return ide_stopped;

	/* use DMA, if possible */
	drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
Linus Torvalds's avatar
Linus Torvalds committed
774

775 776
	if (write)
		cd->devinfo.media_written = 1;
Linus Torvalds's avatar
Linus Torvalds committed
777

778 779
	rq->timeout = ATAPI_WAIT_PC;

780
	return ide_started;
Linus Torvalds's avatar
Linus Torvalds committed
781 782
}

783
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
784 785
{

786 787
	ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x",
				  rq->cmd[0], rq->cmd_type);
788

789 790 791 792
	if (blk_pc_request(rq))
		rq->cmd_flags |= REQ_QUIET;
	else
		rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
793

794
	drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
795

Borislav Petkov's avatar
Borislav Petkov committed
796
	/* sg request */
797
	if (rq->bio) {
798
		struct request_queue *q = drive->queue;
799
		char *buf = bio_data(rq->bio);
800 801
		unsigned int alignment;

802
		drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
Linus Torvalds's avatar
Linus Torvalds committed
803 804 805

		/*
		 * check if dma is safe
806 807 808
		 *
		 * NOTE! The "len" and "addr" checks should possibly have
		 * separate masks.
Linus Torvalds's avatar
Linus Torvalds committed
809
		 */
810
		alignment = queue_dma_alignment(q) | q->dma_pad_mask;
811
		if ((unsigned long)buf & alignment
Tejun Heo's avatar
Tejun Heo committed
812
		    || blk_rq_bytes(rq) & q->dma_pad_mask
813
		    || object_is_on_stack(buf))
814
			drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
815 816 817
	}
}

818
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
819
					sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
820
{
821
	struct ide_cmd cmd;
822
	int uptodate = 0, nsectors;
823

824 825 826 827 828
	ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu",
				  rq->cmd[0], (unsigned long long)block);

	if (drive->debug_mask & IDE_DBG_RQ)
		blk_dump_rq_flags(rq, "ide_cd_do_request");
829

Linus Torvalds's avatar
Linus Torvalds committed
830
	if (blk_fs_request(rq)) {
831
		if (cdrom_start_rw(drive, rq) == ide_stopped)
832
			goto out_end;
833
	} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
834
		   rq->cmd_type == REQ_TYPE_ATA_PC) {
835 836 837
		if (!rq->timeout)
			rq->timeout = ATAPI_WAIT_PC;

838
		cdrom_do_block_pc(drive, rq);
839
	} else if (blk_special_request(rq)) {
Borislav Petkov's avatar
Borislav Petkov committed
840
		/* right now this can only be a reset... */
841 842
		uptodate = 1;
		goto out_end;
843
	} else {
844
		blk_dump_rq_flags(rq, DRV_NAME " bad flags");
845 846
		if (rq->errors == 0)
			rq->errors = -EIO;
847
		goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
848
	}
849

850 851 852
	/* prepare sense request for this command */
	ide_prep_sense(drive, rq);

853 854 855 856 857 858 859
	memset(&cmd, 0, sizeof(cmd));

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

	cmd.rq = rq;

Tejun Heo's avatar
Tejun Heo committed
860 861
	if (blk_fs_request(rq) || blk_rq_bytes(rq)) {
		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
862 863 864
		ide_map_sg(drive, &cmd);
	}