ide-cd.c 56.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
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
#define IDECD_VERSION "5.00"
Linus Torvalds's avatar
Linus Torvalds committed
27
28
29
30
31
32
33
34
35
36
37
38

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

#include <scsi/scsi.h>	/* For SCSI -> ATAPI command conversion */

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

#include "ide-cd.h"

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

54
#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
Linus Torvalds's avatar
Linus Torvalds committed
55
56
57
58
59
60
61
62

#define ide_cd_g(disk) \
	container_of((disk)->private_data, struct cdrom_info, driver)

static struct cdrom_info *ide_cd_get(struct gendisk *disk)
{
	struct cdrom_info *cd = NULL;

63
	mutex_lock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
64
65
66
	cd = ide_cd_g(disk);
	if (cd)
		kref_get(&cd->kref);
67
	mutex_unlock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
68
69
70
71
72
73
74
	return cd;
}

static void ide_cd_release(struct kref *);

static void ide_cd_put(struct cdrom_info *cd)
{
75
	mutex_lock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
76
	kref_put(&cd->kref, ide_cd_release);
77
	mutex_unlock(&idecd_ref_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
78
79
80
81
82
83
84
85
}

/****************************************************************************
 * Generic packet command support and error handling routines.
 */

/* Mark that we've seen a media change, and invalidate our internal
   buffers. */
86
static void cdrom_saw_media_change(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
87
{
88
89
	struct cdrom_info *cd = drive->driver_data;

90
91
	cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
	cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
Linus Torvalds's avatar
Linus Torvalds committed
92
93
94
95
96
97
98
}

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

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

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

static
void cdrom_analyze_sense_data(ide_drive_t *drive,
			      struct request *failed_command,
			      struct request_sense *sense)
{
145
146
147
148
149
	unsigned long sector;
	unsigned long bio_sectors;
	unsigned long valid;
	struct cdrom_info *info = drive->driver_data;

Linus Torvalds's avatar
Linus Torvalds committed
150
151
152
153
154
155
156
157
158
159
160
161
	if (!cdrom_log_sense(drive, failed_command, sense))
		return;

	/*
	 * 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)
	 */
	if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
		if (sense->sense_key == 0x05 && sense->asc == 0x24)
			return;

162
163
	if (sense->error_code == 0x70) {	/* Current Error */
		switch (sense->sense_key) {
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
		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]);

			bio_sectors = bio_sectors(failed_command->bio);
			if (bio_sectors < 4)
				bio_sectors = 4;
			if (drive->queue->hardsect_size == 2048)
				sector <<= 2;	/* Device sector size is 2K */
182
			sector &= ~(bio_sectors - 1);
183
184
185
186
187
188
189
190
			valid = (sector - failed_command->sector) << 9;

			if (valid < 0)
				valid = 0;
			if (sector < get_capacity(info->disk) &&
				drive->probed_capacity - sector < 4 * 75) {
				set_capacity(info->disk, sector);
			}
191
192
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
193

194
	ide_cd_log_error(drive->name, failed_command, sense);
Linus Torvalds's avatar
Linus Torvalds committed
195
196
197
198
199
}

/*
 * Initialize a ide-cd packet command request
 */
200
void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
201
202
203
204
{
	struct cdrom_info *cd = drive->driver_data;

	ide_init_drive_cmd(rq);
205
	rq->cmd_type = REQ_TYPE_ATA_PC;
Linus Torvalds's avatar
Linus Torvalds committed
206
207
208
209
210
211
212
213
214
215
216
217
218
	rq->rq_disk = cd->disk;
}

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;

	if (sense == NULL)
		sense = &info->sense_data;

	/* stuff the sense request in front of our current request */
219
	ide_cd_init_rq(drive, rq);
Linus Torvalds's avatar
Linus Torvalds committed
220
221
222
223
224

	rq->data = sense;
	rq->cmd[0] = GPCMD_REQUEST_SENSE;
	rq->cmd[4] = rq->data_len = 18;

225
	rq->cmd_type = REQ_TYPE_SENSE;
Linus Torvalds's avatar
Linus Torvalds committed
226
227
228
229
230
231
232

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

	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}

233
static void cdrom_end_request(ide_drive_t *drive, int uptodate)
Linus Torvalds's avatar
Linus Torvalds committed
234
235
236
237
{
	struct request *rq = HWGROUP(drive)->rq;
	int nsectors = rq->hard_cur_sectors;

238
	if (blk_sense_request(rq) && uptodate) {
Linus Torvalds's avatar
Linus Torvalds committed
239
		/*
240
241
		 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
		 * failed request
Linus Torvalds's avatar
Linus Torvalds committed
242
243
244
245
246
247
248
249
250
251
252
		 */
		struct request *failed = (struct request *) rq->buffer;
		struct cdrom_info *info = drive->driver_data;
		void *sense = &info->sense_data;
		unsigned long flags;

		if (failed) {
			if (failed->sense) {
				sense = failed->sense;
				failed->sense_len = rq->sense_len;
			}
253
			cdrom_analyze_sense_data(drive, failed, sense);
Linus Torvalds's avatar
Linus Torvalds committed
254
255
256
			/*
			 * now end failed request
			 */
257
258
259
260
261
262
			if (blk_fs_request(failed)) {
				if (ide_end_dequeued_request(drive, failed, 0,
						failed->hard_nr_sectors))
					BUG();
			} else {
				spin_lock_irqsave(&ide_lock, flags);
263
264
265
				if (__blk_end_request(failed, -EIO,
						      failed->data_len))
					BUG();
266
267
268
269
				spin_unlock_irqrestore(&ide_lock, flags);
			}
		} else
			cdrom_analyze_sense_data(drive, NULL, sense);
Linus Torvalds's avatar
Linus Torvalds committed
270
271
272
273
274
275
276
277
278
279
280
281
282
	}

	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;

	ide_end_request(drive, uptodate, nsectors);
}

283
284
285
286
287
288
289
static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
{
	if (stat & 0x80)
		return;
	ide_dump_status(drive, msg, stat);
}

Linus Torvalds's avatar
Linus Torvalds committed
290
291
292
293
294
295
/* Returns 0 if the request should be continued.
   Returns 1 if the request was ended. */
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
	struct request *rq = HWGROUP(drive)->rq;
	int stat, err, sense_key;
296

Linus Torvalds's avatar
Linus Torvalds committed
297
	/* Check for errors. */
298
299
	stat = ide_read_status(drive);

Linus Torvalds's avatar
Linus Torvalds committed
300
301
302
303
304
305
306
	if (stat_ret)
		*stat_ret = stat;

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

	/* Get the IDE error register. */
307
	err = ide_read_error(drive);
Linus Torvalds's avatar
Linus Torvalds committed
308
309
310
311
312
313
314
	sense_key = err >> 4;

	if (rq == NULL) {
		printk("%s: missing rq in cdrom_decode_status\n", drive->name);
		return 1;
	}

315
	if (blk_sense_request(rq)) {
Linus Torvalds's avatar
Linus Torvalds committed
316
317
318
319
		/* We got an error trying to get sense info
		   from the drive (probably while trying
		   to recover from a former error).  Just give up. */

320
		rq->cmd_flags |= REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
321
322
323
324
		cdrom_end_request(drive, 0);
		ide_error(drive, "request sense failure", stat);
		return 1;

325
	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds's avatar
Linus Torvalds committed
326
327
328
329
330
331
		/* All other functions, except for READ. */

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

		/* Check for tray open. */
		if (sense_key == NOT_READY) {
337
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
338
339
		} else if (sense_key == UNIT_ATTENTION) {
			/* Check for media change. */
340
			cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
341
342
			/*printk("%s: media changed\n",drive->name);*/
			return 0;
343
344
345
346
347
348
349
350
351
		} 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!
			 */
352
		} else if (!(rq->cmd_flags & REQ_QUIET)) {
Linus Torvalds's avatar
Linus Torvalds committed
353
354
355
			/* Otherwise, print an error. */
			ide_dump_status(drive, "packet command error", stat);
		}
356

357
		rq->cmd_flags |= REQ_FAILED;
Linus Torvalds's avatar
Linus Torvalds committed
358
359
360
361
362
363

		/*
		 * instead of playing games with moving completions around,
		 * remove failed request completely and end it when the
		 * request sense has completed
		 */
364
		goto end_request;
Linus Torvalds's avatar
Linus Torvalds committed
365
366
367
368
369
370
371
372
373
374
375
376

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

		/* Handle errors from READ and WRITE requests. */

		if (blk_noretry_request(rq))
			do_end_request = 1;

		if (sense_key == NOT_READY) {
			/* Tray open. */
			if (rq_data_dir(rq) == READ) {
377
				cdrom_saw_media_change(drive);
Linus Torvalds's avatar
Linus Torvalds committed
378
379

				/* Fail the request. */
380
				printk("%s: tray open\n", drive->name);
Linus Torvalds's avatar
Linus Torvalds committed
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
				do_end_request = 1;
			} else {
				struct cdrom_info *info = drive->driver_data;

				/* allow the drive 5 seconds to recover, some
				 * devices will return this error while flushing
				 * data from cache */
				if (!rq->errors)
					info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
				rq->errors = 1;
				if (time_after(jiffies, info->write_timeout))
					do_end_request = 1;
				else {
					unsigned long flags;

					/*
					 * take a breather relying on the
					 * unplug timer to kick us again
					 */
					spin_lock_irqsave(&ide_lock, flags);
					blk_plug_device(drive->queue);
402
					spin_unlock_irqrestore(&ide_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
403
404
405
406
407
408
409
					return 1;
				}
			}
		} else if (sense_key == UNIT_ATTENTION) {
			/* Media change. */
			cdrom_saw_media_change (drive);

410
411
412
413
414
			/*
			 * Arrange to retry the request.
			 * But be sure to give up if we've retried
			 * too many times.
			 */
Linus Torvalds's avatar
Linus Torvalds committed
415
416
417
418
			if (++rq->errors > ERROR_MAX)
				do_end_request = 1;
		} else if (sense_key == ILLEGAL_REQUEST ||
			   sense_key == DATA_PROTECT) {
419
420
421
422
423
			/*
			 * No point in retrying after an illegal
			 * request or data protect error.
			 */
			ide_dump_status_no_sense(drive, "command error", stat);
Linus Torvalds's avatar
Linus Torvalds committed
424
425
			do_end_request = 1;
		} else if (sense_key == MEDIUM_ERROR) {
426
427
428
429
430
			/*
			 * No point in re-trying a zillion times on a bad
			 * sector... If we got here the error is not correctable
			 */
			ide_dump_status_no_sense(drive, "media error (bad sector)", stat);
Linus Torvalds's avatar
Linus Torvalds committed
431
432
433
			do_end_request = 1;
		} else if (sense_key == BLANK_CHECK) {
			/* Disk appears blank ?? */
434
			ide_dump_status_no_sense(drive, "media error (blank)", stat);
Linus Torvalds's avatar
Linus Torvalds committed
435
436
437
438
439
440
441
442
443
444
445
			do_end_request = 1;
		} else if ((err & ~ABRT_ERR) != 0) {
			/* 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;
		}

446
447
448
449
		/* End a request through request sense analysis when we have
		   sense data. We need this in order to perform end of media
		   processing */

450
451
		if (do_end_request)
			goto end_request;
452

453
454
455
456
457
458
		/*
		 * If we got a CHECK_CONDITION status,
		 * queue a request sense command.
		 */
		if (stat & ERR_STAT)
			cdrom_queue_request_sense(drive, NULL, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
459
460
461
462
463
464
465
	} else {
		blk_dump_rq_flags(rq, "ide-cd: bad rq");
		cdrom_end_request(drive, 0);
	}

	/* Retry, or handle the next request. */
	return 1;
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480

end_request:
	if (stat & ERR_STAT) {
		unsigned long flags;

		spin_lock_irqsave(&ide_lock, flags);
		blkdev_dequeue_request(rq);
		HWGROUP(drive)->rq = NULL;
		spin_unlock_irqrestore(&ide_lock, flags);

		cdrom_queue_request_sense(drive, rq->sense, rq);
	} else
		cdrom_end_request(drive, 0);

	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
481
482
483
484
485
486
487
488
489
490
491
492
493
494
}

static int cdrom_timer_expiry(ide_drive_t *drive)
{
	struct request *rq = HWGROUP(drive)->rq;
	unsigned long wait = 0;

	/*
	 * Some commands are *slow* and normally take a long time to
	 * complete. Usually we can use the ATAPI "disconnect" to bypass
	 * this, but not all commands/drives support that. Let
	 * ide_timer_expiry keep polling us for these.
	 */
	switch (rq->cmd[0]) {
495
496
497
498
499
500
501
502
503
504
505
506
	case GPCMD_BLANK:
	case GPCMD_FORMAT_UNIT:
	case GPCMD_RESERVE_RZONE_TRACK:
	case GPCMD_CLOSE_TRACK:
	case GPCMD_FLUSH_CACHE:
		wait = ATAPI_WAIT_PC;
		break;
	default:
		if (!(rq->cmd_flags & REQ_QUIET))
			printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
		wait = 0;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
	}
	return wait;
}

/* Set up the device registers for transferring a packet command on DEV,
   expecting to later transfer XFERLEN bytes.  HANDLER is the routine
   which actually transfers the command to the drive.  If this is a
   drq_interrupt device, this routine will arrange for HANDLER to be
   called when the interrupt from the drive arrives.  Otherwise, HANDLER
   will be called immediately after the drive is prepared for the transfer. */

static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
						  int xferlen,
						  ide_handler_t *handler)
{
	ide_startstop_t startstop;
	struct cdrom_info *info = drive->driver_data;
	ide_hwif_t *hwif = drive->hwif;

	/* Wait for the controller to be idle. */
	if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
		return startstop;

530
	/* FIXME: for Virtual DMA we must check harder */
Linus Torvalds's avatar
Linus Torvalds committed
531
532
533
534
	if (info->dma)
		info->dma = !hwif->dma_setup(drive);

	/* Set up the controller registers. */
535
536
	ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
			   IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
537

538
	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
539
540
541
542
		/* waiting for CDB interrupt, not DMA yet. */
		if (info->dma)
			drive->waiting_for_dma = 0;

Linus Torvalds's avatar
Linus Torvalds committed
543
544
545
546
547
548
549
550
		/* packet command */
		ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
		return ide_started;
	} else {
		unsigned long flags;

		/* packet command */
		spin_lock_irqsave(&ide_lock, flags);
551
552
		hwif->OUTBSYNC(drive, WIN_PACKETCMD,
			       hwif->io_ports[IDE_COMMAND_OFFSET]);
Linus Torvalds's avatar
Linus Torvalds committed
553
554
555
556
557
558
559
560
561
562
563
564
565
		ndelay(400);
		spin_unlock_irqrestore(&ide_lock, flags);

		return (*handler) (drive);
	}
}

/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
   The device registers must have already been prepared
   by cdrom_start_packet_command.
   HANDLER is the interrupt handler to call when the command completes
   or there's data ready. */
#define ATAPI_MIN_CDB_BYTES 12
566
static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
Linus Torvalds's avatar
Linus Torvalds committed
567
568
569
570
571
572
573
574
					  struct request *rq,
					  ide_handler_t *handler)
{
	ide_hwif_t *hwif = drive->hwif;
	int cmd_len;
	struct cdrom_info *info = drive->driver_data;
	ide_startstop_t startstop;

575
	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Linus Torvalds's avatar
Linus Torvalds committed
576
577
578
579
580
581
		/* Here we should have been called after receiving an interrupt
		   from the device.  DRQ should how be set. */

		/* Check for errors. */
		if (cdrom_decode_status(drive, DRQ_STAT, NULL))
			return ide_stopped;
582
583
584
585

		/* Ok, next interrupt will be DMA interrupt. */
		if (info->dma)
			drive->waiting_for_dma = 1;
Linus Torvalds's avatar
Linus Torvalds committed
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
	} else {
		/* Otherwise, we must wait for DRQ to get set. */
		if (ide_wait_stat(&startstop, drive, DRQ_STAT,
				BUSY_STAT, WAIT_READY))
			return startstop;
	}

	/* Arm the interrupt handler. */
	ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);

	/* ATAPI commands get padded out to 12 bytes minimum */
	cmd_len = COMMAND_SIZE(rq->cmd[0]);
	if (cmd_len < ATAPI_MIN_CDB_BYTES)
		cmd_len = ATAPI_MIN_CDB_BYTES;

	/* Send the command to the device. */
	HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len);

	/* Start the DMA if need be */
	if (info->dma)
		hwif->dma_start(drive);

	return ide_started;
}

/****************************************************************************
 * Block read functions.
 */

615
616
617
618
619
620
621
622
623
static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
{
	while (len > 0) {
		int dum = 0;
		xf(drive, &dum, sizeof(dum));
		len -= sizeof(dum);
	}
}

624
625
626
627
628
629
630
631
632
633
static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
{
	while (nsects > 0) {
		static char dum[SECTOR_SIZE];

		drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
		nsects--;
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
634
635
636
637
638
/*
 * 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.
 */
639
640
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
641
{
642
643
644
645
646
	/*
	 * 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
647
		return 0;
648
	else if (ireason == (rw << 1)) {
649
		ide_hwif_t *hwif = drive->hwif;
650
		xfer_func_t *xf;
651

652
		/* Whoops... */
653
		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
654
				drive->name, __func__);
Linus Torvalds's avatar
Linus Torvalds committed
655

656
657
658
		xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
		ide_cd_pad_transfer(drive, xf, len);
	} else  if (rw == 0 && ireason == 1) {
Linus Torvalds's avatar
Linus Torvalds committed
659
660
661
		/* Some drives (ASUS) seem to tell us that status
		 * info is available. just get it and ignore.
		 */
662
		(void)ide_read_status(drive);
Linus Torvalds's avatar
Linus Torvalds committed
663
664
665
		return 0;
	} else {
		/* Drive wants a command packet, or invalid ireason... */
666
		printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
667
				drive->name, __func__, ireason);
Linus Torvalds's avatar
Linus Torvalds committed
668
669
	}

670
671
672
	if (rq->cmd_type == REQ_TYPE_ATA_PC)
		rq->cmd_flags |= REQ_FAILED;

Linus Torvalds's avatar
Linus Torvalds committed
673
674
675
676
	cdrom_end_request(drive, 0);
	return -1;
}

677
678
679
680
681
682
683
684
685
686
687
688
/*
 * 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)
{
	struct cdrom_info *cd = drive->driver_data;

	if ((len % SECTOR_SIZE) == 0)
		return 0;

	printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
689
			drive->name, __func__, len);
690
691
692
693
694
695
696
697
698
699
700
701

	if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
		printk(KERN_ERR "  This drive is not supported by "
				"this version of the driver\n");
	else {
		printk(KERN_ERR "  Trying to limit transfer sizes\n");
		cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
	}

	return 1;
}

702
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
703

Linus Torvalds's avatar
Linus Torvalds committed
704
/*
705
706
 * Routine to send a read/write packet command to the drive.
 * This is usually called directly from cdrom_start_{read,write}().
Linus Torvalds's avatar
Linus Torvalds committed
707
708
709
 * However, for drq_interrupt devices, it is called from an interrupt
 * when the drive is ready to accept the command.
 */
710
static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
711
712
713
{
	struct request *rq = HWGROUP(drive)->rq;

714
715
716
717
	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
718

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
		/*
		 * 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) {
			/* Sanity check... */
			if (rq->current_nr_sectors !=
			    bio_cur_sectors(rq->bio)) {
				printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
734
						drive->name, __func__,
735
736
737
738
739
						rq->current_nr_sectors);
				cdrom_end_request(drive, 0);
				return ide_stopped;
			}
			rq->current_nr_sectors += nskip;
Linus Torvalds's avatar
Linus Torvalds committed
740
741
		}
	}
742
743
744
745
746
#if 0
	else
		/* the immediate bit */
		rq->cmd[1] = 1 << 3;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
747
748
749
750
	/* Set up the command */
	rq->timeout = ATAPI_WAIT_PC;

	/* Send the command to the drive and return. */
751
	return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
Linus Torvalds's avatar
Linus Torvalds committed
752
753
754
755
756
757
}

#define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
#define IDECD_SEEK_TIMER	(5 * WAIT_MIN_SLEEP)	/* 100 ms */
#define IDECD_SEEK_TIMEOUT	(2 * WAIT_CMD)		/* 20 sec */

758
static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
759
760
761
762
763
764
765
{
	struct cdrom_info *info = drive->driver_data;
	int stat;
	static int retry = 10;

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

767
	info->cd_flags |= IDE_CD_FLAG_SEEKING;
Linus Torvalds's avatar
Linus Torvalds committed
768
769
770
771
772
773
774

	if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
		if (--retry == 0) {
			/*
			 * this condition is far too common, to bother
			 * users about it
			 */
775
			/* printk("%s: disabled DSC seek overlap\n", drive->name);*/
Linus Torvalds's avatar
Linus Torvalds committed
776
777
778
779
780
781
			drive->dsc_overlap = 0;
		}
	}
	return ide_stopped;
}

782
static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
783
784
785
786
787
788
789
790
791
792
793
794
795
796
{
	struct request *rq = HWGROUP(drive)->rq;
	sector_t frame = rq->sector;

	sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);

	memset(rq->cmd, 0, sizeof(rq->cmd));
	rq->cmd[0] = GPCMD_SEEK;
	put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);

	rq->timeout = ATAPI_WAIT_PC;
	return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
}

797
static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
Linus Torvalds's avatar
Linus Torvalds committed
798
799
800
801
802
803
804
805
{
	struct cdrom_info *info = drive->driver_data;

	info->dma = 0;
	info->start_seek = jiffies;
	return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
}

806
807
808
809
810
/*
 * Fix up a possibly partially-processed request so that we can
 * start it over entirely, or even put it back on the request queue.
 */
static void restore_request(struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
{
	if (rq->buffer != bio_data(rq->bio)) {
		sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;

		rq->buffer = bio_data(rq->bio);
		rq->nr_sectors += n;
		rq->sector -= n;
	}
	rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio);
	rq->hard_nr_sectors = rq->nr_sectors;
	rq->hard_sector = rq->sector;
	rq->q->prep_rq_fn(rq->q, rq);
}

/****************************************************************************
 * Execute all other packet commands.
 */

829
830
831
832
833
834
835
836
837
838
839
840
841
842
static void ide_cd_request_sense_fixup(struct request *rq)
{
	/*
	 * 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;
		}
}

843
int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
844
845
846
{
	struct request_sense sense;
	int retries = 10;
847
	unsigned int flags = rq->cmd_flags;
Linus Torvalds's avatar
Linus Torvalds committed
848
849
850
851
852
853
854
855

	if (rq->sense == NULL)
		rq->sense = &sense;

	/* Start of retry loop. */
	do {
		int error;
		unsigned long time = jiffies;
856
		rq->cmd_flags = flags;
Linus Torvalds's avatar
Linus Torvalds committed
857
858
859
860

		error = ide_do_drive_cmd(drive, rq, ide_wait);
		time = jiffies - time;

861
		/* FIXME: we should probably abort/retry or something
Linus Torvalds's avatar
Linus Torvalds committed
862
		 * in case of failure */
863
		if (rq->cmd_flags & REQ_FAILED) {
Linus Torvalds's avatar
Linus Torvalds committed
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
			/* The request failed.  Retry if it was due to a unit
			   attention status
			   (usually means media was changed). */
			struct request_sense *reqbuf = rq->sense;

			if (reqbuf->sense_key == UNIT_ATTENTION)
				cdrom_saw_media_change(drive);
			else if (reqbuf->sense_key == NOT_READY &&
				 reqbuf->asc == 4 && reqbuf->ascq != 4) {
				/* The drive is in the process of loading
				   a disk.  Retry, but wait a little to give
				   the drive time to complete the load. */
				ssleep(2);
			} else {
				/* Otherwise, don't retry. */
				retries = 0;
			}
			--retries;
		}

		/* End of retry loop. */
885
	} while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
Linus Torvalds's avatar
Linus Torvalds committed
886
887

	/* Return an error if the command failed. */
888
	return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds's avatar
Linus Torvalds committed
889
890
}

891
892
893
894
895
896
897
898
899
900
901
/*
 * Called from blk_end_request_callback() after the data of the request
 * is completed and before the request is completed.
 * By returning value '1', blk_end_request_callback() returns immediately
 * without completing the request.
 */
static int cdrom_newpc_intr_dummy_cb(struct request *rq)
{
	return 1;
}

Linus Torvalds's avatar
Linus Torvalds committed
902
903
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
904
	ide_hwif_t *hwif = drive->hwif;
Linus Torvalds's avatar
Linus Torvalds committed
905
906
907
	struct cdrom_info *info = drive->driver_data;
	struct request *rq = HWGROUP(drive)->rq;
	xfer_func_t *xferfunc;
908
	ide_expiry_t *expiry = NULL;
909
910
911
912
	int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
	unsigned int timeout;
	u8 lowcyl, highcyl;
Linus Torvalds's avatar
Linus Torvalds committed
913
914
915
916
917
918

	/* Check for errors. */
	dma = info->dma;
	if (dma) {
		info->dma = 0;
		dma_error = HWIF(drive)->ide_dma_end(drive);
919
920
		if (dma_error) {
			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
921
					write ? "write" : "read");
922
923
			ide_dma_off(drive);
		}
Linus Torvalds's avatar
Linus Torvalds committed
924
925
926
927
928
929
930
931
932
	}

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

	/*
	 * using dma, transfer is complete now
	 */
	if (dma) {
933
		if (dma_error)
Linus Torvalds's avatar
Linus Torvalds committed
934
			return ide_error(drive, "dma error", stat);
935
936
937
938
		if (blk_fs_request(rq)) {
			ide_end_request(drive, 1, rq->nr_sectors);
			return ide_stopped;
		}
939
		goto end_request;
Linus Torvalds's avatar
Linus Torvalds committed
940
941
942
943
944
	}

	/*
	 * ok we fall to pio :/
	 */
945
946
947
	ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]) & 0x3;
	lowcyl  = hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
	highcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]);
Linus Torvalds's avatar
Linus Torvalds committed
948
949

	len = lowcyl + (256 * highcyl);
950
951

	thislen = blk_fs_request(rq) ? len : rq->data_len;
Linus Torvalds's avatar
Linus Torvalds committed
952
953
954
955
956
957
	if (thislen > len)
		thislen = len;

	/*
	 * If DRQ is clear, the command has completed.
	 */
958
	if ((stat & DRQ_STAT) == 0) {
959
960
961
962
963
964
965
966
967
		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) {
				printk(KERN_ERR "%s: %s: data underrun "
						"(%d blocks)\n",
968
						drive->name, __func__,
969
970
971
972
973
974
975
976
						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)) {
977
978
979
980
981
			ide_cd_request_sense_fixup(rq);
			/* Complain if we still have data left to transfer. */
			uptodate = rq->data_len ? 0 : 1;
		}
		goto end_request;
982
	}
Linus Torvalds's avatar
Linus Torvalds committed
983
984
985
986

	/*
	 * check which way to transfer data
	 */
987
988
	if (ide_cd_check_ireason(drive, rq, len, ireason, write))
		return ide_stopped;
989

990
991
	if (blk_fs_request(rq)) {
		if (write == 0) {
992
993
994
995
996
997
998
999
1000
			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
For faster browsing, not all history is shown. View entire blame