blob: 02488b48fa7aa01ea09bd9af65259393eb8b0959 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/ide/ide-cd.c
3 *
4 * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
5 * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
6 * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * ATAPI CD-ROM driver. To be used with ide.c.
12 * See Documentation/cdrom/ide-cd for usage information.
13 *
14 * Suggestions are welcome. Patches that work are more welcome though. ;-)
15 * For those wishing to work on this driver, please be sure you download
16 * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
17 * (SFF-8020i rev 2.6) standards. These documents can be obtained by
18 * anonymous ftp from:
19 * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
20 * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
21 *
22 * Drives that deviate from these standards will be accommodated as much
23 * as possible via compile time or command-line options. Since I only have
24 * a few drives, you generally need to send me patches...
25 *
26 * ----------------------------------
27 * TO DO LIST:
28 * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
29 * boot
30 *
Bartlomiej Zolnierkiewicz03553352008-02-01 23:09:18 +010031 * For historical changelog please see:
32 * Documentation/ide/ChangeLog.ide-cd.1994-2004
33 */
34
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#define IDECD_VERSION "4.61"
36
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/module.h>
38#include <linux/types.h>
39#include <linux/kernel.h>
40#include <linux/delay.h>
41#include <linux/timer.h>
42#include <linux/slab.h>
43#include <linux/interrupt.h>
44#include <linux/errno.h>
45#include <linux/cdrom.h>
46#include <linux/ide.h>
47#include <linux/completion.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080048#include <linux/mutex.h>
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +010049#include <linux/bcd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
52
53#include <asm/irq.h>
54#include <asm/io.h>
55#include <asm/byteorder.h>
56#include <asm/uaccess.h>
57#include <asm/unaligned.h>
58
59#include "ide-cd.h"
60
Arjan van de Vencf8b8972006-03-23 03:00:45 -080061static DEFINE_MUTEX(idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
64
65#define ide_cd_g(disk) \
66 container_of((disk)->private_data, struct cdrom_info, driver)
67
68static struct cdrom_info *ide_cd_get(struct gendisk *disk)
69{
70 struct cdrom_info *cd = NULL;
71
Arjan van de Vencf8b8972006-03-23 03:00:45 -080072 mutex_lock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 cd = ide_cd_g(disk);
74 if (cd)
75 kref_get(&cd->kref);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080076 mutex_unlock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 return cd;
78}
79
80static void ide_cd_release(struct kref *);
81
82static void ide_cd_put(struct cdrom_info *cd)
83{
Arjan van de Vencf8b8972006-03-23 03:00:45 -080084 mutex_lock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 kref_put(&cd->kref, ide_cd_release);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080086 mutex_unlock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087}
88
89/****************************************************************************
90 * Generic packet command support and error handling routines.
91 */
92
93/* Mark that we've seen a media change, and invalidate our internal
94 buffers. */
95static void cdrom_saw_media_change (ide_drive_t *drive)
96{
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +010097 struct cdrom_info *cd = drive->driver_data;
98
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +010099 cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
100 cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +0100101 cd->nsectors_buffered = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102}
103
104static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
105 struct request_sense *sense)
106{
107 int log = 0;
108
Jens Axboe4aff5e22006-08-10 08:44:47 +0200109 if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return 0;
111
112 switch (sense->sense_key) {
113 case NO_SENSE: case RECOVERED_ERROR:
114 break;
115 case NOT_READY:
116 /*
117 * don't care about tray state messages for
118 * e.g. capacity commands or in-progress or
119 * becoming ready
120 */
121 if (sense->asc == 0x3a || sense->asc == 0x04)
122 break;
123 log = 1;
124 break;
125 case ILLEGAL_REQUEST:
126 /*
127 * don't log START_STOP unit with LoEj set, since
128 * we cannot reliably check if drive can auto-close
129 */
130 if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
Alan Coxdbe217a2006-06-25 05:47:44 -0700131 break;
132 log = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 break;
134 case UNIT_ATTENTION:
135 /*
136 * Make good and sure we've seen this potential media
137 * change. Some drives (i.e. Creative) fail to present
138 * the correct sense key in the error register.
139 */
140 cdrom_saw_media_change(drive);
141 break;
142 default:
143 log = 1;
144 break;
145 }
146 return log;
147}
148
149static
150void cdrom_analyze_sense_data(ide_drive_t *drive,
151 struct request *failed_command,
152 struct request_sense *sense)
153{
Alan Coxdbe217a2006-06-25 05:47:44 -0700154 unsigned long sector;
155 unsigned long bio_sectors;
156 unsigned long valid;
157 struct cdrom_info *info = drive->driver_data;
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 if (!cdrom_log_sense(drive, failed_command, sense))
160 return;
161
162 /*
163 * If a read toc is executed for a CD-R or CD-RW medium where
164 * the first toc has not been recorded yet, it will fail with
165 * 05/24/00 (which is a confusing error)
166 */
167 if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
168 if (sense->sense_key == 0x05 && sense->asc == 0x24)
169 return;
170
Alan Coxdbe217a2006-06-25 05:47:44 -0700171 if (sense->error_code == 0x70) { /* Current Error */
172 switch(sense->sense_key) {
173 case MEDIUM_ERROR:
174 case VOLUME_OVERFLOW:
175 case ILLEGAL_REQUEST:
176 if (!sense->valid)
177 break;
178 if (failed_command == NULL ||
179 !blk_fs_request(failed_command))
180 break;
181 sector = (sense->information[0] << 24) |
182 (sense->information[1] << 16) |
183 (sense->information[2] << 8) |
184 (sense->information[3]);
185
186 bio_sectors = bio_sectors(failed_command->bio);
187 if (bio_sectors < 4)
188 bio_sectors = 4;
189 if (drive->queue->hardsect_size == 2048)
190 sector <<= 2; /* Device sector size is 2K */
191 sector &= ~(bio_sectors -1);
192 valid = (sector - failed_command->sector) << 9;
193
194 if (valid < 0)
195 valid = 0;
196 if (sector < get_capacity(info->disk) &&
197 drive->probed_capacity - sector < 4 * 75) {
198 set_capacity(info->disk, sector);
199 }
200 }
201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#if VERBOSE_IDE_CD_ERRORS
203 {
204 int i;
Matt Mackall70d1d472005-07-12 13:58:09 -0700205 const char *s = "bad sense key!";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 char buf[80];
207
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100208 printk(KERN_ERR "ATAPI device %s:\n", drive->name);
209 if (sense->error_code == 0x70)
210 printk(KERN_CONT " Error: ");
211 else if (sense->error_code == 0x71)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 printk(" Deferred Error: ");
213 else if (sense->error_code == 0x7f)
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100214 printk(KERN_CONT " Vendor-specific Error: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 else
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100216 printk(KERN_CONT " Unknown Error Type: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Robert P. J. Day74c8f972007-07-09 23:17:57 +0200218 if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 s = sense_key_texts[sense->sense_key];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100221 printk(KERN_CONT "%s -- (Sense key=0x%02x)\n",
222 s, sense->sense_key);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
224 if (sense->asc == 0x40) {
225 sprintf(buf, "Diagnostic failure on component 0x%02x",
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100226 sense->ascq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 s = buf;
228 } else {
Robert P. J. Day74c8f972007-07-09 23:17:57 +0200229 int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 unsigned long key = (sense->sense_key << 16);
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100231
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 key |= (sense->asc << 8);
233 if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
234 key |= sense->ascq;
235 s = NULL;
236
237 while (hi > lo) {
238 mid = (lo + hi) / 2;
239 if (sense_data_texts[mid].asc_ascq == key ||
240 sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
241 s = sense_data_texts[mid].text;
242 break;
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100243 } else if (sense_data_texts[mid].asc_ascq > key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 hi = mid;
245 else
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100246 lo = mid + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 }
248 }
249
250 if (s == NULL) {
251 if (sense->asc > 0x80)
252 s = "(vendor-specific error)";
253 else
254 s = "(reserved error code)";
255 }
256
257 printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n",
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100258 s, sense->asc, sense->ascq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 if (failed_command != NULL) {
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100261 int lo = 0, mid, hi = ARRAY_SIZE(packet_command_texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 s = NULL;
263
264 while (hi > lo) {
265 mid = (lo + hi) / 2;
266 if (packet_command_texts[mid].packet_command ==
267 failed_command->cmd[0]) {
268 s = packet_command_texts[mid].text;
269 break;
270 }
271 if (packet_command_texts[mid].packet_command >
272 failed_command->cmd[0])
273 hi = mid;
274 else
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100275 lo = mid + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
277
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100278 printk(KERN_ERR " The failed \"%s\" packet command "
279 "was: \n \"", s);
280 for (i = 0; i < sizeof(failed_command->cmd); i++)
281 printk(KERN_CONT "%02x ",
282 failed_command->cmd[i]);
283 printk(KERN_CONT "\"\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 }
285
286 /* The SKSV bit specifies validity of the sense_key_specific
287 * in the next two commands. It is bit 7 of the first byte.
288 * In the case of NOT_READY, if SKSV is set the drive can
289 * give us nice ETA readings.
290 */
291 if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
292 int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100294 printk(KERN_ERR " Command is %02d%% complete\n",
295 progress / 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 }
297
298 if (sense->sense_key == ILLEGAL_REQUEST &&
299 (sense->sks[0] & 0x80) != 0) {
300 printk(KERN_ERR " Error in %s byte %d",
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100301 (sense->sks[0] & 0x40) != 0 ?
302 "command packet" : "command data",
303 (sense->sks[1] << 8) + sense->sks[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
305 if ((sense->sks[0] & 0x40) != 0)
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100306 printk(KERN_CONT " bit %d",
307 sense->sks[0] & 0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100309 printk(KERN_CONT "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 }
311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312#else /* not VERBOSE_IDE_CD_ERRORS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 /* Suppress printing unit attention and `in progress of becoming ready'
314 errors when we're not being verbose. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 if (sense->sense_key == UNIT_ATTENTION ||
316 (sense->sense_key == NOT_READY && (sense->asc == 4 ||
317 sense->asc == 0x3a)))
318 return;
319
Bartlomiej Zolnierkiewicz89d13ec2008-02-01 23:09:23 +0100320 printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x "
321 "asc: 0x%02x ascq: 0x%02x\n",
322 drive->name, sense->error_code, sense->sense_key,
323 sense->asc, sense->ascq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324#endif /* not VERBOSE_IDE_CD_ERRORS */
325}
326
327/*
328 * Initialize a ide-cd packet command request
329 */
330static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
331{
332 struct cdrom_info *cd = drive->driver_data;
333
334 ide_init_drive_cmd(rq);
Jens Axboecea28852006-10-12 15:08:45 +0200335 rq->cmd_type = REQ_TYPE_ATA_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 rq->rq_disk = cd->disk;
337}
338
339static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
340 struct request *failed_command)
341{
342 struct cdrom_info *info = drive->driver_data;
343 struct request *rq = &info->request_sense_request;
344
345 if (sense == NULL)
346 sense = &info->sense_data;
347
348 /* stuff the sense request in front of our current request */
349 cdrom_prepare_request(drive, rq);
350
351 rq->data = sense;
352 rq->cmd[0] = GPCMD_REQUEST_SENSE;
353 rq->cmd[4] = rq->data_len = 18;
354
Jens Axboe4aff5e22006-08-10 08:44:47 +0200355 rq->cmd_type = REQ_TYPE_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 /* NOTE! Save the failed command in "rq->buffer" */
358 rq->buffer = (void *) failed_command;
359
360 (void) ide_do_drive_cmd(drive, rq, ide_preempt);
361}
362
363static void cdrom_end_request (ide_drive_t *drive, int uptodate)
364{
365 struct request *rq = HWGROUP(drive)->rq;
366 int nsectors = rq->hard_cur_sectors;
367
Jens Axboe4aff5e22006-08-10 08:44:47 +0200368 if (blk_sense_request(rq) && uptodate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 /*
Jens Axboe4aff5e22006-08-10 08:44:47 +0200370 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
371 * failed request
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 */
373 struct request *failed = (struct request *) rq->buffer;
374 struct cdrom_info *info = drive->driver_data;
375 void *sense = &info->sense_data;
376 unsigned long flags;
377
378 if (failed) {
379 if (failed->sense) {
380 sense = failed->sense;
381 failed->sense_len = rq->sense_len;
382 }
Alan Coxdbe217a2006-06-25 05:47:44 -0700383 cdrom_analyze_sense_data(drive, failed, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 /*
385 * now end failed request
386 */
Alan Coxdbe217a2006-06-25 05:47:44 -0700387 if (blk_fs_request(failed)) {
388 if (ide_end_dequeued_request(drive, failed, 0,
389 failed->hard_nr_sectors))
390 BUG();
391 } else {
392 spin_lock_irqsave(&ide_lock, flags);
Kiyoshi Ueda5e36bb62008-01-28 10:34:20 +0100393 if (__blk_end_request(failed, -EIO,
394 failed->data_len))
395 BUG();
Alan Coxdbe217a2006-06-25 05:47:44 -0700396 spin_unlock_irqrestore(&ide_lock, flags);
397 }
398 } else
399 cdrom_analyze_sense_data(drive, NULL, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 }
401
402 if (!rq->current_nr_sectors && blk_fs_request(rq))
403 uptodate = 1;
404 /* make sure it's fully ended */
405 if (blk_pc_request(rq))
406 nsectors = (rq->data_len + 511) >> 9;
407 if (!nsectors)
408 nsectors = 1;
409
410 ide_end_request(drive, uptodate, nsectors);
411}
412
Alan Coxdbe217a2006-06-25 05:47:44 -0700413static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
414{
415 if (stat & 0x80)
416 return;
417 ide_dump_status(drive, msg, stat);
418}
419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420/* Returns 0 if the request should be continued.
421 Returns 1 if the request was ended. */
422static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
423{
424 struct request *rq = HWGROUP(drive)->rq;
425 int stat, err, sense_key;
426
427 /* Check for errors. */
428 stat = HWIF(drive)->INB(IDE_STATUS_REG);
429 if (stat_ret)
430 *stat_ret = stat;
431
432 if (OK_STAT(stat, good_stat, BAD_R_STAT))
433 return 0;
434
435 /* Get the IDE error register. */
436 err = HWIF(drive)->INB(IDE_ERROR_REG);
437 sense_key = err >> 4;
438
439 if (rq == NULL) {
440 printk("%s: missing rq in cdrom_decode_status\n", drive->name);
441 return 1;
442 }
443
Jens Axboe4aff5e22006-08-10 08:44:47 +0200444 if (blk_sense_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 /* We got an error trying to get sense info
446 from the drive (probably while trying
447 to recover from a former error). Just give up. */
448
Jens Axboe4aff5e22006-08-10 08:44:47 +0200449 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 cdrom_end_request(drive, 0);
451 ide_error(drive, "request sense failure", stat);
452 return 1;
453
Jens Axboe8770c012006-10-12 17:24:52 +0200454 } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 /* All other functions, except for READ. */
456 unsigned long flags;
457
458 /*
459 * if we have an error, pass back CHECK_CONDITION as the
460 * scsi status byte
461 */
Jens Axboeb7156732006-11-13 18:05:02 +0100462 if (blk_pc_request(rq) && !rq->errors)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 rq->errors = SAM_STAT_CHECK_CONDITION;
464
465 /* Check for tray open. */
466 if (sense_key == NOT_READY) {
467 cdrom_saw_media_change (drive);
468 } else if (sense_key == UNIT_ATTENTION) {
469 /* Check for media change. */
470 cdrom_saw_media_change (drive);
471 /*printk("%s: media changed\n",drive->name);*/
472 return 0;
Stuart Hayes76ca1af2007-04-10 22:38:43 +0200473 } else if ((sense_key == ILLEGAL_REQUEST) &&
474 (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
475 /*
476 * Don't print error message for this condition--
477 * SFF8090i indicates that 5/24/00 is the correct
478 * response to a request to close the tray if the
479 * drive doesn't have that capability.
480 * cdrom_log_sense() knows this!
481 */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200482 } else if (!(rq->cmd_flags & REQ_QUIET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 /* Otherwise, print an error. */
484 ide_dump_status(drive, "packet command error", stat);
485 }
486
Jens Axboe4aff5e22006-08-10 08:44:47 +0200487 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
489 /*
490 * instead of playing games with moving completions around,
491 * remove failed request completely and end it when the
492 * request sense has completed
493 */
494 if (stat & ERR_STAT) {
495 spin_lock_irqsave(&ide_lock, flags);
496 blkdev_dequeue_request(rq);
497 HWGROUP(drive)->rq = NULL;
498 spin_unlock_irqrestore(&ide_lock, flags);
499
500 cdrom_queue_request_sense(drive, rq->sense, rq);
501 } else
502 cdrom_end_request(drive, 0);
503
504 } else if (blk_fs_request(rq)) {
505 int do_end_request = 0;
506
507 /* Handle errors from READ and WRITE requests. */
508
509 if (blk_noretry_request(rq))
510 do_end_request = 1;
511
512 if (sense_key == NOT_READY) {
513 /* Tray open. */
514 if (rq_data_dir(rq) == READ) {
515 cdrom_saw_media_change (drive);
516
517 /* Fail the request. */
518 printk ("%s: tray open\n", drive->name);
519 do_end_request = 1;
520 } else {
521 struct cdrom_info *info = drive->driver_data;
522
523 /* allow the drive 5 seconds to recover, some
524 * devices will return this error while flushing
525 * data from cache */
526 if (!rq->errors)
527 info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
528 rq->errors = 1;
529 if (time_after(jiffies, info->write_timeout))
530 do_end_request = 1;
531 else {
532 unsigned long flags;
533
534 /*
535 * take a breather relying on the
536 * unplug timer to kick us again
537 */
538 spin_lock_irqsave(&ide_lock, flags);
539 blk_plug_device(drive->queue);
540 spin_unlock_irqrestore(&ide_lock,flags);
541 return 1;
542 }
543 }
544 } else if (sense_key == UNIT_ATTENTION) {
545 /* Media change. */
546 cdrom_saw_media_change (drive);
547
548 /* Arrange to retry the request.
549 But be sure to give up if we've retried
550 too many times. */
551 if (++rq->errors > ERROR_MAX)
552 do_end_request = 1;
553 } else if (sense_key == ILLEGAL_REQUEST ||
554 sense_key == DATA_PROTECT) {
555 /* No point in retrying after an illegal
556 request or data protect error.*/
Alan Coxdbe217a2006-06-25 05:47:44 -0700557 ide_dump_status_no_sense (drive, "command error", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 do_end_request = 1;
559 } else if (sense_key == MEDIUM_ERROR) {
560 /* No point in re-trying a zillion times on a bad
561 * sector... If we got here the error is not correctable */
Alan Coxdbe217a2006-06-25 05:47:44 -0700562 ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 do_end_request = 1;
564 } else if (sense_key == BLANK_CHECK) {
565 /* Disk appears blank ?? */
Alan Coxdbe217a2006-06-25 05:47:44 -0700566 ide_dump_status_no_sense (drive, "media error (blank)", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 do_end_request = 1;
568 } else if ((err & ~ABRT_ERR) != 0) {
569 /* Go to the default handler
570 for other errors. */
571 ide_error(drive, "cdrom_decode_status", stat);
572 return 1;
573 } else if ((++rq->errors > ERROR_MAX)) {
574 /* We've racked up too many retries. Abort. */
575 do_end_request = 1;
576 }
577
Alan Coxdbe217a2006-06-25 05:47:44 -0700578 /* End a request through request sense analysis when we have
579 sense data. We need this in order to perform end of media
580 processing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Alan Coxdbe217a2006-06-25 05:47:44 -0700582 if (do_end_request) {
583 if (stat & ERR_STAT) {
584 unsigned long flags;
585 spin_lock_irqsave(&ide_lock, flags);
586 blkdev_dequeue_request(rq);
587 HWGROUP(drive)->rq = NULL;
588 spin_unlock_irqrestore(&ide_lock, flags);
589
590 cdrom_queue_request_sense(drive, rq->sense, rq);
591 } else
592 cdrom_end_request(drive, 0);
593 } else {
594 /* If we got a CHECK_CONDITION status,
595 queue a request sense command. */
596 if (stat & ERR_STAT)
597 cdrom_queue_request_sense(drive, NULL, NULL);
598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 } else {
600 blk_dump_rq_flags(rq, "ide-cd: bad rq");
601 cdrom_end_request(drive, 0);
602 }
603
604 /* Retry, or handle the next request. */
605 return 1;
606}
607
608static int cdrom_timer_expiry(ide_drive_t *drive)
609{
610 struct request *rq = HWGROUP(drive)->rq;
611 unsigned long wait = 0;
612
613 /*
614 * Some commands are *slow* and normally take a long time to
615 * complete. Usually we can use the ATAPI "disconnect" to bypass
616 * this, but not all commands/drives support that. Let
617 * ide_timer_expiry keep polling us for these.
618 */
619 switch (rq->cmd[0]) {
620 case GPCMD_BLANK:
621 case GPCMD_FORMAT_UNIT:
622 case GPCMD_RESERVE_RZONE_TRACK:
623 case GPCMD_CLOSE_TRACK:
624 case GPCMD_FLUSH_CACHE:
625 wait = ATAPI_WAIT_PC;
626 break;
627 default:
Jens Axboe4aff5e22006-08-10 08:44:47 +0200628 if (!(rq->cmd_flags & REQ_QUIET))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
630 wait = 0;
631 break;
632 }
633 return wait;
634}
635
636/* Set up the device registers for transferring a packet command on DEV,
637 expecting to later transfer XFERLEN bytes. HANDLER is the routine
638 which actually transfers the command to the drive. If this is a
639 drq_interrupt device, this routine will arrange for HANDLER to be
640 called when the interrupt from the drive arrives. Otherwise, HANDLER
641 will be called immediately after the drive is prepared for the transfer. */
642
643static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
644 int xferlen,
645 ide_handler_t *handler)
646{
647 ide_startstop_t startstop;
648 struct cdrom_info *info = drive->driver_data;
649 ide_hwif_t *hwif = drive->hwif;
650
651 /* Wait for the controller to be idle. */
652 if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
653 return startstop;
654
Bartlomiej Zolnierkiewicz3a6a3542008-01-25 22:17:13 +0100655 /* FIXME: for Virtual DMA we must check harder */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 if (info->dma)
657 info->dma = !hwif->dma_setup(drive);
658
659 /* Set up the controller registers. */
Bartlomiej Zolnierkiewicz2fc57382008-01-25 22:17:13 +0100660 ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
661 IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +0100662
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100663 if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Albert Leef0dd8712007-02-17 02:40:21 +0100664 /* waiting for CDB interrupt, not DMA yet. */
665 if (info->dma)
666 drive->waiting_for_dma = 0;
667
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 /* packet command */
669 ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
670 return ide_started;
671 } else {
672 unsigned long flags;
673
674 /* packet command */
675 spin_lock_irqsave(&ide_lock, flags);
676 hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG);
677 ndelay(400);
678 spin_unlock_irqrestore(&ide_lock, flags);
679
680 return (*handler) (drive);
681 }
682}
683
684/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
685 The device registers must have already been prepared
686 by cdrom_start_packet_command.
687 HANDLER is the interrupt handler to call when the command completes
688 or there's data ready. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689#define ATAPI_MIN_CDB_BYTES 12
690static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
691 struct request *rq,
692 ide_handler_t *handler)
693{
694 ide_hwif_t *hwif = drive->hwif;
695 int cmd_len;
696 struct cdrom_info *info = drive->driver_data;
697 ide_startstop_t startstop;
698
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100699 if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 /* Here we should have been called after receiving an interrupt
701 from the device. DRQ should how be set. */
702
703 /* Check for errors. */
704 if (cdrom_decode_status(drive, DRQ_STAT, NULL))
705 return ide_stopped;
Albert Leef0dd8712007-02-17 02:40:21 +0100706
707 /* Ok, next interrupt will be DMA interrupt. */
708 if (info->dma)
709 drive->waiting_for_dma = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 } else {
711 /* Otherwise, we must wait for DRQ to get set. */
712 if (ide_wait_stat(&startstop, drive, DRQ_STAT,
713 BUSY_STAT, WAIT_READY))
714 return startstop;
715 }
716
717 /* Arm the interrupt handler. */
718 ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
719
720 /* ATAPI commands get padded out to 12 bytes minimum */
721 cmd_len = COMMAND_SIZE(rq->cmd[0]);
722 if (cmd_len < ATAPI_MIN_CDB_BYTES)
723 cmd_len = ATAPI_MIN_CDB_BYTES;
724
725 /* Send the command to the device. */
726 HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len);
727
728 /* Start the DMA if need be */
729 if (info->dma)
730 hwif->dma_start(drive);
731
732 return ide_started;
733}
734
735/****************************************************************************
736 * Block read functions.
737 */
738
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +0100739typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
740
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100741static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
742{
743 while (len > 0) {
744 int dum = 0;
745 xf(drive, &dum, sizeof(dum));
746 len -= sizeof(dum);
747 }
748}
749
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750/*
751 * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
752 * buffer. Once the first sector is added, any subsequent sectors are
753 * assumed to be continuous (until the buffer is cleared). For the first
754 * sector added, SECTOR is its sector number. (SECTOR is then ignored until
755 * the buffer is cleared.)
756 */
757static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
758 int sectors_to_transfer)
759{
760 struct cdrom_info *info = drive->driver_data;
761
762 /* Number of sectors to read into the buffer. */
763 int sectors_to_buffer = min_t(int, sectors_to_transfer,
764 (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
765 info->nsectors_buffered);
766
767 char *dest;
768
769 /* If we couldn't get a buffer, don't try to buffer anything... */
770 if (info->buffer == NULL)
771 sectors_to_buffer = 0;
772
773 /* If this is the first sector in the buffer, remember its number. */
774 if (info->nsectors_buffered == 0)
775 info->sector_buffered = sector;
776
777 /* Read the data into the buffer. */
778 dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
779 while (sectors_to_buffer > 0) {
780 HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE);
781 --sectors_to_buffer;
782 --sectors_to_transfer;
783 ++info->nsectors_buffered;
784 dest += SECTOR_SIZE;
785 }
786
787 /* Throw away any remaining data. */
788 while (sectors_to_transfer > 0) {
789 static char dum[SECTOR_SIZE];
790 HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
791 --sectors_to_transfer;
792 }
793}
794
795/*
796 * Check the contents of the interrupt reason register from the cdrom
797 * and attempt to recover if there are problems. Returns 0 if everything's
798 * ok; nonzero if the request has been terminated.
799 */
Arjan van de Ven858119e2006-01-14 13:20:43 -0800800static
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
802{
803 if (ireason == 2)
804 return 0;
805 else if (ireason == 0) {
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100806 ide_hwif_t *hwif = drive->hwif;
807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 /* Whoops... The drive is expecting to receive data from us! */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +0100809 printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
810 drive->name, __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812 /* Throw some data at the drive so it doesn't hang
813 and quit this request. */
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100814 ide_cd_pad_transfer(drive, hwif->atapi_output_bytes, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 } else if (ireason == 1) {
816 /* Some drives (ASUS) seem to tell us that status
817 * info is available. just get it and ignore.
818 */
819 (void) HWIF(drive)->INB(IDE_STATUS_REG);
820 return 0;
821 } else {
822 /* Drive wants a command packet, or invalid ireason... */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +0100823 printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
824 drive->name, __FUNCTION__, ireason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
826
827 cdrom_end_request(drive, 0);
828 return -1;
829}
830
831/*
832 * Interrupt routine. Called when a read request has completed.
833 */
834static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
835{
836 int stat;
837 int ireason, len, sectors_to_transfer, nskip;
838 struct cdrom_info *info = drive->driver_data;
839 u8 lowcyl = 0, highcyl = 0;
840 int dma = info->dma, dma_error = 0;
841
842 struct request *rq = HWGROUP(drive)->rq;
843
844 /*
845 * handle dma case
846 */
847 if (dma) {
848 info->dma = 0;
Bartlomiej Zolnierkiewicz52ef2ed2007-12-24 15:23:43 +0100849 dma_error = HWIF(drive)->ide_dma_end(drive);
850 if (dma_error) {
851 printk(KERN_ERR "%s: DMA read error\n", drive->name);
Bartlomiej Zolnierkiewicz7469aaf2007-02-17 02:40:26 +0100852 ide_dma_off(drive);
Bartlomiej Zolnierkiewicz52ef2ed2007-12-24 15:23:43 +0100853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 }
855
856 if (cdrom_decode_status(drive, 0, &stat))
857 return ide_stopped;
858
859 if (dma) {
860 if (!dma_error) {
861 ide_end_request(drive, 1, rq->nr_sectors);
862 return ide_stopped;
863 } else
864 return ide_error(drive, "dma error", stat);
865 }
866
867 /* Read the interrupt reason and the transfer length. */
868 ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
869 lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
870 highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
871
872 len = lowcyl + (256 * highcyl);
873
874 /* If DRQ is clear, the command has completed. */
875 if ((stat & DRQ_STAT) == 0) {
876 /* If we're not done filling the current buffer, complain.
877 Otherwise, complete the command normally. */
878 if (rq->current_nr_sectors > 0) {
879 printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
880 drive->name, rq->current_nr_sectors);
Jens Axboe4aff5e22006-08-10 08:44:47 +0200881 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 cdrom_end_request(drive, 0);
883 } else
884 cdrom_end_request(drive, 1);
885 return ide_stopped;
886 }
887
888 /* Check that the drive is expecting to do the same thing we are. */
889 if (cdrom_read_check_ireason (drive, len, ireason))
890 return ide_stopped;
891
892 /* Assume that the drive will always provide data in multiples
893 of at least SECTOR_SIZE, as it gets hairy to keep track
894 of the transfers otherwise. */
895 if ((len % SECTOR_SIZE) != 0) {
896 printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n",
897 drive->name, len);
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100898 if (info->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 printk (KERN_ERR " This drive is not supported by this version of the driver\n");
900 else {
901 printk (KERN_ERR " Trying to limit transfer sizes\n");
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100902 info->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 }
904 cdrom_end_request(drive, 0);
905 return ide_stopped;
906 }
907
908 /* The number of sectors we need to read from the drive. */
909 sectors_to_transfer = len / SECTOR_SIZE;
910
911 /* First, figure out if we need to bit-bucket
912 any of the leading sectors. */
913 nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer);
914
915 while (nskip > 0) {
916 /* We need to throw away a sector. */
917 static char dum[SECTOR_SIZE];
918 HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
919
920 --rq->current_nr_sectors;
921 --nskip;
922 --sectors_to_transfer;
923 }
924
925 /* Now loop while we still have data to read from the drive. */
926 while (sectors_to_transfer > 0) {
927 int this_transfer;
928
929 /* If we've filled the present buffer but there's another
930 chained buffer after it, move on. */
931 if (rq->current_nr_sectors == 0 && rq->nr_sectors)
932 cdrom_end_request(drive, 1);
933
934 /* If the buffers are full, cache the rest of the data in our
935 internal buffer. */
936 if (rq->current_nr_sectors == 0) {
937 cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
938 sectors_to_transfer = 0;
939 } else {
940 /* Transfer data to the buffers.
941 Figure out how many sectors we can transfer
942 to the current buffer. */
943 this_transfer = min_t(int, sectors_to_transfer,
944 rq->current_nr_sectors);
945
946 /* Read this_transfer sectors
947 into the current buffer. */
948 while (this_transfer > 0) {
949 HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
950 rq->buffer += SECTOR_SIZE;
951 --rq->nr_sectors;
952 --rq->current_nr_sectors;
953 ++rq->sector;
954 --this_transfer;
955 --sectors_to_transfer;
956 }
957 }
958 }
959
960 /* Done moving data! Wait for another interrupt. */
961 ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
962 return ide_started;
963}
964
965/*
966 * Try to satisfy some of the current read request from our cached data.
967 * Returns nonzero if the request has been completed, zero otherwise.
968 */
969static int cdrom_read_from_buffer (ide_drive_t *drive)
970{
971 struct cdrom_info *info = drive->driver_data;
972 struct request *rq = HWGROUP(drive)->rq;
973 unsigned short sectors_per_frame;
974
975 sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
976
977 /* Can't do anything if there's no buffer. */
978 if (info->buffer == NULL) return 0;
979
980 /* Loop while this request needs data and the next block is present
981 in our cache. */
982 while (rq->nr_sectors > 0 &&
983 rq->sector >= info->sector_buffered &&
984 rq->sector < info->sector_buffered + info->nsectors_buffered) {
985 if (rq->current_nr_sectors == 0)
986 cdrom_end_request(drive, 1);
987
988 memcpy (rq->buffer,
989 info->buffer +
990 (rq->sector - info->sector_buffered) * SECTOR_SIZE,
991 SECTOR_SIZE);
992 rq->buffer += SECTOR_SIZE;
993 --rq->current_nr_sectors;
994 --rq->nr_sectors;
995 ++rq->sector;
996 }
997
998 /* If we've satisfied the current request,
999 terminate it successfully. */
1000 if (rq->nr_sectors == 0) {
1001 cdrom_end_request(drive, 1);
1002 return -1;
1003 }
1004
1005 /* Move on to the next buffer if needed. */
1006 if (rq->current_nr_sectors == 0)
1007 cdrom_end_request(drive, 1);
1008
1009 /* If this condition does not hold, then the kluge i use to
1010 represent the number of sectors to skip at the start of a transfer
1011 will fail. I think that this will never happen, but let's be
1012 paranoid and check. */
1013 if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
1014 (rq->sector & (sectors_per_frame - 1))) {
1015 printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
1016 drive->name, (long)rq->sector);
1017 cdrom_end_request(drive, 0);
1018 return -1;
1019 }
1020
1021 return 0;
1022}
1023
1024/*
1025 * Routine to send a read packet command to the drive.
1026 * This is usually called directly from cdrom_start_read.
1027 * However, for drq_interrupt devices, it is called from an interrupt
1028 * when the drive is ready to accept the command.
1029 */
1030static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
1031{
1032 struct request *rq = HWGROUP(drive)->rq;
1033 unsigned short sectors_per_frame;
1034 int nskip;
1035
1036 sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
1037
1038 /* If the requested sector doesn't start on a cdrom block boundary,
1039 we must adjust the start of the transfer so that it does,
1040 and remember to skip the first few sectors.
1041 If the CURRENT_NR_SECTORS field is larger than the size
1042 of the buffer, it will mean that we're to skip a number
1043 of sectors equal to the amount by which CURRENT_NR_SECTORS
1044 is larger than the buffer size. */
1045 nskip = rq->sector & (sectors_per_frame - 1);
1046 if (nskip > 0) {
1047 /* Sanity check... */
1048 if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) &&
1049 (rq->sector & (sectors_per_frame - 1))) {
1050 printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n",
1051 drive->name, rq->current_nr_sectors);
1052 cdrom_end_request(drive, 0);
1053 return ide_stopped;
1054 }
1055 rq->current_nr_sectors += nskip;
1056 }
1057
1058 /* Set up the command */
1059 rq->timeout = ATAPI_WAIT_PC;
1060
1061 /* Send the command to the drive and return. */
1062 return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
1063}
1064
1065
1066#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
1067#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
1068#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
1069
1070static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
1071{
1072 struct cdrom_info *info = drive->driver_data;
1073 int stat;
1074 static int retry = 10;
1075
1076 if (cdrom_decode_status(drive, 0, &stat))
1077 return ide_stopped;
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001078
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001079 info->cd_flags |= IDE_CD_FLAG_SEEKING;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
1082 if (--retry == 0) {
1083 /*
1084 * this condition is far too common, to bother
1085 * users about it
1086 */
1087 /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
1088 drive->dsc_overlap = 0;
1089 }
1090 }
1091 return ide_stopped;
1092}
1093
1094static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
1095{
1096 struct request *rq = HWGROUP(drive)->rq;
1097 sector_t frame = rq->sector;
1098
1099 sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
1100
1101 memset(rq->cmd, 0, sizeof(rq->cmd));
1102 rq->cmd[0] = GPCMD_SEEK;
1103 put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
1104
1105 rq->timeout = ATAPI_WAIT_PC;
1106 return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
1107}
1108
1109static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
1110{
1111 struct cdrom_info *info = drive->driver_data;
1112
1113 info->dma = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 info->start_seek = jiffies;
1115 return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
1116}
1117
1118/* Fix up a possibly partially-processed request so that we can
1119 start it over entirely, or even put it back on the request queue. */
1120static void restore_request (struct request *rq)
1121{
1122 if (rq->buffer != bio_data(rq->bio)) {
1123 sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
1124
1125 rq->buffer = bio_data(rq->bio);
1126 rq->nr_sectors += n;
1127 rq->sector -= n;
1128 }
1129 rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio);
1130 rq->hard_nr_sectors = rq->nr_sectors;
1131 rq->hard_sector = rq->sector;
1132 rq->q->prep_rq_fn(rq->q, rq);
1133}
1134
1135/*
1136 * Start a read request from the CD-ROM.
1137 */
1138static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
1139{
1140 struct cdrom_info *info = drive->driver_data;
1141 struct request *rq = HWGROUP(drive)->rq;
1142 unsigned short sectors_per_frame;
1143
1144 sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
1145
1146 /* We may be retrying this request after an error. Fix up
1147 any weirdness which might be present in the request packet. */
1148 restore_request(rq);
1149
1150 /* Satisfy whatever we can of this request from our cached sector. */
1151 if (cdrom_read_from_buffer(drive))
1152 return ide_stopped;
1153
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 /* Clear the local sector buffer. */
1155 info->nsectors_buffered = 0;
1156
1157 /* use dma, if possible. */
1158 info->dma = drive->using_dma;
1159 if ((rq->sector & (sectors_per_frame - 1)) ||
1160 (rq->nr_sectors & (sectors_per_frame - 1)))
1161 info->dma = 0;
1162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 /* Start sending the read request to the drive. */
1164 return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
1165}
1166
1167/****************************************************************************
1168 * Execute all other packet commands.
1169 */
1170
1171/* Interrupt routine for packet command completion. */
1172static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
1173{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 struct request *rq = HWGROUP(drive)->rq;
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001175 xfer_func_t *xferfunc = NULL;
1176 int stat, ireason, len, thislen, write;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 u8 lowcyl = 0, highcyl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 /* Check for errors. */
1180 if (cdrom_decode_status(drive, 0, &stat))
1181 return ide_stopped;
1182
1183 /* Read the interrupt reason and the transfer length. */
Bartlomiej Zolnierkiewicz8606ab02007-12-24 15:23:44 +01001184 ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
1186 highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
1187
1188 len = lowcyl + (256 * highcyl);
1189
1190 /* If DRQ is clear, the command has completed.
1191 Complain if we still have data left to transfer. */
1192 if ((stat & DRQ_STAT) == 0) {
1193 /* Some of the trailing request sense fields are optional, and
1194 some drives don't send them. Sigh. */
1195 if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
1196 rq->data_len > 0 &&
1197 rq->data_len <= 5) {
1198 while (rq->data_len > 0) {
1199 *(unsigned char *)rq->data++ = 0;
1200 --rq->data_len;
1201 }
1202 }
1203
1204 if (rq->data_len == 0)
1205 cdrom_end_request(drive, 1);
1206 else {
Jens Axboe4aff5e22006-08-10 08:44:47 +02001207 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 cdrom_end_request(drive, 0);
1209 }
1210 return ide_stopped;
1211 }
1212
1213 /* Figure out how much data to transfer. */
1214 thislen = rq->data_len;
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001215 if (thislen > len)
1216 thislen = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Bartlomiej Zolnierkiewicz8606ab02007-12-24 15:23:44 +01001218 if (ireason == 0) {
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001219 write = 1;
1220 xferfunc = HWIF(drive)->atapi_output_bytes;
1221 } else if (ireason == 2) {
1222 write = 0;
1223 xferfunc = HWIF(drive)->atapi_input_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001226 if (xferfunc) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 if (!rq->data) {
Bartlomiej Zolnierkiewiczf1071e62008-02-01 23:09:17 +01001228 printk(KERN_ERR "%s: confused, missing data\n",
1229 drive->name);
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001230 blk_dump_rq_flags(rq, write ? "cdrom_pc_intr, write"
1231 : "cdrom_pc_intr, read");
Bartlomiej Zolnierkiewiczf1071e62008-02-01 23:09:17 +01001232 goto pad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 }
1234 /* Transfer the data. */
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001235 xferfunc(drive, rq->data, thislen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 /* Keep count of how much data we've moved. */
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001238 len -= thislen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 rq->data += thislen;
1240 rq->data_len -= thislen;
1241
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +01001242 if (write && blk_sense_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 rq->sense_len += thislen;
1244 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
Rachita Kothiyal1ad55442006-06-23 02:02:56 -07001246 "appears confused (ireason = 0x%02x). "
1247 "Trying to recover by ending request.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 drive->name, ireason);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001249 rq->cmd_flags |= REQ_FAILED;
Rachita Kothiyal1ad55442006-06-23 02:02:56 -07001250 cdrom_end_request(drive, 0);
1251 return ide_stopped;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 }
Bartlomiej Zolnierkiewiczf1071e62008-02-01 23:09:17 +01001253pad:
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001254 /*
1255 * If we haven't moved enough data to satisfy the drive,
1256 * add some padding.
1257 */
1258 if (len > 0)
1259 ide_cd_pad_transfer(drive, xferfunc, len);
1260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 /* Now we wait for another interrupt. */
1262 ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry);
1263 return ide_started;
1264}
1265
1266static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
1267{
1268 struct request *rq = HWGROUP(drive)->rq;
1269
1270 if (!rq->timeout)
1271 rq->timeout = ATAPI_WAIT_PC;
1272
1273 /* Send the command to the drive and return. */
1274 return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr);
1275}
1276
1277
1278static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
1279{
1280 int len;
1281 struct request *rq = HWGROUP(drive)->rq;
1282 struct cdrom_info *info = drive->driver_data;
1283
1284 info->dma = 0;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001285 rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 len = rq->data_len;
1287
1288 /* Start sending the command to the drive. */
1289 return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
1290}
1291
1292
Alan Coxdbe217a2006-06-25 05:47:44 -07001293static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294{
1295 struct request_sense sense;
1296 int retries = 10;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001297 unsigned int flags = rq->cmd_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
1299 if (rq->sense == NULL)
1300 rq->sense = &sense;
1301
1302 /* Start of retry loop. */
1303 do {
1304 int error;
1305 unsigned long time = jiffies;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001306 rq->cmd_flags = flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308 error = ide_do_drive_cmd(drive, rq, ide_wait);
1309 time = jiffies - time;
1310
1311 /* FIXME: we should probably abort/retry or something
1312 * in case of failure */
Jens Axboe4aff5e22006-08-10 08:44:47 +02001313 if (rq->cmd_flags & REQ_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 /* The request failed. Retry if it was due to a unit
1315 attention status
1316 (usually means media was changed). */
1317 struct request_sense *reqbuf = rq->sense;
1318
1319 if (reqbuf->sense_key == UNIT_ATTENTION)
1320 cdrom_saw_media_change(drive);
1321 else if (reqbuf->sense_key == NOT_READY &&
1322 reqbuf->asc == 4 && reqbuf->ascq != 4) {
1323 /* The drive is in the process of loading
1324 a disk. Retry, but wait a little to give
1325 the drive time to complete the load. */
1326 ssleep(2);
1327 } else {
1328 /* Otherwise, don't retry. */
1329 retries = 0;
1330 }
1331 --retries;
1332 }
1333
1334 /* End of retry loop. */
Jens Axboe4aff5e22006-08-10 08:44:47 +02001335 } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337 /* Return an error if the command failed. */
Jens Axboe4aff5e22006-08-10 08:44:47 +02001338 return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
1341/*
1342 * Write handling
1343 */
Arjan van de Ven858119e2006-01-14 13:20:43 -08001344static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
1346 /* Two notes about IDE interrupt reason here - 0 means that
1347 * the drive wants to receive data from us, 2 means that
1348 * the drive is expecting to transfer data to us.
1349 */
1350 if (ireason == 0)
1351 return 0;
1352 else if (ireason == 2) {
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001353 ide_hwif_t *hwif = drive->hwif;
1354
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 /* Whoops... The drive wants to send data. */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +01001356 printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
1357 drive->name, __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001359 ide_cd_pad_transfer(drive, hwif->atapi_input_bytes, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 } else {
1361 /* Drive wants a command packet, or invalid ireason... */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +01001362 printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
1363 drive->name, __FUNCTION__, ireason);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 }
1365
1366 cdrom_end_request(drive, 0);
1367 return 1;
1368}
1369
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001370/*
1371 * Called from blk_end_request_callback() after the data of the request
1372 * is completed and before the request is completed.
1373 * By returning value '1', blk_end_request_callback() returns immediately
1374 * without completing the request.
1375 */
1376static int cdrom_newpc_intr_dummy_cb(struct request *rq)
1377{
1378 return 1;
1379}
1380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381/*
1382 * best way to deal with dma that is not sector aligned right now... note
1383 * that in this path we are not using ->data or ->buffer at all. this irs
1384 * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the
1385 * future.
1386 */
1387static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
1388{
1389 struct cdrom_info *info = drive->driver_data;
1390 struct request *rq = HWGROUP(drive)->rq;
1391 int dma_error, dma, stat, ireason, len, thislen;
1392 u8 lowcyl, highcyl;
1393 xfer_func_t *xferfunc;
1394 unsigned long flags;
1395
1396 /* Check for errors. */
1397 dma_error = 0;
1398 dma = info->dma;
1399 if (dma) {
1400 info->dma = 0;
1401 dma_error = HWIF(drive)->ide_dma_end(drive);
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +01001402 if (dma_error) {
1403 printk(KERN_ERR "%s: DMA %s error\n", drive->name,
1404 rq_data_dir(rq) ? "write" : "read");
1405 ide_dma_off(drive);
1406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 }
1408
1409 if (cdrom_decode_status(drive, 0, &stat))
1410 return ide_stopped;
1411
1412 /*
1413 * using dma, transfer is complete now
1414 */
1415 if (dma) {
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +01001416 if (dma_error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return ide_error(drive, "dma error", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001419 spin_lock_irqsave(&ide_lock, flags);
1420 if (__blk_end_request(rq, 0, rq->data_len))
1421 BUG();
1422 HWGROUP(drive)->rq = NULL;
1423 spin_unlock_irqrestore(&ide_lock, flags);
1424
1425 return ide_stopped;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 }
1427
1428 /*
1429 * ok we fall to pio :/
1430 */
1431 ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
1432 lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
1433 highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
1434
1435 len = lowcyl + (256 * highcyl);
1436 thislen = rq->data_len;
1437 if (thislen > len)
1438 thislen = len;
1439
1440 /*
1441 * If DRQ is clear, the command has completed.
1442 */
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001443 if ((stat & DRQ_STAT) == 0) {
1444 spin_lock_irqsave(&ide_lock, flags);
Jens Axboe4f4f6c252008-01-31 13:57:51 +01001445 if (__blk_end_request(rq, 0, rq->data_len))
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001446 BUG();
1447 HWGROUP(drive)->rq = NULL;
1448 spin_unlock_irqrestore(&ide_lock, flags);
1449
1450 return ide_stopped;
1451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
1453 /*
1454 * check which way to transfer data
1455 */
1456 if (rq_data_dir(rq) == WRITE) {
1457 /*
1458 * write to drive
1459 */
1460 if (cdrom_write_check_ireason(drive, len, ireason))
1461 return ide_stopped;
1462
1463 xferfunc = HWIF(drive)->atapi_output_bytes;
1464 } else {
1465 /*
1466 * read from drive
1467 */
1468 if (cdrom_read_check_ireason(drive, len, ireason))
1469 return ide_stopped;
1470
1471 xferfunc = HWIF(drive)->atapi_input_bytes;
1472 }
1473
1474 /*
1475 * transfer data
1476 */
1477 while (thislen > 0) {
1478 int blen = blen = rq->data_len;
1479 char *ptr = rq->data;
1480
1481 /*
1482 * bio backed?
1483 */
1484 if (rq->bio) {
1485 ptr = bio_data(rq->bio);
1486 blen = bio_iovec(rq->bio)->bv_len;
1487 }
1488
1489 if (!ptr) {
1490 printk(KERN_ERR "%s: confused, missing data\n", drive->name);
1491 break;
1492 }
1493
1494 if (blen > thislen)
1495 blen = thislen;
1496
1497 xferfunc(drive, ptr, blen);
1498
1499 thislen -= blen;
1500 len -= blen;
1501 rq->data_len -= blen;
1502
1503 if (rq->bio)
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001504 /*
1505 * The request can't be completed until DRQ is cleared.
1506 * So complete the data, but don't complete the request
1507 * using the dummy function for the callback feature
1508 * of blk_end_request_callback().
1509 */
1510 blk_end_request_callback(rq, 0, blen,
1511 cdrom_newpc_intr_dummy_cb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 else
1513 rq->data += blen;
1514 }
1515
1516 /*
1517 * pad, if necessary
1518 */
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001519 if (len > 0)
1520 ide_cd_pad_transfer(drive, xferfunc, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Eric Sesterhenn125e1872006-06-23 02:06:06 -07001522 BUG_ON(HWGROUP(drive)->handler != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
1524 ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
1525 return ide_started;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
1527
1528static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
1529{
1530 int stat, ireason, len, sectors_to_transfer, uptodate;
1531 struct cdrom_info *info = drive->driver_data;
1532 int dma_error = 0, dma = info->dma;
1533 u8 lowcyl = 0, highcyl = 0;
1534
1535 struct request *rq = HWGROUP(drive)->rq;
1536
1537 /* Check for errors. */
1538 if (dma) {
1539 info->dma = 0;
Bartlomiej Zolnierkiewiczb481b232007-12-24 15:23:43 +01001540 dma_error = HWIF(drive)->ide_dma_end(drive);
1541 if (dma_error) {
1542 printk(KERN_ERR "%s: DMA write error\n", drive->name);
Bartlomiej Zolnierkiewicz7469aaf2007-02-17 02:40:26 +01001543 ide_dma_off(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 }
1545 }
1546
1547 if (cdrom_decode_status(drive, 0, &stat))
1548 return ide_stopped;
1549
1550 /*
1551 * using dma, transfer is complete now
1552 */
1553 if (dma) {
1554 if (dma_error)
1555 return ide_error(drive, "dma error", stat);
1556
1557 ide_end_request(drive, 1, rq->nr_sectors);
1558 return ide_stopped;
1559 }
1560
1561 /* Read the interrupt reason and the transfer length. */
Bartlomiej Zolnierkiewicz31a71192007-12-24 15:23:43 +01001562 ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
1564 highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
1565
1566 len = lowcyl + (256 * highcyl);
1567
1568 /* If DRQ is clear, the command has completed. */
1569 if ((stat & DRQ_STAT) == 0) {
1570 /* If we're not done writing, complain.
1571 * Otherwise, complete the command normally.
1572 */
1573 uptodate = 1;
1574 if (rq->current_nr_sectors > 0) {
Bartlomiej Zolnierkiewiczb481b232007-12-24 15:23:43 +01001575 printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n",
1576 drive->name, __FUNCTION__,
1577 rq->current_nr_sectors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 uptodate = 0;
1579 }
1580 cdrom_end_request(drive, uptodate);
1581 return ide_stopped;
1582 }
1583
1584 /* Check that the drive is expecting to do the same thing we are. */
1585 if (cdrom_write_check_ireason(drive, len, ireason))
1586 return ide_stopped;
1587
1588 sectors_to_transfer = len / SECTOR_SIZE;
1589
1590 /*
1591 * now loop and write out the data
1592 */
1593 while (sectors_to_transfer > 0) {
1594 int this_transfer;
1595
1596 if (!rq->current_nr_sectors) {
Bartlomiej Zolnierkiewiczb481b232007-12-24 15:23:43 +01001597 printk(KERN_ERR "%s: %s: confused, missing data\n",
1598 drive->name, __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 break;
1600 }
1601
1602 /*
1603 * Figure out how many sectors we can transfer
1604 */
1605 this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors);
1606
1607 while (this_transfer > 0) {
1608 HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
1609 rq->buffer += SECTOR_SIZE;
1610 --rq->nr_sectors;
1611 --rq->current_nr_sectors;
1612 ++rq->sector;
1613 --this_transfer;
1614 --sectors_to_transfer;
1615 }
1616
1617 /*
1618 * current buffer complete, move on
1619 */
1620 if (rq->current_nr_sectors == 0 && rq->nr_sectors)
1621 cdrom_end_request(drive, 1);
1622 }
1623
1624 /* re-arm handler */
1625 ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);
1626 return ide_started;
1627}
1628
1629static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
1630{
1631 struct request *rq = HWGROUP(drive)->rq;
1632
1633#if 0 /* the immediate bit */
1634 rq->cmd[1] = 1 << 3;
1635#endif
1636 rq->timeout = ATAPI_WAIT_PC;
1637
1638 return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
1639}
1640
1641static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
1642{
1643 struct cdrom_info *info = drive->driver_data;
1644 struct gendisk *g = info->disk;
1645 unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
1646
1647 /*
1648 * writes *must* be hardware frame aligned
1649 */
1650 if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
1651 (rq->sector & (sectors_per_frame - 1))) {
1652 cdrom_end_request(drive, 0);
1653 return ide_stopped;
1654 }
1655
1656 /*
1657 * disk has become write protected
1658 */
1659 if (g->policy) {
1660 cdrom_end_request(drive, 0);
1661 return ide_stopped;
1662 }
1663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 info->nsectors_buffered = 0;
1665
1666 /* use dma, if possible. we don't need to check more, since we
1667 * know that the transfer is always (at least!) frame aligned */
1668 info->dma = drive->using_dma ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 info->devinfo.media_written = 1;
1671
1672 /* Start sending the write request to the drive. */
1673 return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
1674}
1675
1676static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
1677{
1678 struct request *rq = HWGROUP(drive)->rq;
1679
1680 if (!rq->timeout)
1681 rq->timeout = ATAPI_WAIT_PC;
1682
1683 return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
1684}
1685
1686static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
1687{
1688 struct cdrom_info *info = drive->driver_data;
1689
Jens Axboe4aff5e22006-08-10 08:44:47 +02001690 rq->cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
1692 info->dma = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
1694 /*
1695 * sg request
1696 */
1697 if (rq->bio) {
1698 int mask = drive->queue->dma_alignment;
1699 unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
1700
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 info->dma = drive->using_dma;
1702
1703 /*
1704 * check if dma is safe
Linus Torvalds5d9e4ea2005-05-27 07:36:17 -07001705 *
1706 * NOTE! The "len" and "addr" checks should possibly have
1707 * separate masks.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 */
Jens Axboe4e7c6812005-05-31 17:47:36 +02001709 if ((rq->data_len & 15) || (addr & mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 info->dma = 0;
1711 }
1712
1713 /* Start sending the command to the drive. */
1714 return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont);
1715}
1716
1717/****************************************************************************
1718 * cdrom driver request routine.
1719 */
1720static ide_startstop_t
1721ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
1722{
1723 ide_startstop_t action;
1724 struct cdrom_info *info = drive->driver_data;
1725
1726 if (blk_fs_request(rq)) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001727 if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 unsigned long elapsed = jiffies - info->start_seek;
1729 int stat = HWIF(drive)->INB(IDE_STATUS_REG);
1730
1731 if ((stat & SEEK_STAT) != SEEK_STAT) {
1732 if (elapsed < IDECD_SEEK_TIMEOUT) {
1733 ide_stall_queue(drive, IDECD_SEEK_TIMER);
1734 return ide_stopped;
1735 }
1736 printk (KERN_ERR "%s: DSC timeout\n", drive->name);
1737 }
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001738 info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 }
1740 if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
1741 action = cdrom_start_seek(drive, block);
1742 } else {
1743 if (rq_data_dir(rq) == READ)
1744 action = cdrom_start_read(drive, block);
1745 else
1746 action = cdrom_start_write(drive, rq);
1747 }
1748 info->last_block = block;
1749 return action;
Jens Axboecea28852006-10-12 15:08:45 +02001750 } else if (rq->cmd_type == REQ_TYPE_SENSE ||
1751 rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 return cdrom_do_packet_command(drive);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001753 } else if (blk_pc_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 return cdrom_do_block_pc(drive, rq);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001755 } else if (blk_special_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 /*
1757 * right now this can only be a reset...
1758 */
1759 cdrom_end_request(drive, 1);
1760 return ide_stopped;
1761 }
1762
1763 blk_dump_rq_flags(rq, "ide-cd bad flags");
1764 cdrom_end_request(drive, 0);
1765 return ide_stopped;
1766}
1767
1768
1769
1770/****************************************************************************
1771 * Ioctl handling.
1772 *
1773 * Routines which queue packet commands take as a final argument a pointer
1774 * to a request_sense struct. If execution of the command results
1775 * in an error with a CHECK CONDITION status, this structure will be filled
1776 * with the results of the subsequent request sense command. The pointer
1777 * can also be NULL, in which case no sense information is returned.
1778 */
1779
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780static
1781void msf_from_bcd (struct atapi_msf *msf)
1782{
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001783 msf->minute = BCD2BIN(msf->minute);
1784 msf->second = BCD2BIN(msf->second);
1785 msf->frame = BCD2BIN(msf->frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786}
1787
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788static inline
1789void lba_to_msf (int lba, byte *m, byte *s, byte *f)
1790{
1791 lba += CD_MSF_OFFSET;
1792 lba &= 0xffffff; /* negative lbas use only 24 bits */
1793 *m = lba / (CD_SECS * CD_FRAMES);
1794 lba %= (CD_SECS * CD_FRAMES);
1795 *s = lba / CD_FRAMES;
1796 *f = lba % CD_FRAMES;
1797}
1798
1799
1800static inline
1801int msf_to_lba (byte m, byte s, byte f)
1802{
1803 return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
1804}
1805
1806static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
1807{
1808 struct request req;
1809 struct cdrom_info *info = drive->driver_data;
1810 struct cdrom_device_info *cdi = &info->devinfo;
1811
1812 cdrom_prepare_request(drive, &req);
1813
1814 req.sense = sense;
1815 req.cmd[0] = GPCMD_TEST_UNIT_READY;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001816 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001818 /*
1819 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
1820 * switch CDs instead of supporting the LOAD_UNLOAD opcode.
1821 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 req.cmd[7] = cdi->sanyo_slot % 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
1824 return cdrom_queue_packet_command(drive, &req);
1825}
1826
1827
1828/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
1829static int
1830cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
1831{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001832 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 struct request_sense my_sense;
1834 struct request req;
1835 int stat;
1836
1837 if (sense == NULL)
1838 sense = &my_sense;
1839
1840 /* If the drive cannot lock the door, just pretend. */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001841 if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 stat = 0;
1843 } else {
1844 cdrom_prepare_request(drive, &req);
1845 req.sense = sense;
1846 req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
1847 req.cmd[4] = lockflag ? 1 : 0;
1848 stat = cdrom_queue_packet_command(drive, &req);
1849 }
1850
1851 /* If we got an illegal field error, the drive
1852 probably cannot lock the door. */
1853 if (stat != 0 &&
1854 sense->sense_key == ILLEGAL_REQUEST &&
1855 (sense->asc == 0x24 || sense->asc == 0x20)) {
1856 printk (KERN_ERR "%s: door locking not supported\n",
1857 drive->name);
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001858 cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 stat = 0;
1860 }
1861
1862 /* no medium, that's alright. */
1863 if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
1864 stat = 0;
1865
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001866 if (stat == 0) {
1867 if (lockflag)
1868 cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
1869 else
1870 cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
1871 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
1873 return stat;
1874}
1875
1876
1877/* Eject the disk if EJECTFLAG is 0.
1878 If EJECTFLAG is 1, try to reload the disk. */
1879static int cdrom_eject(ide_drive_t *drive, int ejectflag,
1880 struct request_sense *sense)
1881{
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001882 struct cdrom_info *cd = drive->driver_data;
1883 struct cdrom_device_info *cdi = &cd->devinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 struct request req;
1885 char loej = 0x02;
1886
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001887 if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 return -EDRIVE_CANT_DO_THIS;
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 /* reload fails on some drives, if the tray is locked */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001891 if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 return 0;
1893
1894 cdrom_prepare_request(drive, &req);
1895
1896 /* only tell drive to close tray if open, if it can do that */
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001897 if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 loej = 0;
1899
1900 req.sense = sense;
1901 req.cmd[0] = GPCMD_START_STOP_UNIT;
1902 req.cmd[4] = loej | (ejectflag != 0);
1903 return cdrom_queue_packet_command(drive, &req);
1904}
1905
1906static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
1907 unsigned long *sectors_per_frame,
1908 struct request_sense *sense)
1909{
1910 struct {
1911 __u32 lba;
1912 __u32 blocklen;
1913 } capbuf;
1914
1915 int stat;
1916 struct request req;
1917
1918 cdrom_prepare_request(drive, &req);
1919
1920 req.sense = sense;
1921 req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
1922 req.data = (char *)&capbuf;
1923 req.data_len = sizeof(capbuf);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001924 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925
1926 stat = cdrom_queue_packet_command(drive, &req);
1927 if (stat == 0) {
1928 *capacity = 1 + be32_to_cpu(capbuf.lba);
1929 *sectors_per_frame =
1930 be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
1931 }
1932
1933 return stat;
1934}
1935
1936static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
1937 int format, char *buf, int buflen,
1938 struct request_sense *sense)
1939{
1940 struct request req;
1941
1942 cdrom_prepare_request(drive, &req);
1943
1944 req.sense = sense;
1945 req.data = buf;
1946 req.data_len = buflen;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001947 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
1949 req.cmd[6] = trackno;
1950 req.cmd[7] = (buflen >> 8);
1951 req.cmd[8] = (buflen & 0xff);
1952 req.cmd[9] = (format << 6);
1953
1954 if (msf_flag)
1955 req.cmd[1] = 2;
1956
1957 return cdrom_queue_packet_command(drive, &req);
1958}
1959
1960
1961/* Try to read the entire TOC for the disk into our internal buffer. */
1962static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
1963{
1964 int stat, ntracks, i;
1965 struct cdrom_info *info = drive->driver_data;
1966 struct cdrom_device_info *cdi = &info->devinfo;
1967 struct atapi_toc *toc = info->toc;
1968 struct {
1969 struct atapi_toc_header hdr;
1970 struct atapi_toc_entry ent;
1971 } ms_tmp;
1972 long last_written;
1973 unsigned long sectors_per_frame = SECTORS_PER_FRAME;
1974
1975 if (toc == NULL) {
1976 /* Try to allocate space. */
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001977 toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 if (toc == NULL) {
1979 printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
1980 return -ENOMEM;
1981 }
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001982 info->toc = toc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 }
1984
1985 /* Check to see if the existing data is still valid.
1986 If it is, just return. */
1987 (void) cdrom_check_status(drive, sense);
1988
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001989 if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 return 0;
1991
1992 /* Try to get the total cdrom capacity and sector size. */
1993 stat = cdrom_read_capacity(drive, &toc->capacity, &sectors_per_frame,
1994 sense);
1995 if (stat)
1996 toc->capacity = 0x1fffff;
1997
1998 set_capacity(info->disk, toc->capacity * sectors_per_frame);
Alan Coxdbe217a2006-06-25 05:47:44 -07001999 /* Save a private copy of te TOC capacity for error handling */
2000 drive->probed_capacity = toc->capacity * sectors_per_frame;
2001
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 blk_queue_hardsect_size(drive->queue,
2003 sectors_per_frame << SECTOR_BITS);
2004
2005 /* First read just the header, so we know how long the TOC is. */
2006 stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
2007 sizeof(struct atapi_toc_header), sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002008 if (stat)
2009 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002011 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01002012 toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
2013 toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
2016 ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
2017 if (ntracks <= 0)
2018 return -EIO;
2019 if (ntracks > MAX_TRACKS)
2020 ntracks = MAX_TRACKS;
2021
2022 /* Now read the whole schmeer. */
2023 stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
2024 (char *)&toc->hdr,
2025 sizeof(struct atapi_toc_header) +
2026 (ntracks + 1) *
2027 sizeof(struct atapi_toc_entry), sense);
2028
2029 if (stat && toc->hdr.first_track > 1) {
2030 /* Cds with CDI tracks only don't have any TOC entries,
2031 despite of this the returned values are
2032 first_track == last_track = number of CDI tracks + 1,
2033 so that this case is indistinguishable from the same
2034 layout plus an additional audio track.
2035 If we get an error for the regular case, we assume
2036 a CDI without additional audio tracks. In this case
2037 the readable TOC is empty (CDI tracks are not included)
Jan Engelhardt96de0e22007-10-19 23:21:04 +02002038 and only holds the Leadout entry. Heiko Eißfeldt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 ntracks = 0;
2040 stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
2041 (char *)&toc->hdr,
2042 sizeof(struct atapi_toc_header) +
2043 (ntracks + 1) *
2044 sizeof(struct atapi_toc_entry),
2045 sense);
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01002046 if (stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 return stat;
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01002048
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002049 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01002050 toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
2051 toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01002052 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 toc->hdr.first_track = CDROM_LEADOUT;
2054 toc->hdr.last_track = CDROM_LEADOUT;
2055 }
2056 }
2057
2058 if (stat)
2059 return stat;
2060
2061 toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
2062
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002063 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01002064 toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
2065 toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01002068 for (i = 0; i <= ntracks; i++) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002069 if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
2070 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01002071 toc->ent[i].track = BCD2BIN(toc->ent[i].track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 msf_from_bcd(&toc->ent[i].addr.msf);
2073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
2075 toc->ent[i].addr.msf.second,
2076 toc->ent[i].addr.msf.frame);
2077 }
2078
2079 /* Read the multisession information. */
2080 if (toc->hdr.first_track != CDROM_LEADOUT) {
2081 /* Read the multisession information. */
2082 stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
2083 sizeof(ms_tmp), sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002084 if (stat)
2085 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086
2087 toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
2088 } else {
2089 ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
2090 toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
2091 }
2092
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002093 if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 /* Re-read multisession information using MSF format */
2095 stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
2096 sizeof(ms_tmp), sense);
2097 if (stat)
2098 return stat;
2099
2100 msf_from_bcd (&ms_tmp.ent.addr.msf);
2101 toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
2102 ms_tmp.ent.addr.msf.second,
2103 ms_tmp.ent.addr.msf.frame);
2104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
2106 toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
2107
2108 /* Now try to get the total cdrom capacity. */
2109 stat = cdrom_get_last_written(cdi, &last_written);
2110 if (!stat && (last_written > toc->capacity)) {
2111 toc->capacity = last_written;
2112 set_capacity(info->disk, toc->capacity * sectors_per_frame);
Alan Coxdbe217a2006-06-25 05:47:44 -07002113 drive->probed_capacity = toc->capacity * sectors_per_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 }
2115
2116 /* Remember that we've read this stuff. */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002117 info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
2119 return 0;
2120}
2121
2122
2123static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
2124 int buflen, struct request_sense *sense)
2125{
2126 struct request req;
2127
2128 cdrom_prepare_request(drive, &req);
2129
2130 req.sense = sense;
2131 req.data = buf;
2132 req.data_len = buflen;
2133 req.cmd[0] = GPCMD_READ_SUBCHANNEL;
2134 req.cmd[1] = 2; /* MSF addressing */
2135 req.cmd[2] = 0x40; /* request subQ data */
2136 req.cmd[3] = format;
2137 req.cmd[7] = (buflen >> 8);
2138 req.cmd[8] = (buflen & 0xff);
2139 return cdrom_queue_packet_command(drive, &req);
2140}
2141
2142/* ATAPI cdrom drives are free to select the speed you request or any slower
2143 rate :-( Requesting too fast a speed will _not_ produce an error. */
2144static int cdrom_select_speed(ide_drive_t *drive, int speed,
2145 struct request_sense *sense)
2146{
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002147 struct cdrom_info *cd = drive->driver_data;
2148 struct cdrom_device_info *cdi = &cd->devinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 struct request req;
2150 cdrom_prepare_request(drive, &req);
2151
2152 req.sense = sense;
2153 if (speed == 0)
2154 speed = 0xffff; /* set to max */
2155 else
2156 speed *= 177; /* Nx to kbytes/s */
2157
2158 req.cmd[0] = GPCMD_SET_SPEED;
2159 /* Read Drive speed in kbytes/second MSB */
2160 req.cmd[2] = (speed >> 8) & 0xff;
2161 /* Read Drive speed in kbytes/second LSB */
2162 req.cmd[3] = speed & 0xff;
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002163 if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
2164 (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 /* Write Drive speed in kbytes/second MSB */
2166 req.cmd[4] = (speed >> 8) & 0xff;
2167 /* Write Drive speed in kbytes/second LSB */
2168 req.cmd[5] = speed & 0xff;
2169 }
2170
2171 return cdrom_queue_packet_command(drive, &req);
2172}
2173
2174static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
2175{
2176 struct request_sense sense;
2177 struct request req;
2178
2179 cdrom_prepare_request(drive, &req);
2180
2181 req.sense = &sense;
2182 req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
2183 lba_to_msf(lba_start, &req.cmd[3], &req.cmd[4], &req.cmd[5]);
2184 lba_to_msf(lba_end-1, &req.cmd[6], &req.cmd[7], &req.cmd[8]);
2185
2186 return cdrom_queue_packet_command(drive, &req);
2187}
2188
2189static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
2190 struct atapi_toc_entry **ent)
2191{
2192 struct cdrom_info *info = drive->driver_data;
2193 struct atapi_toc *toc = info->toc;
2194 int ntracks;
2195
2196 /*
2197 * don't serve cached data, if the toc isn't valid
2198 */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002199 if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 return -EINVAL;
2201
2202 /* Check validity of requested track number. */
2203 ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
2204 if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
2205 if (track == CDROM_LEADOUT)
2206 *ent = &toc->ent[ntracks];
2207 else if (track < toc->hdr.first_track ||
2208 track > toc->hdr.last_track)
2209 return -EINVAL;
2210 else
2211 *ent = &toc->ent[track - toc->hdr.first_track];
2212
2213 return 0;
2214}
2215
2216/* the generic packet interface to cdrom.c */
2217static int ide_cdrom_packet(struct cdrom_device_info *cdi,
2218 struct packet_command *cgc)
2219{
2220 struct request req;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002221 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
2223 if (cgc->timeout <= 0)
2224 cgc->timeout = ATAPI_WAIT_PC;
2225
2226 /* here we queue the commands from the uniform CD-ROM
2227 layer. the packet must be complete, as we do not
2228 touch it at all. */
2229 cdrom_prepare_request(drive, &req);
2230 memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
2231 if (cgc->sense)
2232 memset(cgc->sense, 0, sizeof(struct request_sense));
2233 req.data = cgc->buffer;
2234 req.data_len = cgc->buflen;
2235 req.timeout = cgc->timeout;
2236
2237 if (cgc->quiet)
Jens Axboe4aff5e22006-08-10 08:44:47 +02002238 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
2240 req.sense = cgc->sense;
2241 cgc->stat = cdrom_queue_packet_command(drive, &req);
2242 if (!cgc->stat)
2243 cgc->buflen -= req.data_len;
2244 return cgc->stat;
2245}
2246
2247static
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
2249 unsigned int cmd, void *arg)
2250
2251{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002252 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 struct cdrom_info *info = drive->driver_data;
2254 int stat;
2255
2256 switch (cmd) {
2257 /*
2258 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
2259 * atapi doesn't support it
2260 */
2261 case CDROMPLAYTRKIND: {
2262 unsigned long lba_start, lba_end;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002263 struct cdrom_ti *ti = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 struct atapi_toc_entry *first_toc, *last_toc;
2265
2266 stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
2267 if (stat)
2268 return stat;
2269
2270 stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
2271 if (stat)
2272 return stat;
2273
2274 if (ti->cdti_trk1 != CDROM_LEADOUT)
2275 ++last_toc;
2276 lba_start = first_toc->addr.lba;
2277 lba_end = last_toc->addr.lba;
2278
2279 if (lba_end <= lba_start)
2280 return -EINVAL;
2281
2282 return cdrom_play_audio(drive, lba_start, lba_end);
2283 }
2284
2285 case CDROMREADTOCHDR: {
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002286 struct cdrom_tochdr *tochdr = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 struct atapi_toc *toc;
2288
2289 /* Make sure our saved TOC is valid. */
2290 stat = cdrom_read_toc(drive, NULL);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002291 if (stat)
2292 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
2294 toc = info->toc;
2295 tochdr->cdth_trk0 = toc->hdr.first_track;
2296 tochdr->cdth_trk1 = toc->hdr.last_track;
2297
2298 return 0;
2299 }
2300
2301 case CDROMREADTOCENTRY: {
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002302 struct cdrom_tocentry *tocentry = arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 struct atapi_toc_entry *toce;
2304
2305 stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002306 if (stat)
2307 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 tocentry->cdte_ctrl = toce->control;
2310 tocentry->cdte_adr = toce->adr;
2311 if (tocentry->cdte_format == CDROM_MSF) {
2312 lba_to_msf (toce->addr.lba,
2313 &tocentry->cdte_addr.msf.minute,
2314 &tocentry->cdte_addr.msf.second,
2315 &tocentry->cdte_addr.msf.frame);
2316 } else
2317 tocentry->cdte_addr.lba = toce->addr.lba;
2318
2319 return 0;
2320 }
2321
2322 default:
2323 return -EINVAL;
2324 }
2325}
2326
2327static
2328int ide_cdrom_reset (struct cdrom_device_info *cdi)
2329{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002330 ide_drive_t *drive = cdi->handle;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01002331 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 struct request_sense sense;
2333 struct request req;
2334 int ret;
2335
2336 cdrom_prepare_request(drive, &req);
Jens Axboe4aff5e22006-08-10 08:44:47 +02002337 req.cmd_type = REQ_TYPE_SPECIAL;
2338 req.cmd_flags = REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339 ret = ide_do_drive_cmd(drive, &req, ide_wait);
2340
2341 /*
2342 * A reset will unlock the door. If it was previously locked,
2343 * lock it again.
2344 */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002345 if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 (void) cdrom_lockdoor(drive, 1, &sense);
2347
2348 return ret;
2349}
2350
2351
2352static
2353int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
2354{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002355 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 struct request_sense sense;
2357
2358 if (position) {
2359 int stat = cdrom_lockdoor(drive, 0, &sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002360 if (stat)
2361 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 }
2363
2364 return cdrom_eject(drive, !position, &sense);
2365}
2366
2367static
2368int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
2369{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002370 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 return cdrom_lockdoor(drive, lock, NULL);
2372}
2373
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002374static int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
Eric Piel9235e682005-06-23 00:10:29 -07002375{
2376 struct cdrom_info *info = drive->driver_data;
2377 struct cdrom_device_info *cdi = &info->devinfo;
2378 struct packet_command cgc;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002379 int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
Eric Piel9235e682005-06-23 00:10:29 -07002380
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002381 if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002382 size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
Eric Piel9235e682005-06-23 00:10:29 -07002383
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002384 init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
Eric Piel9235e682005-06-23 00:10:29 -07002385 do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
2386 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
2387 if (!stat)
2388 break;
2389 } while (--attempts);
2390 return stat;
2391}
2392
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002393static void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
Eric Piel9235e682005-06-23 00:10:29 -07002394{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002395 struct cdrom_info *cd = drive->driver_data;
Bartlomiej Zolnierkiewicz481c8c62008-02-01 23:09:20 +01002396 u16 curspeed, maxspeed;
2397
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002398 curspeed = *(u16 *)&buf[8 + 14];
2399 maxspeed = *(u16 *)&buf[8 + 8];
2400
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002401 if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002402 curspeed = le16_to_cpu(curspeed);
2403 maxspeed = le16_to_cpu(maxspeed);
Eric Piel9235e682005-06-23 00:10:29 -07002404 } else {
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002405 curspeed = be16_to_cpu(curspeed);
2406 maxspeed = be16_to_cpu(maxspeed);
Eric Piel9235e682005-06-23 00:10:29 -07002407 }
Bartlomiej Zolnierkiewicz481c8c62008-02-01 23:09:20 +01002408
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002409 cd->current_speed = (curspeed + (176/2)) / 176;
2410 cd->max_speed = (maxspeed + (176/2)) / 176;
Eric Piel9235e682005-06-23 00:10:29 -07002411}
2412
2413static
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
2415{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002416 ide_drive_t *drive = cdi->handle;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01002417 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 struct request_sense sense;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002419 u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 int stat;
2421
2422 if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
2423 return stat;
2424
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002425 if (!ide_cdrom_get_capabilities(drive, buf)) {
2426 ide_cdrom_update_speed(drive, buf);
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002427 cdi->speed = cd->current_speed;
Eric Piel9235e682005-06-23 00:10:29 -07002428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 return 0;
2430}
2431
2432/*
2433 * add logic to try GET_EVENT command first to check for media and tray
2434 * status. this should be supported by newer cd-r/w and all DVD etc
2435 * drives
2436 */
2437static
2438int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
2439{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002440 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 struct media_event_desc med;
2442 struct request_sense sense;
2443 int stat;
2444
2445 if (slot_nr != CDSL_CURRENT)
2446 return -EINVAL;
2447
2448 stat = cdrom_check_status(drive, &sense);
2449 if (!stat || sense.sense_key == UNIT_ATTENTION)
2450 return CDS_DISC_OK;
2451
2452 if (!cdrom_get_media_event(cdi, &med)) {
2453 if (med.media_present)
2454 return CDS_DISC_OK;
2455 else if (med.door_open)
2456 return CDS_TRAY_OPEN;
2457 else
2458 return CDS_NO_DISC;
2459 }
2460
2461 if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
2462 return CDS_DISC_OK;
2463
2464 /*
2465 * If not using Mt Fuji extended media tray reports,
2466 * just return TRAY_OPEN since ATAPI doesn't provide
2467 * any other way to detect this...
2468 */
2469 if (sense.sense_key == NOT_READY) {
Alan Coxdbe217a2006-06-25 05:47:44 -07002470 if (sense.asc == 0x3a && sense.ascq == 1)
2471 return CDS_NO_DISC;
2472 else
2473 return CDS_TRAY_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 return CDS_DRIVE_NOT_READY;
2476}
2477
2478static
2479int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
2480 struct cdrom_multisession *ms_info)
2481{
2482 struct atapi_toc *toc;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002483 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 struct cdrom_info *info = drive->driver_data;
2485 struct request_sense sense;
2486 int ret;
2487
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002488 if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || info->toc == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 if ((ret = cdrom_read_toc(drive, &sense)))
2490 return ret;
2491
2492 toc = info->toc;
2493 ms_info->addr.lba = toc->last_session_lba;
2494 ms_info->xa_flag = toc->xa_flag;
2495
2496 return 0;
2497}
2498
2499static
2500int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
2501 struct cdrom_mcn *mcn_info)
2502{
2503 int stat;
2504 char mcnbuf[24];
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002505 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506
2507/* get MCN */
2508 if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
2509 return stat;
2510
2511 memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
2512 sizeof (mcn_info->medium_catalog_number)-1);
2513 mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
2514 = '\0';
2515
2516 return 0;
2517}
2518
2519
2520
2521/****************************************************************************
2522 * Other driver requests (open, close, check media change).
2523 */
2524
2525static
2526int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
2527 int slot_nr)
2528{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002529 ide_drive_t *drive = cdi->handle;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01002530 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 int retval;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01002532
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 if (slot_nr == CDSL_CURRENT) {
2534 (void) cdrom_check_status(drive, NULL);
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002535 retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
2536 cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 return retval;
2538 } else {
2539 return -EINVAL;
2540 }
2541}
2542
2543
2544static
2545int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
2546{
2547 return 0;
2548}
2549
2550/*
2551 * Close down the device. Invalidate all cached blocks.
2552 */
2553
2554static
2555void ide_cdrom_release_real (struct cdrom_device_info *cdi)
2556{
2557 ide_drive_t *drive = cdi->handle;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01002558 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
2560 if (!cdi->use_count)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002561 cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562}
2563
Bartlomiej Zolnierkiewicz20e7f7e2008-02-01 23:09:20 +01002564#define IDE_CD_CAPABILITIES \
2565 (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
2566 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
2567 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
2568 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
2569 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571static struct cdrom_device_ops ide_cdrom_dops = {
2572 .open = ide_cdrom_open_real,
2573 .release = ide_cdrom_release_real,
2574 .drive_status = ide_cdrom_drive_status,
2575 .media_changed = ide_cdrom_check_media_change_real,
2576 .tray_move = ide_cdrom_tray_move,
2577 .lock_door = ide_cdrom_lock_door,
2578 .select_speed = ide_cdrom_select_speed,
2579 .get_last_session = ide_cdrom_get_last_session,
2580 .get_mcn = ide_cdrom_get_mcn,
2581 .reset = ide_cdrom_reset,
2582 .audio_ioctl = ide_cdrom_audio_ioctl,
Bartlomiej Zolnierkiewicz20e7f7e2008-02-01 23:09:20 +01002583 .capability = IDE_CD_CAPABILITIES,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 .generic_packet = ide_cdrom_packet,
2585};
2586
2587static int ide_cdrom_register (ide_drive_t *drive, int nslots)
2588{
2589 struct cdrom_info *info = drive->driver_data;
2590 struct cdrom_device_info *devinfo = &info->devinfo;
2591
2592 devinfo->ops = &ide_cdrom_dops;
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002593 devinfo->speed = info->current_speed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 devinfo->capacity = nslots;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002595 devinfo->handle = drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 strcpy(devinfo->name, drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002598 if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
Bartlomiej Zolnierkiewicz3cbd8142007-12-24 15:23:43 +01002599 devinfo->mask |= CDC_SELECT_SPEED;
2600
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 devinfo->disk = info->disk;
2602 return register_cdrom(devinfo);
2603}
2604
2605static
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606int ide_cdrom_probe_capabilities (ide_drive_t *drive)
2607{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002608 struct cdrom_info *cd = drive->driver_data;
2609 struct cdrom_device_info *cdi = &cd->devinfo;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002610 u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
2611 mechtype_t mechtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 int nslots = 1;
2613
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002614 cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
2615 CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
2616 CDC_MO_DRIVE | CDC_RAM);
2617
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 if (drive->media == ide_optical) {
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002619 cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
2621 return nslots;
2622 }
2623
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002624 if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002625 cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002626 cdi->mask &= ~CDC_PLAY_AUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 return nslots;
2628 }
2629
2630 /*
2631 * we have to cheat a little here. the packet will eventually
2632 * be queued with ide_cdrom_packet(), which extracts the
2633 * drive from cdi->handle. Since this device hasn't been
2634 * registered with the Uniform layer yet, it can't do this.
2635 * Same goes for cdi->ops.
2636 */
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002637 cdi->handle = drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 cdi->ops = &ide_cdrom_dops;
2639
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002640 if (ide_cdrom_get_capabilities(drive, buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 return 0;
2642
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002643 if ((buf[8 + 6] & 0x01) == 0)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002644 cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002645 if (buf[8 + 6] & 0x08)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002646 cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002647 if (buf[8 + 3] & 0x01)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002648 cdi->mask &= ~CDC_CD_R;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002649 if (buf[8 + 3] & 0x02)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002650 cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002651 if (buf[8 + 2] & 0x38)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002652 cdi->mask &= ~CDC_DVD;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002653 if (buf[8 + 3] & 0x20)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002654 cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002655 if (buf[8 + 3] & 0x10)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002656 cdi->mask &= ~CDC_DVD_R;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002657 if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002658 cdi->mask &= ~CDC_PLAY_AUDIO;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002659
2660 mechtype = buf[8 + 6] >> 5;
2661 if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002662 cdi->mask |= CDC_CLOSE_TRAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 if (cdi->sanyo_slot > 0) {
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002665 cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 nslots = 3;
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01002667 } else if (mechtype == mechtype_individual_changer ||
2668 mechtype == mechtype_cartridge_changer) {
Bartlomiej Zolnierkiewicz2609d062008-02-01 23:09:19 +01002669 nslots = cdrom_number_of_slots(cdi);
2670 if (nslots > 1)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002671 cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 }
2673
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002674 ide_cdrom_update_speed(drive, buf);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002675
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 printk(KERN_INFO "%s: ATAPI", drive->name);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002677
2678 /* don't print speed if the drive reported 0 */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002679 if (cd->max_speed)
2680 printk(KERN_CONT " %dX", cd->max_speed);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002681
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002682 printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002684 if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
2685 printk(KERN_CONT " DVD%s%s",
2686 (cdi->mask & CDC_DVD_R) ? "" : "-R",
2687 (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002689 if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
2690 printk(KERN_CONT " CD%s%s",
2691 (cdi->mask & CDC_CD_R) ? "" : "-R",
2692 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002694 if ((cdi->mask & CDC_SELECT_DISC) == 0)
2695 printk(KERN_CONT " changer w/%d slots", nslots);
2696 else
2697 printk(KERN_CONT " drive");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002699 printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700
2701 return nslots;
2702}
2703
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002704#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705static void ide_cdrom_add_settings(ide_drive_t *drive)
2706{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02002707 ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002709#else
2710static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
2711#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712
2713/*
2714 * standard prep_rq_fn that builds 10 byte cmds
2715 */
Jens Axboe165125e2007-07-24 09:28:11 +02002716static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717{
2718 int hard_sect = queue_hardsect_size(q);
2719 long block = (long)rq->hard_sector / (hard_sect >> 9);
2720 unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
2721
2722 memset(rq->cmd, 0, sizeof(rq->cmd));
2723
2724 if (rq_data_dir(rq) == READ)
2725 rq->cmd[0] = GPCMD_READ_10;
2726 else
2727 rq->cmd[0] = GPCMD_WRITE_10;
2728
2729 /*
2730 * fill in lba
2731 */
2732 rq->cmd[2] = (block >> 24) & 0xff;
2733 rq->cmd[3] = (block >> 16) & 0xff;
2734 rq->cmd[4] = (block >> 8) & 0xff;
2735 rq->cmd[5] = block & 0xff;
2736
2737 /*
2738 * and transfer length
2739 */
2740 rq->cmd[7] = (blocks >> 8) & 0xff;
2741 rq->cmd[8] = blocks & 0xff;
2742 rq->cmd_len = 10;
2743 return BLKPREP_OK;
2744}
2745
2746/*
2747 * Most of the SCSI commands are supported directly by ATAPI devices.
2748 * This transform handles the few exceptions.
2749 */
2750static int ide_cdrom_prep_pc(struct request *rq)
2751{
2752 u8 *c = rq->cmd;
2753
2754 /*
2755 * Transform 6-byte read/write commands to the 10-byte version
2756 */
2757 if (c[0] == READ_6 || c[0] == WRITE_6) {
2758 c[8] = c[4];
2759 c[5] = c[3];
2760 c[4] = c[2];
2761 c[3] = c[1] & 0x1f;
2762 c[2] = 0;
2763 c[1] &= 0xe0;
2764 c[0] += (READ_10 - READ_6);
2765 rq->cmd_len = 10;
2766 return BLKPREP_OK;
2767 }
2768
2769 /*
2770 * it's silly to pretend we understand 6-byte sense commands, just
2771 * reject with ILLEGAL_REQUEST and the caller should take the
2772 * appropriate action
2773 */
2774 if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
2775 rq->errors = ILLEGAL_REQUEST;
2776 return BLKPREP_KILL;
2777 }
2778
2779 return BLKPREP_OK;
2780}
2781
Jens Axboe165125e2007-07-24 09:28:11 +02002782static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783{
Jens Axboe4aff5e22006-08-10 08:44:47 +02002784 if (blk_fs_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 return ide_cdrom_prep_fs(q, rq);
Jens Axboe4aff5e22006-08-10 08:44:47 +02002786 else if (blk_pc_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 return ide_cdrom_prep_pc(rq);
2788
2789 return 0;
2790}
2791
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002792struct cd_list_entry {
2793 const char *id_model;
2794 const char *id_firmware;
2795 unsigned int cd_flags;
2796};
2797
2798static const struct cd_list_entry ide_cd_quirks_list[] = {
2799 /* Limit transfer size per interrupt. */
2800 { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
2801 { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
2802 /* SCR-3231 doesn't support the SET_CD_SPEED command. */
2803 { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
2804 /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
2805 { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
2806 IDE_CD_FLAG_PRE_ATAPI12, },
2807 /* Vertos 300, some versions of this drive like to talk BCD. */
2808 { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
2809 /* Vertos 600 ESD. */
2810 { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
2811 /*
2812 * Sanyo 3 CD changer uses a non-standard command for CD changing
2813 * (by default standard ATAPI support for CD changers is used).
2814 */
2815 { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
2816 { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
2817 { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
2818 /* Stingray 8X CD-ROM. */
2819 { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
2820 /*
2821 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
2822 * mode sense page capabilities size, but older drives break.
2823 */
2824 { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
2825 { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
2826 /* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
2827 { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
2828 /*
2829 * Some drives used by Apple don't advertise audio play
2830 * but they do support reading TOC & audio datas.
2831 */
2832 { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2833 { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2834 { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2835 { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2836 { NULL, NULL, 0 }
2837};
2838
2839static unsigned int ide_cd_flags(struct hd_driveid *id)
2840{
2841 const struct cd_list_entry *cle = ide_cd_quirks_list;
2842
2843 while (cle->id_model) {
2844 if (strcmp(cle->id_model, id->model) == 0 &&
2845 (cle->id_firmware == NULL ||
2846 strstr(id->fw_rev, cle->id_firmware)))
2847 return cle->cd_flags;
2848 cle++;
2849 }
2850
2851 return 0;
2852}
2853
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854static
2855int ide_cdrom_setup (ide_drive_t *drive)
2856{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002857 struct cdrom_info *cd = drive->driver_data;
2858 struct cdrom_device_info *cdi = &cd->devinfo;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002859 struct hd_driveid *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 int nslots;
2861
2862 blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
2863 blk_queue_dma_alignment(drive->queue, 31);
2864 drive->queue->unplug_delay = (1 * HZ) / 1000;
2865 if (!drive->queue->unplug_delay)
2866 drive->queue->unplug_delay = 1;
2867
2868 drive->special.all = 0;
2869
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002870 cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
2871 ide_cd_flags(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002873 if ((id->config & 0x0060) == 0x20)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002874 cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
Bartlomiej Zolnierkiewiczb8d25de2008-02-01 23:09:19 +01002875
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002876 if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
2877 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002878 cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
2879 IDE_CD_FLAG_TOCADDR_AS_BCD);
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002880 else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
2881 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002882 cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002883 else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
2884 cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 nslots = ide_cdrom_probe_capabilities (drive);
2887
2888 /*
2889 * set correct block size
2890 */
2891 blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
2892
2893 if (drive->autotune == IDE_TUNE_DEFAULT ||
2894 drive->autotune == IDE_TUNE_AUTO)
2895 drive->dsc_overlap = (drive->next != drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
2897 if (ide_cdrom_register(drive, nslots)) {
2898 printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002899 cd->devinfo.handle = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 return 1;
2901 }
2902 ide_cdrom_add_settings(drive);
2903 return 0;
2904}
2905
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +02002906#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907static
2908sector_t ide_cdrom_capacity (ide_drive_t *drive)
2909{
2910 unsigned long capacity, sectors_per_frame;
2911
2912 if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
2913 return 0;
2914
2915 return capacity * sectors_per_frame;
2916}
Amos Waterlandd97b32142005-10-30 15:02:10 -08002917#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918
Russell King4031bbe2006-01-06 11:41:00 +00002919static void ide_cd_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920{
2921 struct cdrom_info *info = drive->driver_data;
2922
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002923 ide_proc_unregister_driver(drive, info->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924
2925 del_gendisk(info->disk);
2926
2927 ide_cd_put(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928}
2929
2930static void ide_cd_release(struct kref *kref)
2931{
2932 struct cdrom_info *info = to_ide_cd(kref);
2933 struct cdrom_device_info *devinfo = &info->devinfo;
2934 ide_drive_t *drive = info->drive;
2935 struct gendisk *g = info->disk;
2936
Jesper Juhl6044ec82005-11-07 01:01:32 -08002937 kfree(info->buffer);
2938 kfree(info->toc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 if (devinfo->handle == drive && unregister_cdrom(devinfo))
2940 printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
2941 "driver.\n", __FUNCTION__, drive->name);
2942 drive->dsc_overlap = 0;
2943 drive->driver_data = NULL;
2944 blk_queue_prep_rq(drive->queue, NULL);
2945 g->private_data = NULL;
2946 put_disk(g);
2947 kfree(info);
2948}
2949
Russell King4031bbe2006-01-06 11:41:00 +00002950static int ide_cd_probe(ide_drive_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +02002952#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953static int proc_idecd_read_capacity
2954 (char *page, char **start, off_t off, int count, int *eof, void *data)
2955{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002956 ide_drive_t *drive = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 int len;
2958
2959 len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
2960 PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
2961}
2962
2963static ide_proc_entry_t idecd_proc[] = {
2964 { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
2965 { NULL, 0, NULL, NULL }
2966};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967#endif
2968
2969static ide_driver_t ide_cdrom_driver = {
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002970 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +01002971 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002972 .name = "ide-cdrom",
2973 .bus = &ide_bus_type,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002974 },
Russell King4031bbe2006-01-06 11:41:00 +00002975 .probe = ide_cd_probe,
2976 .remove = ide_cd_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 .version = IDECD_VERSION,
2978 .media = ide_cdrom,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 .supports_dsc_overlap = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 .do_request = ide_do_rw_cdrom,
2981 .end_request = ide_end_request,
2982 .error = __ide_error,
2983 .abort = __ide_abort,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002984#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 .proc = idecd_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002986#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987};
2988
2989static int idecd_open(struct inode * inode, struct file * file)
2990{
2991 struct gendisk *disk = inode->i_bdev->bd_disk;
2992 struct cdrom_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 int rc = -ENOMEM;
2994
2995 if (!(info = ide_cd_get(disk)))
2996 return -ENXIO;
2997
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 if (!info->buffer)
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01002999 info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
3000
3001 if (info->buffer)
3002 rc = cdrom_open(&info->devinfo, inode, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
3004 if (rc < 0)
3005 ide_cd_put(info);
3006
3007 return rc;
3008}
3009
3010static int idecd_release(struct inode * inode, struct file * file)
3011{
3012 struct gendisk *disk = inode->i_bdev->bd_disk;
3013 struct cdrom_info *info = ide_cd_g(disk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
3015 cdrom_release (&info->devinfo, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016
3017 ide_cd_put(info);
3018
3019 return 0;
3020}
3021
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08003022static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg)
3023{
3024 struct packet_command cgc;
3025 char buffer[16];
3026 int stat;
3027 char spindown;
3028
3029 if (copy_from_user(&spindown, (void __user *)arg, sizeof(char)))
3030 return -EFAULT;
3031
3032 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
3033
3034 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
3035 if (stat)
3036 return stat;
3037
3038 buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
3039 return cdrom_mode_select(cdi, &cgc);
3040}
3041
3042static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
3043{
3044 struct packet_command cgc;
3045 char buffer[16];
3046 int stat;
3047 char spindown;
3048
3049 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
3050
3051 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
3052 if (stat)
3053 return stat;
3054
3055 spindown = buffer[11] & 0x0f;
3056 if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
3057 return -EFAULT;
3058 return 0;
3059}
3060
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061static int idecd_ioctl (struct inode *inode, struct file *file,
3062 unsigned int cmd, unsigned long arg)
3063{
3064 struct block_device *bdev = inode->i_bdev;
3065 struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
3066 int err;
3067
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08003068 switch (cmd) {
3069 case CDROMSETSPINDOWN:
3070 return idecd_set_spindown(&info->devinfo, arg);
3071 case CDROMGETSPINDOWN:
3072 return idecd_get_spindown(&info->devinfo, arg);
3073 default:
3074 break;
3075 }
3076
3077 err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 if (err == -EINVAL)
3079 err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
3080
3081 return err;
3082}
3083
3084static int idecd_media_changed(struct gendisk *disk)
3085{
3086 struct cdrom_info *info = ide_cd_g(disk);
3087 return cdrom_media_changed(&info->devinfo);
3088}
3089
3090static int idecd_revalidate_disk(struct gendisk *disk)
3091{
3092 struct cdrom_info *info = ide_cd_g(disk);
3093 struct request_sense sense;
3094 cdrom_read_toc(info->drive, &sense);
3095 return 0;
3096}
3097
3098static struct block_device_operations idecd_ops = {
3099 .owner = THIS_MODULE,
3100 .open = idecd_open,
3101 .release = idecd_release,
3102 .ioctl = idecd_ioctl,
3103 .media_changed = idecd_media_changed,
3104 .revalidate_disk= idecd_revalidate_disk
3105};
3106
3107/* options */
3108static char *ignore = NULL;
3109
3110module_param(ignore, charp, 0400);
3111MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
3112
Russell King4031bbe2006-01-06 11:41:00 +00003113static int ide_cd_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114{
3115 struct cdrom_info *info;
3116 struct gendisk *g;
3117 struct request_sense sense;
3118
3119 if (!strstr("ide-cdrom", drive->driver_req))
3120 goto failed;
3121 if (!drive->present)
3122 goto failed;
3123 if (drive->media != ide_cdrom && drive->media != ide_optical)
3124 goto failed;
3125 /* skip drives that we were told to ignore */
3126 if (ignore != NULL) {
3127 if (strstr(ignore, drive->name)) {
3128 printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name);
3129 goto failed;
3130 }
3131 }
3132 if (drive->scsi) {
3133 printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
3134 goto failed;
3135 }
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08003136 info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 if (info == NULL) {
3138 printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
3139 goto failed;
3140 }
3141
3142 g = alloc_disk(1 << PARTN_BITS);
3143 if (!g)
3144 goto out_free_cd;
3145
3146 ide_init_disk(g, drive);
3147
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02003148 ide_proc_register_driver(drive, &ide_cdrom_driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02003149
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 kref_init(&info->kref);
3151
3152 info->drive = drive;
3153 info->driver = &ide_cdrom_driver;
3154 info->disk = g;
3155
3156 g->private_data = &info->driver;
3157
3158 drive->driver_data = info;
3159
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 g->minors = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 g->driverfs_dev = &drive->gendev;
3162 g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
3163 if (ide_cdrom_setup(drive)) {
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02003164 ide_proc_unregister_driver(drive, &ide_cdrom_driver);
Bartlomiej Zolnierkiewicz05017db2007-12-24 15:23:43 +01003165 ide_cd_release(&info->kref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 goto failed;
3167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168
3169 cdrom_read_toc(drive, &sense);
3170 g->fops = &idecd_ops;
3171 g->flags |= GENHD_FL_REMOVABLE;
3172 add_disk(g);
3173 return 0;
3174
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175out_free_cd:
3176 kfree(info);
3177failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02003178 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179}
3180
3181static void __exit ide_cdrom_exit(void)
3182{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02003183 driver_unregister(&ide_cdrom_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184}
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01003185
3186static int __init ide_cdrom_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02003188 return driver_register(&ide_cdrom_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189}
3190
Kay Sievers263756e2005-12-12 18:03:44 +01003191MODULE_ALIAS("ide:*m-cdrom*");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192module_init(ide_cdrom_init);
3193module_exit(ide_cdrom_exit);
3194MODULE_LICENSE("GPL");