blob: 3a8e8eb61e291f1ed412501a8078c1fc10a49ccc [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Bartlomiej Zolnierkiewicz3bb46632008-02-01 23:09:28 +01002 * ATAPI CD-ROM driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Bartlomiej Zolnierkiewicz59bca8c2008-02-01 23:09:33 +01004 * Copyright (C) 1994-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 * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * May be copied or modified under the terms of the GNU General Public
10 * License. See linux/COPYING for more information.
11 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 * 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
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +020016 * 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 * 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 *
Bartlomiej Zolnierkiewicz03553352008-02-01 23:09:18 +010022 * For historical changelog please see:
23 * Documentation/ide/ChangeLog.ide-cd.1994-2004
24 */
25
Bartlomiej Zolnierkiewicz3bb46632008-02-01 23:09:28 +010026#define IDECD_VERSION "5.00"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
29#include <linux/types.h>
30#include <linux/kernel.h>
31#include <linux/delay.h>
32#include <linux/timer.h>
33#include <linux/slab.h>
34#include <linux/interrupt.h>
35#include <linux/errno.h>
36#include <linux/cdrom.h>
37#include <linux/ide.h>
38#include <linux/completion.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080039#include <linux/mutex.h>
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +010040#include <linux/bcd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
43
44#include <asm/irq.h>
45#include <asm/io.h>
46#include <asm/byteorder.h>
47#include <asm/uaccess.h>
48#include <asm/unaligned.h>
49
50#include "ide-cd.h"
51
Arjan van de Vencf8b8972006-03-23 03:00:45 -080052static DEFINE_MUTEX(idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +020054#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#define ide_cd_g(disk) \
57 container_of((disk)->private_data, struct cdrom_info, driver)
58
59static struct cdrom_info *ide_cd_get(struct gendisk *disk)
60{
61 struct cdrom_info *cd = NULL;
62
Arjan van de Vencf8b8972006-03-23 03:00:45 -080063 mutex_lock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 cd = ide_cd_g(disk);
65 if (cd)
66 kref_get(&cd->kref);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080067 mutex_unlock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 return cd;
69}
70
71static void ide_cd_release(struct kref *);
72
73static void ide_cd_put(struct cdrom_info *cd)
74{
Arjan van de Vencf8b8972006-03-23 03:00:45 -080075 mutex_lock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 kref_put(&cd->kref, ide_cd_release);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080077 mutex_unlock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078}
79
80/****************************************************************************
81 * Generic packet command support and error handling routines.
82 */
83
84/* Mark that we've seen a media change, and invalidate our internal
85 buffers. */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +020086static void cdrom_saw_media_change(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087{
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +010088 struct cdrom_info *cd = drive->driver_data;
89
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +010090 cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
91 cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092}
93
94static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
95 struct request_sense *sense)
96{
97 int log = 0;
98
Jens Axboe4aff5e22006-08-10 08:44:47 +020099 if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 return 0;
101
102 switch (sense->sense_key) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200103 case NO_SENSE:
104 case RECOVERED_ERROR:
105 break;
106 case NOT_READY:
107 /*
108 * don't care about tray state messages for
109 * e.g. capacity commands or in-progress or
110 * becoming ready
111 */
112 if (sense->asc == 0x3a || sense->asc == 0x04)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 break;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200114 log = 1;
115 break;
116 case ILLEGAL_REQUEST:
117 /*
118 * don't log START_STOP unit with LoEj set, since
119 * we cannot reliably check if drive can auto-close
120 */
121 if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 break;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200123 log = 1;
124 break;
125 case UNIT_ATTENTION:
126 /*
127 * Make good and sure we've seen this potential media
128 * change. Some drives (i.e. Creative) fail to present
129 * the correct sense key in the error register.
130 */
131 cdrom_saw_media_change(drive);
132 break;
133 default:
134 log = 1;
135 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 }
137 return log;
138}
139
140static
141void cdrom_analyze_sense_data(ide_drive_t *drive,
142 struct request *failed_command,
143 struct request_sense *sense)
144{
Alan Coxdbe217a2006-06-25 05:47:44 -0700145 unsigned long sector;
146 unsigned long bio_sectors;
147 unsigned long valid;
148 struct cdrom_info *info = drive->driver_data;
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 if (!cdrom_log_sense(drive, failed_command, sense))
151 return;
152
153 /*
154 * If a read toc is executed for a CD-R or CD-RW medium where
155 * the first toc has not been recorded yet, it will fail with
156 * 05/24/00 (which is a confusing error)
157 */
158 if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
159 if (sense->sense_key == 0x05 && sense->asc == 0x24)
160 return;
161
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200162 if (sense->error_code == 0x70) { /* Current Error */
163 switch (sense->sense_key) {
Alan Coxdbe217a2006-06-25 05:47:44 -0700164 case MEDIUM_ERROR:
165 case VOLUME_OVERFLOW:
166 case ILLEGAL_REQUEST:
167 if (!sense->valid)
168 break;
169 if (failed_command == NULL ||
170 !blk_fs_request(failed_command))
171 break;
172 sector = (sense->information[0] << 24) |
173 (sense->information[1] << 16) |
174 (sense->information[2] << 8) |
175 (sense->information[3]);
176
177 bio_sectors = bio_sectors(failed_command->bio);
178 if (bio_sectors < 4)
179 bio_sectors = 4;
180 if (drive->queue->hardsect_size == 2048)
181 sector <<= 2; /* Device sector size is 2K */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200182 sector &= ~(bio_sectors - 1);
Alan Coxdbe217a2006-06-25 05:47:44 -0700183 valid = (sector - failed_command->sector) << 9;
184
185 if (valid < 0)
186 valid = 0;
187 if (sector < get_capacity(info->disk) &&
188 drive->probed_capacity - sector < 4 * 75) {
189 set_capacity(info->disk, sector);
190 }
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200191 }
192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
Bartlomiej Zolnierkiewicz972560f2008-02-01 23:09:23 +0100194 ide_cd_log_error(drive->name, failed_command, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195}
196
197/*
198 * Initialize a ide-cd packet command request
199 */
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +0100200void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 struct cdrom_info *cd = drive->driver_data;
203
204 ide_init_drive_cmd(rq);
Jens Axboecea28852006-10-12 15:08:45 +0200205 rq->cmd_type = REQ_TYPE_ATA_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 rq->rq_disk = cd->disk;
207}
208
209static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
210 struct request *failed_command)
211{
212 struct cdrom_info *info = drive->driver_data;
213 struct request *rq = &info->request_sense_request;
214
215 if (sense == NULL)
216 sense = &info->sense_data;
217
218 /* stuff the sense request in front of our current request */
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +0100219 ide_cd_init_rq(drive, rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221 rq->data = sense;
222 rq->cmd[0] = GPCMD_REQUEST_SENSE;
223 rq->cmd[4] = rq->data_len = 18;
224
Jens Axboe4aff5e22006-08-10 08:44:47 +0200225 rq->cmd_type = REQ_TYPE_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227 /* NOTE! Save the failed command in "rq->buffer" */
228 rq->buffer = (void *) failed_command;
229
230 (void) ide_do_drive_cmd(drive, rq, ide_preempt);
231}
232
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200233static void cdrom_end_request(ide_drive_t *drive, int uptodate)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
235 struct request *rq = HWGROUP(drive)->rq;
236 int nsectors = rq->hard_cur_sectors;
237
Jens Axboe4aff5e22006-08-10 08:44:47 +0200238 if (blk_sense_request(rq) && uptodate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 /*
Jens Axboe4aff5e22006-08-10 08:44:47 +0200240 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
241 * failed request
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 */
243 struct request *failed = (struct request *) rq->buffer;
244 struct cdrom_info *info = drive->driver_data;
245 void *sense = &info->sense_data;
246 unsigned long flags;
247
248 if (failed) {
249 if (failed->sense) {
250 sense = failed->sense;
251 failed->sense_len = rq->sense_len;
252 }
Alan Coxdbe217a2006-06-25 05:47:44 -0700253 cdrom_analyze_sense_data(drive, failed, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 /*
255 * now end failed request
256 */
Alan Coxdbe217a2006-06-25 05:47:44 -0700257 if (blk_fs_request(failed)) {
258 if (ide_end_dequeued_request(drive, failed, 0,
259 failed->hard_nr_sectors))
260 BUG();
261 } else {
262 spin_lock_irqsave(&ide_lock, flags);
Kiyoshi Ueda5e36bb62008-01-28 10:34:20 +0100263 if (__blk_end_request(failed, -EIO,
264 failed->data_len))
265 BUG();
Alan Coxdbe217a2006-06-25 05:47:44 -0700266 spin_unlock_irqrestore(&ide_lock, flags);
267 }
268 } else
269 cdrom_analyze_sense_data(drive, NULL, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 }
271
272 if (!rq->current_nr_sectors && blk_fs_request(rq))
273 uptodate = 1;
274 /* make sure it's fully ended */
275 if (blk_pc_request(rq))
276 nsectors = (rq->data_len + 511) >> 9;
277 if (!nsectors)
278 nsectors = 1;
279
280 ide_end_request(drive, uptodate, nsectors);
281}
282
Alan Coxdbe217a2006-06-25 05:47:44 -0700283static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
284{
285 if (stat & 0x80)
286 return;
287 ide_dump_status(drive, msg, stat);
288}
289
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290/* Returns 0 if the request should be continued.
291 Returns 1 if the request was ended. */
292static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
293{
294 struct request *rq = HWGROUP(drive)->rq;
295 int stat, err, sense_key;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200296
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 /* Check for errors. */
Bartlomiej Zolnierkiewiczc47137a2008-02-06 02:57:51 +0100298 stat = ide_read_status(drive);
299
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 if (stat_ret)
301 *stat_ret = stat;
302
303 if (OK_STAT(stat, good_stat, BAD_R_STAT))
304 return 0;
305
306 /* Get the IDE error register. */
Bartlomiej Zolnierkiewicz64a57fe2008-02-06 02:57:51 +0100307 err = ide_read_error(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 sense_key = err >> 4;
309
310 if (rq == NULL) {
311 printk("%s: missing rq in cdrom_decode_status\n", drive->name);
312 return 1;
313 }
314
Jens Axboe4aff5e22006-08-10 08:44:47 +0200315 if (blk_sense_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 /* We got an error trying to get sense info
317 from the drive (probably while trying
318 to recover from a former error). Just give up. */
319
Jens Axboe4aff5e22006-08-10 08:44:47 +0200320 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 cdrom_end_request(drive, 0);
322 ide_error(drive, "request sense failure", stat);
323 return 1;
324
Jens Axboe8770c012006-10-12 17:24:52 +0200325 } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 /* All other functions, except for READ. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
328 /*
329 * if we have an error, pass back CHECK_CONDITION as the
330 * scsi status byte
331 */
Jens Axboeb7156732006-11-13 18:05:02 +0100332 if (blk_pc_request(rq) && !rq->errors)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 rq->errors = SAM_STAT_CHECK_CONDITION;
334
335 /* Check for tray open. */
336 if (sense_key == NOT_READY) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200337 cdrom_saw_media_change(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 } else if (sense_key == UNIT_ATTENTION) {
339 /* Check for media change. */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200340 cdrom_saw_media_change(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 /*printk("%s: media changed\n",drive->name);*/
342 return 0;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200343 } else if (sense_key == ILLEGAL_REQUEST &&
344 rq->cmd[0] == GPCMD_START_STOP_UNIT) {
345 /*
346 * Don't print error message for this condition--
347 * SFF8090i indicates that 5/24/00 is the correct
348 * response to a request to close the tray if the
349 * drive doesn't have that capability.
350 * cdrom_log_sense() knows this!
351 */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200352 } else if (!(rq->cmd_flags & REQ_QUIET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 /* Otherwise, print an error. */
354 ide_dump_status(drive, "packet command error", stat);
355 }
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200356
Jens Axboe4aff5e22006-08-10 08:44:47 +0200357 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359 /*
360 * instead of playing games with moving completions around,
361 * remove failed request completely and end it when the
362 * request sense has completed
363 */
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100364 goto end_request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 } else if (blk_fs_request(rq)) {
367 int do_end_request = 0;
368
369 /* Handle errors from READ and WRITE requests. */
370
371 if (blk_noretry_request(rq))
372 do_end_request = 1;
373
374 if (sense_key == NOT_READY) {
375 /* Tray open. */
376 if (rq_data_dir(rq) == READ) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200377 cdrom_saw_media_change(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 /* Fail the request. */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200380 printk("%s: tray open\n", drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 do_end_request = 1;
382 } else {
383 struct cdrom_info *info = drive->driver_data;
384
385 /* allow the drive 5 seconds to recover, some
386 * devices will return this error while flushing
387 * data from cache */
388 if (!rq->errors)
389 info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
390 rq->errors = 1;
391 if (time_after(jiffies, info->write_timeout))
392 do_end_request = 1;
393 else {
394 unsigned long flags;
395
396 /*
397 * take a breather relying on the
398 * unplug timer to kick us again
399 */
400 spin_lock_irqsave(&ide_lock, flags);
401 blk_plug_device(drive->queue);
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200402 spin_unlock_irqrestore(&ide_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 return 1;
404 }
405 }
406 } else if (sense_key == UNIT_ATTENTION) {
407 /* Media change. */
408 cdrom_saw_media_change (drive);
409
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200410 /*
411 * Arrange to retry the request.
412 * But be sure to give up if we've retried
413 * too many times.
414 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 if (++rq->errors > ERROR_MAX)
416 do_end_request = 1;
417 } else if (sense_key == ILLEGAL_REQUEST ||
418 sense_key == DATA_PROTECT) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200419 /*
420 * No point in retrying after an illegal
421 * request or data protect error.
422 */
423 ide_dump_status_no_sense(drive, "command error", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 do_end_request = 1;
425 } else if (sense_key == MEDIUM_ERROR) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200426 /*
427 * No point in re-trying a zillion times on a bad
428 * sector... If we got here the error is not correctable
429 */
430 ide_dump_status_no_sense(drive, "media error (bad sector)", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 do_end_request = 1;
432 } else if (sense_key == BLANK_CHECK) {
433 /* Disk appears blank ?? */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200434 ide_dump_status_no_sense(drive, "media error (blank)", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 do_end_request = 1;
436 } else if ((err & ~ABRT_ERR) != 0) {
437 /* Go to the default handler
438 for other errors. */
439 ide_error(drive, "cdrom_decode_status", stat);
440 return 1;
441 } else if ((++rq->errors > ERROR_MAX)) {
442 /* We've racked up too many retries. Abort. */
443 do_end_request = 1;
444 }
445
Alan Coxdbe217a2006-06-25 05:47:44 -0700446 /* End a request through request sense analysis when we have
447 sense data. We need this in order to perform end of media
448 processing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100450 if (do_end_request)
451 goto end_request;
Alan Coxdbe217a2006-06-25 05:47:44 -0700452
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100453 /*
454 * If we got a CHECK_CONDITION status,
455 * queue a request sense command.
456 */
457 if (stat & ERR_STAT)
458 cdrom_queue_request_sense(drive, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 } else {
460 blk_dump_rq_flags(rq, "ide-cd: bad rq");
461 cdrom_end_request(drive, 0);
462 }
463
464 /* Retry, or handle the next request. */
465 return 1;
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100466
467end_request:
468 if (stat & ERR_STAT) {
469 unsigned long flags;
470
471 spin_lock_irqsave(&ide_lock, flags);
472 blkdev_dequeue_request(rq);
473 HWGROUP(drive)->rq = NULL;
474 spin_unlock_irqrestore(&ide_lock, flags);
475
476 cdrom_queue_request_sense(drive, rq->sense, rq);
477 } else
478 cdrom_end_request(drive, 0);
479
480 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481}
482
483static int cdrom_timer_expiry(ide_drive_t *drive)
484{
485 struct request *rq = HWGROUP(drive)->rq;
486 unsigned long wait = 0;
487
488 /*
489 * Some commands are *slow* and normally take a long time to
490 * complete. Usually we can use the ATAPI "disconnect" to bypass
491 * this, but not all commands/drives support that. Let
492 * ide_timer_expiry keep polling us for these.
493 */
494 switch (rq->cmd[0]) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200495 case GPCMD_BLANK:
496 case GPCMD_FORMAT_UNIT:
497 case GPCMD_RESERVE_RZONE_TRACK:
498 case GPCMD_CLOSE_TRACK:
499 case GPCMD_FLUSH_CACHE:
500 wait = ATAPI_WAIT_PC;
501 break;
502 default:
503 if (!(rq->cmd_flags & REQ_QUIET))
504 printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
505 wait = 0;
506 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
508 return wait;
509}
510
511/* Set up the device registers for transferring a packet command on DEV,
512 expecting to later transfer XFERLEN bytes. HANDLER is the routine
513 which actually transfers the command to the drive. If this is a
514 drq_interrupt device, this routine will arrange for HANDLER to be
515 called when the interrupt from the drive arrives. Otherwise, HANDLER
516 will be called immediately after the drive is prepared for the transfer. */
517
518static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
519 int xferlen,
520 ide_handler_t *handler)
521{
522 ide_startstop_t startstop;
523 struct cdrom_info *info = drive->driver_data;
524 ide_hwif_t *hwif = drive->hwif;
525
526 /* Wait for the controller to be idle. */
527 if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
528 return startstop;
529
Bartlomiej Zolnierkiewicz3a6a3542008-01-25 22:17:13 +0100530 /* FIXME: for Virtual DMA we must check harder */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (info->dma)
532 info->dma = !hwif->dma_setup(drive);
533
534 /* Set up the controller registers. */
Bartlomiej Zolnierkiewicz2fc57382008-01-25 22:17:13 +0100535 ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
536 IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +0100537
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100538 if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Albert Leef0dd8712007-02-17 02:40:21 +0100539 /* waiting for CDB interrupt, not DMA yet. */
540 if (info->dma)
541 drive->waiting_for_dma = 0;
542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 /* packet command */
544 ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
545 return ide_started;
546 } else {
547 unsigned long flags;
548
549 /* packet command */
550 spin_lock_irqsave(&ide_lock, flags);
Bartlomiej Zolnierkiewicz23579a22008-04-18 00:46:26 +0200551 hwif->OUTBSYNC(drive, WIN_PACKETCMD,
552 hwif->io_ports[IDE_COMMAND_OFFSET]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 ndelay(400);
554 spin_unlock_irqrestore(&ide_lock, flags);
555
556 return (*handler) (drive);
557 }
558}
559
560/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
561 The device registers must have already been prepared
562 by cdrom_start_packet_command.
563 HANDLER is the interrupt handler to call when the command completes
564 or there's data ready. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565#define ATAPI_MIN_CDB_BYTES 12
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200566static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 struct request *rq,
568 ide_handler_t *handler)
569{
570 ide_hwif_t *hwif = drive->hwif;
571 int cmd_len;
572 struct cdrom_info *info = drive->driver_data;
573 ide_startstop_t startstop;
574
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100575 if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 /* Here we should have been called after receiving an interrupt
577 from the device. DRQ should how be set. */
578
579 /* Check for errors. */
580 if (cdrom_decode_status(drive, DRQ_STAT, NULL))
581 return ide_stopped;
Albert Leef0dd8712007-02-17 02:40:21 +0100582
583 /* Ok, next interrupt will be DMA interrupt. */
584 if (info->dma)
585 drive->waiting_for_dma = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 } else {
587 /* Otherwise, we must wait for DRQ to get set. */
588 if (ide_wait_stat(&startstop, drive, DRQ_STAT,
589 BUSY_STAT, WAIT_READY))
590 return startstop;
591 }
592
593 /* Arm the interrupt handler. */
594 ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
595
596 /* ATAPI commands get padded out to 12 bytes minimum */
597 cmd_len = COMMAND_SIZE(rq->cmd[0]);
598 if (cmd_len < ATAPI_MIN_CDB_BYTES)
599 cmd_len = ATAPI_MIN_CDB_BYTES;
600
601 /* Send the command to the device. */
602 HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len);
603
604 /* Start the DMA if need be */
605 if (info->dma)
606 hwif->dma_start(drive);
607
608 return ide_started;
609}
610
611/****************************************************************************
612 * Block read functions.
613 */
614
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100615static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
616{
617 while (len > 0) {
618 int dum = 0;
619 xf(drive, &dum, sizeof(dum));
620 len -= sizeof(dum);
621 }
622}
623
Bartlomiej Zolnierkiewiczb4ab7262008-02-01 23:09:26 +0100624static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
625{
626 while (nsects > 0) {
627 static char dum[SECTOR_SIZE];
628
629 drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
630 nsects--;
631 }
632}
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 * Check the contents of the interrupt reason register from the cdrom
636 * and attempt to recover if there are problems. Returns 0 if everything's
637 * ok; nonzero if the request has been terminated.
638 */
Bartlomiej Zolnierkiewicz9f10d9e2008-02-26 21:50:35 +0100639static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
640 int len, int ireason, int rw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100642 /*
643 * ireason == 0: the drive wants to receive data from us
644 * ireason == 2: the drive is expecting to transfer data to us
645 */
646 if (ireason == (!rw << 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 return 0;
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100648 else if (ireason == (rw << 1)) {
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100649 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100650 xfer_func_t *xf;
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100651
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100652 /* Whoops... */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +0100653 printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
Paolo Ciarrocchi177773e2008-04-26 17:36:42 +0200654 drive->name, __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100656 xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
657 ide_cd_pad_transfer(drive, xf, len);
658 } else if (rw == 0 && ireason == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 /* Some drives (ASUS) seem to tell us that status
660 * info is available. just get it and ignore.
661 */
Bartlomiej Zolnierkiewiczc47137a2008-02-06 02:57:51 +0100662 (void)ide_read_status(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 return 0;
664 } else {
665 /* Drive wants a command packet, or invalid ireason... */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +0100666 printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
Paolo Ciarrocchi177773e2008-04-26 17:36:42 +0200667 drive->name, __func__, ireason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 }
669
Bartlomiej Zolnierkiewicz9f10d9e2008-02-26 21:50:35 +0100670 if (rq->cmd_type == REQ_TYPE_ATA_PC)
671 rq->cmd_flags |= REQ_FAILED;
672
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 cdrom_end_request(drive, 0);
674 return -1;
675}
676
677/*
Bartlomiej Zolnierkiewicz64814f22008-02-01 23:09:26 +0100678 * Assume that the drive will always provide data in multiples of at least
679 * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
680 */
681static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
682{
683 struct cdrom_info *cd = drive->driver_data;
684
685 if ((len % SECTOR_SIZE) == 0)
686 return 0;
687
688 printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
Paolo Ciarrocchi177773e2008-04-26 17:36:42 +0200689 drive->name, __func__, len);
Bartlomiej Zolnierkiewicz64814f22008-02-01 23:09:26 +0100690
691 if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
692 printk(KERN_ERR " This drive is not supported by "
693 "this version of the driver\n");
694 else {
695 printk(KERN_ERR " Trying to limit transfer sizes\n");
696 cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
697 }
698
699 return 1;
700}
701
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100702static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
Bartlomiej Zolnierkiewicz94f5a862008-02-01 23:09:26 +0100703
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704/*
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100705 * Routine to send a read/write packet command to the drive.
706 * This is usually called directly from cdrom_start_{read,write}().
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 * However, for drq_interrupt devices, it is called from an interrupt
708 * when the drive is ready to accept the command.
709 */
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100710static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
712 struct request *rq = HWGROUP(drive)->rq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100714 if (rq_data_dir(rq) == READ) {
715 unsigned short sectors_per_frame =
716 queue_hardsect_size(drive->queue) >> SECTOR_BITS;
717 int nskip = rq->sector & (sectors_per_frame - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100719 /*
720 * If the requested sector doesn't start on a frame boundary,
721 * we must adjust the start of the transfer so that it does,
722 * and remember to skip the first few sectors.
723 *
724 * If the rq->current_nr_sectors field is larger than the size
725 * of the buffer, it will mean that we're to skip a number of
726 * sectors equal to the amount by which rq->current_nr_sectors
727 * is larger than the buffer size.
728 */
729 if (nskip > 0) {
730 /* Sanity check... */
731 if (rq->current_nr_sectors !=
732 bio_cur_sectors(rq->bio)) {
733 printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
Paolo Ciarrocchi177773e2008-04-26 17:36:42 +0200734 drive->name, __func__,
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100735 rq->current_nr_sectors);
736 cdrom_end_request(drive, 0);
737 return ide_stopped;
738 }
739 rq->current_nr_sectors += nskip;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 }
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100742#if 0
743 else
744 /* the immediate bit */
745 rq->cmd[1] = 1 << 3;
746#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 /* Set up the command */
748 rq->timeout = ATAPI_WAIT_PC;
749
750 /* Send the command to the drive and return. */
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100751 return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752}
753
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
755#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
756#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
757
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200758static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 struct cdrom_info *info = drive->driver_data;
761 int stat;
762 static int retry = 10;
763
764 if (cdrom_decode_status(drive, 0, &stat))
765 return ide_stopped;
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +0100766
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100767 info->cd_flags |= IDE_CD_FLAG_SEEKING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
770 if (--retry == 0) {
771 /*
772 * this condition is far too common, to bother
773 * users about it
774 */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200775 /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 drive->dsc_overlap = 0;
777 }
778 }
779 return ide_stopped;
780}
781
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200782static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 struct request *rq = HWGROUP(drive)->rq;
785 sector_t frame = rq->sector;
786
787 sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
788
789 memset(rq->cmd, 0, sizeof(rq->cmd));
790 rq->cmd[0] = GPCMD_SEEK;
791 put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
792
793 rq->timeout = ATAPI_WAIT_PC;
794 return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
795}
796
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200797static ide_startstop_t cdrom_start_seek(ide_drive_t *drive, unsigned int block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
799 struct cdrom_info *info = drive->driver_data;
800
801 info->dma = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 info->start_seek = jiffies;
803 return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
804}
805
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200806/*
807 * Fix up a possibly partially-processed request so that we can
808 * start it over entirely, or even put it back on the request queue.
809 */
810static void restore_request(struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811{
812 if (rq->buffer != bio_data(rq->bio)) {
813 sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
814
815 rq->buffer = bio_data(rq->bio);
816 rq->nr_sectors += n;
817 rq->sector -= n;
818 }
819 rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio);
820 rq->hard_nr_sectors = rq->nr_sectors;
821 rq->hard_sector = rq->sector;
822 rq->q->prep_rq_fn(rq->q, rq);
823}
824
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825/****************************************************************************
826 * Execute all other packet commands.
827 */
828
Bartlomiej Zolnierkiewicz8ee69f52008-02-01 23:09:25 +0100829static void ide_cd_request_sense_fixup(struct request *rq)
830{
831 /*
832 * Some of the trailing request sense fields are optional,
833 * and some drives don't send them. Sigh.
834 */
835 if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
836 rq->data_len > 0 && rq->data_len <= 5)
837 while (rq->data_len > 0) {
838 *(u8 *)rq->data++ = 0;
839 --rq->data_len;
840 }
841}
842
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +0100843int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
845 struct request_sense sense;
846 int retries = 10;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200847 unsigned int flags = rq->cmd_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
849 if (rq->sense == NULL)
850 rq->sense = &sense;
851
852 /* Start of retry loop. */
853 do {
854 int error;
855 unsigned long time = jiffies;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200856 rq->cmd_flags = flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
858 error = ide_do_drive_cmd(drive, rq, ide_wait);
859 time = jiffies - time;
860
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +0200861 /* FIXME: we should probably abort/retry or something
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 * in case of failure */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200863 if (rq->cmd_flags & REQ_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 /* The request failed. Retry if it was due to a unit
865 attention status
866 (usually means media was changed). */
867 struct request_sense *reqbuf = rq->sense;
868
869 if (reqbuf->sense_key == UNIT_ATTENTION)
870 cdrom_saw_media_change(drive);
871 else if (reqbuf->sense_key == NOT_READY &&
872 reqbuf->asc == 4 && reqbuf->ascq != 4) {
873 /* The drive is in the process of loading
874 a disk. Retry, but wait a little to give
875 the drive time to complete the load. */
876 ssleep(2);
877 } else {
878 /* Otherwise, don't retry. */
879 retries = 0;
880 }
881 --retries;
882 }
883
884 /* End of retry loop. */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200885 } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 /* Return an error if the command failed. */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200888 return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889}
890
891/*
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -0500892 * Called from blk_end_request_callback() after the data of the request
893 * is completed and before the request is completed.
894 * By returning value '1', blk_end_request_callback() returns immediately
895 * without completing the request.
896 */
897static int cdrom_newpc_intr_dummy_cb(struct request *rq)
898{
899 return 1;
900}
901
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
903{
Bartlomiej Zolnierkiewicz23579a22008-04-18 00:46:26 +0200904 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 struct cdrom_info *info = drive->driver_data;
906 struct request *rq = HWGROUP(drive)->rq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 xfer_func_t *xferfunc;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100908 ide_expiry_t *expiry = NULL;
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +0100909 int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
910 int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
911 unsigned int timeout;
912 u8 lowcyl, highcyl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
914 /* Check for errors. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 dma = info->dma;
916 if (dma) {
917 info->dma = 0;
918 dma_error = HWIF(drive)->ide_dma_end(drive);
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +0100919 if (dma_error) {
920 printk(KERN_ERR "%s: DMA %s error\n", drive->name,
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +0100921 write ? "write" : "read");
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +0100922 ide_dma_off(drive);
923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 }
925
926 if (cdrom_decode_status(drive, 0, &stat))
927 return ide_stopped;
928
929 /*
930 * using dma, transfer is complete now
931 */
932 if (dma) {
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +0100933 if (dma_error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 return ide_error(drive, "dma error", stat);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100935 if (blk_fs_request(rq)) {
936 ide_end_request(drive, 1, rq->nr_sectors);
937 return ide_stopped;
938 }
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +0100939 goto end_request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 }
941
942 /*
943 * ok we fall to pio :/
944 */
Bartlomiej Zolnierkiewicz23579a22008-04-18 00:46:26 +0200945 ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]) & 0x3;
946 lowcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
947 highcyl = hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
949 len = lowcyl + (256 * highcyl);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100950
951 thislen = blk_fs_request(rq) ? len : rq->data_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 if (thislen > len)
953 thislen = len;
954
955 /*
956 * If DRQ is clear, the command has completed.
957 */
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -0500958 if ((stat & DRQ_STAT) == 0) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100959 if (blk_fs_request(rq)) {
960 /*
961 * If we're not done reading/writing, complain.
962 * Otherwise, complete the command normally.
963 */
964 uptodate = 1;
965 if (rq->current_nr_sectors > 0) {
966 printk(KERN_ERR "%s: %s: data underrun "
967 "(%d blocks)\n",
Paolo Ciarrocchi177773e2008-04-26 17:36:42 +0200968 drive->name, __func__,
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100969 rq->current_nr_sectors);
970 if (!write)
971 rq->cmd_flags |= REQ_FAILED;
972 uptodate = 0;
973 }
974 cdrom_end_request(drive, uptodate);
975 return ide_stopped;
976 } else if (!blk_pc_request(rq)) {
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +0100977 ide_cd_request_sense_fixup(rq);
978 /* Complain if we still have data left to transfer. */
979 uptodate = rq->data_len ? 0 : 1;
980 }
981 goto end_request;
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -0500982 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 /*
985 * check which way to transfer data
986 */
Bartlomiej Zolnierkiewicz9f10d9e2008-02-26 21:50:35 +0100987 if (ide_cd_check_ireason(drive, rq, len, ireason, write))
988 return ide_stopped;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100989
Bartlomiej Zolnierkiewicz9f10d9e2008-02-26 21:50:35 +0100990 if (blk_fs_request(rq)) {
991 if (write == 0) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100992 int nskip;
993
994 if (ide_cd_check_transfer_size(drive, len)) {
995 cdrom_end_request(drive, 0);
996 return ide_stopped;
997 }
998
999 /*
1000 * First, figure out if we need to bit-bucket
1001 * any of the leading sectors.
1002 */
1003 nskip = min_t(int, rq->current_nr_sectors
1004 - bio_cur_sectors(rq->bio),
1005 thislen >> 9);
1006 if (nskip > 0) {
1007 ide_cd_drain_data(drive, nskip);
1008 rq->current_nr_sectors -= nskip;
1009 thislen -= (nskip << 9);
1010 }
1011 }
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001014 if (ireason == 0) {
1015 write = 1;
1016 xferfunc = HWIF(drive)->atapi_output_bytes;
Bartlomiej Zolnierkiewicz9f10d9e2008-02-26 21:50:35 +01001017 } else {
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001018 write = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 xferfunc = HWIF(drive)->atapi_input_bytes;
1020 }
1021
1022 /*
1023 * transfer data
1024 */
1025 while (thislen > 0) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001026 u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
Bartlomiej Zolnierkiewicza11e77d2008-02-01 23:09:27 +01001027 int blen = rq->data_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 /*
1030 * bio backed?
1031 */
1032 if (rq->bio) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001033 if (blk_fs_request(rq)) {
1034 ptr = rq->buffer;
1035 blen = rq->current_nr_sectors << 9;
1036 } else {
1037 ptr = bio_data(rq->bio);
1038 blen = bio_iovec(rq->bio)->bv_len;
1039 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 }
1041
1042 if (!ptr) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001043 if (blk_fs_request(rq) && !write)
1044 /*
Borislav Petkov968c4962008-04-26 17:36:37 +02001045 * If the buffers are full, pipe the rest into
1046 * oblivion. */
1047 ide_cd_drain_data(drive, thislen >> 9);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001048 else {
1049 printk(KERN_ERR "%s: confused, missing data\n",
1050 drive->name);
1051 blk_dump_rq_flags(rq, rq_data_dir(rq)
1052 ? "cdrom_newpc_intr, write"
1053 : "cdrom_newpc_intr, read");
1054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 break;
1056 }
1057
1058 if (blen > thislen)
1059 blen = thislen;
1060
1061 xferfunc(drive, ptr, blen);
1062
1063 thislen -= blen;
1064 len -= blen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001066 if (blk_fs_request(rq)) {
1067 rq->buffer += blen;
1068 rq->nr_sectors -= (blen >> 9);
1069 rq->current_nr_sectors -= (blen >> 9);
1070 rq->sector += (blen >> 9);
1071
1072 if (rq->current_nr_sectors == 0 && rq->nr_sectors)
1073 cdrom_end_request(drive, 1);
1074 } else {
1075 rq->data_len -= blen;
1076
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001077 /*
1078 * The request can't be completed until DRQ is cleared.
1079 * So complete the data, but don't complete the request
1080 * using the dummy function for the callback feature
1081 * of blk_end_request_callback().
1082 */
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001083 if (rq->bio)
1084 blk_end_request_callback(rq, 0, blen,
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001085 cdrom_newpc_intr_dummy_cb);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001086 else
1087 rq->data += blen;
1088 }
Andreas Schwabbcd88ac2008-02-26 21:50:35 +01001089 if (!write && blk_sense_request(rq))
1090 rq->sense_len += blen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
1092
1093 /*
1094 * pad, if necessary
1095 */
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001096 if (!blk_fs_request(rq) && len > 0)
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001097 ide_cd_pad_transfer(drive, xferfunc, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001099 if (blk_pc_request(rq)) {
1100 timeout = rq->timeout;
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001101 } else {
1102 timeout = ATAPI_WAIT_PC;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001103 if (!blk_fs_request(rq))
1104 expiry = cdrom_timer_expiry;
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001105 }
1106
1107 ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return ide_started;
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001109
1110end_request:
1111 if (blk_pc_request(rq)) {
1112 unsigned long flags;
Kiyoshi Ueda14e04c32008-02-19 01:41:26 +01001113 unsigned int dlen = rq->data_len;
1114
1115 if (dma)
1116 rq->data_len = 0;
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001117
1118 spin_lock_irqsave(&ide_lock, flags);
Kiyoshi Ueda14e04c32008-02-19 01:41:26 +01001119 if (__blk_end_request(rq, 0, dlen))
Bartlomiej Zolnierkiewiczff1bfbc12008-02-01 23:09:25 +01001120 BUG();
1121 HWGROUP(drive)->rq = NULL;
1122 spin_unlock_irqrestore(&ide_lock, flags);
1123 } else {
1124 if (!uptodate)
1125 rq->cmd_flags |= REQ_FAILED;
1126 cdrom_end_request(drive, uptodate);
1127 }
1128 return ide_stopped;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129}
1130
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001131static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001133 struct cdrom_info *cd = drive->driver_data;
1134 int write = rq_data_dir(rq) == WRITE;
1135 unsigned short sectors_per_frame =
1136 queue_hardsect_size(drive->queue) >> SECTOR_BITS;
1137
1138 if (write) {
1139 /*
1140 * disk has become write protected
1141 */
1142 if (cd->disk->policy) {
1143 cdrom_end_request(drive, 0);
1144 return ide_stopped;
1145 }
1146 } else {
1147 /*
1148 * We may be retrying this request after an error. Fix up any
1149 * weirdness which might be present in the request packet.
1150 */
1151 restore_request(rq);
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 /*
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001155 * use DMA, if possible / writes *must* be hardware frame aligned
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 */
1157 if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
1158 (rq->sector & (sectors_per_frame - 1))) {
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001159 if (write) {
1160 cdrom_end_request(drive, 0);
1161 return ide_stopped;
1162 }
1163 cd->dma = 0;
1164 } else
1165 cd->dma = drive->using_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001167 if (write)
1168 cd->devinfo.media_written = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001170 /* Start sending the read/write request to the drive. */
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +01001171 return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172}
1173
1174static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
1175{
1176 struct request *rq = HWGROUP(drive)->rq;
1177
1178 if (!rq->timeout)
1179 rq->timeout = ATAPI_WAIT_PC;
1180
1181 return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
1182}
1183
1184static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
1185{
1186 struct cdrom_info *info = drive->driver_data;
1187
Bartlomiej Zolnierkiewiczc9f56a82008-02-01 23:09:26 +01001188 if (blk_pc_request(rq))
1189 rq->cmd_flags |= REQ_QUIET;
1190 else
1191 rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193 info->dma = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
1195 /*
1196 * sg request
1197 */
1198 if (rq->bio) {
1199 int mask = drive->queue->dma_alignment;
1200 unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
1201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 info->dma = drive->using_dma;
1203
1204 /*
1205 * check if dma is safe
Linus Torvalds5d9e4ea2005-05-27 07:36:17 -07001206 *
1207 * NOTE! The "len" and "addr" checks should possibly have
1208 * separate masks.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 */
Jens Axboe4e7c6812005-05-31 17:47:36 +02001210 if ((rq->data_len & 15) || (addr & mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 info->dma = 0;
1212 }
1213
1214 /* Start sending the command to the drive. */
1215 return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont);
1216}
1217
1218/****************************************************************************
1219 * cdrom driver request routine.
1220 */
1221static ide_startstop_t
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001222ide_do_rw_cdrom(ide_drive_t *drive, struct request *rq, sector_t block)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223{
1224 ide_startstop_t action;
1225 struct cdrom_info *info = drive->driver_data;
1226
1227 if (blk_fs_request(rq)) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001228 if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 unsigned long elapsed = jiffies - info->start_seek;
Bartlomiej Zolnierkiewiczc47137a2008-02-06 02:57:51 +01001230 int stat = ide_read_status(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 if ((stat & SEEK_STAT) != SEEK_STAT) {
1233 if (elapsed < IDECD_SEEK_TIMEOUT) {
1234 ide_stall_queue(drive, IDECD_SEEK_TIMER);
1235 return ide_stopped;
1236 }
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001237 printk(KERN_ERR "%s: DSC timeout\n", drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 }
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001239 info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 }
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001241 if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 action = cdrom_start_seek(drive, block);
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001243 else
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001244 action = cdrom_start_rw(drive, rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 info->last_block = block;
1246 return action;
Bartlomiej Zolnierkiewiczc9f56a82008-02-01 23:09:26 +01001247 } else if (blk_sense_request(rq) || blk_pc_request(rq) ||
Jens Axboecea28852006-10-12 15:08:45 +02001248 rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 return cdrom_do_block_pc(drive, rq);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001250 } else if (blk_special_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 /*
1252 * right now this can only be a reset...
1253 */
1254 cdrom_end_request(drive, 1);
1255 return ide_stopped;
1256 }
1257
1258 blk_dump_rq_flags(rq, "ide-cd bad flags");
1259 cdrom_end_request(drive, 0);
1260 return ide_stopped;
1261}
1262
1263
1264
1265/****************************************************************************
1266 * Ioctl handling.
1267 *
1268 * Routines which queue packet commands take as a final argument a pointer
1269 * to a request_sense struct. If execution of the command results
1270 * in an error with a CHECK CONDITION status, this structure will be filled
1271 * with the results of the subsequent request sense command. The pointer
1272 * can also be NULL, in which case no sense information is returned.
1273 */
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275static
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001276void msf_from_bcd(struct atapi_msf *msf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277{
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001278 msf->minute = BCD2BIN(msf->minute);
1279 msf->second = BCD2BIN(msf->second);
1280 msf->frame = BCD2BIN(msf->frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281}
1282
Borislav Petkovf9afd182008-02-01 23:09:29 +01001283int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284{
1285 struct request req;
1286 struct cdrom_info *info = drive->driver_data;
1287 struct cdrom_device_info *cdi = &info->devinfo;
1288
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001289 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291 req.sense = sense;
1292 req.cmd[0] = GPCMD_TEST_UNIT_READY;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001293 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001295 /*
1296 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
1297 * switch CDs instead of supporting the LOAD_UNLOAD opcode.
1298 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 req.cmd[7] = cdi->sanyo_slot % 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001301 return ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302}
1303
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
1305 unsigned long *sectors_per_frame,
1306 struct request_sense *sense)
1307{
1308 struct {
1309 __u32 lba;
1310 __u32 blocklen;
1311 } capbuf;
1312
1313 int stat;
1314 struct request req;
1315
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001316 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
1318 req.sense = sense;
1319 req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
1320 req.data = (char *)&capbuf;
1321 req.data_len = sizeof(capbuf);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001322 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001324 stat = ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 if (stat == 0) {
1326 *capacity = 1 + be32_to_cpu(capbuf.lba);
1327 *sectors_per_frame =
1328 be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
1329 }
1330
1331 return stat;
1332}
1333
1334static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
1335 int format, char *buf, int buflen,
1336 struct request_sense *sense)
1337{
1338 struct request req;
1339
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001340 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
1342 req.sense = sense;
1343 req.data = buf;
1344 req.data_len = buflen;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001345 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
1347 req.cmd[6] = trackno;
1348 req.cmd[7] = (buflen >> 8);
1349 req.cmd[8] = (buflen & 0xff);
1350 req.cmd[9] = (format << 6);
1351
1352 if (msf_flag)
1353 req.cmd[1] = 2;
1354
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001355 return ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356}
1357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358/* Try to read the entire TOC for the disk into our internal buffer. */
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001359int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360{
1361 int stat, ntracks, i;
1362 struct cdrom_info *info = drive->driver_data;
1363 struct cdrom_device_info *cdi = &info->devinfo;
1364 struct atapi_toc *toc = info->toc;
1365 struct {
1366 struct atapi_toc_header hdr;
1367 struct atapi_toc_entry ent;
1368 } ms_tmp;
1369 long last_written;
1370 unsigned long sectors_per_frame = SECTORS_PER_FRAME;
1371
1372 if (toc == NULL) {
1373 /* Try to allocate space. */
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001374 toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 if (toc == NULL) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001376 printk(KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 return -ENOMEM;
1378 }
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001379 info->toc = toc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 }
1381
1382 /* Check to see if the existing data is still valid.
1383 If it is, just return. */
1384 (void) cdrom_check_status(drive, sense);
1385
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001386 if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return 0;
1388
1389 /* Try to get the total cdrom capacity and sector size. */
1390 stat = cdrom_read_capacity(drive, &toc->capacity, &sectors_per_frame,
1391 sense);
1392 if (stat)
1393 toc->capacity = 0x1fffff;
1394
1395 set_capacity(info->disk, toc->capacity * sectors_per_frame);
Alan Coxdbe217a2006-06-25 05:47:44 -07001396 /* Save a private copy of te TOC capacity for error handling */
1397 drive->probed_capacity = toc->capacity * sectors_per_frame;
1398
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 blk_queue_hardsect_size(drive->queue,
1400 sectors_per_frame << SECTOR_BITS);
1401
1402 /* First read just the header, so we know how long the TOC is. */
1403 stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
1404 sizeof(struct atapi_toc_header), sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001405 if (stat)
1406 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001408 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001409 toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
1410 toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413 ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
1414 if (ntracks <= 0)
1415 return -EIO;
1416 if (ntracks > MAX_TRACKS)
1417 ntracks = MAX_TRACKS;
1418
1419 /* Now read the whole schmeer. */
1420 stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
1421 (char *)&toc->hdr,
1422 sizeof(struct atapi_toc_header) +
1423 (ntracks + 1) *
1424 sizeof(struct atapi_toc_entry), sense);
1425
1426 if (stat && toc->hdr.first_track > 1) {
1427 /* Cds with CDI tracks only don't have any TOC entries,
1428 despite of this the returned values are
1429 first_track == last_track = number of CDI tracks + 1,
1430 so that this case is indistinguishable from the same
1431 layout plus an additional audio track.
1432 If we get an error for the regular case, we assume
1433 a CDI without additional audio tracks. In this case
1434 the readable TOC is empty (CDI tracks are not included)
Jan Engelhardt96de0e22007-10-19 23:21:04 +02001435 and only holds the Leadout entry. Heiko Eißfeldt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 ntracks = 0;
1437 stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
1438 (char *)&toc->hdr,
1439 sizeof(struct atapi_toc_header) +
1440 (ntracks + 1) *
1441 sizeof(struct atapi_toc_entry),
1442 sense);
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001443 if (stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 return stat;
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001445
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001446 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001447 toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
1448 toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001449 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 toc->hdr.first_track = CDROM_LEADOUT;
1451 toc->hdr.last_track = CDROM_LEADOUT;
1452 }
1453 }
1454
1455 if (stat)
1456 return stat;
1457
Borislav Petkov7eb43fd2008-02-11 00:32:13 +01001458 toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001460 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001461 toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
1462 toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001465 for (i = 0; i <= ntracks; i++) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001466 if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
1467 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001468 toc->ent[i].track = BCD2BIN(toc->ent[i].track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 msf_from_bcd(&toc->ent[i].addr.msf);
1470 }
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001471 toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute,
1472 toc->ent[i].addr.msf.second,
1473 toc->ent[i].addr.msf.frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 }
1475
1476 /* Read the multisession information. */
1477 if (toc->hdr.first_track != CDROM_LEADOUT) {
1478 /* Read the multisession information. */
1479 stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
1480 sizeof(ms_tmp), sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001481 if (stat)
1482 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
1484 toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
1485 } else {
1486 ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
1487 toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
1488 }
1489
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001490 if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 /* Re-read multisession information using MSF format */
1492 stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
1493 sizeof(ms_tmp), sense);
1494 if (stat)
1495 return stat;
1496
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001497 msf_from_bcd(&ms_tmp.ent.addr.msf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001499 ms_tmp.ent.addr.msf.second,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 ms_tmp.ent.addr.msf.frame);
1501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
1503 toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
1504
1505 /* Now try to get the total cdrom capacity. */
1506 stat = cdrom_get_last_written(cdi, &last_written);
1507 if (!stat && (last_written > toc->capacity)) {
1508 toc->capacity = last_written;
1509 set_capacity(info->disk, toc->capacity * sectors_per_frame);
Alan Coxdbe217a2006-06-25 05:47:44 -07001510 drive->probed_capacity = toc->capacity * sectors_per_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 }
1512
1513 /* Remember that we've read this stuff. */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001514 info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 return 0;
1517}
1518
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001519int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
Eric Piel9235e682005-06-23 00:10:29 -07001520{
1521 struct cdrom_info *info = drive->driver_data;
1522 struct cdrom_device_info *cdi = &info->devinfo;
1523 struct packet_command cgc;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001524 int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
Eric Piel9235e682005-06-23 00:10:29 -07001525
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001526 if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001527 size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
Eric Piel9235e682005-06-23 00:10:29 -07001528
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001529 init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
Eric Piel9235e682005-06-23 00:10:29 -07001530 do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
1531 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
1532 if (!stat)
1533 break;
1534 } while (--attempts);
1535 return stat;
1536}
1537
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001538void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
Eric Piel9235e682005-06-23 00:10:29 -07001539{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001540 struct cdrom_info *cd = drive->driver_data;
Bartlomiej Zolnierkiewicz481c8c62008-02-01 23:09:20 +01001541 u16 curspeed, maxspeed;
1542
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001543 curspeed = *(u16 *)&buf[8 + 14];
1544 maxspeed = *(u16 *)&buf[8 + 8];
1545
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001546 if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001547 curspeed = le16_to_cpu(curspeed);
1548 maxspeed = le16_to_cpu(maxspeed);
Eric Piel9235e682005-06-23 00:10:29 -07001549 } else {
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001550 curspeed = be16_to_cpu(curspeed);
1551 maxspeed = be16_to_cpu(maxspeed);
Eric Piel9235e682005-06-23 00:10:29 -07001552 }
Bartlomiej Zolnierkiewicz481c8c62008-02-01 23:09:20 +01001553
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001554 cd->current_speed = (curspeed + (176/2)) / 176;
1555 cd->max_speed = (maxspeed + (176/2)) / 176;
Eric Piel9235e682005-06-23 00:10:29 -07001556}
1557
Bartlomiej Zolnierkiewicz20e7f7e2008-02-01 23:09:20 +01001558#define IDE_CD_CAPABILITIES \
1559 (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
1560 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
1561 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
1562 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
1563 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565static struct cdrom_device_ops ide_cdrom_dops = {
1566 .open = ide_cdrom_open_real,
1567 .release = ide_cdrom_release_real,
1568 .drive_status = ide_cdrom_drive_status,
1569 .media_changed = ide_cdrom_check_media_change_real,
1570 .tray_move = ide_cdrom_tray_move,
1571 .lock_door = ide_cdrom_lock_door,
1572 .select_speed = ide_cdrom_select_speed,
1573 .get_last_session = ide_cdrom_get_last_session,
1574 .get_mcn = ide_cdrom_get_mcn,
1575 .reset = ide_cdrom_reset,
1576 .audio_ioctl = ide_cdrom_audio_ioctl,
Bartlomiej Zolnierkiewicz20e7f7e2008-02-01 23:09:20 +01001577 .capability = IDE_CD_CAPABILITIES,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 .generic_packet = ide_cdrom_packet,
1579};
1580
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001581static int ide_cdrom_register(ide_drive_t *drive, int nslots)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582{
1583 struct cdrom_info *info = drive->driver_data;
1584 struct cdrom_device_info *devinfo = &info->devinfo;
1585
1586 devinfo->ops = &ide_cdrom_dops;
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001587 devinfo->speed = info->current_speed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 devinfo->capacity = nslots;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001589 devinfo->handle = drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 strcpy(devinfo->name, drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001592 if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
Bartlomiej Zolnierkiewicz3cbd8142007-12-24 15:23:43 +01001593 devinfo->mask |= CDC_SELECT_SPEED;
1594
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 devinfo->disk = info->disk;
1596 return register_cdrom(devinfo);
1597}
1598
1599static
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001600int ide_cdrom_probe_capabilities(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001602 struct cdrom_info *cd = drive->driver_data;
1603 struct cdrom_device_info *cdi = &cd->devinfo;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001604 u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
1605 mechtype_t mechtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 int nslots = 1;
1607
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001608 cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
1609 CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
1610 CDC_MO_DRIVE | CDC_RAM);
1611
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 if (drive->media == ide_optical) {
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001613 cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
1615 return nslots;
1616 }
1617
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001618 if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001619 cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001620 cdi->mask &= ~CDC_PLAY_AUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 return nslots;
1622 }
1623
1624 /*
1625 * we have to cheat a little here. the packet will eventually
1626 * be queued with ide_cdrom_packet(), which extracts the
1627 * drive from cdi->handle. Since this device hasn't been
1628 * registered with the Uniform layer yet, it can't do this.
1629 * Same goes for cdi->ops.
1630 */
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001631 cdi->handle = drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 cdi->ops = &ide_cdrom_dops;
1633
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001634 if (ide_cdrom_get_capabilities(drive, buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 return 0;
1636
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001637 if ((buf[8 + 6] & 0x01) == 0)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001638 cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001639 if (buf[8 + 6] & 0x08)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001640 cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001641 if (buf[8 + 3] & 0x01)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001642 cdi->mask &= ~CDC_CD_R;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001643 if (buf[8 + 3] & 0x02)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001644 cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001645 if (buf[8 + 2] & 0x38)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001646 cdi->mask &= ~CDC_DVD;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001647 if (buf[8 + 3] & 0x20)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001648 cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001649 if (buf[8 + 3] & 0x10)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001650 cdi->mask &= ~CDC_DVD_R;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001651 if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001652 cdi->mask &= ~CDC_PLAY_AUDIO;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001653
1654 mechtype = buf[8 + 6] >> 5;
1655 if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001656 cdi->mask |= CDC_CLOSE_TRAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 if (cdi->sanyo_slot > 0) {
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001659 cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 nslots = 3;
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001661 } else if (mechtype == mechtype_individual_changer ||
1662 mechtype == mechtype_cartridge_changer) {
Bartlomiej Zolnierkiewicz2609d062008-02-01 23:09:19 +01001663 nslots = cdrom_number_of_slots(cdi);
1664 if (nslots > 1)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001665 cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 }
1667
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001668 ide_cdrom_update_speed(drive, buf);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001669
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 printk(KERN_INFO "%s: ATAPI", drive->name);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001671
1672 /* don't print speed if the drive reported 0 */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001673 if (cd->max_speed)
1674 printk(KERN_CONT " %dX", cd->max_speed);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001675
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001676 printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001678 if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
1679 printk(KERN_CONT " DVD%s%s",
1680 (cdi->mask & CDC_DVD_R) ? "" : "-R",
1681 (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001683 if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
1684 printk(KERN_CONT " CD%s%s",
1685 (cdi->mask & CDC_CD_R) ? "" : "-R",
1686 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001688 if ((cdi->mask & CDC_SELECT_DISC) == 0)
1689 printk(KERN_CONT " changer w/%d slots", nslots);
1690 else
1691 printk(KERN_CONT " drive");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001693 printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
1695 return nslots;
1696}
1697
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001698#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699static void ide_cdrom_add_settings(ide_drive_t *drive)
1700{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02001701 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 -07001702}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001703#else
1704static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
1705#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707/*
1708 * standard prep_rq_fn that builds 10 byte cmds
1709 */
Jens Axboe165125e2007-07-24 09:28:11 +02001710static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
1712 int hard_sect = queue_hardsect_size(q);
1713 long block = (long)rq->hard_sector / (hard_sect >> 9);
1714 unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
1715
1716 memset(rq->cmd, 0, sizeof(rq->cmd));
1717
1718 if (rq_data_dir(rq) == READ)
1719 rq->cmd[0] = GPCMD_READ_10;
1720 else
1721 rq->cmd[0] = GPCMD_WRITE_10;
1722
1723 /*
1724 * fill in lba
1725 */
1726 rq->cmd[2] = (block >> 24) & 0xff;
1727 rq->cmd[3] = (block >> 16) & 0xff;
1728 rq->cmd[4] = (block >> 8) & 0xff;
1729 rq->cmd[5] = block & 0xff;
1730
1731 /*
1732 * and transfer length
1733 */
1734 rq->cmd[7] = (blocks >> 8) & 0xff;
1735 rq->cmd[8] = blocks & 0xff;
1736 rq->cmd_len = 10;
1737 return BLKPREP_OK;
1738}
1739
1740/*
1741 * Most of the SCSI commands are supported directly by ATAPI devices.
1742 * This transform handles the few exceptions.
1743 */
1744static int ide_cdrom_prep_pc(struct request *rq)
1745{
1746 u8 *c = rq->cmd;
1747
1748 /*
1749 * Transform 6-byte read/write commands to the 10-byte version
1750 */
1751 if (c[0] == READ_6 || c[0] == WRITE_6) {
1752 c[8] = c[4];
1753 c[5] = c[3];
1754 c[4] = c[2];
1755 c[3] = c[1] & 0x1f;
1756 c[2] = 0;
1757 c[1] &= 0xe0;
1758 c[0] += (READ_10 - READ_6);
1759 rq->cmd_len = 10;
1760 return BLKPREP_OK;
1761 }
1762
1763 /*
1764 * it's silly to pretend we understand 6-byte sense commands, just
1765 * reject with ILLEGAL_REQUEST and the caller should take the
1766 * appropriate action
1767 */
1768 if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
1769 rq->errors = ILLEGAL_REQUEST;
1770 return BLKPREP_KILL;
1771 }
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001772
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 return BLKPREP_OK;
1774}
1775
Jens Axboe165125e2007-07-24 09:28:11 +02001776static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777{
Jens Axboe4aff5e22006-08-10 08:44:47 +02001778 if (blk_fs_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 return ide_cdrom_prep_fs(q, rq);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001780 else if (blk_pc_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 return ide_cdrom_prep_pc(rq);
1782
1783 return 0;
1784}
1785
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001786struct cd_list_entry {
1787 const char *id_model;
1788 const char *id_firmware;
1789 unsigned int cd_flags;
1790};
1791
1792static const struct cd_list_entry ide_cd_quirks_list[] = {
1793 /* Limit transfer size per interrupt. */
1794 { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
1795 { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
1796 /* SCR-3231 doesn't support the SET_CD_SPEED command. */
1797 { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
1798 /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
1799 { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
1800 IDE_CD_FLAG_PRE_ATAPI12, },
1801 /* Vertos 300, some versions of this drive like to talk BCD. */
1802 { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
1803 /* Vertos 600 ESD. */
1804 { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
1805 /*
1806 * Sanyo 3 CD changer uses a non-standard command for CD changing
1807 * (by default standard ATAPI support for CD changers is used).
1808 */
1809 { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
1810 { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
1811 { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
1812 /* Stingray 8X CD-ROM. */
1813 { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
1814 /*
1815 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
1816 * mode sense page capabilities size, but older drives break.
1817 */
1818 { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
1819 { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
1820 /* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
1821 { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
1822 /*
1823 * Some drives used by Apple don't advertise audio play
1824 * but they do support reading TOC & audio datas.
1825 */
1826 { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
1827 { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
1828 { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
1829 { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
Borislav Petkovacbe44e2008-02-26 21:50:32 +01001830 { "Optiarc DVD RW AD-5200A", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001831 { NULL, NULL, 0 }
1832};
1833
1834static unsigned int ide_cd_flags(struct hd_driveid *id)
1835{
1836 const struct cd_list_entry *cle = ide_cd_quirks_list;
1837
1838 while (cle->id_model) {
1839 if (strcmp(cle->id_model, id->model) == 0 &&
1840 (cle->id_firmware == NULL ||
1841 strstr(id->fw_rev, cle->id_firmware)))
1842 return cle->cd_flags;
1843 cle++;
1844 }
1845
1846 return 0;
1847}
1848
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849static
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001850int ide_cdrom_setup(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001852 struct cdrom_info *cd = drive->driver_data;
1853 struct cdrom_device_info *cdi = &cd->devinfo;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001854 struct hd_driveid *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 int nslots;
1856
1857 blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
1858 blk_queue_dma_alignment(drive->queue, 31);
1859 drive->queue->unplug_delay = (1 * HZ) / 1000;
1860 if (!drive->queue->unplug_delay)
1861 drive->queue->unplug_delay = 1;
1862
1863 drive->special.all = 0;
1864
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001865 cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
1866 ide_cd_flags(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001868 if ((id->config & 0x0060) == 0x20)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001869 cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
Bartlomiej Zolnierkiewiczb8d25de2008-02-01 23:09:19 +01001870
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001871 if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
1872 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001873 cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
1874 IDE_CD_FLAG_TOCADDR_AS_BCD);
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001875 else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
1876 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001877 cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001878 else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
1879 cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001881 nslots = ide_cdrom_probe_capabilities(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882
1883 /*
1884 * set correct block size
1885 */
1886 blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
1887
1888 if (drive->autotune == IDE_TUNE_DEFAULT ||
1889 drive->autotune == IDE_TUNE_AUTO)
1890 drive->dsc_overlap = (drive->next != drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891
1892 if (ide_cdrom_register(drive, nslots)) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001893 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 +01001894 cd->devinfo.handle = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 return 1;
1896 }
1897 ide_cdrom_add_settings(drive);
1898 return 0;
1899}
1900
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +02001901#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902static
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001903sector_t ide_cdrom_capacity(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
1905 unsigned long capacity, sectors_per_frame;
1906
1907 if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
1908 return 0;
1909
1910 return capacity * sectors_per_frame;
1911}
Amos Waterlandd97b32142005-10-30 15:02:10 -08001912#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Russell King4031bbe2006-01-06 11:41:00 +00001914static void ide_cd_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915{
1916 struct cdrom_info *info = drive->driver_data;
1917
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001918 ide_proc_unregister_driver(drive, info->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
1920 del_gendisk(info->disk);
1921
1922 ide_cd_put(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923}
1924
1925static void ide_cd_release(struct kref *kref)
1926{
1927 struct cdrom_info *info = to_ide_cd(kref);
1928 struct cdrom_device_info *devinfo = &info->devinfo;
1929 ide_drive_t *drive = info->drive;
1930 struct gendisk *g = info->disk;
1931
Jesper Juhl6044ec82005-11-07 01:01:32 -08001932 kfree(info->toc);
Akinobu Mita0a0c4112008-03-26 12:09:02 +01001933 if (devinfo->handle == drive)
1934 unregister_cdrom(devinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 drive->dsc_overlap = 0;
1936 drive->driver_data = NULL;
1937 blk_queue_prep_rq(drive->queue, NULL);
1938 g->private_data = NULL;
1939 put_disk(g);
1940 kfree(info);
1941}
1942
Russell King4031bbe2006-01-06 11:41:00 +00001943static int ide_cd_probe(ide_drive_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +02001945#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946static int proc_idecd_read_capacity
1947 (char *page, char **start, off_t off, int count, int *eof, void *data)
1948{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001949 ide_drive_t *drive = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 int len;
1951
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001952 len = sprintf(page, "%llu\n", (long long)ide_cdrom_capacity(drive));
1953 PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954}
1955
1956static ide_proc_entry_t idecd_proc[] = {
1957 { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
1958 { NULL, 0, NULL, NULL }
1959};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960#endif
1961
1962static ide_driver_t ide_cdrom_driver = {
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001963 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +01001964 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001965 .name = "ide-cdrom",
1966 .bus = &ide_bus_type,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02001967 },
Russell King4031bbe2006-01-06 11:41:00 +00001968 .probe = ide_cd_probe,
1969 .remove = ide_cd_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 .version = IDECD_VERSION,
1971 .media = ide_cdrom,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 .supports_dsc_overlap = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 .do_request = ide_do_rw_cdrom,
1974 .end_request = ide_end_request,
1975 .error = __ide_error,
1976 .abort = __ide_abort,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001977#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 .proc = idecd_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02001979#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980};
1981
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001982static int idecd_open(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983{
1984 struct gendisk *disk = inode->i_bdev->bd_disk;
1985 struct cdrom_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 int rc = -ENOMEM;
1987
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02001988 info = ide_cd_get(disk);
1989 if (!info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 return -ENXIO;
1991
Borislav Petkov968c4962008-04-26 17:36:37 +02001992 rc = cdrom_open(&info->devinfo, inode, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993
1994 if (rc < 0)
1995 ide_cd_put(info);
1996
1997 return rc;
1998}
1999
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002000static int idecd_release(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001{
2002 struct gendisk *disk = inode->i_bdev->bd_disk;
2003 struct cdrom_info *info = ide_cd_g(disk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002005 cdrom_release(&info->devinfo, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
2007 ide_cd_put(info);
2008
2009 return 0;
2010}
2011
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002012static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg)
2013{
2014 struct packet_command cgc;
2015 char buffer[16];
2016 int stat;
2017 char spindown;
2018
2019 if (copy_from_user(&spindown, (void __user *)arg, sizeof(char)))
2020 return -EFAULT;
2021
2022 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
2023
2024 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
2025 if (stat)
2026 return stat;
2027
2028 buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
2029 return cdrom_mode_select(cdi, &cgc);
2030}
2031
2032static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
2033{
2034 struct packet_command cgc;
2035 char buffer[16];
2036 int stat;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002037 char spindown;
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002038
2039 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
2040
2041 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
2042 if (stat)
2043 return stat;
2044
2045 spindown = buffer[11] & 0x0f;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002046 if (copy_to_user((void __user *)arg, &spindown, sizeof(char)))
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002047 return -EFAULT;
2048 return 0;
2049}
2050
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002051static int idecd_ioctl(struct inode *inode, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 unsigned int cmd, unsigned long arg)
2053{
2054 struct block_device *bdev = inode->i_bdev;
2055 struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
2056 int err;
2057
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002058 switch (cmd) {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002059 case CDROMSETSPINDOWN:
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002060 return idecd_set_spindown(&info->devinfo, arg);
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002061 case CDROMGETSPINDOWN:
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002062 return idecd_get_spindown(&info->devinfo, arg);
2063 default:
2064 break;
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002065 }
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002066
2067 err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 if (err == -EINVAL)
2069 err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
2070
2071 return err;
2072}
2073
2074static int idecd_media_changed(struct gendisk *disk)
2075{
2076 struct cdrom_info *info = ide_cd_g(disk);
2077 return cdrom_media_changed(&info->devinfo);
2078}
2079
2080static int idecd_revalidate_disk(struct gendisk *disk)
2081{
2082 struct cdrom_info *info = ide_cd_g(disk);
2083 struct request_sense sense;
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01002084
2085 ide_cd_read_toc(info->drive, &sense);
2086
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 return 0;
2088}
2089
2090static struct block_device_operations idecd_ops = {
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002091 .owner = THIS_MODULE,
2092 .open = idecd_open,
2093 .release = idecd_release,
2094 .ioctl = idecd_ioctl,
2095 .media_changed = idecd_media_changed,
2096 .revalidate_disk = idecd_revalidate_disk
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097};
2098
2099/* options */
Paolo Ciarrocchi9ce70fb2008-04-26 17:36:42 +02002100static char *ignore;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
2102module_param(ignore, charp, 0400);
2103MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
2104
Russell King4031bbe2006-01-06 11:41:00 +00002105static int ide_cd_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106{
2107 struct cdrom_info *info;
2108 struct gendisk *g;
2109 struct request_sense sense;
2110
2111 if (!strstr("ide-cdrom", drive->driver_req))
2112 goto failed;
2113 if (!drive->present)
2114 goto failed;
2115 if (drive->media != ide_cdrom && drive->media != ide_optical)
2116 goto failed;
2117 /* skip drives that we were told to ignore */
2118 if (ignore != NULL) {
2119 if (strstr(ignore, drive->name)) {
2120 printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name);
2121 goto failed;
2122 }
2123 }
2124 if (drive->scsi) {
2125 printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
2126 goto failed;
2127 }
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08002128 info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129 if (info == NULL) {
2130 printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
2131 goto failed;
2132 }
2133
2134 g = alloc_disk(1 << PARTN_BITS);
2135 if (!g)
2136 goto out_free_cd;
2137
2138 ide_init_disk(g, drive);
2139
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002140 ide_proc_register_driver(drive, &ide_cdrom_driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002141
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 kref_init(&info->kref);
2143
2144 info->drive = drive;
2145 info->driver = &ide_cdrom_driver;
2146 info->disk = g;
2147
2148 g->private_data = &info->driver;
2149
2150 drive->driver_data = info;
2151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 g->minors = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 g->driverfs_dev = &drive->gendev;
2154 g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
2155 if (ide_cdrom_setup(drive)) {
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002156 ide_proc_unregister_driver(drive, &ide_cdrom_driver);
Bartlomiej Zolnierkiewicz05017db2007-12-24 15:23:43 +01002157 ide_cd_release(&info->kref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 goto failed;
2159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01002161 ide_cd_read_toc(drive, &sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 g->fops = &idecd_ops;
2163 g->flags |= GENHD_FL_REMOVABLE;
2164 add_disk(g);
2165 return 0;
2166
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167out_free_cd:
2168 kfree(info);
2169failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002170 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171}
2172
2173static void __exit ide_cdrom_exit(void)
2174{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002175 driver_unregister(&ide_cdrom_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176}
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01002177
2178static int __init ide_cdrom_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002180 return driver_register(&ide_cdrom_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181}
2182
Kay Sievers263756e2005-12-12 18:03:44 +01002183MODULE_ALIAS("ide:*m-cdrom*");
Bartlomiej Zolnierkiewicz972560f2008-02-01 23:09:23 +01002184MODULE_ALIAS("ide-cd");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185module_init(ide_cdrom_init);
2186module_exit(ide_cdrom_exit);
2187MODULE_LICENSE("GPL");