ide-cd.c 53 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 7
 * 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>
 * Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
Linus Torvalds's avatar
Linus Torvalds committed
8 9 10 11 12 13 14 15
 *
 * 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. ;-)
 * For those wishing to work on this driver, please be sure you download
16 17
 * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
 * (SFF-8020i rev 2.6) standards. These documents can be obtained by
Linus Torvalds's avatar
Linus Torvalds committed
18 19 20 21
 * anonymous ftp from:
 * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
 * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
 *
22 23 24 25
 * For historical changelog please see:
 *	Documentation/ide/ChangeLog.ide-cd.1994-2004
 */

26 27 28
#define DRV_NAME "ide-cd"
#define PFX DRV_NAME ": "

29
#define IDECD_VERSION "5.00"
Linus Torvalds's avatar
Linus Torvalds committed
30 31 32 33 34 35 36 37 38 39 40 41

#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>
42
#include <linux/mutex.h>
43
#include <linux/bcd.h>
Linus Torvalds's avatar
Linus Torvalds committed
44

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

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

#include "ide-cd.h"

56
static DEFINE_MUTEX(idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
57

58 59
static void ide_cd_release(struct kref *);

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

64
	mutex_lock(&idecd_ref_mutex);
65
	cd = ide_drv_g(disk, cdrom_info);
66
	if (cd) {
67
		if (ide_device_get(cd->drive))
68
			cd = NULL;
69 70 71
		else
			kref_get(&cd->kref);

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

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

81
	mutex_lock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
82
	kref_put(&cd->kref, ide_cd_release);
83
	ide_device_put(drive);
84
	mutex_unlock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
85 86
}

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

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

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

103 104 105
	ide_debug_log(IDE_DBG_SENSE, "Call %s, sense_key: 0x%x\n", __func__,
		      sense->sense_key);

106
	if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
Linus Torvalds's avatar
Linus Torvalds committed
107 108 109
		return 0;

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

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

154 155 156 157 158 159 160 161
	ide_debug_log(IDE_DBG_SENSE, "Call %s, error_code: 0x%x, "
			"sense_key: 0x%x\n", __func__, sense->error_code,
			sense->sense_key);

	if (failed_command)
		ide_debug_log(IDE_DBG_SENSE, "%s: failed cmd: 0x%x\n",
				__func__, failed_command->cmd[0]);

Linus Torvalds's avatar
Linus Torvalds committed
162 163 164 165
	if (!cdrom_log_sense(drive, failed_command, sense))
		return;

	/*
Borislav Petkov's avatar
Borislav Petkov committed
166 167 168
	 * 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
169 170 171 172 173
	 */
	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
174 175
	/* current error */
	if (sense->error_code == 0x70) {
176
		switch (sense->sense_key) {
177 178 179 180 181 182 183 184 185 186 187 188 189 190
		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
191 192
				/* device sector size is 2K */
				sector <<= 2;
193 194

			bio_sectors = max(bio_sectors(failed_command->bio), 4U);
195
			sector &= ~(bio_sectors - 1);
196 197

			if (sector < get_capacity(info->disk) &&
198
			    drive->probed_capacity - sector < 4 * 75)
199
				set_capacity(info->disk, sector);
200 201
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
202

203
	ide_cd_log_error(drive->name, failed_command, sense);
Linus Torvalds's avatar
Linus Torvalds committed
204 205 206 207 208 209 210 211
}

static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
				      struct request *failed_command)
{
	struct cdrom_info *info		= drive->driver_data;
	struct request *rq		= &info->request_sense_request;

212 213
	ide_debug_log(IDE_DBG_SENSE, "Call %s\n", __func__);

Linus Torvalds's avatar
Linus Torvalds committed
214 215 216 217
	if (sense == NULL)
		sense = &info->sense_data;

	/* stuff the sense request in front of our current request */
218 219 220
	blk_rq_init(NULL, rq);
	rq->cmd_type = REQ_TYPE_ATA_PC;
	rq->rq_disk = info->disk;
Linus Torvalds's avatar
Linus Torvalds committed
221 222 223

	rq->data = sense;
	rq->cmd[0] = GPCMD_REQUEST_SENSE;
224 225
	rq->cmd[4] = 18;
	rq->data_len = 18;
Linus Torvalds's avatar
Linus Torvalds committed
226

227
	rq->cmd_type = REQ_TYPE_SENSE;
228
	rq->cmd_flags |= REQ_PREEMPT;
Linus Torvalds's avatar
Linus Torvalds committed
229 230 231 232

	/* NOTE! Save the failed command in "rq->buffer" */
	rq->buffer = (void *) failed_command;

233 234 235 236
	if (failed_command)
		ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
			      failed_command->cmd[0]);

237
	ide_do_drive_cmd(drive, rq);
Linus Torvalds's avatar
Linus Torvalds committed
238 239
}

240
static void cdrom_end_request(ide_drive_t *drive, int uptodate)
Linus Torvalds's avatar
Linus Torvalds committed
241
{
242
	struct request *rq = drive->hwif->rq;
Linus Torvalds's avatar
Linus Torvalds committed
243 244
	int nsectors = rq->hard_cur_sectors;

245 246 247 248
	ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
		      "nsectors: %d\n", __func__, rq->cmd[0], uptodate,
		      nsectors);

249
	if (blk_sense_request(rq) && uptodate) {
Linus Torvalds's avatar
Linus Torvalds committed
250
		/*
251 252
		 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
		 * failed request
Linus Torvalds's avatar
Linus Torvalds committed
253 254 255 256 257 258 259 260 261 262
		 */
		struct request *failed = (struct request *) rq->buffer;
		struct cdrom_info *info = drive->driver_data;
		void *sense = &info->sense_data;

		if (failed) {
			if (failed->sense) {
				sense = failed->sense;
				failed->sense_len = rq->sense_len;
			}
263
			cdrom_analyze_sense_data(drive, failed, sense);
Linus Torvalds's avatar
Linus Torvalds committed
264
			/*
Borislav Petkov's avatar
Borislav Petkov committed
265
			 * now end the failed request
Linus Torvalds's avatar
Linus Torvalds committed
266
			 */
267 268 269 270 271
			if (blk_fs_request(failed)) {
				if (ide_end_dequeued_request(drive, failed, 0,
						failed->hard_nr_sectors))
					BUG();
			} else {
272 273
				if (blk_end_request(failed, -EIO,
						    failed->data_len))
274
					BUG();
275 276 277
			}
		} else
			cdrom_analyze_sense_data(drive, NULL, sense);
Linus Torvalds's avatar
Linus Torvalds committed
278 279 280 281 282 283 284 285 286 287
	}

	if (!rq->current_nr_sectors && blk_fs_request(rq))
		uptodate = 1;
	/* make sure it's fully ended */
	if (blk_pc_request(rq))
		nsectors = (rq->data_len + 511) >> 9;
	if (!nsectors)
		nsectors = 1;

288 289 290
	ide_debug_log(IDE_DBG_FUNC, "Exit %s, uptodate: 0x%x, nsectors: %d\n",
		      __func__, uptodate, nsectors);

Linus Torvalds's avatar
Linus Torvalds committed
291 292 293
	ide_end_request(drive, uptodate, nsectors);
}

294
static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
295
{
296
	if (st & 0x80)
297
		return;
298
	ide_dump_status(drive, msg, st);
299 300
}

Borislav Petkov's avatar
Borislav Petkov committed
301 302 303 304 305
/*
 * Returns:
 * 0: if the request should be continued.
 * 1: if the request was ended.
 */
Linus Torvalds's avatar
Linus Torvalds committed
306 307
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
308
	ide_hwif_t *hwif = drive->hwif;
309
	struct request *rq = hwif->rq;
Linus Torvalds's avatar
Linus Torvalds committed
310
	int stat, err, sense_key;
311

Borislav Petkov's avatar
Borislav Petkov committed
312
	/* check for errors */
313
	stat = hwif->tp_ops->read_status(hwif);
314

Linus Torvalds's avatar
Linus Torvalds committed
315 316 317 318 319 320
	if (stat_ret)
		*stat_ret = stat;

	if (OK_STAT(stat, good_stat, BAD_R_STAT))
		return 0;

Borislav Petkov's avatar
Borislav Petkov committed
321
	/* get the IDE error register */
322
	err = ide_read_error(drive);
Linus Torvalds's avatar
Linus Torvalds committed
323 324 325
	sense_key = err >> 4;

	if (rq == NULL) {
326
		printk(KERN_ERR PFX "%s: missing rq in %s\n",
327
				drive->name, __func__);
Linus Torvalds's avatar
Linus Torvalds committed
328 329 330
		return 1;
	}

331
	ide_debug_log(IDE_DBG_RQ, "%s: stat: 0x%x, good_stat: 0x%x, "
332 333
		      "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x, err: 0x%x\n",
		      __func__, stat, good_stat, rq->cmd[0], rq->cmd_type, err);
334

335
	if (blk_sense_request(rq)) {
Borislav Petkov's avatar
Borislav Petkov committed
336 337 338 339 340
		/*
		 * We got an error trying to get sense info from the drive
		 * (probably while trying to recover from a former error).
		 * Just give up.
		 */
341
		rq->cmd_flags |= REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
342 343 344 345
		cdrom_end_request(drive, 0);
		ide_error(drive, "request sense failure", stat);
		return 1;

346
	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds's avatar
Linus Torvalds committed
347 348 349 350 351 352
		/* All other functions, except for READ. */

		/*
		 * if we have an error, pass back CHECK_CONDITION as the
		 * scsi status byte
		 */
353
		if (blk_pc_request(rq) && !rq->errors)
Linus Torvalds's avatar
Linus Torvalds committed
354 355
			rq->errors = SAM_STAT_CHECK_CONDITION;

Borislav Petkov's avatar
Borislav Petkov committed
356
		/* check for tray open */
Linus Torvalds's avatar
Linus Torvalds committed
357
		if (sense_key == NOT_READY) {
358
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
359
		} else if (sense_key == UNIT_ATTENTION) {
Borislav Petkov's avatar
Borislav Petkov committed
360
			/* check for media change */
361
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
362
			return 0;
363 364 365 366 367 368 369 370 371
		} else if (sense_key == ILLEGAL_REQUEST &&
			   rq->cmd[0] == GPCMD_START_STOP_UNIT) {
			/*
			 * 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!
			 */
372
		} else if (!(rq->cmd_flags & REQ_QUIET)) {
Borislav Petkov's avatar
Borislav Petkov committed
373
			/* otherwise, print an error */
Linus Torvalds's avatar
Linus Torvalds committed
374 375
			ide_dump_status(drive, "packet command error", stat);
		}
376

377
		rq->cmd_flags |= REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
378 379 380 381 382 383

		/*
		 * instead of playing games with moving completions around,
		 * remove failed request completely and end it when the
		 * request sense has completed
		 */
384
		goto end_request;
Linus Torvalds's avatar
Linus Torvalds committed
385 386 387 388

	} else if (blk_fs_request(rq)) {
		int do_end_request = 0;

Borislav Petkov's avatar
Borislav Petkov committed
389
		/* handle errors from READ and WRITE requests */
Linus Torvalds's avatar
Linus Torvalds committed
390 391 392 393 394

		if (blk_noretry_request(rq))
			do_end_request = 1;

		if (sense_key == NOT_READY) {
Borislav Petkov's avatar
Borislav Petkov committed
395
			/* tray open */
Linus Torvalds's avatar
Linus Torvalds committed
396
			if (rq_data_dir(rq) == READ) {
397
				cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
398

Borislav Petkov's avatar
Borislav Petkov committed
399
				/* fail the request */
400 401
				printk(KERN_ERR PFX "%s: tray open\n",
						drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
402 403 404 405
				do_end_request = 1;
			} else {
				struct cdrom_info *info = drive->driver_data;

Borislav Petkov's avatar
Borislav Petkov committed
406 407
				/*
				 * Allow the drive 5 seconds to recover, some
Linus Torvalds's avatar
Linus Torvalds committed
408
				 * devices will return this error while flushing
Borislav Petkov's avatar
Borislav Petkov committed
409 410
				 * data from cache.
				 */
Linus Torvalds's avatar
Linus Torvalds committed
411
				if (!rq->errors)
412 413
					info->write_timeout = jiffies +
							ATAPI_WAIT_WRITE_BUSY;
Linus Torvalds's avatar
Linus Torvalds committed
414 415 416 417
				rq->errors = 1;
				if (time_after(jiffies, info->write_timeout))
					do_end_request = 1;
				else {
418
					struct request_queue *q = drive->queue;
Linus Torvalds's avatar
Linus Torvalds committed
419 420 421
					unsigned long flags;

					/*
Borislav Petkov's avatar
Borislav Petkov committed
422 423
					 * take a breather relying on the unplug
					 * timer to kick us again
Linus Torvalds's avatar
Linus Torvalds committed
424
					 */
425 426 427 428
					spin_lock_irqsave(q->queue_lock, flags);
					blk_plug_device(q);
					spin_unlock_irqrestore(q->queue_lock, flags);

Linus Torvalds's avatar
Linus Torvalds committed
429 430 431 432
					return 1;
				}
			}
		} else if (sense_key == UNIT_ATTENTION) {
Borislav Petkov's avatar
Borislav Petkov committed
433
			/* media change */
434
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
435

436
			/*
Borislav Petkov's avatar
Borislav Petkov committed
437 438
			 * Arrange to retry the request but be sure to give up
			 * if we've retried too many times.
439
			 */
Linus Torvalds's avatar
Linus Torvalds committed
440 441 442 443
			if (++rq->errors > ERROR_MAX)
				do_end_request = 1;
		} else if (sense_key == ILLEGAL_REQUEST ||
			   sense_key == DATA_PROTECT) {
444
			/*
Borislav Petkov's avatar
Borislav Petkov committed
445 446
			 * No point in retrying after an illegal request or data
			 * protect error.
447 448
			 */
			ide_dump_status_no_sense(drive, "command error", stat);
Linus Torvalds's avatar
Linus Torvalds committed
449 450
			do_end_request = 1;
		} else if (sense_key == MEDIUM_ERROR) {
451 452
			/*
			 * No point in re-trying a zillion times on a bad
Borislav Petkov's avatar
Borislav Petkov committed
453
			 * sector. If we got here the error is not correctable.
454
			 */
455 456 457
			ide_dump_status_no_sense(drive,
						 "media error (bad sector)",
						 stat);
Linus Torvalds's avatar
Linus Torvalds committed
458 459
			do_end_request = 1;
		} else if (sense_key == BLANK_CHECK) {
Borislav Petkov's avatar
Borislav Petkov committed
460
			/* disk appears blank ?? */
461 462
			ide_dump_status_no_sense(drive, "media error (blank)",
						 stat);
Linus Torvalds's avatar
Linus Torvalds committed
463
			do_end_request = 1;
464
		} else if ((err & ~ATA_ABORTED) != 0) {
Borislav Petkov's avatar
Borislav Petkov committed
465
			/* go to the default handler for other errors */
Linus Torvalds's avatar
Linus Torvalds committed
466 467 468
			ide_error(drive, "cdrom_decode_status", stat);
			return 1;
		} else if ((++rq->errors > ERROR_MAX)) {
Borislav Petkov's avatar
Borislav Petkov committed
469
			/* we've racked up too many retries, abort */
Linus Torvalds's avatar
Linus Torvalds committed
470 471 472
			do_end_request = 1;
		}

Borislav Petkov's avatar
Borislav Petkov committed
473 474 475 476 477
		/*
		 * End a request through request sense analysis when we have
		 * sense data. We need this in order to perform end of media
		 * processing.
		 */
478 479
		if (do_end_request)
			goto end_request;
480

481
		/*
Borislav Petkov's avatar
Borislav Petkov committed
482 483
		 * If we got a CHECK_CONDITION status, queue
		 * a request sense command.
484
		 */
485
		if (stat & ATA_ERR)
486
			cdrom_queue_request_sense(drive, NULL, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
487
	} else {
488
		blk_dump_rq_flags(rq, PFX "bad rq");
Linus Torvalds's avatar
Linus Torvalds committed
489 490 491
		cdrom_end_request(drive, 0);
	}

Borislav Petkov's avatar
Borislav Petkov committed
492
	/* retry, or handle the next request */
Linus Torvalds's avatar
Linus Torvalds committed
493
	return 1;
494 495

end_request:
496
	if (stat & ATA_ERR) {
497
		struct request_queue *q = drive->queue;
498 499
		unsigned long flags;

500
		spin_lock_irqsave(q->queue_lock, flags);
501
		blkdev_dequeue_request(rq);
502
		spin_unlock_irqrestore(q->queue_lock, flags);
503

504
		hwif->rq = NULL;
505

506 507 508 509 510
		cdrom_queue_request_sense(drive, rq->sense, rq);
	} else
		cdrom_end_request(drive, 0);

	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
511 512 513 514 515 516 517
}

/*
 * 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.
 */
518 519
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
520
{
521 522
	ide_hwif_t *hwif = drive->hwif;

523 524 525
	ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
		      __func__, ireason, rw);

526 527 528 529 530
	/*
	 * 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
531
		return 0;
532
	else if (ireason == (rw << 1)) {
533

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

538
		ide_pad_transfer(drive, rw, len);
539
	} else  if (rw == 0 && ireason == 1) {
Borislav Petkov's avatar
Borislav Petkov committed
540 541 542
		/*
		 * Some drives (ASUS) seem to tell us that status info is
		 * available.  Just get it and ignore.
Linus Torvalds's avatar
Linus Torvalds committed
543
		 */
544
		(void)hwif->tp_ops->read_status(hwif);
Linus Torvalds's avatar
Linus Torvalds committed
545 546
		return 0;
	} else {
Borislav Petkov's avatar
Borislav Petkov committed
547
		/* drive wants a command packet, or invalid ireason... */
548
		printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
549
				drive->name, __func__, ireason);
Linus Torvalds's avatar
Linus Torvalds committed
550 551
	}

552 553 554
	if (rq->cmd_type == REQ_TYPE_ATA_PC)
		rq->cmd_flags |= REQ_FAILED;

Linus Torvalds's avatar
Linus Torvalds committed
555 556 557 558
	cdrom_end_request(drive, 0);
	return -1;
}

559 560 561 562 563 564
/*
 * Assume that the drive will always provide data in multiples of at least
 * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
 */
static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
{
565 566
	ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);

567 568 569
	if ((len % SECTOR_SIZE) == 0)
		return 0;

570 571
	printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name,
			__func__, len);
572

573
	if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
574 575
		printk(KERN_ERR PFX "This drive is not supported by this "
				"version of the driver\n");
576
	else {
577
		printk(KERN_ERR PFX "Trying to limit transfer sizes\n");
578
		drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
579 580 581 582 583
	}

	return 1;
}

584 585
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
						 struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
586
{
587 588 589
	ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
		      rq->cmd_flags);

590 591 592 593
	if (rq_data_dir(rq) == READ) {
		unsigned short sectors_per_frame =
			queue_hardsect_size(drive->queue) >> SECTOR_BITS;
		int nskip = rq->sector & (sectors_per_frame - 1);
Linus Torvalds's avatar
Linus Torvalds committed
594

595 596 597 598 599 600 601 602 603 604 605
		/*
		 * If the requested sector doesn't start on a frame boundary,
		 * we must adjust the start of the transfer so that it does,
		 * and remember to skip the first few sectors.
		 *
		 * If the rq->current_nr_sectors field is larger than the size
		 * of the buffer, it will mean that we're to skip a number of
		 * sectors equal to the amount by which rq->current_nr_sectors
		 * is larger than the buffer size.
		 */
		if (nskip > 0) {
Borislav Petkov's avatar
Borislav Petkov committed
606
			/* sanity check... */
607 608
			if (rq->current_nr_sectors !=
			    bio_cur_sectors(rq->bio)) {
609
				printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
610
						drive->name, __func__,
611 612 613 614 615
						rq->current_nr_sectors);
				cdrom_end_request(drive, 0);
				return ide_stopped;
			}
			rq->current_nr_sectors += nskip;
Linus Torvalds's avatar
Linus Torvalds committed
616 617
		}
	}
618

Borislav Petkov's avatar
Borislav Petkov committed
619
	/* set up the command */
Linus Torvalds's avatar
Linus Torvalds committed
620 621
	rq->timeout = ATAPI_WAIT_PC;

622 623 624
	return ide_started;
}

625
/*
Borislav Petkov's avatar
Borislav Petkov committed
626 627
 * Fix up a possibly partially-processed request so that we can start it over
 * entirely, or even put it back on the request queue.
628
 */
629
static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
630
{
631 632 633

	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

Linus Torvalds's avatar
Linus Torvalds committed
634
	if (rq->buffer != bio_data(rq->bio)) {
635 636
		sector_t n =
			(rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
Linus Torvalds's avatar
Linus Torvalds committed
637 638 639 640 641

		rq->buffer = bio_data(rq->bio);
		rq->nr_sectors += n;
		rq->sector -= n;
	}
642 643
	rq->current_nr_sectors = bio_cur_sectors(rq->bio);
	rq->hard_cur_sectors = rq->current_nr_sectors;
Linus Torvalds's avatar
Linus Torvalds committed
644 645 646 647 648
	rq->hard_nr_sectors = rq->nr_sectors;
	rq->hard_sector = rq->sector;
	rq->q->prep_rq_fn(rq->q, rq);
}

649
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
650
{
651 652
	ide_debug_log(IDE_DBG_FUNC, "Call %s, rq->cmd[0]: 0x%x\n",
		      __func__, rq->cmd[0]);
653

654 655 656 657 658 659 660 661 662 663 664 665
	/*
	 * Some of the trailing request sense fields are optional,
	 * and some drives don't send them.  Sigh.
	 */
	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
	    rq->data_len > 0 && rq->data_len <= 5)
		while (rq->data_len > 0) {
			*(u8 *)rq->data++ = 0;
			--rq->data_len;
		}
}

666 667 668 669
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
670
{
671 672
	struct cdrom_info *info = drive->driver_data;
	struct request_sense local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
673
	int retries = 10;
674
	unsigned int flags = 0;
Linus Torvalds's avatar
Linus Torvalds committed
675

676 677
	if (!sense)
		sense = &local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
678

679
	ide_debug_log(IDE_DBG_PC, "Call %s, cmd[0]: 0x%x, write: 0x%x, "
680 681 682
		      "timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
		      timeout, cmd_flags);

Borislav Petkov's avatar
Borislav Petkov committed
683
	/* start of retry loop */
Linus Torvalds's avatar
Linus Torvalds committed
684
	do {
685
		struct request *rq;
Linus Torvalds's avatar
Linus Torvalds committed
686 687
		int error;

688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
		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) {
			rq->data = buffer;
			rq->data_len = *bufflen;
		}

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

		if (buffer)
			*bufflen = rq->data_len;

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

Borislav Petkov's avatar
Borislav Petkov committed
708 709 710 711
		/*
		 * FIXME: we should probably abort/retry or something in case of
		 * failure.
		 */
712
		if (flags & REQ_FAILED) {
Borislav Petkov's avatar
Borislav Petkov committed
713 714 715 716
			/*
			 * The request failed.  Retry if it was due to a unit
			 * attention status (usually means media was changed).
			 */
717
			struct request_sense *reqbuf = sense;
Linus Torvalds's avatar
Linus Torvalds committed
718 719 720 721 722

			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
723 724 725 726 727
				/*
				 * 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
728 729
				ssleep(2);
			} else {
Borislav Petkov's avatar
Borislav Petkov committed
730
				/* otherwise, don't retry */
Linus Torvalds's avatar
Linus Torvalds committed
731 732 733 734 735
				retries = 0;
			}
			--retries;
		}

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

Borislav Petkov's avatar
Borislav Petkov committed
739
	/* return an error if the command failed */
740
	return (flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds's avatar
Linus Torvalds committed
741 742
}

743
/*
Borislav Petkov's avatar
Borislav Petkov committed
744 745 746
 * Called from blk_end_request_callback() after the data of the request is
 * completed and before the request itself is completed. By returning value '1',
 * blk_end_request_callback() returns immediately without completing it.
747 748 749 750 751 752
 */
static int cdrom_newpc_intr_dummy_cb(struct request *rq)
{
	return 1;
}

Linus Torvalds's avatar
Linus Torvalds committed
753 754
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
755
	ide_hwif_t *hwif = drive->hwif;
756
	struct request *rq = hwif->rq;
Linus Torvalds's avatar
Linus Torvalds committed
757
	xfer_func_t *xferfunc;
758
	ide_expiry_t *expiry = NULL;
759
	int dma_error = 0, dma, stat, thislen, uptodate = 0;
760 761
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
	unsigned int timeout;
762 763
	u16 len;
	u8 ireason;
Linus Torvalds's avatar
Linus Torvalds committed
764

765 766 767
	ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x\n",
		      __func__, rq->cmd[0], write);

Borislav Petkov's avatar
Borislav Petkov committed
768
	/* check for errors */
769
	dma = drive->dma;
Linus Torvalds's avatar
Linus Torvalds committed
770
	if (dma) {
771
		drive->dma = 0;
772
		dma_error = hwif->dma_ops->dma_end(drive);
773
		if (dma_error) {
774
			printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
775
					write ? "write" : "read");
776 777
			ide_dma_off(drive);
		}
Linus Torvalds's avatar
Linus Torvalds committed
778 779 780 781 782
	}

	if (cdrom_decode_status(drive, 0, &stat))
		return ide_stopped;

Borislav Petkov's avatar
Borislav Petkov committed
783
	/* using dma, transfer is complete now */
Linus Torvalds's avatar
Linus Torvalds committed
784
	if (dma) {
785
		if (dma_error)
Linus Torvalds's avatar
Linus Torvalds committed
786
			return ide_error(drive, "dma error", stat);
787 788 789 790
		if (blk_fs_request(rq)) {
			ide_end_request(drive, 1, rq->nr_sectors);
			return ide_stopped;
		}
791
		goto end_request;
Linus Torvalds's avatar
Linus Torvalds committed
792 793
	}

794
	ide_read_bcount_and_ireason(drive, &len, &ireason);
795 796

	thislen = blk_fs_request(rq) ? len : rq->data_len;
Linus Torvalds's avatar
Linus Torvalds committed
797 798 799
	if (thislen > len)
		thislen = len;

800 801 802
	ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
		      __func__, stat, thislen);

Borislav Petkov's avatar
Borislav Petkov committed
803
	/* If DRQ is clear, the command has completed. */
804
	if ((stat & ATA_DRQ) == 0) {
805 806 807 808 809 810 811
		if (blk_fs_request(rq)) {
			/*
			 * If we're not done reading/writing, complain.
			 * Otherwise, complete the command normally.
			 */
			uptodate = 1;
			if (rq->current_nr_sectors > 0) {
812
				printk(KERN_ERR PFX "%s: %s: data underrun "
813
						"(%d blocks)\n",
814
						drive->name, __func__,
815 816 817 818 819 820 821 822
						rq->current_nr_sectors);
				if (!write)
					rq->cmd_flags |= REQ_FAILED;
				uptodate = 0;
			}
			cdrom_end_request(drive, uptodate);
			return ide_stopped;
		} else if (!blk_pc_request(rq)) {
823
			ide_cd_request_sense_fixup(drive, rq);
Borislav Petkov's avatar
Borislav Petkov committed
824
			/* complain if we still have data left to transfer */
825 826 827
			uptodate = rq->data_len ? 0 : 1;
		}
		goto end_request;
828
	}
Linus Torvalds's avatar
Linus Torvalds committed
829

Borislav Petkov's avatar
Borislav Petkov committed
830
	/* check which way to transfer data */
831 832
	if (ide_cd_check_ireason(drive, rq, len, ireason, write))
		return ide_stopped;
833

834 835
	if (blk_fs_request(rq)) {
		if (write == 0) {
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
			int nskip;

			if (ide_cd_check_transfer_size(drive, len)) {
				cdrom_end_request(drive, 0);
				return ide_stopped;
			}

			/*
			 * First, figure out if we need to bit-bucket
			 * any of the leading sectors.
			 */
			nskip = min_t(int, rq->current_nr_sectors
					   - bio_cur_sectors(rq->bio),
					   thislen >> 9);
			if (nskip > 0) {
851
				ide_pad_transfer(drive, write, nskip << 9);
852 853 854 855
				rq->current_nr_sectors -= nskip;
				thislen -= (nskip << 9);
			}
		}
856
	}
Linus Torvalds's avatar
Linus Torvalds committed
857

858 859
	if (ireason == 0) {
		write = 1;
860
		xferfunc = hwif->tp_ops->output_data;
861
	} else {
862
		write = 0;
863
		xferfunc = hwif->tp_ops->input_data;
Linus Torvalds's avatar
Linus Torvalds committed
864 865
	}

866 867 868
	ide_debug_log(IDE_DBG_PC, "%s: data transfer, rq->cmd_type: 0x%x, "
		      "ireason: 0x%x\n", __func__, rq->cmd_type, ireason);

Borislav Petkov's avatar
Borislav Petkov committed
869
	/* transfer data */
Linus Torvalds's avatar
Linus Torvalds committed
870
	while (thislen > 0) {
871
		u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
872
		int blen = rq->data_len;
Linus Torvalds's avatar
Linus Torvalds committed
873

Borislav Petkov's avatar
Borislav Petkov committed
874
		/* bio backed? */
Linus Torvalds's avatar
Linus Torvalds committed
875
		if (rq->bio) {
876 877 878 879 880 881 882
			if (blk_fs_request(rq)) {
				ptr = rq->buffer;
				blen = rq->current_nr_sectors << 9;
			} else {
				ptr = bio_data(rq->bio);
				blen = bio_iovec(rq->bio)->bv_len;
			}
Linus Torvalds's avatar
Linus Torvalds committed
883 884 885
		}

		if (!ptr) {
886 887
			if (blk_fs_request(rq) && !write)
				/*
888
				 * If the buffers are full, pipe the rest into
Borislav Petkov's avatar
Borislav Petkov committed
889 890
				 * oblivion.
				 */
891
				ide_pad_transfer(drive, 0, thislen);
892
			else {
893
				printk(KERN_ERR PFX "%s: confused, missing data\n",
894 895 896 897 898
						drive->name);
				blk_dump_rq_flags(rq, rq_data_dir(rq)
						  ? "cdrom_newpc_intr, write"
						  : "cdrom_newpc_intr, read");
			}
Linus Torvalds's avatar
Linus Torvalds committed
899 900 901 902 903 904
			break;
		}

		if (blen > thislen)
			blen = thislen;

905
		xferfunc(drive, NULL, ptr, blen);
Linus Torvalds's avatar
Linus Torvalds committed
906 907 908 909

		thislen -= blen;
		len -= blen;

910 911 912 913 914 915 916 917 918 919 920
		if (blk_fs_request(rq)) {
			rq->buffer += blen;
			rq->nr_sectors -= (blen >> 9);
			rq->current_nr_sectors -= (blen >> 9);
			rq->sector += (blen >> 9);

			if (rq->current_nr_sectors == 0 && rq->nr_sectors)
				cdrom_end_request(drive, 1);
		} else {
			rq->data_len -= blen;

921 922 923 924 925 926
			/*
			 * The request can't be completed until DRQ is cleared.
			 * So complete the data, but don't complete the request
			 * using the dummy function for the callback feature
			 * of blk_end_request_callback().
			 */
927 928
			if (rq->bio)
				blk_end_request_callback(rq, 0, blen,
929
						 cdrom_newpc_intr_dummy_cb);
930 931 932
			else
				rq->data += blen;
		}
Andreas Schwab's avatar
Andreas Schwab committed
933 934
		if (!write && blk_sense_request(rq))
			rq->sense_len += blen;
Linus Torvalds's avatar
Linus Torvalds committed
935 936
	}

Borislav Petkov's avatar
Borislav Petkov committed
937
	/* pad, if necessary */
938
	if (!blk_fs_request(rq) && len > 0)
939
		ide_pad_transfer(drive, write, len);
Linus Torvalds's avatar
Linus Torvalds committed
940

941 942 943 944
	if (blk_pc_request(rq)) {
		timeout = rq->timeout;
	} else {
		timeout = ATAPI_WAIT_PC;
945
		if (!blk_fs_request(rq))
946
			expiry = ide_cd_expiry;
947 948 949
	}

	ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
Linus Torvalds's avatar
Linus Torvalds committed
950
	return ide_started;
951 952 953

end_request:
	if (blk_pc_request(rq)) {
954 955 956 957
		unsigned int dlen = rq->data_len;

		if (dma)
			rq->data_len = 0;
958

959
		if (blk_end_request(rq, 0, dlen))
960
			BUG();
961

962
		hwif->rq = NULL;
963 964 965 966 967 968
	} else {
		if (!uptodate)
			rq->cmd_flags |= REQ_FAILED;
		cdrom_end_request(drive, uptodate);
	}
	return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
969 970
}

971
static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
972
{
973 974 975 976
	struct cdrom_info *cd = drive->driver_data;
	int write = rq_data_dir(rq) == WRITE;
	unsigned short sectors_per_frame =
		queue_hardsect_size(drive->queue) >> SECTOR_BITS;
Linus Torvalds's avatar
Linus Torvalds committed
977

978 979 980
	ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, write: 0x%x, "
		      "secs_per_frame: %u\n",
		      __func__, rq->cmd[0], write, sectors_per_frame);
981

982
	if (write) {
Borislav Petkov's avatar
Borislav Petkov committed
983
		/* disk has become write protected */
984
		if (get_disk_ro(cd->disk)) {
985 986 987 988 989 990 991 992
			cdrom_end_request(drive, 0);
			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.
		 */
993
		ide_cd_restore_request(drive, rq);
Linus Torvalds's avatar
Linus Torvalds committed
994 995
	}

Borislav Petkov's avatar
Borislav Petkov committed
996
	/* use DMA, if possible / writes *must* be hardware frame aligned */
997 998 999 1000 1001 1002
	if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
	    (rq->sector & (sectors_per_frame - 1))) {
		if (write) {
			cdrom_end_request(drive, 0);
			return ide_stopped;
		}
1003
		drive->dma = 0;
1004
	} else
1005
		drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
Linus Torvalds's avatar
Linus Torvalds committed
1006

1007 1008
	if (write)
		cd->devinfo.media_written = 1;
Linus Torvalds's avatar
Linus Torvalds committed
1009

1010
	return ide_started;
Linus Torvalds's avatar
Linus Torvalds committed
1011 1012
}

1013
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
1014 1015
{

1016 1017
	ide_debug_log(IDE_DBG_PC, "Call %s, rq->cmd[0]: 0x%x, "
		      "rq->cmd_type: 0x%x\n", __func__, rq->cmd[0],
1018 1019
		      rq->cmd_type);

1020 1021 1022 1023
	if (blk_pc_request(rq))
		rq->cmd_flags |= REQ_QUIET;
	else
		rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
1024

1025
	drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1026

Borislav Petkov's avatar
Borislav Petkov committed
1027
	/* sg request */
1028 1029 1030
	if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
		struct request_queue *q = drive->queue;
		unsigned int alignment;
1031
		char *buf;
Linus Torvalds's avatar
Linus Torvalds committed
1032

1033
		if (rq->bio)
1034
			buf = bio_data(rq->bio);
1035
		else
1036
			buf = rq->data;
1037

1038
		drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
Linus Torvalds's avatar
Linus Torvalds committed
1039 1040 1041

		/*
		 * check if dma is safe
1042 1043 1044
		 *
		 * NOTE! The "len" and "addr" checks should possibly have
		 * separate masks.
Linus Torvalds's avatar
Linus Torvalds committed
1045
		 */
1046
		alignment = queue_dma_alignment(q) | q->dma_pad_mask;
1047 1048
		if ((unsigned long)buf & alignment
		    || rq->data_len & q->dma_pad_mask
1049
		    || object_is_on_stack(buf))
1050
			drive->dma = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1051 1052 1053
	}
}

1054
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
1055
					sector_t block)
Linus Torvalds's avatar
Linus Torvalds committed
1056
{
1057 1058 1059 1060
	ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, "
		      "rq->cmd_type: 0x%x, block: %llu\n",
		      __func__, rq->cmd[0], rq->cmd_type,
		      (unsigned long long)block);
1061

Linus Torvalds's avatar
Linus Torvalds committed
1062
	if (blk_fs_request(rq)) {
1063 1064
		if (cdrom_start_rw(drive, rq) == ide_stopped)
			return ide_stopped;
1065

1066 1067
		if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
			return ide_stopped;
1068
	} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
1069
		   rq->cmd_type == REQ_TYPE_ATA_PC) {
1070 1071 1072
		if (!rq->timeout)
			rq->timeout = ATAPI_WAIT_PC;

1073
		cdrom_do_block_pc(drive, rq);
1074
	} else if (blk_special_request(rq)) {
Borislav Petkov's avatar
Borislav Petkov committed
1075
		/* right now this can only be a reset... */
Linus Torvalds's avatar
Linus Torvalds committed
1076 1077
		cdrom_end_request(drive, 1);
		return ide_stopped;
1078
	} else {
1079
		blk_dump_rq_flags(rq, DRV_NAME " bad flags");
1080 1081
		cdrom_end_request(drive, 0);
		return ide_stopped;
Linus Torvalds's avatar
Linus Torvalds committed
1082
	}
1083

1084
	return ide_issue_pc(drive);
Linus Torvalds's avatar
Linus Torvalds committed
1085 1086
}

Borislav Petkov's avatar
Borislav Petkov committed
1087
/*
Linus Torvalds's avatar
Linus Torvalds committed
1088 1089
 * Ioctl handling.
 *
Borislav Petkov's avatar
Borislav Petkov committed
1090 1091 1092 1093 1094
 * 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
1095
 */
1096
static void msf_from_bcd(struct atapi_msf *msf)
Linus Torvalds's avatar
Linus Torvalds committed
1097
{
Adrian Bunk's avatar
Adrian Bunk committed
1098 1099 1100
	msf->minute = bcd2bin(msf->minute);
	msf->second = bcd2bin(msf->second);
	msf->frame  = bcd2bin(msf->frame);
Linus Torvalds's avatar
Linus Torvalds committed
1101 1102
}

1103
int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds's avatar
Linus Torvalds committed
1104 1105 1106
{
	struct cdrom_info *info = drive->driver_data;
	struct cdrom_device_info *cdi = &info->devinfo;
1107
	unsigned char cmd[BLK_MAX_CDB];
Linus Torvalds's avatar
Linus Torvalds committed
1108

1109 1110
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1111 1112
	memset(cmd, 0, BLK_MAX_CDB);
	cmd[0] = GPCMD_TEST_UNIT_READY;
Linus Torvalds's avatar
Linus Torvalds committed
1113

1114
	/*
Borislav Petkov's avatar
Borislav Petkov committed
1115 1116
	 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to switch CDs
	 * instead of supporting the LOAD_UNLOAD opcode.
1117
	 */
1118
	cmd[7] = cdi->sanyo_slot % 3;
Linus Torvalds's avatar
Linus Torvalds committed
1119

1120
	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
Linus Torvalds's avatar
Linus Torvalds committed
1121 1122 1123 1124 1125 1126 1127
}

static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
			       unsigned long *sectors_per_frame,
			       struct request_sense *sense)
{
	struct {
1128 1129
		__be32 lba;
		__be32 blocklen;
Linus Torvalds's avatar
Linus Torvalds committed
1130 1131 1132
	} capbuf;

	int stat;
1133 1134
	unsigned char cmd[BLK_MAX_CDB];
	unsigned len = sizeof(capbuf);
1135
	u32 blocklen;
Linus Torvalds's avatar
Linus Torvalds committed
1136

1137 1138
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1139 1140
	memset(cmd, 0, BLK_MAX_CDB);
	cmd[0] = GPCMD_READ_CDVD_CAPACITY;
Linus Torvalds's avatar
Linus Torvalds committed
1141

1142 1143
	stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
			       REQ_QUIET);
1144 1145 1146 1147 1148 1149
	if (stat)
		return stat;

	/*
	 * Sanity check the given block size
	 */
1150 1151 1152 1153 1154 1155
	blocklen = be32_to_cpu(capbuf.blocklen);
	switch (blocklen) {
	case 512:
	case 1024:
	case 2048:
	case 4096:
1156 1157
		break;
	default:
1158 1159 1160 1161
		printk(KERN_ERR PFX "%s: weird block size %u\n",
				drive->name, blocklen);
		printk(KERN_ERR PFX "%s: default to 2kb block size\n",
				drive->name);
1162
		blocklen = 2048;
1163
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1164 1165
	}

1166
	*capacity = 1 + be32_to_cpu(capbuf.lba);
1167
	*sectors_per_frame = blocklen >> SECTOR_BITS;
1168 1169 1170 1171

	ide_debug_log(IDE_DBG_PROBE, "%s: cap: %lu, sectors_per_frame: %lu\n",
		      __func__, *capacity, *sectors_per_frame);

1172
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1173 1174 1175 1176 1177 1178
}

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

1181 1182
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1183
	memset(cmd, 0, BLK_MAX_CDB);
Linus Torvalds's avatar
Linus Torvalds committed
1184

1185 1186 1187 1188 1189
	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
1190 1191

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

1194
	return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET);
Linus Torvalds's avatar
Linus Torvalds committed
1195 1196 1197
}

/* Try to read the entire TOC for the disk into our internal buffer. */
1198
int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds's avatar
Linus Torvalds committed
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
{
	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;

1211 1212
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

Linus Torvalds's avatar
Linus Torvalds committed
1213
	if (toc == NULL) {
Borislav Petkov's avatar
Borislav Petkov committed
1214
		/* try to allocate space */
1215
		toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
1216
		if (toc == NULL) {
1217
			printk(KERN_ERR PFX "%s: No cdrom TOC buffer!\n",
1218
					drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
1219 1220
			return -ENOMEM;
		}
1221
		info->toc = toc;
Linus Torvalds's avatar
Linus Torvalds committed
1222 1223
	}

Borislav Petkov's avatar
Borislav Petkov committed
1224 1225 1226 1227
	/*
	 * Check to see if the existing data is still valid. If it is,
	 * just return.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
1228 1229
	(void) cdrom_check_status(drive, sense);

1230
	if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
Linus Torvalds's avatar
Linus Torvalds committed
1231 1232
		return 0;

Borislav Petkov's avatar
Borislav Petkov committed
1233
	/* try to get the total cdrom capacity and sector size */
Linus Torvalds's avatar
Linus Torvalds committed
1234 1235 1236 1237 1238 1239
	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
1240
	/* save a private copy of the TOC capacity for error handling */
1241 1242
	drive->probed_capacity = toc->capacity * sectors_per_frame;

Linus Torvalds's avatar
Linus Torvalds committed
1243 1244 1245
	blk_queue_hardsect_size(drive->queue,
				sectors_per_frame << SECTOR_BITS);

Borislav Petkov's avatar
Borislav Petkov committed
1246
	/* first read just the header, so we know how long the TOC is */
Linus Torvalds's avatar
Linus Torvalds committed
1247 1248
	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
				    sizeof(struct atapi_toc_header), sense);
1249 1250
	if (stat)
		return stat;
Linus Torvalds's avatar
Linus Torvalds committed
1251

1252
	if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
Adrian Bunk's avatar
Adrian Bunk committed
1253 1254
		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
1255 1256 1257 1258 1259 1260 1261 1262
	}

	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
1263
	/* now read the whole schmeer */
Linus Torvalds's avatar
Linus Torvalds committed
1264 1265 1266 1267 1268 1269 1270
	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
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
		/*
		 * 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
1283 1284 1285 1286 1287 1288 1289
		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);
1290
		if (stat)
Linus Torvalds's avatar
Linus Torvalds committed
1291
			return stat;
1292

1293
		if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
Adrian Bunk's avatar
Adrian Bunk committed
1294 1295
			toc->hdr.first_track = (u8)bin2bcd(CDROM_LEADOUT);
			toc->hdr.last_track = (u8)bin2bcd(CDROM_LEADOUT);
1296
		} else {
Linus Torvalds's avatar
Linus Torvalds committed
1297 1298 1299 1300 1301 1302 1303 1304
			toc->hdr.first_track = CDROM_LEADOUT;
			toc->hdr.last_track = CDROM_LEADOUT;
		}
	}

	if (stat)
		return stat;

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

1307
	if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
Adrian Bunk's avatar
Adrian Bunk committed
1308 1309
		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
1310 1311
	}

1312
	for (i = 0; i <= ntracks; i++) {
1313 1314
		if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
			if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
Adrian Bunk's avatar
Adrian Bunk committed
1315
				toc->ent[i].track = bcd2bin(toc->ent[i].track);
Linus Torvalds's avatar
Linus Torvalds committed
1316 1317
			msf_from_bcd(&toc->ent[i].addr.msf);
		}
1318 1319 1320
		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
1321 1322 1323
	}

	if (toc->hdr.first_track != CDROM_LEADOUT) {
Borislav Petkov's avatar
Borislav Petkov committed
1324
		/* read the multisession information */
Linus Torvalds's avatar
Linus Torvalds committed
1325 1326
		stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
					   sizeof(ms_tmp), sense);
1327 1328
		if (stat)
			return stat;
Linus Torvalds's avatar
Linus Torvalds committed
1329 1330 1331

		toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
	} else {
1332 1333
		ms_tmp.hdr.last_track = CDROM_LEADOUT;
		ms_tmp.hdr.first_track = ms_tmp.hdr.last_track;
Linus Torvalds's avatar
Linus Torvalds committed
1334 1335 1336
		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
	}

1337
	if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
Borislav Petkov's avatar
Borislav Petkov committed
1338
		/* re-read multisession information using MSF format */
Linus Torvalds's avatar
Linus Torvalds committed
1339 1340 1341 1342 1343
		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
					   sizeof(ms_tmp), sense);
		if (stat)
			return stat;

1344
		msf_from_bcd(&ms_tmp.ent.addr.msf);
Linus Torvalds's avatar
Linus Torvalds committed
1345
		toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
1346
						   ms_tmp.ent.addr.msf.second,
Linus Torvalds's avatar
Linus Torvalds committed
1347 1348 1349 1350 1351
						   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
1352
	/* now try to get the total cdrom capacity */
Linus Torvalds's avatar
Linus Torvalds committed
1353 1354 1355 1356
	stat = cdrom_get_last_written(cdi, &last_written);
	if (!stat && (last_written > toc->capacity)) {
		toc->capacity = last_written;
		set_capacity(info->disk, toc->capacity * sectors_per_frame);
1357
		drive->probed_capacity = toc->capacity * sectors_per_frame;
Linus Torvalds's avatar
Linus Torvalds committed
1358 1359 1360
	}

	/* Remember that we've read this stuff. */
1361
	drive->atapi_flags |= IDE_AFLAG_TOC_VALID;
Linus Torvalds's avatar
Linus Torvalds committed
1362 1363 1364 1365

	return 0;
}

1366
int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
1367 1368 1369 1370
{
	struct cdrom_info *info = drive->driver_data;
	struct cdrom_device_info *cdi = &info->devinfo;
	struct packet_command cgc;
1371
	int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
1372

1373 1374
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1375
	if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
1376
		size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
1377

1378
	init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
Borislav Petkov's avatar
Borislav Petkov committed
1379 1380
	do {
		/* we seem to get stat=0x01,err=0x00 the first time (??) */
1381 1382 1383 1384 1385 1386 1387
		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
		if (!stat)
			break;
	} while (--attempts);
	return stat;
}

1388
void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
1389
{
1390
	struct cdrom_info *cd = drive->driver_data;
1391 1392
	u16 curspeed, maxspeed;

1393 1394
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1395
	if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
1396 1397
		curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
		maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
1398
	} else {
1399 1400
		curspeed = be16_to_cpup((__be16 *)&buf[8 + 14]);
		maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
1401
	}
1402

1403 1404 1405
	ide_debug_log(IDE_DBG_PROBE, "%s: curspeed: %u, maxspeed: %u\n",
		      __func__, curspeed, maxspeed);

1406 1407
	cd->current_speed = (curspeed + (176/2)) / 176;
	cd->max_speed = (maxspeed + (176/2)) / 176;
1408 1409
}

1410 1411 1412 1413 1414 1415
#define IDE_CD_CAPABILITIES \
	(CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
	 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
	 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
	 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
	 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
Linus Torvalds's avatar
Linus Torvalds committed
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428

static struct cdrom_device_ops ide_cdrom_dops = {
	.open			= ide_cdrom_open_real,
	.release		= ide_cdrom_release_real,
	.drive_status		= ide_cdrom_drive_status,
	.media_changed		= ide_cdrom_check_media_change_real,
	.tray_move		= ide_cdrom_tray_move,
	.lock_door		= ide_cdrom_lock_door,
	.select_speed		= ide_cdrom_select_speed,
	.get_last_session	= ide_cdrom_get_last_session,
	.get_mcn		= ide_cdrom_get_mcn,
	.reset			= ide_cdrom_reset,
	.audio_ioctl		= ide_cdrom_audio_ioctl,
1429
	.capability		= IDE_CD_CAPABILITIES,
Linus Torvalds's avatar
Linus Torvalds committed
1430 1431 1432
	.generic_packet		= ide_cdrom_packet,
};

1433
static int ide_cdrom_register(ide_drive_t *drive, int nslots)
Linus Torvalds's avatar
Linus Torvalds committed
1434 1435 1436 1437
{
	struct cdrom_info *info = drive->driver_data;
	struct cdrom_device_info *devinfo = &info->devinfo;

1438 1439
	ide_debug_log(IDE_DBG_PROBE, "Call %s, nslots: %d\n", __func__, nslots);

Linus Torvalds's avatar
Linus Torvalds committed
1440
	devinfo->ops = &ide_cdrom_dops;
1441
	devinfo->speed = info->current_speed;
Linus Torvalds's avatar
Linus Torvalds committed
1442
	devinfo->capacity = nslots;
1443
	devinfo->handle = drive;
Linus Torvalds's avatar
Linus Torvalds committed
1444 1445
	strcpy(devinfo->name, drive->name);

1446
	if (drive->atapi_flags & IDE_AFLAG_NO_SPEED_SELECT)
1447 1448
		devinfo->mask |= CDC_SELECT_SPEED;

Linus Torvalds's avatar
Linus Torvalds committed
1449 1450 1451 1452
	devinfo->disk = info->disk;
	return register_cdrom(devinfo);
}

1453
static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
1454
{
1455 1456
	struct cdrom_info *cd = drive->driver_data;
	struct cdrom_device_info *cdi = &cd->devinfo;
1457 1458
	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
	mechtype_t mechtype;
Linus Torvalds's avatar
Linus Torvalds committed
1459 1460
	int nslots = 1;

1461 1462 1463 1464
	ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->media: 0x%x, "
		      "drive->atapi_flags: 0x%lx\n", __func__, drive->media,
		      drive->atapi_flags);

1465 1466 1467 1468
	cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
		     CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
		     CDC_MO_DRIVE | CDC_RAM);

Linus Torvalds's avatar
Linus Torvalds committed
1469
	if (drive->media == ide_optical) {
1470
		cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
1471
		printk(KERN_ERR PFX "%s: ATAPI magneto-optical drive\n",
1472
				drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
1473 1474 1475
		return nslots;
	}

1476 1477
	if (drive->atapi_flags & IDE_AFLAG_PRE_ATAPI12) {
		drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
1478
		cdi->mask &= ~CDC_PLAY_AUDIO;
Linus Torvalds's avatar
Linus Torvalds committed
1479 1480 1481 1482
		return nslots;
	}

	/*
Borislav Petkov's avatar
Borislav Petkov committed
1483 1484 1485 1486
	 * We have to cheat a little here. the packet will eventually be queued
	 * with ide_cdrom_packet(), which extracts the drive from cdi->handle.
	 * Since this device hasn't been registered with the Uniform layer yet,
	 * it can't do this. Same goes for cdi->ops.
Linus Torvalds's avatar
Linus Torvalds committed
1487
	 */
1488
	cdi->handle = drive;
Linus Torvalds's avatar
Linus Torvalds committed
1489 1490
	cdi->ops = &ide_cdrom_dops;

1491
	if (ide_cdrom_get_capabilities(drive, buf))
Linus Torvalds's avatar
Linus Torvalds committed
1492 1493
		return 0;

1494
	if ((buf[8 + 6] & 0x01) == 0)
1495
		drive->dev_flags &= ~IDE_DFLAG_DOORLOCKING;
1496
	if (buf[8 + 6] & 0x08)
1497
		drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
1498
	if (buf[8 + 3] & 0x01)
1499
		cdi->mask &= ~CDC_CD_R;
1500
	if (buf[8 + 3] & 0x02)
1501
		cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
1502
	if (buf[8 + 2] & 0x38)
1503
		cdi->mask &= ~CDC_DVD;
1504
	if (buf[8 + 3] & 0x20)
1505
		cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
1506
	if (buf[8 + 3] & 0x10)
1507
		cdi->mask &= ~CDC_DVD_R;
1508
	if ((buf[8 + 4] & 0x01) || (drive->atapi_flags & IDE_AFLAG_PLAY_AUDIO_OK))
1509
		cdi->mask &= ~CDC_PLAY_AUDIO;
1510 1511

	mechtype = buf[8 + 6] >> 5;
1512 1513 1514
	if (mechtype == mechtype_caddy ||
	    mechtype == mechtype_popup ||
	    (drive->atapi_flags & IDE_AFLAG_NO_AUTOCLOSE))
1515
		cdi->mask |= CDC_CLOSE_TRAY;
Linus Torvalds's avatar
Linus Torvalds committed
1516 1517

	if (cdi->sanyo_slot > 0) {
1518
		cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds's avatar
Linus Torvalds committed
1519
		nslots = 3;
1520 1521
	} else if (mechtype == mechtype_individual_changer ||
		   mechtype == mechtype_cartridge_changer) {
1522 1523
		nslots = cdrom_number_of_slots(cdi);
		if (nslots > 1)
1524
			cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds's avatar
Linus Torvalds committed
1525 1526
	}

1527
	ide_cdrom_update_speed(drive, buf);
1528

1529
	printk(KERN_INFO PFX "%s: ATAPI", drive->name);
1530 1531

	/* don't print speed if the drive reported 0 */
1532 1533
	if (cd->max_speed)
		printk(KERN_CONT " %dX", cd->max_speed);
1534

1535
	printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
Linus Torvalds's avatar
Linus Torvalds committed
1536

1537 1538 1539
	if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
		printk(KERN_CONT " DVD%s%s",
				 (cdi->mask & CDC_DVD_R) ? "" : "-R",
1540
				 (cdi->mask & CDC_DVD_RAM) ? "" : "/RAM");
Linus Torvalds's avatar
Linus Torvalds committed
1541

1542 1543 1544 1545
	if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
		printk(KERN_CONT " CD%s%s",
				 (cdi->mask & CDC_CD_R) ? "" : "-R",
				 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
Linus Torvalds's avatar
Linus Torvalds committed
1546

1547 1548 1549 1550
	if ((cdi->mask & CDC_SELECT_DISC) == 0)
		printk(KERN_CONT " changer w/%d slots", nslots);
	else
		printk(KERN_CONT " drive");
Linus Torvalds's avatar
Linus Torvalds committed
1551

1552 1553
	printk(KERN_CONT ", %dkB Cache\n",
			 be16_to_cpup((__be16 *)&buf[8 + 12]));
Linus Torvalds's avatar
Linus Torvalds committed
1554 1555 1556 1557

	return nslots;
}

Borislav Petkov's avatar
Borislav Petkov committed
1558
/* standard prep_rq_fn that builds 10 byte cmds */
1559
static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
1560 1561 1562 1563 1564
{
	int hard_sect = queue_hardsect_size(q);
	long block = (long)rq->hard_sector / (hard_sect >> 9);
	unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);

1565
	memset(rq->cmd, 0, BLK_MAX_CDB);
Linus Torvalds's avatar
Linus Torvalds committed
1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596

	if (rq_data_dir(rq) == READ)
		rq->cmd[0] = GPCMD_READ_10;
	else
		rq->cmd[0] = GPCMD_WRITE_10;

	/*
	 * fill in lba
	 */
	rq->cmd[2] = (block >> 24) & 0xff;
	rq->cmd[3] = (block >> 16) & 0xff;
	rq->cmd[4] = (block >>  8) & 0xff;
	rq->cmd[5] = block & 0xff;

	/*
	 * and transfer length
	 */
	rq->cmd[7] = (blocks >> 8) & 0xff;
	rq->cmd[8] = blocks & 0xff;
	rq->cmd_len = 10;
	return BLKPREP_OK;
}

/*
 * Most of the SCSI commands are supported directly by ATAPI devices.
 * This transform handles the few exceptions.
 */
static int ide_cdrom_prep_pc(struct request *rq)
{
	u8 *c = rq->cmd;

Borislav Petkov's avatar
Borislav Petkov committed
1597
	/* transform 6-byte read/write commands to the 10-byte version */
Linus Torvalds's avatar
Linus Torvalds committed
1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
	if (c[0] == READ_6 || c[0] == WRITE_6) {
		c[8] = c[4];
		c[5] = c[3];
		c[4] = c[2];
		c[3] = c[1] & 0x1f;
		c[2] = 0;
		c[1] &= 0xe0;
		c[0] += (READ_10 - READ_6);
		rq->cmd_len = 10;
		return BLKPREP_OK;
	}

	/*
	 * it's silly to pretend we understand 6-byte sense commands, just
	 * reject with ILLEGAL_REQUEST and the caller should take the
	 * appropriate action
	 */
	if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
		rq->errors = ILLEGAL_REQUEST;
		return BLKPREP_KILL;
	}
1619

Linus Torvalds's avatar
Linus Torvalds committed
1620 1621 1622
	return BLKPREP_OK;
}

1623
static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
1624
{
1625
	if (blk_fs_request(rq))
Linus Torvalds's avatar
Linus Torvalds committed
1626
		return ide_cdrom_prep_fs(q, rq);
1627
	else if (blk_pc_request(rq))
Linus Torvalds's avatar
Linus Torvalds committed
1628 1629 1630 1631 1632
		return ide_cdrom_prep_pc(rq);

	return 0;
}

1633 1634 1635 1636 1637 1638
struct cd_list_entry {
	const char	*id_model;
	const char	*id_firmware;
	unsigned int	cd_flags;
};

1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
#ifdef CONFIG_IDE_PROC_FS
static sector_t ide_cdrom_capacity(ide_drive_t *drive)
{
	unsigned long capacity, sectors_per_frame;

	if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
		return 0;

	return capacity * sectors_per_frame;
}

1650 1651
static int proc_idecd_read_capacity(char *page, char **start, off_t off,
					int count, int *eof, void *data)
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
{
	ide_drive_t *drive = data;
	int len;

	len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
}

static ide_proc_entry_t idecd_proc[] = {
	{ "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
	{ NULL, 0, NULL, NULL }
};

1665 1666 1667 1668 1669 1670 1671
static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
{
	return idecd_proc;
}

static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive)
{
1672
	return NULL;
1673
}
1674 1675
#endif

1676 1677
static const struct cd_list_entry ide_cd_quirks_list[] = {
	/* Limit transfer size per interrupt. */
1678 1679
	{ "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_AFLAG_LIMIT_NFRAMES	     },
	{ "SAMSUNG CD-ROM SCR-2432", NULL,   IDE_AFLAG_LIMIT_NFRAMES	     },
1680
	/* SCR-3231 doesn't support the SET_CD_SPEED command. */
1681
	{ "SAMSUNG CD-ROM SCR-3231", NULL,   IDE_AFLAG_NO_SPEED_SELECT	     },
1682
	/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
1683 1684
	{ "NEC CD-ROM DRIVE:260",    "1.01", IDE_AFLAG_TOCADDR_AS_BCD |
					     IDE_AFLAG_PRE_ATAPI12,	     },
1685
	/* Vertos 300, some versions of this drive like to talk BCD. */
1686
	{ "V003S0DS",		     NULL,   IDE_AFLAG_VERTOS_300_SSD,	     },
1687
	/* Vertos 600 ESD. */
1688
	{ "V006E0DS",		     NULL,   IDE_AFLAG_VERTOS_600_ESD,	     },
1689 1690 1691 1692
	/*
	 * Sanyo 3 CD changer uses a non-standard command for CD changing
	 * (by default standard ATAPI support for CD changers is used).
	 */
1693 1694 1695
	{ "CD-ROM CDR-C3 G",	     NULL,   IDE_AFLAG_SANYO_3CD	     },
	{ "CD-ROM CDR-C3G",	     NULL,   IDE_AFLAG_SANYO_3CD	     },
	{ "CD-ROM CDR_C36",	     NULL,   IDE_AFLAG_SANYO_3CD	     },
1696
	/* Stingray 8X CD-ROM. */
1697
	{ "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_AFLAG_PRE_ATAPI12 },
1698 1699 1700 1701
	/*
	 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
	 * mode sense page capabilities size, but older drives break.
	 */
1702 1703
	{ "ATAPI CD ROM DRIVE 50X MAX",	NULL,	IDE_AFLAG_FULL_CAPS_PAGE     },
	{ "WPI CDS-32X",		NULL,	IDE_AFLAG_FULL_CAPS_PAGE     },
1704
	/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
1705
	{ "",			     "241N", IDE_AFLAG_LE_SPEED_FIELDS       },
1706 1707 1708 1709
	/*
	 * Some drives used by Apple don't advertise audio play
	 * but they do support reading TOC & audio datas.
	 */
1710 1711 1712 1713 1714
	{ "MATSHITADVD-ROM SR-8187", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
	{ "MATSHITADVD-ROM SR-8186", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
	{ "Optiarc DVD RW AD-5200A", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
1715
	{ "Optiarc DVD RW AD-7200A", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
1716
	{ "Optiarc DVD RW AD-7543A", NULL,   IDE_AFLAG_NO_AUTOCLOSE	     },
1717
	{ "TEAC CD-ROM CD-224E",     NULL,   IDE_AFLAG_NO_AUTOCLOSE	     },
1718 1719 1720
	{ NULL, NULL, 0 }
};

1721
static unsigned int ide_cd_flags(u16 *id)
1722 1723 1724 1725
{
	const struct cd_list_entry *cle = ide_cd_quirks_list;

	while (cle->id_model) {
1726
		if (strcmp(cle->id_model, (char *)&id[ATA_ID_PROD]) == 0 &&
1727
		    (cle->id_firmware == NULL ||
1728
		     strstr((char *)&id[ATA_ID_FW_REV], cle->id_firmware)))
1729 1730 1731 1732 1733 1734 1735
			return cle->cd_flags;
		cle++;
	}

	return 0;
}

1736
static int ide_cdrom_setup(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
1737
{
1738 1739
	struct cdrom_info *cd = drive->driver_data;
	struct cdrom_device_info *cdi = &cd->devinfo;
1740 1741
	u16 *id = drive->id;
	char *fw_rev = (char *)&id[ATA_ID_FW_REV];
Linus Torvalds's avatar
Linus Torvalds committed
1742 1743
	int nslots;

1744 1745
	ide_debug_log(IDE_DBG_PROBE, "Call %s\n", __func__);

Linus Torvalds's avatar
Linus Torvalds committed
1746 1747
	blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
	blk_queue_dma_alignment(drive->queue, 31);
1748
	blk_queue_update_dma_pad(drive->queue, 15);
Linus Torvalds's avatar
Linus Torvalds committed
1749 1750 1751 1752
	drive->queue->unplug_delay = (1 * HZ) / 1000;
	if (!drive->queue->unplug_delay)
		drive->queue->unplug_delay = 1;

1753 1754
	drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
	drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id);
Linus Torvalds's avatar
Linus Torvalds committed
1755

1756
	if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
1757
	    fw_rev[4] == '1' && fw_rev[6] <= '2')
1758 1759 1760
		drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
				     IDE_AFLAG_TOCADDR_AS_BCD);
	else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
1761
		 fw_rev[4] == '1' && fw_rev[6] <= '2')
1762 1763
		drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
	else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
Borislav Petkov's avatar
Borislav Petkov committed
1764 1765
		/* 3 => use CD in slot 0 */
		cdi->sanyo_slot = 3;
Linus Torvalds's avatar
Linus Torvalds committed
1766

1767
	nslots = ide_cdrom_probe_capabilities(drive);
Linus Torvalds's avatar
Linus Torvalds committed
1768

Borislav Petkov's avatar
Borislav Petkov committed
1769
	/* set correct block size */
Linus Torvalds's avatar
Linus Torvalds committed
1770 1771 1772
	blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);

	if (ide_cdrom_register(drive, nslots)) {
1773
		printk(KERN_ERR PFX "%s: %s failed to register device with the"
1774
				" cdrom driver.\n", drive->name, __func__);
1775
		cd->devinfo.handle = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
1776 1777
		return 1;
	}
1778 1779

	ide_proc_register_driver(drive, cd->driver);
Linus Torvalds's avatar
Linus Torvalds committed
1780 1781 1782
	return 0;
}

1783
static void ide_cd_remove(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
1784 1785 1786
{
	struct cdrom_info *info = drive->driver_data;

1787 1788
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1789
	ide_proc_unregister_driver(drive, info->driver);
Linus Torvalds's avatar
Linus Torvalds committed
1790 1791 1792 1793 1794 1795 1796 1797

	del_gendisk(info->disk);

	ide_cd_put(info);
}

static void ide_cd_release(struct kref *kref)
{
1798
	struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
Linus Torvalds's avatar
Linus Torvalds committed
1799 1800 1801 1802
	struct cdrom_device_info *devinfo = &info->devinfo;
	ide_drive_t *drive = info->drive;
	struct gendisk *g = info->disk;

1803 1804
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);

1805
	kfree(info->toc);
1806 1807
	if (devinfo->handle == drive)
		unregister_cdrom(devinfo);
Linus Torvalds's avatar
Linus Torvalds committed
1808 1809 1810 1811 1812 1813 1814
	drive->driver_data = NULL;
	blk_queue_prep_rq(drive->queue, NULL);
	g->private_data = NULL;
	put_disk(g);
	kfree(info);
}

1815
static int ide_cd_probe(ide_drive_t *);
Linus Torvalds's avatar
Linus Torvalds committed
1816

1817
static struct ide_driver ide_cdrom_driver = {
1818
	.gen_driver = {
1819
		.owner		= THIS_MODULE,
1820 1821 1822
		.name		= "ide-cdrom",
		.bus		= &ide_bus_type,
	},
1823 1824
	.probe			= ide_cd_probe,
	.remove			= ide_cd_remove,
Linus Torvalds's avatar
Linus Torvalds committed
1825
	.version		= IDECD_VERSION,
1826
	.do_request		= ide_cd_do_request,
Linus Torvalds's avatar
Linus Torvalds committed
1827
	.end_request		= ide_end_request,
1828
#ifdef CONFIG_IDE_PROC_FS
1829 1830
	.proc_entries		= ide_cd_proc_entries,
	.proc_devsets		= ide_cd_proc_devsets,
1831
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1832 1833
};

Al Viro's avatar
Al Viro committed
1834
static int idecd_open(struct block_device *bdev, fmode_t mode)
Linus Torvalds's avatar
Linus Torvalds committed
1835
{
Al Viro's avatar
Al Viro committed
1836
	struct cdrom_info *info = ide_cd_get(bdev->bd_disk);
Linus Torvalds's avatar
Linus Torvalds committed
1837 1838
	int rc = -ENOMEM;

1839
	if (!info)
Linus Torvalds's avatar
Linus Torvalds committed
1840 1841
		return -ENXIO;

Al Viro's avatar
Al Viro committed
1842
	rc = cdrom_open(&info->devinfo, bdev, mode);
Linus Torvalds's avatar
Linus Torvalds committed
1843 1844 1845 1846 1847 1848 1849

	if (rc < 0)
		ide_cd_put(info);

	return rc;
}

Al Viro's avatar
Al Viro committed
1850
static int idecd_release(struct gendisk *disk, fmode_t mode)
Linus Torvalds's avatar
Linus Torvalds committed
1851
{
1852
	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
Linus Torvalds's avatar
Linus Torvalds committed
1853

Al Viro's avatar
Al Viro committed
1854
	cdrom_release(&info->devinfo, mode);
Linus Torvalds's avatar
Linus Torvalds committed
1855 1856 1857 1858 1859 1860

	ide_cd_put(info);

	return 0;
}

1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885
static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg)
{
	struct packet_command cgc;
	char buffer[16];
	int stat;
	char spindown;

	if (copy_from_user(&spindown, (void __user *)arg, sizeof(char)))
		return -EFAULT;

	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);

	stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
	if (stat)
		return stat;

	buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
	return cdrom_mode_select(cdi, &cgc);
}

static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
{
	struct packet_command cgc;
	char buffer[16];
	int stat;
1886
	char spindown;
1887 1888 1889 1890 1891 1892 1893 1894

	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);

	stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
	if (stat)
		return stat;

	spindown = buffer[11] & 0x0f;
1895
	if (copy_to_user((void __user *)arg, &spindown, sizeof(char)))
1896 1897 1898 1899
		return -EFAULT;
	return 0;
}

Al Viro's avatar
Al Viro committed
1900
static int idecd_ioctl(struct block_device *bdev, fmode_t mode,
Linus Torvalds's avatar
Linus Torvalds committed
1901 1902
			unsigned int cmd, unsigned long arg)
{
1903
	struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info);
Linus Torvalds's avatar
Linus Torvalds committed
1904 1905
	int err;

1906
	switch (cmd) {
1907
	case CDROMSETSPINDOWN:
1908
		return idecd_set_spindown(&info->devinfo, arg);
1909
	case CDROMGETSPINDOWN:
1910 1911 1912
		return idecd_get_spindown(&info->devinfo, arg);
	default:
		break;
1913
	}
1914

1915
	err = generic_ide_ioctl(info->drive, bdev, cmd, arg);
Linus Torvalds's avatar
Linus Torvalds committed
1916
	if (err == -EINVAL)
Al Viro's avatar
Al Viro committed
1917
		err = cdrom_ioctl(&info->devinfo, bdev, mode, cmd, arg);
Linus Torvalds's avatar
Linus Torvalds committed
1918 1919 1920 1921 1922 1923

	return err;
}

static int idecd_media_changed(struct gendisk *disk)
{
1924
	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
Linus Torvalds's avatar
Linus Torvalds committed
1925 1926 1927 1928 1929
	return cdrom_media_changed(&info->devinfo);
}

static int idecd_revalidate_disk(struct gendisk *disk)
{
1930
	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
Linus Torvalds's avatar
Linus Torvalds committed
1931
	struct request_sense sense;
1932 1933 1934

	ide_cd_read_toc(info->drive, &sense);

Linus Torvalds's avatar
Linus Torvalds committed
1935 1936 1937 1938
	return  0;
}

static struct block_device_operations idecd_ops = {
1939
	.owner			= THIS_MODULE,
Al Viro's avatar
Al Viro committed
1940 1941 1942
	.open			= idecd_open,
	.release		= idecd_release,
	.locked_ioctl		= idecd_ioctl,
1943 1944
	.media_changed		= idecd_media_changed,
	.revalidate_disk	= idecd_revalidate_disk
Linus Torvalds's avatar
Linus Torvalds committed
1945 1946
};

Borislav Petkov's avatar
Borislav Petkov committed
1947
/* module options */
1948
static char *ignore;
Linus Torvalds's avatar
Linus Torvalds committed
1949
module_param(ignore, charp, 0400);
1950 1951 1952 1953

static unsigned long debug_mask;
module_param(debug_mask, ulong, 0644);

Linus Torvalds's avatar
Linus Torvalds committed
1954 1955
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");

1956
static int ide_cd_probe(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
1957 1958 1959 1960 1961
{
	struct cdrom_info *info;
	struct gendisk *g;
	struct request_sense sense;

1962 1963 1964 1965
	ide_debug_log(IDE_DBG_PROBE, "Call %s, drive->driver_req: %s, "
		      "drive->media: 0x%x\n", __func__, drive->driver_req,
		      drive->media);

Linus Torvalds's avatar
Linus Torvalds committed
1966 1967
	if (!strstr("ide-cdrom", drive->driver_req))
		goto failed;
1968

Linus Torvalds's avatar
Linus Torvalds committed
1969 1970
	if (drive->media != ide_cdrom && drive->media != ide_optical)
		goto failed;
1971

Linus Torvalds's avatar
Linus Torvalds committed
1972 1973 1974
	/* skip drives that we were told to ignore */
	if (ignore != NULL) {
		if (strstr(ignore, drive->name)) {
1975
			printk(KERN_INFO PFX "ignoring drive %s\n",
1976
					 drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
1977 1978 1979
			goto failed;
		}
	}
1980 1981

	drive->debug_mask = debug_mask;
1982
	drive->irq_handler = cdrom_newpc_intr;
1983

1984
	info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
1985
	if (info == NULL) {
1986
		printk(KERN_ERR PFX "%s: Can't allocate a cdrom structure\n",
1987
				drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
		goto failed;
	}

	g = alloc_disk(1 << PARTN_BITS);
	if (!g)
		goto out_free_cd;

	ide_init_disk(g, drive);

	kref_init(&info->kref);

	info->drive = drive;
	info->driver = &ide_cdrom_driver;
	info->disk = g;

	g->private_data = &info->driver;

	drive->driver_data = info;

	g->minors = 1;
	g->driverfs_dev = &drive->gendev;
	g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
	if (ide_cdrom_setup(drive)) {
2011
		ide_cd_release(&info->kref);
Linus Torvalds's avatar
Linus Torvalds committed
2012 2013 2014
		goto failed;
	}

2015
	ide_cd_read_toc(drive, &sense);
Linus Torvalds's avatar
Linus Torvalds committed
2016 2017 2018 2019 2020 2021 2022 2023
	g->fops = &idecd_ops;
	g->flags |= GENHD_FL_REMOVABLE;
	add_disk(g);
	return 0;

out_free_cd:
	kfree(info);
failed:
2024
	return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
2025 2026 2027 2028
}

static void __exit ide_cdrom_exit(void)
{
2029
	driver_unregister(&ide_cdrom_driver.gen_driver);
Linus Torvalds's avatar
Linus Torvalds committed
2030
}
2031 2032

static int __init ide_cdrom_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
2033
{
2034
	printk(KERN_INFO DRV_NAME " driver " IDECD_VERSION "\n");
2035
	return driver_register(&ide_cdrom_driver.gen_driver);
Linus Torvalds's avatar
Linus Torvalds committed
2036 2037
}

2038
MODULE_ALIAS("ide:*m-cdrom*");
2039
MODULE_ALIAS("ide-cd");
Linus Torvalds's avatar
Linus Torvalds committed
2040 2041 2042
module_init(ide_cdrom_init);
module_exit(ide_cdrom_exit);
MODULE_LICENSE("GPL");