ide-cd.c 55.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
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);
Borislav Petkov's avatar
Borislav Petkov committed
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
static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *);
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);

Borislav Petkov's avatar
Borislav Petkov committed
516
517
518
519
520
521
522
523
/*
 * 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.
 */
524
static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive)
Linus Torvalds's avatar
Linus Torvalds committed
525
526
{
	ide_hwif_t *hwif = drive->hwif;
527
	struct request *rq = hwif->rq;
528
529
530
	int xferlen;

	xferlen = ide_cd_get_xferlen(rq);
Linus Torvalds's avatar
Linus Torvalds committed
531

532
533
	ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);

534
	/* FIXME: for Virtual DMA we must check harder */
535
536
	if (drive->dma)
		drive->dma = !hwif->dma_ops->dma_setup(drive);
Linus Torvalds's avatar
Linus Torvalds committed
537

Borislav Petkov's avatar
Borislav Petkov committed
538
	/* set up the controller registers */
539
	ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
540
			   xferlen, drive->dma);
541

542
	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
543
		/* waiting for CDB interrupt, not DMA yet. */
544
		if (drive->dma)
545
546
			drive->waiting_for_dma = 0;

Linus Torvalds's avatar
Linus Torvalds committed
547
		/* packet command */
548
549
		ide_execute_command(drive, ATA_CMD_PACKET,
				    cdrom_transfer_packet_command,
550
				    ATAPI_WAIT_PC, ide_cd_expiry);
Linus Torvalds's avatar
Linus Torvalds committed
551
552
		return ide_started;
	} else {
553
		ide_execute_pkt_cmd(drive);
Linus Torvalds's avatar
Linus Torvalds committed
554

555
		return cdrom_transfer_packet_command(drive);
Linus Torvalds's avatar
Linus Torvalds committed
556
557
558
	}
}

Borislav Petkov's avatar
Borislav Petkov committed
559
560
561
562
563
564
/*
 * 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.
 */
Linus Torvalds's avatar
Linus Torvalds committed
565
#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
{
	ide_hwif_t *hwif = drive->hwif;
569
	struct request *rq = hwif->rq;
Linus Torvalds's avatar
Linus Torvalds committed
570
571
572
	int cmd_len;
	ide_startstop_t startstop;

573
574
	ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);

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

Borislav Petkov's avatar
Borislav Petkov committed
581
		/* check for errors */
582
		if (cdrom_decode_status(drive, ATA_DRQ, NULL))
Linus Torvalds's avatar
Linus Torvalds committed
583
			return ide_stopped;
584

Borislav Petkov's avatar
Borislav Petkov committed
585
		/* ok, next interrupt will be DMA interrupt */
586
		if (drive->dma)
587
			drive->waiting_for_dma = 1;
Linus Torvalds's avatar
Linus Torvalds committed
588
	} else {
Borislav Petkov's avatar
Borislav Petkov committed
589
		/* otherwise, we must wait for DRQ to get set */
590
591
		if (ide_wait_stat(&startstop, drive, ATA_DRQ,
				  ATA_BUSY, WAIT_READY))
Linus Torvalds's avatar
Linus Torvalds committed
592
593
594
			return startstop;
	}

Borislav Petkov's avatar
Borislav Petkov committed
595
	/* arm the interrupt handler */
596
	ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, ide_cd_expiry);
Linus Torvalds's avatar
Linus Torvalds committed
597
598
599
600
601
602

	/* 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;

Borislav Petkov's avatar
Borislav Petkov committed
603
	/* send the command to the device */
604
	hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
Linus Torvalds's avatar
Linus Torvalds committed
605

Borislav Petkov's avatar
Borislav Petkov committed
606
	/* start the DMA if need be */
607
	if (drive->dma)
608
		hwif->dma_ops->dma_start(drive);
Linus Torvalds's avatar
Linus Torvalds committed
609
610
611
612
613
614
615
616
617

	return ide_started;
}

/*
 * 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.
 */
618
619
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
620
{
621
622
	ide_hwif_t *hwif = drive->hwif;

623
624
625
	ide_debug_log(IDE_DBG_FUNC, "Call %s, ireason: 0x%x, rw: 0x%x\n",
		      __func__, ireason, rw);

626
627
628
629
630
	/*
	 * 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
631
		return 0;
632
	else if (ireason == (rw << 1)) {
633

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

638
		ide_pad_transfer(drive, rw, len);
639
	} else  if (rw == 0 && ireason == 1) {
Borislav Petkov's avatar
Borislav Petkov committed
640
641
642
		/*
		 * Some drives (ASUS) seem to tell us that status info is
		 * available.  Just get it and ignore.
Linus Torvalds's avatar
Linus Torvalds committed
643
		 */
644
		(void)hwif->tp_ops->read_status(hwif);
Linus Torvalds's avatar
Linus Torvalds committed
645
646
		return 0;
	} else {
Borislav Petkov's avatar
Borislav Petkov committed
647
		/* drive wants a command packet, or invalid ireason... */
648
		printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
649
				drive->name, __func__, ireason);
Linus Torvalds's avatar
Linus Torvalds committed
650
651
	}

652
653
654
	if (rq->cmd_type == REQ_TYPE_ATA_PC)
		rq->cmd_flags |= REQ_FAILED;

Linus Torvalds's avatar
Linus Torvalds committed
655
656
657
658
	cdrom_end_request(drive, 0);
	return -1;
}

659
660
661
662
663
664
/*
 * 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)
{
665
666
	ide_debug_log(IDE_DBG_FUNC, "Call %s, len: %d\n", __func__, len);

667
668
669
	if ((len % SECTOR_SIZE) == 0)
		return 0;

670
671
	printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name,
			__func__, len);
672

673
	if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
674
675
		printk(KERN_ERR PFX "This drive is not supported by this "
				"version of the driver\n");
676
	else {
677
		printk(KERN_ERR PFX "Trying to limit transfer sizes\n");
678
		drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
679
680
681
682
683
	}

	return 1;
}

684
685
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
						 struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
686
{
687
688
689
	ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd_flags: 0x%x\n", __func__,
		      rq->cmd_flags);

690
691
692
693
	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
694

695
696
697
698
699
700
701
702
703
704
705
		/*
		 * 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
706
			/* sanity check... */
707
708
			if (rq->current_nr_sectors !=
			    bio_cur_sectors(rq->bio)) {
709
				printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
710
						drive->name, __func__,
711
712
713
714
715
						rq->current_nr_sectors);
				cdrom_end_request(drive, 0);
				return ide_stopped;
			}
			rq->current_nr_sectors += nskip;
Linus Torvalds's avatar
Linus Torvalds committed
716
717
		}
	}
718

Borislav Petkov's avatar
Borislav Petkov committed
719
	/* set up the command */
Linus Torvalds's avatar
Linus Torvalds committed
720
721
	rq->timeout = ATAPI_WAIT_PC;

722
723
724
	return ide_started;
}

725
/*
Borislav Petkov's avatar
Borislav Petkov committed
726
727
 * Fix up a possibly partially-processed request so that we can start it over
 * entirely, or even put it back on the request queue.
728
 */
729
static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
Linus Torvalds's avatar
Linus Torvalds committed
730
{
731
732
733

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

Linus Torvalds's avatar
Linus Torvalds committed
734
	if (rq->buffer != bio_data(rq->bio)) {
735
736
		sector_t n =
			(rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
Linus Torvalds's avatar
Linus Torvalds committed
737
738
739
740
741

		rq->buffer = bio_data(rq->bio);
		rq->nr_sectors += n;
		rq->sector -= n;
	}
742
743
	rq->current_nr_sectors = bio_cur_sectors(rq->bio);
	rq->hard_cur_sectors = rq->current_nr_sectors;
Linus Torvalds's avatar
Linus Torvalds committed
744
745
746
747
748
	rq->hard_nr_sectors = rq->nr_sectors;
	rq->hard_sector = rq->sector;
	rq->q->prep_rq_fn(rq->q, rq);
}

749
static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
750
{
751
752
	ide_debug_log(IDE_DBG_FUNC, "Call %s, rq->cmd[0]: 0x%x\n",
		      __func__, rq->cmd[0]);
753

754
755
756
757
758
759
760
761
762
763
764
765
	/*
	 * 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;
		}
}

766
767
768
769
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
770
{
771
772
	struct cdrom_info *info = drive->driver_data;
	struct request_sense local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
773
	int retries = 10;
774
	unsigned int flags = 0;
Linus Torvalds's avatar
Linus Torvalds committed
775

776
777
	if (!sense)
		sense = &local_sense;
Linus Torvalds's avatar
Linus Torvalds committed
778

779
	ide_debug_log(IDE_DBG_PC, "Call %s, cmd[0]: 0x%x, write: 0x%x, "
780
781
782
		      "timeout: %d, cmd_flags: 0x%x\n", __func__, cmd[0], write,
		      timeout, cmd_flags);

Borislav Petkov's avatar
Borislav Petkov committed
783
	/* start of retry loop */
Linus Torvalds's avatar
Linus Torvalds committed
784
	do {
785
		struct request *rq;
Linus Torvalds's avatar
Linus Torvalds committed
786
787
		int error;

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
		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
807

Borislav Petkov's avatar
Borislav Petkov committed
808
809
810
811
		/*
		 * FIXME: we should probably abort/retry or something in case of
		 * failure.
		 */
812
		if (flags & REQ_FAILED) {
Borislav Petkov's avatar
Borislav Petkov committed
813
814
815
816
			/*
			 * The request failed.  Retry if it was due to a unit
			 * attention status (usually means media was changed).
			 */
817
			struct request_sense *reqbuf = sense;
Linus Torvalds's avatar
Linus Torvalds committed
818
819
820
821
822

			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
823
824
825
826
827
				/*
				 * 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
828
829
				ssleep(2);
			} else {
Borislav Petkov's avatar
Borislav Petkov committed
830
				/* otherwise, don't retry */
Linus Torvalds's avatar
Linus Torvalds committed
831
832
833
834
835
				retries = 0;
			}
			--retries;
		}

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

Borislav Petkov's avatar
Borislav Petkov committed
839
	/* return an error if the command failed */
840
	return (flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds's avatar
Linus Torvalds committed
841
842
}

843
/*
Borislav Petkov's avatar
Borislav Petkov committed
844
845
846
 * 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.
847
848
849
850
851
852
 */
static int cdrom_newpc_intr_dummy_cb(struct request *rq)
{
	return 1;
}

Linus Torvalds's avatar
Linus Torvalds committed
853
854
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
855
	ide_hwif_t *hwif = drive->hwif;
856
	struct request *rq = hwif->rq;
Linus Torvalds's avatar
Linus Torvalds committed
857
	xfer_func_t *xferfunc;
858
	ide_expiry_t *expiry = NULL;
859
	int dma_error = 0, dma, stat, thislen, uptodate = 0;
860
861
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
	unsigned int timeout;
862
863
	u16 len;
	u8 ireason;
Linus Torvalds's avatar
Linus Torvalds committed
864

865
866
867
	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
868
	/* check for errors */
869
	dma = drive->dma;
Linus Torvalds's avatar
Linus Torvalds committed
870
	if (dma) {
871
		drive->dma = 0;
872
		dma_error = hwif->dma_ops->dma_end(drive);
873
		if (dma_error) {
874
			printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
875
					write ? "write" : "read");
876
877
			ide_dma_off(drive);
		}
Linus Torvalds's avatar
Linus Torvalds committed
878
879
880
881
882
	}

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

Borislav Petkov's avatar
Borislav Petkov committed
883
	/* using dma, transfer is complete now */
Linus Torvalds's avatar
Linus Torvalds committed
884
	if (dma) {
885
		if (dma_error)
Linus Torvalds's avatar
Linus Torvalds committed
886
			return ide_error(drive, "dma error", stat);
887
888
889
890
		if (blk_fs_request(rq)) {
			ide_end_request(drive, 1, rq->nr_sectors);
			return ide_stopped;
		}
891
		goto end_request;
Linus Torvalds's avatar
Linus Torvalds committed
892
893
	}

894
	ide_read_bcount_and_ireason(drive, &len, &ireason);
895
896

	thislen = blk_fs_request(rq) ? len : rq->data_len;
Linus Torvalds's avatar
Linus Torvalds committed
897
898
899
	if (thislen > len)
		thislen = len;

900
901
902
	ide_debug_log(IDE_DBG_PC, "%s: DRQ: stat: 0x%x, thislen: %d\n",
		      __func__, stat, thislen);

Borislav Petkov's avatar
Borislav Petkov committed
903
	/* If DRQ is clear, the command has completed. */
904
	if ((stat & ATA_DRQ) == 0) {
905
906
907
908
909
910
911
		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) {
912
				printk(KERN_ERR PFX "%s: %s: data underrun "
913
						"(%d blocks)\n",
914
						drive->name, __func__,
915
916
917
918
919
920
921
922
						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)) {
923
			ide_cd_request_sense_fixup(drive, rq);
Borislav Petkov's avatar
Borislav Petkov committed
924
			/* complain if we still have data left to transfer */
925
926
927
			uptodate = rq->data_len ? 0 : 1;
		}
		goto end_request;
928
	}
Linus Torvalds's avatar
Linus Torvalds committed
929

Borislav Petkov's avatar
Borislav Petkov committed
930
	/* check which way to transfer data */
931
932
	if (ide_cd_check_ireason(drive, rq, len, ireason, write))
		return ide_stopped;
933

934
935
	if (blk_fs_request(rq)) {
		if (write == 0) {
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
			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) {
951
				ide_pad_transfer(drive, write, nskip << 9);
952
953
954
955
				rq->current_nr_sectors -= nskip;
				thislen -= (nskip << 9);
			}
		}
956
	}
Linus Torvalds's avatar
Linus Torvalds committed
957

958
959
	if (ireason == 0) {
		write = 1;
960
		xferfunc = hwif->tp_ops->output_data;
961
	} else {
962
		write = 0;
963
		xferfunc = hwif->tp_ops->input_data;
Linus Torvalds's avatar
Linus Torvalds committed
964
965
	}

966
967
968
	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
969
	/* transfer data */