ide-cd.c 45.9 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

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
33
#include <linux/seq_file.h>
Linus Torvalds's avatar
Linus Torvalds committed
34 35 36 37 38 39
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
#include <linux/completion.h>
40
#include <linux/mutex.h>
41
#include <linux/bcd.h>
Linus Torvalds's avatar
Linus Torvalds committed
42

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

46
#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(ide_cd_mutex);
54
static DEFINE_MUTEX(idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
55

56
static void ide_cd_release(struct device *);
57

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

62
	mutex_lock(&idecd_ref_mutex);
63
	cd = ide_drv_g(disk, cdrom_info);
64
	if (cd) {
65
		if (ide_device_get(cd->drive))
66
			cd = NULL;
67
		else
68
			get_device(&cd->dev);
69

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

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

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

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

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

96
static int cdrom_log_sense(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
97
{
98
	struct request_sense *sense = &drive->sense_data;
Linus Torvalds's avatar
Linus Torvalds committed
99 100
	int log = 0;

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

104 105
	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);

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

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

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

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

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

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

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

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

193 194 195 196 197 198 199 200
			/*
			 * 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.
			 */
201
			if (sector < get_capacity(info->disk) &&
202
			    drive->probed_capacity - sector < 4 * 75)
203
				set_capacity(info->disk, sector);
204 205
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
206

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

210 211 212
static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
{
	/*
213
	 * For REQ_TYPE_ATA_SENSE, "rq->special" points to the original
214 215 216
	 * 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.
217
	 */
218
	struct request *failed = (struct request *)rq->special;
219
	void *sense = bio_data(rq->bio);
220 221 222

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

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

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
 * 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 {
		/*
261
		 * take a breather
262
		 */
263
		blk_delay_queue(drive->queue, 1);
264 265 266 267 268
		return 1;
	}
}

/**
Borislav Petkov's avatar
Borislav Petkov committed
269 270
 * Returns:
 * 0: if the request should be continued.
271 272
 * 1: if the request will be going through error recovery.
 * 2: if the request should be ended.
Borislav Petkov's avatar
Borislav Petkov committed
273
 */
274
static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
Linus Torvalds's avatar
Linus Torvalds committed
275
{
276
	ide_hwif_t *hwif = drive->hwif;
277
	struct request *rq = hwif->rq;
278
	int err, sense_key, do_end_request = 0;
Linus Torvalds's avatar
Linus Torvalds committed
279

Borislav Petkov's avatar
Borislav Petkov committed
280
	/* get the IDE error register */
281
	err = ide_read_error(drive);
Linus Torvalds's avatar
Linus Torvalds committed
282 283
	sense_key = err >> 4;

284 285 286
	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);
287

288
	if (rq->cmd_type == REQ_TYPE_ATA_SENSE) {
Borislav Petkov's avatar
Borislav Petkov committed
289 290 291 292 293
		/*
		 * We got an error trying to get sense info from the drive
		 * (probably while trying to recover from a former error).
		 * Just give up.
		 */
294
		rq->cmd_flags |= REQ_FAILED;
295
		return 2;
296
	}
Linus Torvalds's avatar
Linus Torvalds committed
297

298
	/* if we have an error, pass CHECK_CONDITION as the SCSI status byte */
299
	if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !rq->errors)
300
		rq->errors = SAM_STAT_CHECK_CONDITION;
Linus Torvalds's avatar
Linus Torvalds committed
301

302 303
	if (blk_noretry_request(rq))
		do_end_request = 1;
Linus Torvalds's avatar
Linus Torvalds committed
304

305 306
	switch (sense_key) {
	case NOT_READY:
307
		if (rq->cmd_type == REQ_TYPE_FS && rq_data_dir(rq) == WRITE) {
308 309 310
			if (ide_cd_breathe(drive, rq))
				return 1;
		} else {
311
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
312

313
			if (rq->cmd_type == REQ_TYPE_FS &&
314
			    !(rq->cmd_flags & REQ_QUIET))
315 316
				printk(KERN_ERR PFX "%s: tray open\n",
					drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
317
		}
318 319 320 321
		do_end_request = 1;
		break;
	case UNIT_ATTENTION:
		cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
322

323
		if (rq->cmd_type != REQ_TYPE_FS)
324
			return 0;
325

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

382
	if (rq->cmd_type != REQ_TYPE_FS) {
383 384 385 386 387 388 389 390 391 392 393 394 395
		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)
396
		return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
397 398
	return 1;

399
end_request:
400
	if (stat & ATA_ERR) {
401
		hwif->rq = NULL;
402
		return ide_queue_sense_rq(drive, rq) ? 2 : 1;
403
	} else
404
		return 2;
Linus Torvalds's avatar
Linus Torvalds committed
405 406
}

407
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
408
{
409 410
	struct request *rq = cmd->rq;

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

413 414 415 416 417
	/*
	 * Some of the trailing request sense fields are optional,
	 * and some drives don't send them.  Sigh.
	 */
	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
418 419
	    cmd->nleft > 0 && cmd->nleft <= 5)
		cmd->nleft = 0;
420 421
}

422 423 424 425
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
426
{
427 428
	struct cdrom_info *info = drive->driver_data;
	struct request_sense local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
429
	int retries = 10;
430
	unsigned int flags = 0;
Linus Torvalds's avatar
Linus Torvalds committed
431

432 433
	if (!sense)
		sense = &local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
434

435 436 437
	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);
438

Borislav Petkov's avatar
Borislav Petkov committed
439
	/* start of retry loop */
Linus Torvalds's avatar
Linus Torvalds committed
440
	do {
441
		struct request *rq;
Linus Torvalds's avatar
Linus Torvalds committed
442 443
		int error;

444
		rq = blk_get_request(drive->queue, write, __GFP_RECLAIM);
445 446 447 448 449 450 451

		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) {
452 453 454 455 456 457
			error = blk_rq_map_kern(drive->queue, rq, buffer,
						*bufflen, GFP_NOIO);
			if (error) {
				blk_put_request(rq);
				return error;
			}
458 459 460 461 462
		}

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

		if (buffer)
Tejun Heo's avatar
Tejun Heo committed
463
			*bufflen = rq->resid_len;
464 465 466

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

Borislav Petkov's avatar
Borislav Petkov committed
468 469 470 471
		/*
		 * FIXME: we should probably abort/retry or something in case of
		 * failure.
		 */
472
		if (flags & REQ_FAILED) {
Borislav Petkov's avatar
Borislav Petkov committed
473 474 475 476
			/*
			 * The request failed.  Retry if it was due to a unit
			 * attention status (usually means media was changed).
			 */
477
			struct request_sense *reqbuf = sense;
Linus Torvalds's avatar
Linus Torvalds committed
478 479 480 481 482

			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
483 484 485 486 487
				/*
				 * 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
488 489
				ssleep(2);
			} else {
Borislav Petkov's avatar
Borislav Petkov committed
490
				/* otherwise, don't retry */
Linus Torvalds's avatar
Linus Torvalds committed
491 492 493 494 495
				retries = 0;
			}
			--retries;
		}

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

Borislav Petkov's avatar
Borislav Petkov committed
499
	/* return an error if the command failed */
500
	return (flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds's avatar
Linus Torvalds committed
501 502
}

503 504 505 506
/*
 * returns true if rq has been completed
 */
static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
507 508 509 510 511 512
{
	unsigned int nr_bytes = cmd->nbytes - cmd->nleft;

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

513
	if (nr_bytes > 0) {
514
		ide_complete_rq(drive, 0, nr_bytes);
515 516 517 518
		return true;
	}

	return false;
519 520
}

Linus Torvalds's avatar
Linus Torvalds committed
521 522
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
523
	ide_hwif_t *hwif = drive->hwif;
524
	struct ide_cmd *cmd = &hwif->cmd;
525
	struct request *rq = hwif->rq;
526
	ide_expiry_t *expiry = NULL;
527
	int dma_error = 0, dma, thislen, uptodate = 0;
528
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0;
529
	int sense = (rq->cmd_type == REQ_TYPE_ATA_SENSE);
530
	unsigned int timeout;
531
	u16 len;
532
	u8 ireason, stat;
Linus Torvalds's avatar
Linus Torvalds committed
533

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

Borislav Petkov's avatar
Borislav Petkov committed
536
	/* check for errors */
537
	dma = drive->dma;
Linus Torvalds's avatar
Linus Torvalds committed
538
	if (dma) {
539
		drive->dma = 0;
540
		drive->waiting_for_dma = 0;
541
		dma_error = hwif->dma_ops->dma_end(drive);
542
		ide_dma_unmap_sg(drive, cmd);
543
		if (dma_error) {
544
			printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
545
					write ? "write" : "read");
546 547
			ide_dma_off(drive);
		}
Linus Torvalds's avatar
Linus Torvalds committed
548 549
	}

550 551 552 553 554 555 556 557 558 559
	/* 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;
		}
560
	}
Linus Torvalds's avatar
Linus Torvalds committed
561

Borislav Petkov's avatar
Borislav Petkov committed
562
	/* using dma, transfer is complete now */
Linus Torvalds's avatar
Linus Torvalds committed
563
	if (dma) {
564
		if (dma_error)
Linus Torvalds's avatar
Linus Torvalds committed
565
			return ide_error(drive, "dma error", stat);
566
		uptodate = 1;
567
		goto out_end;
Linus Torvalds's avatar
Linus Torvalds committed
568 569
	}

570
	ide_read_bcount_and_ireason(drive, &len, &ireason);
571

572
	thislen = (rq->cmd_type == REQ_TYPE_FS) ? len : cmd->nleft;
Linus Torvalds's avatar
Linus Torvalds committed
573 574 575
	if (thislen > len)
		thislen = len;

576 577
	ide_debug_log(IDE_DBG_PC, "DRQ: stat: 0x%x, thislen: %d",
				  stat, thislen);
578

Borislav Petkov's avatar
Borislav Petkov committed
579
	/* If DRQ is clear, the command has completed. */
580
	if ((stat & ATA_DRQ) == 0) {
581
		if (rq->cmd_type == REQ_TYPE_FS) {
582 583 584 585 586
			/*
			 * If we're not done reading/writing, complain.
			 * Otherwise, complete the command normally.
			 */
			uptodate = 1;
587
			if (cmd->nleft > 0) {
588
				printk(KERN_ERR PFX "%s: %s: data underrun "
589 590
					"(%u bytes)\n", drive->name, __func__,
					cmd->nleft);
591 592 593 594
				if (!write)
					rq->cmd_flags |= REQ_FAILED;
				uptodate = 0;
			}
595
		} else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) {
596
			ide_cd_request_sense_fixup(drive, cmd);
597

598
			uptodate = cmd->nleft ? 0 : 1;
599 600 601 602 603 604 605 606 607 608 609

			/*
			 * suck out the remaining bytes from the drive in an
			 * attempt to complete the data xfer. (see BZ#13399)
			 */
			if (!(stat & ATA_ERR) && !uptodate && thislen) {
				ide_pio_bytes(drive, cmd, write, thislen);
				uptodate = cmd->nleft ? 0 : 1;
			}

			if (!uptodate)
610
				rq->cmd_flags |= REQ_FAILED;
611
		}
612
		goto out_end;
613
	}
Linus Torvalds's avatar
Linus Torvalds committed
614

615
	rc = ide_check_ireason(drive, rq, len, ireason, write);
616 617
	if (rc)
		goto out_end;
618

619
	cmd->last_xfer_len = 0;
Linus Torvalds's avatar
Linus Torvalds committed
620

621 622 623
	ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, "
				  "ireason: 0x%x",
				  rq->cmd_type, ireason);
624

Borislav Petkov's avatar
Borislav Petkov committed
625
	/* transfer data */
Linus Torvalds's avatar
Linus Torvalds committed
626
	while (thislen > 0) {
627
		int blen = min_t(int, thislen, cmd->nleft);
Linus Torvalds's avatar
Linus Torvalds committed
628

629
		if (cmd->nleft == 0)
Linus Torvalds's avatar
Linus Torvalds committed
630 631
			break;

632 633
		ide_pio_bytes(drive, cmd, write, blen);
		cmd->last_xfer_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
634 635 636 637

		thislen -= blen;
		len -= blen;

638
		if (sense && write == 0)
639
			rq->sense_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
640 641
	}

Borislav Petkov's avatar
Borislav Petkov committed
642
	/* pad, if necessary */
643
	if (len > 0) {
644
		if (rq->cmd_type != REQ_TYPE_FS || write == 0)
645 646 647 648 649 650 651
			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
652

653
	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
654 655 656
		timeout = rq->timeout;
	} else {
		timeout = ATAPI_WAIT_PC;
657
		if (rq->cmd_type != REQ_TYPE_FS)
658
			expiry = ide_cd_expiry;
659 660
	}

661 662
	hwif->expiry = expiry;
	ide_set_handler(drive, cdrom_newpc_intr, timeout);
Linus Torvalds's avatar
Linus Torvalds committed
663
	return ide_started;
664

665
out_end:
666
	if (rq->cmd_type == REQ_TYPE_BLOCK_PC && rc == 0) {
667
		rq->resid_len = 0;
668
		blk_end_request_all(rq, 0);
669
		hwif->rq = NULL;
670
	} else {
671 672 673
		if (sense && uptodate)
			ide_cd_complete_failed_rq(drive, rq);

674
		if (rq->cmd_type == REQ_TYPE_FS) {
675
			if (cmd->nleft == 0)
676 677 678 679 680 681
				uptodate = 1;
		} else {
			if (uptodate <= 0 && rq->errors == 0)
				rq->errors = -EIO;
		}

682
		if (uptodate == 0 && rq->bio)
683 684
			if (ide_cd_error_cmd(drive, cmd))
				return ide_stopped;
685

686
		/* make sure it's fully ended */
687
		if (rq->cmd_type != REQ_TYPE_FS) {
688
			rq->resid_len -= cmd->nbytes - cmd->nleft;
689
			if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
Tejun Heo's avatar
Tejun Heo committed
690
				rq->resid_len += cmd->last_xfer_len;
691 692
		}

693
		ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq));
694

695 696
		if (sense && rc == 2)
			ide_error(drive, "request sense failure", stat);
697 698
	}
	return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
699 700
}

701
static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
702
{
703
	struct cdrom_info *cd = drive->driver_data;
704
	struct request_queue *q = drive->queue;
705 706
	int write = rq_data_dir(rq) == WRITE;
	unsigned short sectors_per_frame =
707
		queue_logical_block_size(q) >> SECTOR_BITS;
Linus Torvalds's avatar
Linus Torvalds committed
708

709
	ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, "
710
				  "secs_per_frame: %u",
711
				  rq->cmd[0], rq->cmd_flags, sectors_per_frame);
712

713
	if (write) {
Borislav Petkov's avatar
Borislav Petkov committed
714
		/* disk has become write protected */
715
		if (get_disk_ro(cd->disk))
716 717 718 719 720 721
			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.
		 */
722
		q->prep_rq_fn(q, rq);
Linus Torvalds's avatar
Linus Torvalds committed
723 724
	}

725
	/* fs requests *must* be hardware frame aligned */
726 727
	if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) ||
	    (blk_rq_pos(rq) & (sectors_per_frame - 1)))
728 729 730 731
		return ide_stopped;

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

733 734
	if (write)
		cd->devinfo.media_written = 1;
Linus Torvalds's avatar
Linus Torvalds committed
735

736 737
	rq->timeout = ATAPI_WAIT_PC;

738
	return ide_started;
Linus Torvalds's avatar
Linus Torvalds committed
739 740
}

741
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
742 743
{

744 745
	ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x",
				  rq->cmd[0], rq->cmd_type);
746

747
	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
748 749 750
		rq->cmd_flags |= REQ_QUIET;
	else
		rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
751

752
	drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
753

Borislav Petkov's avatar
Borislav Petkov committed
754
	/* sg request */
755
	if (rq->bio) {
756
		struct request_queue *q = drive->queue;
757
		char *buf = bio_data(rq->bio);
758 759
		unsigned int alignment;

760
		drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
Linus Torvalds's avatar
Linus Torvalds committed
761 762 763

		/*
		 * check if dma is safe
764 765 766
		 *
		 * NOTE! The "len" and "addr" checks should possibly have
		 * separate masks.
Linus Torvalds's avatar
Linus Torvalds committed
767
		 */
768
		alignment = queue_dma_alignment(q) | q->dma_pad_mask;
769
		if ((unsigned long)buf & alignment
770
		    || blk_rq_bytes(rq) & q->dma_pad_mask
771
		    || object_is_on_stack(buf))
772
			drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
773 774 775
	}
}

776
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
777
					sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
778
{
779
	struct ide_cmd cmd;
780 781
	int uptodate = 0;
	unsigned int nsectors;
782

783 784 785 786 787
	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");
788

789 790
	switch (rq->cmd_type) {
	case REQ_TYPE_FS:
791
		if (cdrom_start_rw(drive, rq) == ide_stopped)
792
			goto out_end;
793
		break;
794
	case REQ_TYPE_ATA_SENSE:
795 796
	case REQ_TYPE_BLOCK_PC:
	case REQ_TYPE_ATA_PC:
797 798 799
		if (!rq->timeout)
			rq->timeout = ATAPI_WAIT_PC;

800
		cdrom_do_block_pc(drive, rq);
801
		break;
802
	case REQ_TYPE_DRV_PRIV:
Borislav Petkov's avatar
Borislav Petkov committed
803
		/* right now this can only be a reset... */
804 805
		uptodate = 1;
		goto out_end;
806
	default:
807
		BUG();
808
	}
809

810 811 812
	/* prepare sense request for this command */
	ide_prep_sense(drive, rq);

813 814 815 816 817 818 819
	memset(&cmd, 0, sizeof(cmd));

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

	cmd.rq = rq;

820
	if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) {
821
		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
822 823 824
		ide_map_sg(drive, &cmd);
	}

825
	return ide_issue_pc(drive, &cmd);
826
out_end:
827
	nsectors = blk_rq_sectors(rq);
828 829 830 831 832 833

	if (nsectors == 0)
		nsectors = 1;

	ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);

834
	return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
835 836
}

Borislav Petkov's avatar
Borislav Petkov committed
837
/*
Linus Torvalds's avatar
Linus Torvalds committed
838 839
 * Ioctl handling.
 *
Borislav Petkov's avatar
Borislav Petkov committed
840 841 842 843 844
 * Routines which queue packet commands take as a final argument a pointer to a
 * request_sense struct. If execution of the command results in an error with a
 * CHECK CONDITION status, this structure will be filled with the results of the
 * subsequent request sense command. The pointer can also be NULL, in which case
 * no sense information is returned.
Linus Torvalds's avatar
Linus Torvalds committed
845
 */
846
static void msf_from_bcd(struct atapi_msf *msf)
Linus Torvalds's avatar
Linus Torvalds committed
847
{
848 849 850
	msf->minute = bcd2bin(msf->minute);
	msf->second = bcd2bin(msf->second);
	msf->frame  = bcd2bin(msf->frame);
Linus Torvalds's avatar
Linus Torvalds committed
851 852
}

853
int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds's avatar
Linus Torvalds committed
854 855 856
{
	struct cdrom_info *info = drive->driver_data;
	struct cdrom_device_info *cdi = &info->devinfo;
857
	unsigned char cmd[BLK_MAX_CDB];
Linus Torvalds's avatar
Linus Torvalds committed
858

859
	ide_debug_log(IDE_DBG_FUNC, "enter");
860

861 862
	memset(cmd, 0, BLK_MAX_CDB);
	cmd[0] = GPCMD_TEST_UNIT_READY;
Linus Torvalds's avatar
Linus Torvalds committed
863

864
	/*
Borislav Petkov's avatar
Borislav Petkov committed
865 866
	 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs
	 * instead of supporting the LOAD_UNLOAD opcode.
867
	 */
868
	cmd[7] = cdi->sanyo_slot % 3;
Linus Torvalds's avatar
Linus Torvalds committed
869

870
	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
Linus Torvalds's avatar
Linus Torvalds committed
871 872 873 874 875 876 877
}

static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
			       unsigned long *sectors_per_frame,
			       struct request_sense *sense)
{
	struct {
878 879
		__be32 lba;
		__be32 blocklen;
Linus Torvalds's avatar
Linus Torvalds committed
880 881 882
	} capbuf;

	int stat;
883 884
	unsigned char cmd[BLK_MAX_CDB];
	unsigned len = sizeof(capbuf);
885
	u32 blocklen;
Linus Torvalds's avatar
Linus Torvalds committed
886

887
	ide_debug_log(IDE_DBG_FUNC, "enter");
888

889 890
	memset(cmd, 0, BLK_MAX_CDB);
	cmd[0] = GPCMD_READ_CDVD_CAPACITY;
Linus Torvalds's avatar
Linus Torvalds committed
891

892 893
	stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
			       REQ_QUIET);
894 895 896 897
	if (stat)
		return stat;

	/*
898 899 900
	 * Sanity check the given block size, in so far as making
	 * sure the sectors_per_frame we give to the caller won't
	 * end up being bogus.
901
	 */
902
	blocklen = be32_to_cpu(capbuf.blocklen);
903
	blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS;
904 905 906 907 908
	switch (blocklen) {
	case 512:
	case 1024:
	case 2048:
	case 4096:
909 910
		break;
	default:
911 912
		printk_once(KERN_ERR PFX "%s: weird block size %u; "
				"setting default block size to 2048\n",
913
				drive->name, blocklen);
914
		blocklen = 2048;
915
		break;
Linus Torvalds's avatar
Linus Torvalds committed
916 917
	}

918
	*capacity = 1 + be32_to_cpu(capbuf.lba);
919
	*sectors_per_frame = blocklen >> SECTOR_BITS;
920

921 922
	ide_debug_log(IDE_DBG_PROBE, "cap: %lu, sectors_per_frame: %lu",
				     *capacity, *sectors_per_frame);
923

924
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
925 926 927 928 929 930
}

static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
				int format, char *buf, int buflen,
				struct request_sense *sense)
{
931
	unsigned char cmd[BLK_MAX_CDB];
Linus Torvalds's avatar
Linus Torvalds committed
932

933
	ide_debug_log(IDE_DBG_FUNC, "enter");
934

935
	memset(cmd, 0, BLK_MAX_CDB);
Linus Torvalds's avatar
Linus Torvalds committed
936

937 938 939 940 941
	cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
	cmd[6] = trackno;
	cmd[7] = (buflen >> 8);
	cmd[8] = (buflen & 0xff);
	cmd[9] = (format << 6);
Linus Torvalds's avatar
Linus Torvalds committed
942 943

	if (msf_flag)
944
		cmd[1] = 2;
Linus Torvalds's avatar
Linus Torvalds committed
945

946
	return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET);
Linus Torvalds's avatar
Linus Torvalds committed
947 948 949
}

/* Try to read the entire TOC for the disk into our internal buffer. */
950
int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds's avatar
Linus Torvalds committed
951 952 953 954 955 956 957 958 959 960 961 962
{
	int stat, ntracks, i;
	struct cdrom_info *info = drive->driver_data;
	struct cdrom_device_info *cdi = &info->devinfo;
	struct atapi_toc *toc = info->toc;
	struct {
		struct atapi_toc_header hdr;
		struct atapi_toc_entry  ent;
	} ms_tmp;
	long last_written;
	unsigned long sectors_per_frame = SECTORS_PER_FRAME;

963
	ide_debug_log(IDE_DBG_FUNC, "enter");
964

Linus Torvalds's avatar
Linus Torvalds committed
965
	if (toc == NULL) {
Borislav Petkov's avatar
Borislav Petkov committed
966
		/* try to allocate space */
967
		toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
968
		if (toc == NULL) {
969
			printk(KERN_ERR PFX "%s: No cdrom TOC buffer!\n",
970
					drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
971 972
			return -ENOMEM;
		}
973
		info->toc = toc;
Linus Torvalds's avatar
Linus Torvalds committed
974 975
	}

Borislav Petkov's avatar
Borislav Petkov committed
976 977 978 979
	/*
	 * Check to see if the existing data is still valid. If it is,
	 * just return.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
980 981
	(void) cdrom_check_status(drive, sense);

982
	if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
Linus Torvalds's avatar
Linus Torvalds committed
983 984
		return 0;

Borislav Petkov's avatar
Borislav Petkov committed
985
	/* try to get the total cdrom capacity and sector size */
Linus Torvalds's avatar
Linus Torvalds committed
986 987 988 989 990 991
	stat = cdrom_read_capacity(drive, &toc->capacity, &sectors_per_frame,
				   sense);
	if (stat)
		toc->capacity = 0x1fffff;

	set_capacity(info->disk, toc->capacity * sectors_per_frame);
Borislav Petkov's avatar
Borislav Petkov committed
992
	/* save a private copy of the TOC capacity for error handling */
993 994
	drive->probed_capacity = toc->capacity * sectors_per_frame;

995 996
	blk_queue_logical_block_size(drive->queue,
				     sectors_per_frame << SECTOR_BITS);
Linus Torvalds's avatar
Linus Torvalds committed
997

Borislav Petkov's avatar
Borislav Petkov committed
998
	/* first read just the header, so we know how long the TOC is */
Linus Torvalds's avatar
Linus Torvalds committed
999 1000
	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
				    sizeof(struct atapi_toc_header), sense);
1001 1002
	if (stat)
		return stat;
Linus Torvalds's avatar
Linus Torvalds committed
1003

1004
	if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
1005 1006
		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
Linus Torvalds's avatar
Linus Torvalds committed
1007 1008 1009 1010 1011 1012 1013 1014
	}

	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
	if (ntracks <= 0)
		return -EIO;
	if (ntracks > MAX_TRACKS)
		ntracks = MAX_TRACKS;

Borislav Petkov's avatar
Borislav Petkov committed
1015
	/* now read the whole schmeer */
Linus Torvalds's avatar
Linus Torvalds committed
1016 1017 1018 1019 1020 1021 1022
	stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
				  (char *)&toc->hdr,
				   sizeof(struct atapi_toc_header) +
				   (ntracks + 1) *
				   sizeof(struct atapi_toc_entry), sense);

	if (stat && toc->hdr.first_track > 1) {
Borislav Petkov's avatar
Borislav Petkov committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
		/*
		 * Cds with CDI tracks only don't have any TOC entries, despite
		 * of this the returned values are
		 * first_track == last_track = number of CDI tracks + 1,
		 * so that this case is indistinguishable from the same layout
		 * plus an additional audio track. If we get an error for the
		 * regular case, we assume a CDI without additional audio
		 * tracks. In this case the readable TOC is empty (CDI tracks
		 * are not included) and only holds the Leadout entry.
		 *
		 * Heiko Eißfeldt.
		 */
Linus Torvalds's avatar
Linus Torvalds committed
1035 1036 1037 1038 1039 1040 1041
		ntracks = 0;
		stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
					   (char *)&toc->hdr,
					   sizeof(struct atapi_toc_header) +
					   (ntracks + 1) *
					   sizeof(struct atapi_toc_entry),
					   sense);
1042
		if (stat)
Linus Torvalds's avatar
Linus Torvalds committed
1043
			return stat;
1044

1045
		if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
1046 1047
			toc->hdr.first_track = (u8)bin2bcd(CDROM_LEADOUT);
			toc->hdr.last_track = (u8)bin2bcd(CDROM_LEADOUT);
1048
		} else {
Linus Torvalds's avatar
Linus Torvalds committed
1049 1050 1051 1052 1053 1054 1055 1056
			toc->hdr.first_track = CDROM_LEADOUT;
			toc->hdr.last_track = CDROM_LEADOUT;
		}
	}

	if (stat)
		return stat;

1057
	toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
Linus Torvalds's avatar
Linus Torvalds committed
1058

1059
	if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
1060 1061
		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
Linus Torvalds's avatar
Linus Torvalds committed
1062 1063
	}

1064
	for (i = 0; i <= ntracks; i++) {
1065 1066
		if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
			if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
1067
				toc->ent[i].track = bcd2bin(toc->ent[i].track);
Linus Torvalds's avatar
Linus Torvalds committed
1068 1069
			msf_from_bcd(&toc->ent[i].addr.msf);
		}
1070 1071 1072
		toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
						  toc->ent[i].addr.msf.second,
						  toc->ent[i].addr.msf.frame);
Linus Torvalds's avatar
Linus Torvalds committed
1073 1074 1075
	}

	if (toc->hdr.first_track != CDROM_LEADOUT) {
Borislav Petkov's avatar
Borislav Petkov committed
1076
		/* read the multisession information */
Linus Torvalds's avatar
Linus Torvalds committed
1077 1078
		stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
					   sizeof(ms_tmp), sense);
1079 1080
		if (stat)
			return stat;
Linus Torvalds's avatar
Linus Torvalds committed
1081 1082 1083

		toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
	} else {
1084 1085
		ms_tmp.hdr.last_track = CDROM_LEADOUT;
		ms_tmp.hdr.first_track = ms_tmp.hdr.last_track;
Linus Torvalds's avatar
Linus Torvalds committed
1086 1087 1088
		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
	}

1089
	if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
Borislav Petkov's avatar
Borislav Petkov committed
1090
		/* re-read multisession information using MSF format */
Linus Torvalds's avatar
Linus Torvalds committed
1091 1092 1093 1094 1095
		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
					   sizeof(ms_tmp), sense);
		if (stat)
			return stat;

1096
		msf_from_bcd(&ms_tmp.ent.addr.msf);
Linus Torvalds's avatar
Linus Torvalds committed
1097
		toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
1098
						   ms_tmp.ent.addr.msf.second,
Linus Torvalds's avatar
Linus Torvalds committed
1099 1100 1101 1102 1103
						   ms_tmp.ent.addr.msf.frame);
	}

	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);

Borislav Petkov's avatar
Borislav Petkov committed
1104
	/* now try to get the total cdrom capacity */