ide-cd.c 46 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
		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]);

185
			if (queue_logical_block_size(drive->queue) == 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;
Linus Torvalds's avatar
Linus Torvalds committed
286

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

291 292 293
	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);
294

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

305 306 307
	/* 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
308

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

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

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

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

Borislav Petkov's avatar
Borislav Petkov committed
332
		/*
333 334
		 * 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
335
		 */
336 337 338 339
		if (++rq->errors > ERROR_MAX)
			do_end_request = 1;
		break;
	case ILLEGAL_REQUEST:
340
		/*
341 342 343 344 345
		 * 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!
346
		 */
347 348 349 350 351 352 353 354
		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.
		 */
355
		if (!blk_rq_quiet(rq))
356 357 358 359 360 361 362 363
			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.
		 */
364
		if (!blk_rq_quiet(rq))
365 366 367 368 369 370
			ide_dump_status(drive, "media error "
					"(bad sector)", stat);
		do_end_request = 1;
		break;
	case BLANK_CHECK:
		/* disk appears blank? */
371
		if (!blk_rq_quiet(rq))
372 373 374 375 376 377 378 379 380 381 382 383 384 385
			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
386 387
	}

388 389 390 391 392 393 394 395 396 397 398 399 400 401
	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)
402
		return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
403 404
	return 1;

405
end_request:
406
	if (stat & ATA_ERR) {
407
		hwif->rq = NULL;
408
		return ide_queue_sense_rq(drive, rq) ? 2 : 1;
409
	} else
410
		return 2;
Linus Torvalds's avatar
Linus Torvalds committed
411 412 413 414 415 416 417
}

/*
 * 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.
 */
418 419
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
420
{
421 422
	ide_hwif_t *hwif = drive->hwif;

423
	ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw);
424

425 426 427 428 429
	/*
	 * 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
430
		return 0;
431
	else if (ireason == (rw << 1)) {
432

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

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

451 452 453
	if (rq->cmd_type == REQ_TYPE_ATA_PC)
		rq->cmd_flags |= REQ_FAILED;

Linus Torvalds's avatar
Linus Torvalds committed
454 455 456
	return -1;
}

457
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
458
{
459 460
	struct request *rq = cmd->rq;

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

463 464 465 466 467
	/*
	 * Some of the trailing request sense fields are optional,
	 * and some drives don't send them.  Sigh.
	 */
	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
468 469
	    cmd->nleft > 0 && cmd->nleft <= 5)
		cmd->nleft = 0;
470 471
}

472 473 474 475
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
476
{
477 478
	struct cdrom_info *info = drive->driver_data;
	struct request_sense local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
479
	int retries = 10;
480
	unsigned int flags = 0;
Linus Torvalds's avatar
Linus Torvalds committed
481

482 483
	if (!sense)
		sense = &local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
484

485 486 487
	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);
488

Borislav Petkov's avatar
Borislav Petkov committed
489
	/* start of retry loop */
Linus Torvalds's avatar
Linus Torvalds committed
490
	do {
491
		struct request *rq;
Linus Torvalds's avatar
Linus Torvalds committed
492 493
		int error;

494 495 496 497 498 499 500 501
		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) {
502 503 504 505 506 507
			error = blk_rq_map_kern(drive->queue, rq, buffer,
						*bufflen, GFP_NOIO);
			if (error) {
				blk_put_request(rq);
				return error;
			}
508 509 510 511 512
		}

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

		if (buffer)
Tejun Heo's avatar
Tejun Heo committed
513
			*bufflen = rq->resid_len;
514 515 516

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

Borislav Petkov's avatar
Borislav Petkov committed
518 519 520 521
		/*
		 * FIXME: we should probably abort/retry or something in case of
		 * failure.
		 */
522
		if (flags & REQ_FAILED) {
Borislav Petkov's avatar
Borislav Petkov committed
523 524 525 526
			/*
			 * The request failed.  Retry if it was due to a unit
			 * attention status (usually means media was changed).
			 */
527
			struct request_sense *reqbuf = sense;
Linus Torvalds's avatar
Linus Torvalds committed
528 529 530 531 532

			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
533 534 535 536 537
				/*
				 * 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
538 539
				ssleep(2);
			} else {
Borislav Petkov's avatar
Borislav Petkov committed
540
				/* otherwise, don't retry */
Linus Torvalds's avatar
Linus Torvalds committed
541 542 543 544 545
				retries = 0;
			}
			--retries;
		}

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

Borislav Petkov's avatar
Borislav Petkov committed
549
	/* return an error if the command failed */
550
	return (flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds's avatar
Linus Torvalds committed
551 552
}

553 554 555 556 557 558 559 560 561 562 563
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
564 565
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
566
	ide_hwif_t *hwif = drive->hwif;
567
	struct ide_cmd *cmd = &hwif->cmd;
568
	struct request *rq = hwif->rq;
569
	ide_expiry_t *expiry = NULL;
570
	int dma_error = 0, dma, thislen, uptodate = 0;
Tejun Heo's avatar
Tejun Heo committed
571
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0;
572
	int sense = blk_sense_request(rq);
573
	unsigned int timeout;
574
	u16 len;
575
	u8 ireason, stat;
Linus Torvalds's avatar
Linus Torvalds committed
576

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

Borislav Petkov's avatar
Borislav Petkov committed
579
	/* check for errors */
580
	dma = drive->dma;
Linus Torvalds's avatar
Linus Torvalds committed
581
	if (dma) {
582
		drive->dma = 0;
583
		drive->waiting_for_dma = 0;
584
		dma_error = hwif->dma_ops->dma_end(drive);
585
		ide_dma_unmap_sg(drive, cmd);
586
		if (dma_error) {
587
			printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
588
					write ? "write" : "read");
589 590
			ide_dma_off(drive);
		}
Linus Torvalds's avatar
Linus Torvalds committed
591 592
	}

593 594 595 596 597 598 599 600 601 602
	/* 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;
		}
603
	}
Linus Torvalds's avatar
Linus Torvalds committed
604

Borislav Petkov's avatar
Borislav Petkov committed
605
	/* using dma, transfer is complete now */
Linus Torvalds's avatar
Linus Torvalds committed
606
	if (dma) {
607
		if (dma_error)
Linus Torvalds's avatar
Linus Torvalds committed
608
			return ide_error(drive, "dma error", stat);
609
		uptodate = 1;
610
		goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
611 612
	}

613
	ide_read_bcount_and_ireason(drive, &len, &ireason);
614

615
	thislen = blk_fs_request(rq) ? len : cmd->nleft;
Linus Torvalds's avatar
Linus Torvalds committed
616 617 618
	if (thislen > len)
		thislen = len;

619 620
	ide_debug_log(IDE_DBG_PC, "DRQ: stat: 0x%x, thislen: %d",
				  stat, thislen);
621

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

Borislav Petkov's avatar
Borislav Petkov committed
648
	/* check which way to transfer data */
649 650 651
	rc = ide_cd_check_ireason(drive, rq, len, ireason, write);
	if (rc)
		goto out_end;
652

653
	cmd->last_xfer_len = 0;
Linus Torvalds's avatar
Linus Torvalds committed
654

655 656 657
	ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, "
				  "ireason: 0x%x",
				  rq->cmd_type, ireason);
658

Borislav Petkov's avatar
Borislav Petkov committed
659
	/* transfer data */
Linus Torvalds's avatar
Linus Torvalds committed
660
	while (thislen > 0) {
661
		int blen = min_t(int, thislen, cmd->nleft);
Linus Torvalds's avatar
Linus Torvalds committed
662

663
		if (cmd->nleft == 0)
Linus Torvalds's avatar
Linus Torvalds committed
664 665
			break;

666 667
		ide_pio_bytes(drive, cmd, write, blen);
		cmd->last_xfer_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
668 669 670 671

		thislen -= blen;
		len -= blen;

672
		if (sense && write == 0)
Andreas Schwab's avatar
Andreas Schwab committed
673
			rq->sense_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
674 675
	}

Borislav Petkov's avatar
Borislav Petkov committed
676
	/* pad, if necessary */
677 678 679 680 681 682 683 684 685
	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
686

687 688 689 690
	if (blk_pc_request(rq)) {
		timeout = rq->timeout;
	} else {
		timeout = ATAPI_WAIT_PC;
691
		if (!blk_fs_request(rq))
692
			expiry = ide_cd_expiry;
693 694
	}

695 696
	hwif->expiry = expiry;
	ide_set_handler(drive, cdrom_newpc_intr, timeout);
Linus Torvalds's avatar
Linus Torvalds committed
697
	return ide_started;
698

699
out_end:
700
	if (blk_pc_request(rq) && rc == 0) {
701
		rq->resid_len = 0;
Tejun Heo's avatar
Tejun Heo committed
702
		blk_end_request_all(rq, 0);
703
		hwif->rq = NULL;
704
	} else {
705 706 707 708
		if (sense && uptodate)
			ide_cd_complete_failed_rq(drive, rq);

		if (blk_fs_request(rq)) {
709
			if (cmd->nleft == 0)
710 711 712 713 714 715
				uptodate = 1;
		} else {
			if (uptodate <= 0 && rq->errors == 0)
				rq->errors = -EIO;
		}

716 717 718
		if (uptodate == 0)
			ide_cd_error_cmd(drive, cmd);

719
		/* make sure it's fully ended */
720
		if (blk_fs_request(rq) == 0) {
721
			rq->resid_len -= cmd->nbytes - cmd->nleft;
722
			if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
Tejun Heo's avatar
Tejun Heo committed
723
				rq->resid_len += cmd->last_xfer_len;
724 725
		}

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

728 729
		if (sense && rc == 2)
			ide_error(drive, "request sense failure", stat);
730 731
	}
	return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
732 733
}

734
static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
735
{
736
	struct cdrom_info *cd = drive->driver_data;
737
	struct request_queue *q = drive->queue;
738 739
	int write = rq_data_dir(rq) == WRITE;
	unsigned short sectors_per_frame =
740
		queue_logical_block_size(q) >> SECTOR_BITS;
Linus Torvalds's avatar
Linus Torvalds committed
741

742
	ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, "
743
				  "secs_per_frame: %u",
744
				  rq->cmd[0], rq->cmd_flags, sectors_per_frame);
745

746
	if (write) {
Borislav Petkov's avatar
Borislav Petkov committed
747
		/* disk has become write protected */
748
		if (get_disk_ro(cd->disk))
749 750 751 752 753 754
			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.
		 */
755
		q->prep_rq_fn(q, rq);
Linus Torvalds's avatar
Linus Torvalds committed
756 757
	}

758
	/* fs requests *must* be hardware frame aligned */
759 760
	if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) ||
	    (blk_rq_pos(rq) & (sectors_per_frame - 1)))
761 762 763 764
		return ide_stopped;

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

766 767
	if (write)
		cd->devinfo.media_written = 1;
Linus Torvalds's avatar
Linus Torvalds committed
768

769 770
	rq->timeout = ATAPI_WAIT_PC;

771
	return ide_started;
Linus Torvalds's avatar
Linus Torvalds committed
772 773
}

774
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
775 776
{

777 778
	ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x",
				  rq->cmd[0], rq->cmd_type);
779

780 781 782 783
	if (blk_pc_request(rq))
		rq->cmd_flags |= REQ_QUIET;
	else
		rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
784

785
	drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
786

Borislav Petkov's avatar
Borislav Petkov committed
787
	/* sg request */
788
	if (rq->bio) {
789
		struct request_queue *q = drive->queue;
790
		char *buf = bio_data(rq->bio);
791 792
		unsigned int alignment;

793
		drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
Linus Torvalds's avatar
Linus Torvalds committed
794 795 796

		/*
		 * check if dma is safe
797 798 799
		 *
		 * NOTE! The "len" and "addr" checks should possibly have
		 * separate masks.
Linus Torvalds's avatar
Linus Torvalds committed
800
		 */
801
		alignment = queue_dma_alignment(q) | q->dma_pad_mask;
802
		if ((unsigned long)buf & alignment
Tejun Heo's avatar
Tejun Heo committed
803
		    || blk_rq_bytes(rq) & q->dma_pad_mask
804
		    || object_is_on_stack(buf))
805
			drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
806 807 808
	}
}

809
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
810
					sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
811
{
812
	struct ide_cmd cmd;
813
	int uptodate = 0, nsectors;
814

815 816 817 818 819
	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");
820

Linus Torvalds's avatar
Linus Torvalds committed
821
	if (blk_fs_request(rq)) {
822
		if (cdrom_start_rw(drive, rq) == ide_stopped)
823
			goto out_end;
824
	} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
825
		   rq->cmd_type == REQ_TYPE_ATA_PC) {
826 827 828
		if (!rq->timeout)
			rq->timeout = ATAPI_WAIT_PC;

829
		cdrom_do_block_pc(drive, rq);
830
	} else if (blk_special_request(rq)) {
Borislav Petkov's avatar
Borislav Petkov committed
831
		/* right now this can only be a reset... */
832 833
		uptodate = 1;
		goto out_end;
834
	} else {
835
		blk_dump_rq_flags(rq, DRV_NAME " bad flags");
836 837
		if (rq->errors == 0)
			rq->errors = -EIO;
838
		goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
839
	}
840

841 842 843
	/* prepare sense request for this command */
	ide_prep_sense(drive, rq);

844 845 846 847 848 849 850
	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
851 852
	if (blk_fs_request(rq) || blk_rq_bytes(rq)) {
		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
853 854 855
		ide_map_sg(drive, &cmd);
	}

856
	return ide_issue_pc(drive, &cmd);
857
out_end:
858
	nsectors = blk_rq_sectors(rq);