blob: c758e63b0fca7d74283e0f5b1e14809ef22453ee [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/ide/ide-cd.c
3 *
4 * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
5 * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
6 * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
7 *
8 * May be copied or modified under the terms of the GNU General Public
9 * License. See linux/COPYING for more information.
10 *
11 * ATAPI CD-ROM driver. To be used with ide.c.
12 * See Documentation/cdrom/ide-cd for usage information.
13 *
14 * Suggestions are welcome. Patches that work are more welcome though. ;-)
15 * For those wishing to work on this driver, please be sure you download
16 * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
17 * (SFF-8020i rev 2.6) standards. These documents can be obtained by
18 * anonymous ftp from:
19 * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
20 * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
21 *
22 * Drives that deviate from these standards will be accommodated as much
23 * as possible via compile time or command-line options. Since I only have
24 * a few drives, you generally need to send me patches...
25 *
26 * ----------------------------------
27 * TO DO LIST:
28 * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
29 * boot
30 *
Bartlomiej Zolnierkiewicz03553352008-02-01 23:09:18 +010031 * For historical changelog please see:
32 * Documentation/ide/ChangeLog.ide-cd.1994-2004
33 */
34
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#define IDECD_VERSION "4.61"
36
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/module.h>
38#include <linux/types.h>
39#include <linux/kernel.h>
40#include <linux/delay.h>
41#include <linux/timer.h>
42#include <linux/slab.h>
43#include <linux/interrupt.h>
44#include <linux/errno.h>
45#include <linux/cdrom.h>
46#include <linux/ide.h>
47#include <linux/completion.h>
Arjan van de Vencf8b8972006-03-23 03:00:45 -080048#include <linux/mutex.h>
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +010049#include <linux/bcd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
52
53#include <asm/irq.h>
54#include <asm/io.h>
55#include <asm/byteorder.h>
56#include <asm/uaccess.h>
57#include <asm/unaligned.h>
58
59#include "ide-cd.h"
60
Arjan van de Vencf8b8972006-03-23 03:00:45 -080061static DEFINE_MUTEX(idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
64
65#define ide_cd_g(disk) \
66 container_of((disk)->private_data, struct cdrom_info, driver)
67
68static struct cdrom_info *ide_cd_get(struct gendisk *disk)
69{
70 struct cdrom_info *cd = NULL;
71
Arjan van de Vencf8b8972006-03-23 03:00:45 -080072 mutex_lock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 cd = ide_cd_g(disk);
74 if (cd)
75 kref_get(&cd->kref);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080076 mutex_unlock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 return cd;
78}
79
80static void ide_cd_release(struct kref *);
81
82static void ide_cd_put(struct cdrom_info *cd)
83{
Arjan van de Vencf8b8972006-03-23 03:00:45 -080084 mutex_lock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 kref_put(&cd->kref, ide_cd_release);
Arjan van de Vencf8b8972006-03-23 03:00:45 -080086 mutex_unlock(&idecd_ref_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087}
88
89/****************************************************************************
90 * Generic packet command support and error handling routines.
91 */
92
93/* Mark that we've seen a media change, and invalidate our internal
94 buffers. */
95static void cdrom_saw_media_change (ide_drive_t *drive)
96{
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +010097 struct cdrom_info *cd = drive->driver_data;
98
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +010099 cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
100 cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +0100101 cd->nsectors_buffered = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102}
103
104static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
105 struct request_sense *sense)
106{
107 int log = 0;
108
Jens Axboe4aff5e22006-08-10 08:44:47 +0200109 if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return 0;
111
112 switch (sense->sense_key) {
113 case NO_SENSE: case RECOVERED_ERROR:
114 break;
115 case NOT_READY:
116 /*
117 * don't care about tray state messages for
118 * e.g. capacity commands or in-progress or
119 * becoming ready
120 */
121 if (sense->asc == 0x3a || sense->asc == 0x04)
122 break;
123 log = 1;
124 break;
125 case ILLEGAL_REQUEST:
126 /*
127 * don't log START_STOP unit with LoEj set, since
128 * we cannot reliably check if drive can auto-close
129 */
130 if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
Alan Coxdbe217a2006-06-25 05:47:44 -0700131 break;
132 log = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 break;
134 case UNIT_ATTENTION:
135 /*
136 * Make good and sure we've seen this potential media
137 * change. Some drives (i.e. Creative) fail to present
138 * the correct sense key in the error register.
139 */
140 cdrom_saw_media_change(drive);
141 break;
142 default:
143 log = 1;
144 break;
145 }
146 return log;
147}
148
149static
150void cdrom_analyze_sense_data(ide_drive_t *drive,
151 struct request *failed_command,
152 struct request_sense *sense)
153{
Alan Coxdbe217a2006-06-25 05:47:44 -0700154 unsigned long sector;
155 unsigned long bio_sectors;
156 unsigned long valid;
157 struct cdrom_info *info = drive->driver_data;
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 if (!cdrom_log_sense(drive, failed_command, sense))
160 return;
161
162 /*
163 * If a read toc is executed for a CD-R or CD-RW medium where
164 * the first toc has not been recorded yet, it will fail with
165 * 05/24/00 (which is a confusing error)
166 */
167 if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP)
168 if (sense->sense_key == 0x05 && sense->asc == 0x24)
169 return;
170
Alan Coxdbe217a2006-06-25 05:47:44 -0700171 if (sense->error_code == 0x70) { /* Current Error */
172 switch(sense->sense_key) {
173 case MEDIUM_ERROR:
174 case VOLUME_OVERFLOW:
175 case ILLEGAL_REQUEST:
176 if (!sense->valid)
177 break;
178 if (failed_command == NULL ||
179 !blk_fs_request(failed_command))
180 break;
181 sector = (sense->information[0] << 24) |
182 (sense->information[1] << 16) |
183 (sense->information[2] << 8) |
184 (sense->information[3]);
185
186 bio_sectors = bio_sectors(failed_command->bio);
187 if (bio_sectors < 4)
188 bio_sectors = 4;
189 if (drive->queue->hardsect_size == 2048)
190 sector <<= 2; /* Device sector size is 2K */
191 sector &= ~(bio_sectors -1);
192 valid = (sector - failed_command->sector) << 9;
193
194 if (valid < 0)
195 valid = 0;
196 if (sector < get_capacity(info->disk) &&
197 drive->probed_capacity - sector < 4 * 75) {
198 set_capacity(info->disk, sector);
199 }
200 }
201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
Bartlomiej Zolnierkiewicz972560f2008-02-01 23:09:23 +0100203 ide_cd_log_error(drive->name, failed_command, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204}
205
206/*
207 * Initialize a ide-cd packet command request
208 */
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +0100209void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
211 struct cdrom_info *cd = drive->driver_data;
212
213 ide_init_drive_cmd(rq);
Jens Axboecea28852006-10-12 15:08:45 +0200214 rq->cmd_type = REQ_TYPE_ATA_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 rq->rq_disk = cd->disk;
216}
217
218static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
219 struct request *failed_command)
220{
221 struct cdrom_info *info = drive->driver_data;
222 struct request *rq = &info->request_sense_request;
223
224 if (sense == NULL)
225 sense = &info->sense_data;
226
227 /* stuff the sense request in front of our current request */
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +0100228 ide_cd_init_rq(drive, rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 rq->data = sense;
231 rq->cmd[0] = GPCMD_REQUEST_SENSE;
232 rq->cmd[4] = rq->data_len = 18;
233
Jens Axboe4aff5e22006-08-10 08:44:47 +0200234 rq->cmd_type = REQ_TYPE_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
236 /* NOTE! Save the failed command in "rq->buffer" */
237 rq->buffer = (void *) failed_command;
238
239 (void) ide_do_drive_cmd(drive, rq, ide_preempt);
240}
241
242static void cdrom_end_request (ide_drive_t *drive, int uptodate)
243{
244 struct request *rq = HWGROUP(drive)->rq;
245 int nsectors = rq->hard_cur_sectors;
246
Jens Axboe4aff5e22006-08-10 08:44:47 +0200247 if (blk_sense_request(rq) && uptodate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 /*
Jens Axboe4aff5e22006-08-10 08:44:47 +0200249 * For REQ_TYPE_SENSE, "rq->buffer" points to the original
250 * failed request
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 */
252 struct request *failed = (struct request *) rq->buffer;
253 struct cdrom_info *info = drive->driver_data;
254 void *sense = &info->sense_data;
255 unsigned long flags;
256
257 if (failed) {
258 if (failed->sense) {
259 sense = failed->sense;
260 failed->sense_len = rq->sense_len;
261 }
Alan Coxdbe217a2006-06-25 05:47:44 -0700262 cdrom_analyze_sense_data(drive, failed, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 /*
264 * now end failed request
265 */
Alan Coxdbe217a2006-06-25 05:47:44 -0700266 if (blk_fs_request(failed)) {
267 if (ide_end_dequeued_request(drive, failed, 0,
268 failed->hard_nr_sectors))
269 BUG();
270 } else {
271 spin_lock_irqsave(&ide_lock, flags);
Kiyoshi Ueda5e36bb62008-01-28 10:34:20 +0100272 if (__blk_end_request(failed, -EIO,
273 failed->data_len))
274 BUG();
Alan Coxdbe217a2006-06-25 05:47:44 -0700275 spin_unlock_irqrestore(&ide_lock, flags);
276 }
277 } else
278 cdrom_analyze_sense_data(drive, NULL, sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280
281 if (!rq->current_nr_sectors && blk_fs_request(rq))
282 uptodate = 1;
283 /* make sure it's fully ended */
284 if (blk_pc_request(rq))
285 nsectors = (rq->data_len + 511) >> 9;
286 if (!nsectors)
287 nsectors = 1;
288
289 ide_end_request(drive, uptodate, nsectors);
290}
291
Alan Coxdbe217a2006-06-25 05:47:44 -0700292static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
293{
294 if (stat & 0x80)
295 return;
296 ide_dump_status(drive, msg, stat);
297}
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299/* Returns 0 if the request should be continued.
300 Returns 1 if the request was ended. */
301static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
302{
303 struct request *rq = HWGROUP(drive)->rq;
304 int stat, err, sense_key;
305
306 /* Check for errors. */
307 stat = HWIF(drive)->INB(IDE_STATUS_REG);
308 if (stat_ret)
309 *stat_ret = stat;
310
311 if (OK_STAT(stat, good_stat, BAD_R_STAT))
312 return 0;
313
314 /* Get the IDE error register. */
315 err = HWIF(drive)->INB(IDE_ERROR_REG);
316 sense_key = err >> 4;
317
318 if (rq == NULL) {
319 printk("%s: missing rq in cdrom_decode_status\n", drive->name);
320 return 1;
321 }
322
Jens Axboe4aff5e22006-08-10 08:44:47 +0200323 if (blk_sense_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 /* We got an error trying to get sense info
325 from the drive (probably while trying
326 to recover from a former error). Just give up. */
327
Jens Axboe4aff5e22006-08-10 08:44:47 +0200328 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 cdrom_end_request(drive, 0);
330 ide_error(drive, "request sense failure", stat);
331 return 1;
332
Jens Axboe8770c012006-10-12 17:24:52 +0200333 } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 /* All other functions, except for READ. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336 /*
337 * if we have an error, pass back CHECK_CONDITION as the
338 * scsi status byte
339 */
Jens Axboeb7156732006-11-13 18:05:02 +0100340 if (blk_pc_request(rq) && !rq->errors)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 rq->errors = SAM_STAT_CHECK_CONDITION;
342
343 /* Check for tray open. */
344 if (sense_key == NOT_READY) {
345 cdrom_saw_media_change (drive);
346 } else if (sense_key == UNIT_ATTENTION) {
347 /* Check for media change. */
348 cdrom_saw_media_change (drive);
349 /*printk("%s: media changed\n",drive->name);*/
350 return 0;
Stuart Hayes76ca1af2007-04-10 22:38:43 +0200351 } else if ((sense_key == ILLEGAL_REQUEST) &&
352 (rq->cmd[0] == GPCMD_START_STOP_UNIT)) {
353 /*
354 * Don't print error message for this condition--
355 * SFF8090i indicates that 5/24/00 is the correct
356 * response to a request to close the tray if the
357 * drive doesn't have that capability.
358 * cdrom_log_sense() knows this!
359 */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200360 } else if (!(rq->cmd_flags & REQ_QUIET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 /* Otherwise, print an error. */
362 ide_dump_status(drive, "packet command error", stat);
363 }
364
Jens Axboe4aff5e22006-08-10 08:44:47 +0200365 rq->cmd_flags |= REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 /*
368 * instead of playing games with moving completions around,
369 * remove failed request completely and end it when the
370 * request sense has completed
371 */
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100372 goto end_request;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
374 } else if (blk_fs_request(rq)) {
375 int do_end_request = 0;
376
377 /* Handle errors from READ and WRITE requests. */
378
379 if (blk_noretry_request(rq))
380 do_end_request = 1;
381
382 if (sense_key == NOT_READY) {
383 /* Tray open. */
384 if (rq_data_dir(rq) == READ) {
385 cdrom_saw_media_change (drive);
386
387 /* Fail the request. */
388 printk ("%s: tray open\n", drive->name);
389 do_end_request = 1;
390 } else {
391 struct cdrom_info *info = drive->driver_data;
392
393 /* allow the drive 5 seconds to recover, some
394 * devices will return this error while flushing
395 * data from cache */
396 if (!rq->errors)
397 info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY;
398 rq->errors = 1;
399 if (time_after(jiffies, info->write_timeout))
400 do_end_request = 1;
401 else {
402 unsigned long flags;
403
404 /*
405 * take a breather relying on the
406 * unplug timer to kick us again
407 */
408 spin_lock_irqsave(&ide_lock, flags);
409 blk_plug_device(drive->queue);
410 spin_unlock_irqrestore(&ide_lock,flags);
411 return 1;
412 }
413 }
414 } else if (sense_key == UNIT_ATTENTION) {
415 /* Media change. */
416 cdrom_saw_media_change (drive);
417
418 /* Arrange to retry the request.
419 But be sure to give up if we've retried
420 too many times. */
421 if (++rq->errors > ERROR_MAX)
422 do_end_request = 1;
423 } else if (sense_key == ILLEGAL_REQUEST ||
424 sense_key == DATA_PROTECT) {
425 /* No point in retrying after an illegal
426 request or data protect error.*/
Alan Coxdbe217a2006-06-25 05:47:44 -0700427 ide_dump_status_no_sense (drive, "command error", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 do_end_request = 1;
429 } else if (sense_key == MEDIUM_ERROR) {
430 /* No point in re-trying a zillion times on a bad
431 * sector... If we got here the error is not correctable */
Alan Coxdbe217a2006-06-25 05:47:44 -0700432 ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 do_end_request = 1;
434 } else if (sense_key == BLANK_CHECK) {
435 /* Disk appears blank ?? */
Alan Coxdbe217a2006-06-25 05:47:44 -0700436 ide_dump_status_no_sense (drive, "media error (blank)", stat);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 do_end_request = 1;
438 } else if ((err & ~ABRT_ERR) != 0) {
439 /* Go to the default handler
440 for other errors. */
441 ide_error(drive, "cdrom_decode_status", stat);
442 return 1;
443 } else if ((++rq->errors > ERROR_MAX)) {
444 /* We've racked up too many retries. Abort. */
445 do_end_request = 1;
446 }
447
Alan Coxdbe217a2006-06-25 05:47:44 -0700448 /* End a request through request sense analysis when we have
449 sense data. We need this in order to perform end of media
450 processing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100452 if (do_end_request)
453 goto end_request;
Alan Coxdbe217a2006-06-25 05:47:44 -0700454
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100455 /*
456 * If we got a CHECK_CONDITION status,
457 * queue a request sense command.
458 */
459 if (stat & ERR_STAT)
460 cdrom_queue_request_sense(drive, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 } else {
462 blk_dump_rq_flags(rq, "ide-cd: bad rq");
463 cdrom_end_request(drive, 0);
464 }
465
466 /* Retry, or handle the next request. */
467 return 1;
Bartlomiej Zolnierkiewiczbbb89e32008-02-01 23:09:28 +0100468
469end_request:
470 if (stat & ERR_STAT) {
471 unsigned long flags;
472
473 spin_lock_irqsave(&ide_lock, flags);
474 blkdev_dequeue_request(rq);
475 HWGROUP(drive)->rq = NULL;
476 spin_unlock_irqrestore(&ide_lock, flags);
477
478 cdrom_queue_request_sense(drive, rq->sense, rq);
479 } else
480 cdrom_end_request(drive, 0);
481
482 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483}
484
485static int cdrom_timer_expiry(ide_drive_t *drive)
486{
487 struct request *rq = HWGROUP(drive)->rq;
488 unsigned long wait = 0;
489
490 /*
491 * Some commands are *slow* and normally take a long time to
492 * complete. Usually we can use the ATAPI "disconnect" to bypass
493 * this, but not all commands/drives support that. Let
494 * ide_timer_expiry keep polling us for these.
495 */
496 switch (rq->cmd[0]) {
497 case GPCMD_BLANK:
498 case GPCMD_FORMAT_UNIT:
499 case GPCMD_RESERVE_RZONE_TRACK:
500 case GPCMD_CLOSE_TRACK:
501 case GPCMD_FLUSH_CACHE:
502 wait = ATAPI_WAIT_PC;
503 break;
504 default:
Jens Axboe4aff5e22006-08-10 08:44:47 +0200505 if (!(rq->cmd_flags & REQ_QUIET))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
507 wait = 0;
508 break;
509 }
510 return wait;
511}
512
513/* Set up the device registers for transferring a packet command on DEV,
514 expecting to later transfer XFERLEN bytes. HANDLER is the routine
515 which actually transfers the command to the drive. If this is a
516 drq_interrupt device, this routine will arrange for HANDLER to be
517 called when the interrupt from the drive arrives. Otherwise, HANDLER
518 will be called immediately after the drive is prepared for the transfer. */
519
520static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
521 int xferlen,
522 ide_handler_t *handler)
523{
524 ide_startstop_t startstop;
525 struct cdrom_info *info = drive->driver_data;
526 ide_hwif_t *hwif = drive->hwif;
527
528 /* Wait for the controller to be idle. */
529 if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
530 return startstop;
531
Bartlomiej Zolnierkiewicz3a6a3542008-01-25 22:17:13 +0100532 /* FIXME: for Virtual DMA we must check harder */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 if (info->dma)
534 info->dma = !hwif->dma_setup(drive);
535
536 /* Set up the controller registers. */
Bartlomiej Zolnierkiewicz2fc57382008-01-25 22:17:13 +0100537 ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
538 IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +0100539
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100540 if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Albert Leef0dd8712007-02-17 02:40:21 +0100541 /* waiting for CDB interrupt, not DMA yet. */
542 if (info->dma)
543 drive->waiting_for_dma = 0;
544
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 /* packet command */
546 ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
547 return ide_started;
548 } else {
549 unsigned long flags;
550
551 /* packet command */
552 spin_lock_irqsave(&ide_lock, flags);
553 hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG);
554 ndelay(400);
555 spin_unlock_irqrestore(&ide_lock, flags);
556
557 return (*handler) (drive);
558 }
559}
560
561/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN.
562 The device registers must have already been prepared
563 by cdrom_start_packet_command.
564 HANDLER is the interrupt handler to call when the command completes
565 or there's data ready. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566#define ATAPI_MIN_CDB_BYTES 12
567static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
568 struct request *rq,
569 ide_handler_t *handler)
570{
571 ide_hwif_t *hwif = drive->hwif;
572 int cmd_len;
573 struct cdrom_info *info = drive->driver_data;
574 ide_startstop_t startstop;
575
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100576 if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 /* Here we should have been called after receiving an interrupt
578 from the device. DRQ should how be set. */
579
580 /* Check for errors. */
581 if (cdrom_decode_status(drive, DRQ_STAT, NULL))
582 return ide_stopped;
Albert Leef0dd8712007-02-17 02:40:21 +0100583
584 /* Ok, next interrupt will be DMA interrupt. */
585 if (info->dma)
586 drive->waiting_for_dma = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 } else {
588 /* Otherwise, we must wait for DRQ to get set. */
589 if (ide_wait_stat(&startstop, drive, DRQ_STAT,
590 BUSY_STAT, WAIT_READY))
591 return startstop;
592 }
593
594 /* Arm the interrupt handler. */
595 ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
596
597 /* ATAPI commands get padded out to 12 bytes minimum */
598 cmd_len = COMMAND_SIZE(rq->cmd[0]);
599 if (cmd_len < ATAPI_MIN_CDB_BYTES)
600 cmd_len = ATAPI_MIN_CDB_BYTES;
601
602 /* Send the command to the device. */
603 HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len);
604
605 /* Start the DMA if need be */
606 if (info->dma)
607 hwif->dma_start(drive);
608
609 return ide_started;
610}
611
612/****************************************************************************
613 * Block read functions.
614 */
615
Bartlomiej Zolnierkiewicz68661c52008-02-01 23:09:17 +0100616typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
617
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100618static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
619{
620 while (len > 0) {
621 int dum = 0;
622 xf(drive, &dum, sizeof(dum));
623 len -= sizeof(dum);
624 }
625}
626
Bartlomiej Zolnierkiewiczb4ab7262008-02-01 23:09:26 +0100627static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
628{
629 while (nsects > 0) {
630 static char dum[SECTOR_SIZE];
631
632 drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
633 nsects--;
634 }
635}
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637/*
638 * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
639 * buffer. Once the first sector is added, any subsequent sectors are
640 * assumed to be continuous (until the buffer is cleared). For the first
641 * sector added, SECTOR is its sector number. (SECTOR is then ignored until
642 * the buffer is cleared.)
643 */
644static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
645 int sectors_to_transfer)
646{
647 struct cdrom_info *info = drive->driver_data;
648
649 /* Number of sectors to read into the buffer. */
650 int sectors_to_buffer = min_t(int, sectors_to_transfer,
651 (SECTOR_BUFFER_SIZE >> SECTOR_BITS) -
652 info->nsectors_buffered);
653
654 char *dest;
655
656 /* If we couldn't get a buffer, don't try to buffer anything... */
657 if (info->buffer == NULL)
658 sectors_to_buffer = 0;
659
660 /* If this is the first sector in the buffer, remember its number. */
661 if (info->nsectors_buffered == 0)
662 info->sector_buffered = sector;
663
664 /* Read the data into the buffer. */
665 dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
666 while (sectors_to_buffer > 0) {
667 HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE);
668 --sectors_to_buffer;
669 --sectors_to_transfer;
670 ++info->nsectors_buffered;
671 dest += SECTOR_SIZE;
672 }
673
674 /* Throw away any remaining data. */
Bartlomiej Zolnierkiewiczb4ab7262008-02-01 23:09:26 +0100675 ide_cd_drain_data(drive, sectors_to_transfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676}
677
678/*
679 * Check the contents of the interrupt reason register from the cdrom
680 * and attempt to recover if there are problems. Returns 0 if everything's
681 * ok; nonzero if the request has been terminated.
682 */
Arjan van de Ven858119e2006-01-14 13:20:43 -0800683static
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100684int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100686 /*
687 * ireason == 0: the drive wants to receive data from us
688 * ireason == 2: the drive is expecting to transfer data to us
689 */
690 if (ireason == (!rw << 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 return 0;
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100692 else if (ireason == (rw << 1)) {
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100693 ide_hwif_t *hwif = drive->hwif;
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100694 xfer_func_t *xf;
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +0100695
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100696 /* Whoops... */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +0100697 printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
698 drive->name, __FUNCTION__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +0100700 xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
701 ide_cd_pad_transfer(drive, xf, len);
702 } else if (rw == 0 && ireason == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 /* Some drives (ASUS) seem to tell us that status
704 * info is available. just get it and ignore.
705 */
706 (void) HWIF(drive)->INB(IDE_STATUS_REG);
707 return 0;
708 } else {
709 /* Drive wants a command packet, or invalid ireason... */
Bartlomiej Zolnierkiewicz35379c02007-12-24 15:23:43 +0100710 printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
711 drive->name, __FUNCTION__, ireason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 }
713
714 cdrom_end_request(drive, 0);
715 return -1;
716}
717
718/*
Bartlomiej Zolnierkiewicz64814f22008-02-01 23:09:26 +0100719 * Assume that the drive will always provide data in multiples of at least
720 * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
721 */
722static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
723{
724 struct cdrom_info *cd = drive->driver_data;
725
726 if ((len % SECTOR_SIZE) == 0)
727 return 0;
728
729 printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
730 drive->name, __FUNCTION__, len);
731
732 if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
733 printk(KERN_ERR " This drive is not supported by "
734 "this version of the driver\n");
735 else {
736 printk(KERN_ERR " Trying to limit transfer sizes\n");
737 cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
738 }
739
740 return 1;
741}
742
743/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 * Try to satisfy some of the current read request from our cached data.
745 * Returns nonzero if the request has been completed, zero otherwise.
746 */
747static int cdrom_read_from_buffer (ide_drive_t *drive)
748{
749 struct cdrom_info *info = drive->driver_data;
750 struct request *rq = HWGROUP(drive)->rq;
751 unsigned short sectors_per_frame;
752
753 sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
754
755 /* Can't do anything if there's no buffer. */
756 if (info->buffer == NULL) return 0;
757
758 /* Loop while this request needs data and the next block is present
759 in our cache. */
760 while (rq->nr_sectors > 0 &&
761 rq->sector >= info->sector_buffered &&
762 rq->sector < info->sector_buffered + info->nsectors_buffered) {
763 if (rq->current_nr_sectors == 0)
764 cdrom_end_request(drive, 1);
765
766 memcpy (rq->buffer,
767 info->buffer +
768 (rq->sector - info->sector_buffered) * SECTOR_SIZE,
769 SECTOR_SIZE);
770 rq->buffer += SECTOR_SIZE;
771 --rq->current_nr_sectors;
772 --rq->nr_sectors;
773 ++rq->sector;
774 }
775
776 /* If we've satisfied the current request,
777 terminate it successfully. */
778 if (rq->nr_sectors == 0) {
779 cdrom_end_request(drive, 1);
780 return -1;
781 }
782
783 /* Move on to the next buffer if needed. */
784 if (rq->current_nr_sectors == 0)
785 cdrom_end_request(drive, 1);
786
787 /* If this condition does not hold, then the kluge i use to
788 represent the number of sectors to skip at the start of a transfer
789 will fail. I think that this will never happen, but let's be
790 paranoid and check. */
791 if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) &&
792 (rq->sector & (sectors_per_frame - 1))) {
793 printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
794 drive->name, (long)rq->sector);
795 cdrom_end_request(drive, 0);
796 return -1;
797 }
798
799 return 0;
800}
801
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100802static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
Bartlomiej Zolnierkiewicz94f5a862008-02-01 23:09:26 +0100803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804/*
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100805 * Routine to send a read/write packet command to the drive.
806 * This is usually called directly from cdrom_start_{read,write}().
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 * However, for drq_interrupt devices, it is called from an interrupt
808 * when the drive is ready to accept the command.
809 */
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100810static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811{
812 struct request *rq = HWGROUP(drive)->rq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100814 if (rq_data_dir(rq) == READ) {
815 unsigned short sectors_per_frame =
816 queue_hardsect_size(drive->queue) >> SECTOR_BITS;
817 int nskip = rq->sector & (sectors_per_frame - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100819 /*
820 * If the requested sector doesn't start on a frame boundary,
821 * we must adjust the start of the transfer so that it does,
822 * and remember to skip the first few sectors.
823 *
824 * If the rq->current_nr_sectors field is larger than the size
825 * of the buffer, it will mean that we're to skip a number of
826 * sectors equal to the amount by which rq->current_nr_sectors
827 * is larger than the buffer size.
828 */
829 if (nskip > 0) {
830 /* Sanity check... */
831 if (rq->current_nr_sectors !=
832 bio_cur_sectors(rq->bio)) {
833 printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
834 drive->name, __FUNCTION__,
835 rq->current_nr_sectors);
836 cdrom_end_request(drive, 0);
837 return ide_stopped;
838 }
839 rq->current_nr_sectors += nskip;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 }
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +0100842#if 0
843 else
844 /* the immediate bit */
845 rq->cmd[1] = 1 << 3;
846#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 /* Set up the command */
848 rq->timeout = ATAPI_WAIT_PC;
849
850 /* Send the command to the drive and return. */
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +0100851 return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852}
853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
855#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
856#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
857
858static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
859{
860 struct cdrom_info *info = drive->driver_data;
861 int stat;
862 static int retry = 10;
863
864 if (cdrom_decode_status(drive, 0, &stat))
865 return ide_stopped;
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +0100866
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +0100867 info->cd_flags |= IDE_CD_FLAG_SEEKING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869 if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
870 if (--retry == 0) {
871 /*
872 * this condition is far too common, to bother
873 * users about it
874 */
875 /* printk("%s: disabled DSC seek overlap\n", drive->name);*/
876 drive->dsc_overlap = 0;
877 }
878 }
879 return ide_stopped;
880}
881
882static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive)
883{
884 struct request *rq = HWGROUP(drive)->rq;
885 sector_t frame = rq->sector;
886
887 sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
888
889 memset(rq->cmd, 0, sizeof(rq->cmd));
890 rq->cmd[0] = GPCMD_SEEK;
891 put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
892
893 rq->timeout = ATAPI_WAIT_PC;
894 return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
895}
896
897static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block)
898{
899 struct cdrom_info *info = drive->driver_data;
900
901 info->dma = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 info->start_seek = jiffies;
903 return cdrom_start_packet_command(drive, 0, cdrom_start_seek_continuation);
904}
905
906/* Fix up a possibly partially-processed request so that we can
907 start it over entirely, or even put it back on the request queue. */
908static void restore_request (struct request *rq)
909{
910 if (rq->buffer != bio_data(rq->bio)) {
911 sector_t n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
912
913 rq->buffer = bio_data(rq->bio);
914 rq->nr_sectors += n;
915 rq->sector -= n;
916 }
917 rq->hard_cur_sectors = rq->current_nr_sectors = bio_cur_sectors(rq->bio);
918 rq->hard_nr_sectors = rq->nr_sectors;
919 rq->hard_sector = rq->sector;
920 rq->q->prep_rq_fn(rq->q, rq);
921}
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923/****************************************************************************
924 * Execute all other packet commands.
925 */
926
Bartlomiej Zolnierkiewicz8ee69f52008-02-01 23:09:25 +0100927static void ide_cd_request_sense_fixup(struct request *rq)
928{
929 /*
930 * Some of the trailing request sense fields are optional,
931 * and some drives don't send them. Sigh.
932 */
933 if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
934 rq->data_len > 0 && rq->data_len <= 5)
935 while (rq->data_len > 0) {
936 *(u8 *)rq->data++ = 0;
937 --rq->data_len;
938 }
939}
940
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +0100941int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942{
943 struct request_sense sense;
944 int retries = 10;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200945 unsigned int flags = rq->cmd_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
947 if (rq->sense == NULL)
948 rq->sense = &sense;
949
950 /* Start of retry loop. */
951 do {
952 int error;
953 unsigned long time = jiffies;
Jens Axboe4aff5e22006-08-10 08:44:47 +0200954 rq->cmd_flags = flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 error = ide_do_drive_cmd(drive, rq, ide_wait);
957 time = jiffies - time;
958
959 /* FIXME: we should probably abort/retry or something
960 * in case of failure */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200961 if (rq->cmd_flags & REQ_FAILED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 /* The request failed. Retry if it was due to a unit
963 attention status
964 (usually means media was changed). */
965 struct request_sense *reqbuf = rq->sense;
966
967 if (reqbuf->sense_key == UNIT_ATTENTION)
968 cdrom_saw_media_change(drive);
969 else if (reqbuf->sense_key == NOT_READY &&
970 reqbuf->asc == 4 && reqbuf->ascq != 4) {
971 /* The drive is in the process of loading
972 a disk. Retry, but wait a little to give
973 the drive time to complete the load. */
974 ssleep(2);
975 } else {
976 /* Otherwise, don't retry. */
977 retries = 0;
978 }
979 --retries;
980 }
981
982 /* End of retry loop. */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200983 } while ((rq->cmd_flags & REQ_FAILED) && retries >= 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984
985 /* Return an error if the command failed. */
Jens Axboe4aff5e22006-08-10 08:44:47 +0200986 return (rq->cmd_flags & REQ_FAILED) ? -EIO : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987}
988
989/*
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -0500990 * Called from blk_end_request_callback() after the data of the request
991 * is completed and before the request is completed.
992 * By returning value '1', blk_end_request_callback() returns immediately
993 * without completing the request.
994 */
995static int cdrom_newpc_intr_dummy_cb(struct request *rq)
996{
997 return 1;
998}
999
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
1001{
1002 struct cdrom_info *info = drive->driver_data;
1003 struct request *rq = HWGROUP(drive)->rq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 xfer_func_t *xferfunc;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001005 ide_expiry_t *expiry = NULL;
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001006 int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
1007 int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
1008 unsigned int timeout;
1009 u8 lowcyl, highcyl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
1011 /* Check for errors. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 dma = info->dma;
1013 if (dma) {
1014 info->dma = 0;
1015 dma_error = HWIF(drive)->ide_dma_end(drive);
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +01001016 if (dma_error) {
1017 printk(KERN_ERR "%s: DMA %s error\n", drive->name,
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001018 write ? "write" : "read");
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +01001019 ide_dma_off(drive);
1020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
1022
1023 if (cdrom_decode_status(drive, 0, &stat))
1024 return ide_stopped;
1025
1026 /*
1027 * using dma, transfer is complete now
1028 */
1029 if (dma) {
Bartlomiej Zolnierkiewiczeba15fb2008-02-01 23:09:17 +01001030 if (dma_error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 return ide_error(drive, "dma error", stat);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001032 if (blk_fs_request(rq)) {
1033 ide_end_request(drive, 1, rq->nr_sectors);
1034 return ide_stopped;
1035 }
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001036 goto end_request;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
1038
1039 /*
1040 * ok we fall to pio :/
1041 */
1042 ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
1043 lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG);
1044 highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
1045
1046 len = lowcyl + (256 * highcyl);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001047
1048 thislen = blk_fs_request(rq) ? len : rq->data_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if (thislen > len)
1050 thislen = len;
1051
1052 /*
1053 * If DRQ is clear, the command has completed.
1054 */
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001055 if ((stat & DRQ_STAT) == 0) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001056 if (blk_fs_request(rq)) {
1057 /*
1058 * If we're not done reading/writing, complain.
1059 * Otherwise, complete the command normally.
1060 */
1061 uptodate = 1;
1062 if (rq->current_nr_sectors > 0) {
1063 printk(KERN_ERR "%s: %s: data underrun "
1064 "(%d blocks)\n",
1065 drive->name, __FUNCTION__,
1066 rq->current_nr_sectors);
1067 if (!write)
1068 rq->cmd_flags |= REQ_FAILED;
1069 uptodate = 0;
1070 }
1071 cdrom_end_request(drive, uptodate);
1072 return ide_stopped;
1073 } else if (!blk_pc_request(rq)) {
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001074 ide_cd_request_sense_fixup(rq);
1075 /* Complain if we still have data left to transfer. */
1076 uptodate = rq->data_len ? 0 : 1;
1077 }
1078 goto end_request;
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 /*
1082 * check which way to transfer data
1083 */
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +01001084 if (blk_fs_request(rq) || blk_pc_request(rq)) {
1085 if (ide_cd_check_ireason(drive, len, ireason, write))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 return ide_stopped;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001087
Bartlomiej Zolnierkiewicz0d6f7e32008-02-01 23:09:28 +01001088 if (blk_fs_request(rq) && write == 0) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001089 int nskip;
1090
1091 if (ide_cd_check_transfer_size(drive, len)) {
1092 cdrom_end_request(drive, 0);
1093 return ide_stopped;
1094 }
1095
1096 /*
1097 * First, figure out if we need to bit-bucket
1098 * any of the leading sectors.
1099 */
1100 nskip = min_t(int, rq->current_nr_sectors
1101 - bio_cur_sectors(rq->bio),
1102 thislen >> 9);
1103 if (nskip > 0) {
1104 ide_cd_drain_data(drive, nskip);
1105 rq->current_nr_sectors -= nskip;
1106 thislen -= (nskip << 9);
1107 }
1108 }
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001111 if (ireason == 0) {
1112 write = 1;
1113 xferfunc = HWIF(drive)->atapi_output_bytes;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001114 } else if (ireason == 2 || (ireason == 1 &&
1115 (blk_fs_request(rq) || blk_pc_request(rq)))) {
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001116 write = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 xferfunc = HWIF(drive)->atapi_input_bytes;
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001118 } else {
1119 printk(KERN_ERR "%s: %s: The drive "
1120 "appears confused (ireason = 0x%02x). "
1121 "Trying to recover by ending request.\n",
1122 drive->name, __FUNCTION__, ireason);
1123 goto end_request;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
1125
1126 /*
1127 * transfer data
1128 */
1129 while (thislen > 0) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001130 u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
Bartlomiej Zolnierkiewicza11e77d2008-02-01 23:09:27 +01001131 int blen = rq->data_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
1133 /*
1134 * bio backed?
1135 */
1136 if (rq->bio) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001137 if (blk_fs_request(rq)) {
1138 ptr = rq->buffer;
1139 blen = rq->current_nr_sectors << 9;
1140 } else {
1141 ptr = bio_data(rq->bio);
1142 blen = bio_iovec(rq->bio)->bv_len;
1143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 }
1145
1146 if (!ptr) {
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001147 if (blk_fs_request(rq) && !write)
1148 /*
1149 * If the buffers are full, cache the rest
1150 * of the data in our internal buffer.
1151 */
1152 cdrom_buffer_sectors(drive, rq->sector,
1153 thislen >> 9);
1154 else {
1155 printk(KERN_ERR "%s: confused, missing data\n",
1156 drive->name);
1157 blk_dump_rq_flags(rq, rq_data_dir(rq)
1158 ? "cdrom_newpc_intr, write"
1159 : "cdrom_newpc_intr, read");
1160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 break;
1162 }
1163
1164 if (blen > thislen)
1165 blen = thislen;
1166
1167 xferfunc(drive, ptr, blen);
1168
1169 thislen -= blen;
1170 len -= blen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001172 if (blk_fs_request(rq)) {
1173 rq->buffer += blen;
1174 rq->nr_sectors -= (blen >> 9);
1175 rq->current_nr_sectors -= (blen >> 9);
1176 rq->sector += (blen >> 9);
1177
1178 if (rq->current_nr_sectors == 0 && rq->nr_sectors)
1179 cdrom_end_request(drive, 1);
1180 } else {
1181 rq->data_len -= blen;
1182
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001183 /*
1184 * The request can't be completed until DRQ is cleared.
1185 * So complete the data, but don't complete the request
1186 * using the dummy function for the callback feature
1187 * of blk_end_request_callback().
1188 */
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001189 if (rq->bio)
1190 blk_end_request_callback(rq, 0, blen,
Kiyoshi Uedaaaa04c22007-12-11 17:51:23 -05001191 cdrom_newpc_intr_dummy_cb);
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001192 else
1193 rq->data += blen;
1194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 }
1196
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001197 if (write && blk_sense_request(rq))
1198 rq->sense_len += thislen;
1199
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 /*
1201 * pad, if necessary
1202 */
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001203 if (!blk_fs_request(rq) && len > 0)
Bartlomiej Zolnierkiewicz5a5222d2008-02-01 23:09:17 +01001204 ide_cd_pad_transfer(drive, xferfunc, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001206 if (blk_pc_request(rq)) {
1207 timeout = rq->timeout;
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001208 } else {
1209 timeout = ATAPI_WAIT_PC;
Bartlomiej Zolnierkiewicz0041e7c2008-02-01 23:09:28 +01001210 if (!blk_fs_request(rq))
1211 expiry = cdrom_timer_expiry;
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001212 }
1213
1214 ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 return ide_started;
Bartlomiej Zolnierkiewiczff1bfbc2008-02-01 23:09:25 +01001216
1217end_request:
1218 if (blk_pc_request(rq)) {
1219 unsigned long flags;
1220
1221 spin_lock_irqsave(&ide_lock, flags);
1222 if (__blk_end_request(rq, 0, rq->data_len))
1223 BUG();
1224 HWGROUP(drive)->rq = NULL;
1225 spin_unlock_irqrestore(&ide_lock, flags);
1226 } else {
1227 if (!uptodate)
1228 rq->cmd_flags |= REQ_FAILED;
1229 cdrom_end_request(drive, uptodate);
1230 }
1231 return ide_stopped;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232}
1233
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001234static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001236 struct cdrom_info *cd = drive->driver_data;
1237 int write = rq_data_dir(rq) == WRITE;
1238 unsigned short sectors_per_frame =
1239 queue_hardsect_size(drive->queue) >> SECTOR_BITS;
1240
1241 if (write) {
1242 /*
1243 * disk has become write protected
1244 */
1245 if (cd->disk->policy) {
1246 cdrom_end_request(drive, 0);
1247 return ide_stopped;
1248 }
1249 } else {
1250 /*
1251 * We may be retrying this request after an error. Fix up any
1252 * weirdness which might be present in the request packet.
1253 */
1254 restore_request(rq);
1255
1256 /* Satisfy whatever we can of this request from our cache. */
1257 if (cdrom_read_from_buffer(drive))
1258 return ide_stopped;
1259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
1261 /*
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001262 * use DMA, if possible / writes *must* be hardware frame aligned
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 */
1264 if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
1265 (rq->sector & (sectors_per_frame - 1))) {
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001266 if (write) {
1267 cdrom_end_request(drive, 0);
1268 return ide_stopped;
1269 }
1270 cd->dma = 0;
1271 } else
1272 cd->dma = drive->using_dma;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001274 /* Clear the local sector buffer. */
1275 cd->nsectors_buffered = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001277 if (write)
1278 cd->devinfo.media_written = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001280 /* Start sending the read/write request to the drive. */
Bartlomiej Zolnierkiewicz29f3aac2008-02-01 23:09:27 +01001281 return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282}
1283
1284static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
1285{
1286 struct request *rq = HWGROUP(drive)->rq;
1287
1288 if (!rq->timeout)
1289 rq->timeout = ATAPI_WAIT_PC;
1290
1291 return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
1292}
1293
1294static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
1295{
1296 struct cdrom_info *info = drive->driver_data;
1297
Bartlomiej Zolnierkiewiczc9f56a82008-02-01 23:09:26 +01001298 if (blk_pc_request(rq))
1299 rq->cmd_flags |= REQ_QUIET;
1300 else
1301 rq->cmd_flags &= ~REQ_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
1303 info->dma = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
1305 /*
1306 * sg request
1307 */
1308 if (rq->bio) {
1309 int mask = drive->queue->dma_alignment;
1310 unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));
1311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 info->dma = drive->using_dma;
1313
1314 /*
1315 * check if dma is safe
Linus Torvalds5d9e4ea2005-05-27 07:36:17 -07001316 *
1317 * NOTE! The "len" and "addr" checks should possibly have
1318 * separate masks.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 */
Jens Axboe4e7c6812005-05-31 17:47:36 +02001320 if ((rq->data_len & 15) || (addr & mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 info->dma = 0;
1322 }
1323
1324 /* Start sending the command to the drive. */
1325 return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont);
1326}
1327
1328/****************************************************************************
1329 * cdrom driver request routine.
1330 */
1331static ide_startstop_t
1332ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
1333{
1334 ide_startstop_t action;
1335 struct cdrom_info *info = drive->driver_data;
1336
1337 if (blk_fs_request(rq)) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001338 if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 unsigned long elapsed = jiffies - info->start_seek;
1340 int stat = HWIF(drive)->INB(IDE_STATUS_REG);
1341
1342 if ((stat & SEEK_STAT) != SEEK_STAT) {
1343 if (elapsed < IDECD_SEEK_TIMEOUT) {
1344 ide_stall_queue(drive, IDECD_SEEK_TIMER);
1345 return ide_stopped;
1346 }
1347 printk (KERN_ERR "%s: DSC timeout\n", drive->name);
1348 }
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001349 info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 }
1351 if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
1352 action = cdrom_start_seek(drive, block);
Bartlomiej Zolnierkiewicz21ea1f02008-02-01 23:09:27 +01001353 } else
1354 action = cdrom_start_rw(drive, rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 info->last_block = block;
1356 return action;
Bartlomiej Zolnierkiewiczc9f56a82008-02-01 23:09:26 +01001357 } else if (blk_sense_request(rq) || blk_pc_request(rq) ||
Jens Axboecea28852006-10-12 15:08:45 +02001358 rq->cmd_type == REQ_TYPE_ATA_PC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 return cdrom_do_block_pc(drive, rq);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001360 } else if (blk_special_request(rq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 /*
1362 * right now this can only be a reset...
1363 */
1364 cdrom_end_request(drive, 1);
1365 return ide_stopped;
1366 }
1367
1368 blk_dump_rq_flags(rq, "ide-cd bad flags");
1369 cdrom_end_request(drive, 0);
1370 return ide_stopped;
1371}
1372
1373
1374
1375/****************************************************************************
1376 * Ioctl handling.
1377 *
1378 * Routines which queue packet commands take as a final argument a pointer
1379 * to a request_sense struct. If execution of the command results
1380 * in an error with a CHECK CONDITION status, this structure will be filled
1381 * with the results of the subsequent request sense command. The pointer
1382 * can also be NULL, in which case no sense information is returned.
1383 */
1384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385static
1386void msf_from_bcd (struct atapi_msf *msf)
1387{
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001388 msf->minute = BCD2BIN(msf->minute);
1389 msf->second = BCD2BIN(msf->second);
1390 msf->frame = BCD2BIN(msf->frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391}
1392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
1394{
1395 struct request req;
1396 struct cdrom_info *info = drive->driver_data;
1397 struct cdrom_device_info *cdi = &info->devinfo;
1398
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001399 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 req.sense = sense;
1402 req.cmd[0] = GPCMD_TEST_UNIT_READY;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001403 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001405 /*
1406 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
1407 * switch CDs instead of supporting the LOAD_UNLOAD opcode.
1408 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 req.cmd[7] = cdi->sanyo_slot % 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001411 return ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412}
1413
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001415int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
1416 struct request_sense *sense)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001418 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 struct request_sense my_sense;
1420 struct request req;
1421 int stat;
1422
1423 if (sense == NULL)
1424 sense = &my_sense;
1425
1426 /* If the drive cannot lock the door, just pretend. */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001427 if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 stat = 0;
1429 } else {
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001430 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 req.sense = sense;
1432 req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
1433 req.cmd[4] = lockflag ? 1 : 0;
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001434 stat = ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 }
1436
1437 /* If we got an illegal field error, the drive
1438 probably cannot lock the door. */
1439 if (stat != 0 &&
1440 sense->sense_key == ILLEGAL_REQUEST &&
1441 (sense->asc == 0x24 || sense->asc == 0x20)) {
1442 printk (KERN_ERR "%s: door locking not supported\n",
1443 drive->name);
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001444 cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 stat = 0;
1446 }
1447
1448 /* no medium, that's alright. */
1449 if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
1450 stat = 0;
1451
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001452 if (stat == 0) {
1453 if (lockflag)
1454 cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
1455 else
1456 cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
1457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 return stat;
1460}
1461
1462
1463/* Eject the disk if EJECTFLAG is 0.
1464 If EJECTFLAG is 1, try to reload the disk. */
1465static int cdrom_eject(ide_drive_t *drive, int ejectflag,
1466 struct request_sense *sense)
1467{
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001468 struct cdrom_info *cd = drive->driver_data;
1469 struct cdrom_device_info *cdi = &cd->devinfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 struct request req;
1471 char loej = 0x02;
1472
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001473 if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 return -EDRIVE_CANT_DO_THIS;
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001475
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 /* reload fails on some drives, if the tray is locked */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001477 if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 return 0;
1479
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001480 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
1482 /* only tell drive to close tray if open, if it can do that */
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001483 if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 loej = 0;
1485
1486 req.sense = sense;
1487 req.cmd[0] = GPCMD_START_STOP_UNIT;
1488 req.cmd[4] = loej | (ejectflag != 0);
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001489
1490 return ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491}
1492
1493static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
1494 unsigned long *sectors_per_frame,
1495 struct request_sense *sense)
1496{
1497 struct {
1498 __u32 lba;
1499 __u32 blocklen;
1500 } capbuf;
1501
1502 int stat;
1503 struct request req;
1504
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001505 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
1507 req.sense = sense;
1508 req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
1509 req.data = (char *)&capbuf;
1510 req.data_len = sizeof(capbuf);
Jens Axboe4aff5e22006-08-10 08:44:47 +02001511 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001513 stat = ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 if (stat == 0) {
1515 *capacity = 1 + be32_to_cpu(capbuf.lba);
1516 *sectors_per_frame =
1517 be32_to_cpu(capbuf.blocklen) >> SECTOR_BITS;
1518 }
1519
1520 return stat;
1521}
1522
1523static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
1524 int format, char *buf, int buflen,
1525 struct request_sense *sense)
1526{
1527 struct request req;
1528
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001529 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
1531 req.sense = sense;
1532 req.data = buf;
1533 req.data_len = buflen;
Jens Axboe4aff5e22006-08-10 08:44:47 +02001534 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 req.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
1536 req.cmd[6] = trackno;
1537 req.cmd[7] = (buflen >> 8);
1538 req.cmd[8] = (buflen & 0xff);
1539 req.cmd[9] = (format << 6);
1540
1541 if (msf_flag)
1542 req.cmd[1] = 2;
1543
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001544 return ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545}
1546
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547/* Try to read the entire TOC for the disk into our internal buffer. */
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001548int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549{
1550 int stat, ntracks, i;
1551 struct cdrom_info *info = drive->driver_data;
1552 struct cdrom_device_info *cdi = &info->devinfo;
1553 struct atapi_toc *toc = info->toc;
1554 struct {
1555 struct atapi_toc_header hdr;
1556 struct atapi_toc_entry ent;
1557 } ms_tmp;
1558 long last_written;
1559 unsigned long sectors_per_frame = SECTORS_PER_FRAME;
1560
1561 if (toc == NULL) {
1562 /* Try to allocate space. */
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001563 toc = kmalloc(sizeof(struct atapi_toc), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 if (toc == NULL) {
1565 printk (KERN_ERR "%s: No cdrom TOC buffer!\n", drive->name);
1566 return -ENOMEM;
1567 }
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001568 info->toc = toc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 }
1570
1571 /* Check to see if the existing data is still valid.
1572 If it is, just return. */
1573 (void) cdrom_check_status(drive, sense);
1574
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001575 if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 return 0;
1577
1578 /* Try to get the total cdrom capacity and sector size. */
1579 stat = cdrom_read_capacity(drive, &toc->capacity, &sectors_per_frame,
1580 sense);
1581 if (stat)
1582 toc->capacity = 0x1fffff;
1583
1584 set_capacity(info->disk, toc->capacity * sectors_per_frame);
Alan Coxdbe217a2006-06-25 05:47:44 -07001585 /* Save a private copy of te TOC capacity for error handling */
1586 drive->probed_capacity = toc->capacity * sectors_per_frame;
1587
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 blk_queue_hardsect_size(drive->queue,
1589 sectors_per_frame << SECTOR_BITS);
1590
1591 /* First read just the header, so we know how long the TOC is. */
1592 stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
1593 sizeof(struct atapi_toc_header), sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001594 if (stat)
1595 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001597 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001598 toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
1599 toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602 ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
1603 if (ntracks <= 0)
1604 return -EIO;
1605 if (ntracks > MAX_TRACKS)
1606 ntracks = MAX_TRACKS;
1607
1608 /* Now read the whole schmeer. */
1609 stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
1610 (char *)&toc->hdr,
1611 sizeof(struct atapi_toc_header) +
1612 (ntracks + 1) *
1613 sizeof(struct atapi_toc_entry), sense);
1614
1615 if (stat && toc->hdr.first_track > 1) {
1616 /* Cds with CDI tracks only don't have any TOC entries,
1617 despite of this the returned values are
1618 first_track == last_track = number of CDI tracks + 1,
1619 so that this case is indistinguishable from the same
1620 layout plus an additional audio track.
1621 If we get an error for the regular case, we assume
1622 a CDI without additional audio tracks. In this case
1623 the readable TOC is empty (CDI tracks are not included)
Jan Engelhardt96de0e22007-10-19 23:21:04 +02001624 and only holds the Leadout entry. Heiko Eißfeldt */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 ntracks = 0;
1626 stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
1627 (char *)&toc->hdr,
1628 sizeof(struct atapi_toc_header) +
1629 (ntracks + 1) *
1630 sizeof(struct atapi_toc_entry),
1631 sense);
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001632 if (stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 return stat;
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001634
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001635 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001636 toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
1637 toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001638 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 toc->hdr.first_track = CDROM_LEADOUT;
1640 toc->hdr.last_track = CDROM_LEADOUT;
1641 }
1642 }
1643
1644 if (stat)
1645 return stat;
1646
1647 toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
1648
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001649 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001650 toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
1651 toc->hdr.last_track = BCD2BIN(toc->hdr.last_track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001654 for (i = 0; i <= ntracks; i++) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001655 if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
1656 if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
Bartlomiej Zolnierkiewicz9a6dc662008-02-01 23:09:22 +01001657 toc->ent[i].track = BCD2BIN(toc->ent[i].track);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 msf_from_bcd(&toc->ent[i].addr.msf);
1659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
1661 toc->ent[i].addr.msf.second,
1662 toc->ent[i].addr.msf.frame);
1663 }
1664
1665 /* Read the multisession information. */
1666 if (toc->hdr.first_track != CDROM_LEADOUT) {
1667 /* Read the multisession information. */
1668 stat = cdrom_read_tocentry(drive, 0, 0, 1, (char *)&ms_tmp,
1669 sizeof(ms_tmp), sense);
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001670 if (stat)
1671 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
1673 toc->last_session_lba = be32_to_cpu(ms_tmp.ent.addr.lba);
1674 } else {
1675 ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
1676 toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
1677 }
1678
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001679 if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 /* Re-read multisession information using MSF format */
1681 stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
1682 sizeof(ms_tmp), sense);
1683 if (stat)
1684 return stat;
1685
1686 msf_from_bcd (&ms_tmp.ent.addr.msf);
1687 toc->last_session_lba = msf_to_lba(ms_tmp.ent.addr.msf.minute,
1688 ms_tmp.ent.addr.msf.second,
1689 ms_tmp.ent.addr.msf.frame);
1690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
1692 toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
1693
1694 /* Now try to get the total cdrom capacity. */
1695 stat = cdrom_get_last_written(cdi, &last_written);
1696 if (!stat && (last_written > toc->capacity)) {
1697 toc->capacity = last_written;
1698 set_capacity(info->disk, toc->capacity * sectors_per_frame);
Alan Coxdbe217a2006-06-25 05:47:44 -07001699 drive->probed_capacity = toc->capacity * sectors_per_frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 }
1701
1702 /* Remember that we've read this stuff. */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001703 info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704
1705 return 0;
1706}
1707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708/* the generic packet interface to cdrom.c */
1709static int ide_cdrom_packet(struct cdrom_device_info *cdi,
1710 struct packet_command *cgc)
1711{
1712 struct request req;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001713 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
1715 if (cgc->timeout <= 0)
1716 cgc->timeout = ATAPI_WAIT_PC;
1717
1718 /* here we queue the commands from the uniform CD-ROM
1719 layer. the packet must be complete, as we do not
1720 touch it at all. */
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001721 ide_cd_init_rq(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
1723 if (cgc->sense)
1724 memset(cgc->sense, 0, sizeof(struct request_sense));
1725 req.data = cgc->buffer;
1726 req.data_len = cgc->buflen;
1727 req.timeout = cgc->timeout;
1728
1729 if (cgc->quiet)
Jens Axboe4aff5e22006-08-10 08:44:47 +02001730 req.cmd_flags |= REQ_QUIET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
1732 req.sense = cgc->sense;
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001733 cgc->stat = ide_cd_queue_pc(drive, &req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 if (!cgc->stat)
1735 cgc->buflen -= req.data_len;
1736 return cgc->stat;
1737}
1738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739static
1740int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
1741{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001742 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 struct request_sense sense;
1744
1745 if (position) {
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01001746 int stat = ide_cd_lockdoor(drive, 0, &sense);
1747
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001748 if (stat)
1749 return stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 }
1751
1752 return cdrom_eject(drive, !position, &sense);
1753}
1754
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001755int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
Eric Piel9235e682005-06-23 00:10:29 -07001756{
1757 struct cdrom_info *info = drive->driver_data;
1758 struct cdrom_device_info *cdi = &info->devinfo;
1759 struct packet_command cgc;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001760 int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
Eric Piel9235e682005-06-23 00:10:29 -07001761
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001762 if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001763 size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
Eric Piel9235e682005-06-23 00:10:29 -07001764
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001765 init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
Eric Piel9235e682005-06-23 00:10:29 -07001766 do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
1767 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
1768 if (!stat)
1769 break;
1770 } while (--attempts);
1771 return stat;
1772}
1773
Bartlomiej Zolnierkiewicz17802992008-02-01 23:09:25 +01001774void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
Eric Piel9235e682005-06-23 00:10:29 -07001775{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001776 struct cdrom_info *cd = drive->driver_data;
Bartlomiej Zolnierkiewicz481c8c62008-02-01 23:09:20 +01001777 u16 curspeed, maxspeed;
1778
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001779 curspeed = *(u16 *)&buf[8 + 14];
1780 maxspeed = *(u16 *)&buf[8 + 8];
1781
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001782 if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001783 curspeed = le16_to_cpu(curspeed);
1784 maxspeed = le16_to_cpu(maxspeed);
Eric Piel9235e682005-06-23 00:10:29 -07001785 } else {
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001786 curspeed = be16_to_cpu(curspeed);
1787 maxspeed = be16_to_cpu(maxspeed);
Eric Piel9235e682005-06-23 00:10:29 -07001788 }
Bartlomiej Zolnierkiewicz481c8c62008-02-01 23:09:20 +01001789
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001790 cd->current_speed = (curspeed + (176/2)) / 176;
1791 cd->max_speed = (maxspeed + (176/2)) / 176;
Eric Piel9235e682005-06-23 00:10:29 -07001792}
1793
Bartlomiej Zolnierkiewicz5c684292008-02-01 23:09:24 +01001794/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 * add logic to try GET_EVENT command first to check for media and tray
1796 * status. this should be supported by newer cd-r/w and all DVD etc
1797 * drives
1798 */
1799static
1800int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
1801{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001802 ide_drive_t *drive = cdi->handle;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 struct media_event_desc med;
1804 struct request_sense sense;
1805 int stat;
1806
1807 if (slot_nr != CDSL_CURRENT)
1808 return -EINVAL;
1809
1810 stat = cdrom_check_status(drive, &sense);
1811 if (!stat || sense.sense_key == UNIT_ATTENTION)
1812 return CDS_DISC_OK;
1813
1814 if (!cdrom_get_media_event(cdi, &med)) {
1815 if (med.media_present)
1816 return CDS_DISC_OK;
1817 else if (med.door_open)
1818 return CDS_TRAY_OPEN;
1819 else
1820 return CDS_NO_DISC;
1821 }
1822
1823 if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
1824 return CDS_DISC_OK;
1825
1826 /*
1827 * If not using Mt Fuji extended media tray reports,
1828 * just return TRAY_OPEN since ATAPI doesn't provide
1829 * any other way to detect this...
1830 */
1831 if (sense.sense_key == NOT_READY) {
Alan Coxdbe217a2006-06-25 05:47:44 -07001832 if (sense.asc == 0x3a && sense.ascq == 1)
1833 return CDS_NO_DISC;
1834 else
1835 return CDS_TRAY_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 return CDS_DRIVE_NOT_READY;
1838}
1839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840/****************************************************************************
1841 * Other driver requests (open, close, check media change).
1842 */
1843
1844static
1845int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
1846 int slot_nr)
1847{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001848 ide_drive_t *drive = cdi->handle;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01001849 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 int retval;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01001851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 if (slot_nr == CDSL_CURRENT) {
1853 (void) cdrom_check_status(drive, NULL);
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001854 retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
1855 cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 return retval;
1857 } else {
1858 return -EINVAL;
1859 }
1860}
1861
1862
1863static
1864int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
1865{
1866 return 0;
1867}
1868
1869/*
1870 * Close down the device. Invalidate all cached blocks.
1871 */
1872
1873static
1874void ide_cdrom_release_real (struct cdrom_device_info *cdi)
1875{
1876 ide_drive_t *drive = cdi->handle;
Bartlomiej Zolnierkiewicz0ba11212008-02-01 23:09:21 +01001877 struct cdrom_info *cd = drive->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878
1879 if (!cdi->use_count)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001880 cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881}
1882
Bartlomiej Zolnierkiewicz20e7f7e2008-02-01 23:09:20 +01001883#define IDE_CD_CAPABILITIES \
1884 (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
1885 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
1886 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
1887 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
1888 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890static struct cdrom_device_ops ide_cdrom_dops = {
1891 .open = ide_cdrom_open_real,
1892 .release = ide_cdrom_release_real,
1893 .drive_status = ide_cdrom_drive_status,
1894 .media_changed = ide_cdrom_check_media_change_real,
1895 .tray_move = ide_cdrom_tray_move,
1896 .lock_door = ide_cdrom_lock_door,
1897 .select_speed = ide_cdrom_select_speed,
1898 .get_last_session = ide_cdrom_get_last_session,
1899 .get_mcn = ide_cdrom_get_mcn,
1900 .reset = ide_cdrom_reset,
1901 .audio_ioctl = ide_cdrom_audio_ioctl,
Bartlomiej Zolnierkiewicz20e7f7e2008-02-01 23:09:20 +01001902 .capability = IDE_CD_CAPABILITIES,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 .generic_packet = ide_cdrom_packet,
1904};
1905
1906static int ide_cdrom_register (ide_drive_t *drive, int nslots)
1907{
1908 struct cdrom_info *info = drive->driver_data;
1909 struct cdrom_device_info *devinfo = &info->devinfo;
1910
1911 devinfo->ops = &ide_cdrom_dops;
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001912 devinfo->speed = info->current_speed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 devinfo->capacity = nslots;
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001914 devinfo->handle = drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 strcpy(devinfo->name, drive->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001917 if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
Bartlomiej Zolnierkiewicz3cbd8142007-12-24 15:23:43 +01001918 devinfo->mask |= CDC_SELECT_SPEED;
1919
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 devinfo->disk = info->disk;
1921 return register_cdrom(devinfo);
1922}
1923
1924static
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925int ide_cdrom_probe_capabilities (ide_drive_t *drive)
1926{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001927 struct cdrom_info *cd = drive->driver_data;
1928 struct cdrom_device_info *cdi = &cd->devinfo;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001929 u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
1930 mechtype_t mechtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 int nslots = 1;
1932
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001933 cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
1934 CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
1935 CDC_MO_DRIVE | CDC_RAM);
1936
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 if (drive->media == ide_optical) {
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001938 cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
1940 return nslots;
1941 }
1942
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001943 if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001944 cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001945 cdi->mask &= ~CDC_PLAY_AUDIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 return nslots;
1947 }
1948
1949 /*
1950 * we have to cheat a little here. the packet will eventually
1951 * be queued with ide_cdrom_packet(), which extracts the
1952 * drive from cdi->handle. Since this device hasn't been
1953 * registered with the Uniform layer yet, it can't do this.
1954 * Same goes for cdi->ops.
1955 */
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08001956 cdi->handle = drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 cdi->ops = &ide_cdrom_dops;
1958
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001959 if (ide_cdrom_get_capabilities(drive, buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 return 0;
1961
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001962 if ((buf[8 + 6] & 0x01) == 0)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001963 cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001964 if (buf[8 + 6] & 0x08)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001965 cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001966 if (buf[8 + 3] & 0x01)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001967 cdi->mask &= ~CDC_CD_R;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001968 if (buf[8 + 3] & 0x02)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001969 cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001970 if (buf[8 + 2] & 0x38)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001971 cdi->mask &= ~CDC_DVD;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001972 if (buf[8 + 3] & 0x20)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001973 cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001974 if (buf[8 + 3] & 0x10)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001975 cdi->mask &= ~CDC_DVD_R;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01001976 if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001977 cdi->mask &= ~CDC_PLAY_AUDIO;
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001978
1979 mechtype = buf[8 + 6] >> 5;
1980 if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001981 cdi->mask |= CDC_CLOSE_TRAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 if (cdi->sanyo_slot > 0) {
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001984 cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 nslots = 3;
Bartlomiej Zolnierkiewiczcdf60002008-02-01 23:09:22 +01001986 } else if (mechtype == mechtype_individual_changer ||
1987 mechtype == mechtype_cartridge_changer) {
Bartlomiej Zolnierkiewicz2609d062008-02-01 23:09:19 +01001988 nslots = cdrom_number_of_slots(cdi);
1989 if (nslots > 1)
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01001990 cdi->mask &= ~CDC_SELECT_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 }
1992
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01001993 ide_cdrom_update_speed(drive, buf);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001994
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 printk(KERN_INFO "%s: ATAPI", drive->name);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01001996
1997 /* don't print speed if the drive reported 0 */
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01001998 if (cd->max_speed)
1999 printk(KERN_CONT " %dX", cd->max_speed);
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002000
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002001 printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002003 if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
2004 printk(KERN_CONT " DVD%s%s",
2005 (cdi->mask & CDC_DVD_R) ? "" : "-R",
2006 (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002008 if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
2009 printk(KERN_CONT " CD%s%s",
2010 (cdi->mask & CDC_CD_R) ? "" : "-R",
2011 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012
Bartlomiej Zolnierkiewicz3f1b86d2008-02-01 23:09:20 +01002013 if ((cdi->mask & CDC_SELECT_DISC) == 0)
2014 printk(KERN_CONT " changer w/%d slots", nslots);
2015 else
2016 printk(KERN_CONT " drive");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Bartlomiej Zolnierkiewicz455d80a2008-02-01 23:09:21 +01002018 printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
2020 return nslots;
2021}
2022
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002023#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024static void ide_cdrom_add_settings(ide_drive_t *drive)
2025{
Bartlomiej Zolnierkiewicz14979432007-05-10 00:01:10 +02002026 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 -07002027}
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002028#else
2029static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
2030#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031
2032/*
2033 * standard prep_rq_fn that builds 10 byte cmds
2034 */
Jens Axboe165125e2007-07-24 09:28:11 +02002035static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036{
2037 int hard_sect = queue_hardsect_size(q);
2038 long block = (long)rq->hard_sector / (hard_sect >> 9);
2039 unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
2040
2041 memset(rq->cmd, 0, sizeof(rq->cmd));
2042
2043 if (rq_data_dir(rq) == READ)
2044 rq->cmd[0] = GPCMD_READ_10;
2045 else
2046 rq->cmd[0] = GPCMD_WRITE_10;
2047
2048 /*
2049 * fill in lba
2050 */
2051 rq->cmd[2] = (block >> 24) & 0xff;
2052 rq->cmd[3] = (block >> 16) & 0xff;
2053 rq->cmd[4] = (block >> 8) & 0xff;
2054 rq->cmd[5] = block & 0xff;
2055
2056 /*
2057 * and transfer length
2058 */
2059 rq->cmd[7] = (blocks >> 8) & 0xff;
2060 rq->cmd[8] = blocks & 0xff;
2061 rq->cmd_len = 10;
2062 return BLKPREP_OK;
2063}
2064
2065/*
2066 * Most of the SCSI commands are supported directly by ATAPI devices.
2067 * This transform handles the few exceptions.
2068 */
2069static int ide_cdrom_prep_pc(struct request *rq)
2070{
2071 u8 *c = rq->cmd;
2072
2073 /*
2074 * Transform 6-byte read/write commands to the 10-byte version
2075 */
2076 if (c[0] == READ_6 || c[0] == WRITE_6) {
2077 c[8] = c[4];
2078 c[5] = c[3];
2079 c[4] = c[2];
2080 c[3] = c[1] & 0x1f;
2081 c[2] = 0;
2082 c[1] &= 0xe0;
2083 c[0] += (READ_10 - READ_6);
2084 rq->cmd_len = 10;
2085 return BLKPREP_OK;
2086 }
2087
2088 /*
2089 * it's silly to pretend we understand 6-byte sense commands, just
2090 * reject with ILLEGAL_REQUEST and the caller should take the
2091 * appropriate action
2092 */
2093 if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
2094 rq->errors = ILLEGAL_REQUEST;
2095 return BLKPREP_KILL;
2096 }
2097
2098 return BLKPREP_OK;
2099}
2100
Jens Axboe165125e2007-07-24 09:28:11 +02002101static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102{
Jens Axboe4aff5e22006-08-10 08:44:47 +02002103 if (blk_fs_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 return ide_cdrom_prep_fs(q, rq);
Jens Axboe4aff5e22006-08-10 08:44:47 +02002105 else if (blk_pc_request(rq))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 return ide_cdrom_prep_pc(rq);
2107
2108 return 0;
2109}
2110
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002111struct cd_list_entry {
2112 const char *id_model;
2113 const char *id_firmware;
2114 unsigned int cd_flags;
2115};
2116
2117static const struct cd_list_entry ide_cd_quirks_list[] = {
2118 /* Limit transfer size per interrupt. */
2119 { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
2120 { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_CD_FLAG_LIMIT_NFRAMES },
2121 /* SCR-3231 doesn't support the SET_CD_SPEED command. */
2122 { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_CD_FLAG_NO_SPEED_SELECT },
2123 /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
2124 { "NEC CD-ROM DRIVE:260", "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
2125 IDE_CD_FLAG_PRE_ATAPI12, },
2126 /* Vertos 300, some versions of this drive like to talk BCD. */
2127 { "V003S0DS", NULL, IDE_CD_FLAG_VERTOS_300_SSD, },
2128 /* Vertos 600 ESD. */
2129 { "V006E0DS", NULL, IDE_CD_FLAG_VERTOS_600_ESD, },
2130 /*
2131 * Sanyo 3 CD changer uses a non-standard command for CD changing
2132 * (by default standard ATAPI support for CD changers is used).
2133 */
2134 { "CD-ROM CDR-C3 G", NULL, IDE_CD_FLAG_SANYO_3CD },
2135 { "CD-ROM CDR-C3G", NULL, IDE_CD_FLAG_SANYO_3CD },
2136 { "CD-ROM CDR_C36", NULL, IDE_CD_FLAG_SANYO_3CD },
2137 /* Stingray 8X CD-ROM. */
2138 { "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
2139 /*
2140 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
2141 * mode sense page capabilities size, but older drives break.
2142 */
2143 { "ATAPI CD ROM DRIVE 50X MAX", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
2144 { "WPI CDS-32X", NULL, IDE_CD_FLAG_FULL_CAPS_PAGE },
2145 /* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
2146 { "", "241N", IDE_CD_FLAG_LE_SPEED_FIELDS },
2147 /*
2148 * Some drives used by Apple don't advertise audio play
2149 * but they do support reading TOC & audio datas.
2150 */
2151 { "MATSHITADVD-ROM SR-8187", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2152 { "MATSHITADVD-ROM SR-8186", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2153 { "MATSHITADVD-ROM SR-8176", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2154 { "MATSHITADVD-ROM SR-8174", NULL, IDE_CD_FLAG_PLAY_AUDIO_OK },
2155 { NULL, NULL, 0 }
2156};
2157
2158static unsigned int ide_cd_flags(struct hd_driveid *id)
2159{
2160 const struct cd_list_entry *cle = ide_cd_quirks_list;
2161
2162 while (cle->id_model) {
2163 if (strcmp(cle->id_model, id->model) == 0 &&
2164 (cle->id_firmware == NULL ||
2165 strstr(id->fw_rev, cle->id_firmware)))
2166 return cle->cd_flags;
2167 cle++;
2168 }
2169
2170 return 0;
2171}
2172
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173static
2174int ide_cdrom_setup (ide_drive_t *drive)
2175{
Bartlomiej Zolnierkiewicz4fe67172008-02-01 23:09:21 +01002176 struct cdrom_info *cd = drive->driver_data;
2177 struct cdrom_device_info *cdi = &cd->devinfo;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002178 struct hd_driveid *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 int nslots;
2180
2181 blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
2182 blk_queue_dma_alignment(drive->queue, 31);
2183 drive->queue->unplug_delay = (1 * HZ) / 1000;
2184 if (!drive->queue->unplug_delay)
2185 drive->queue->unplug_delay = 1;
2186
2187 drive->special.all = 0;
2188
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002189 cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
2190 ide_cd_flags(id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002192 if ((id->config & 0x0060) == 0x20)
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002193 cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
Bartlomiej Zolnierkiewiczb8d25de2008-02-01 23:09:19 +01002194
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002195 if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
2196 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002197 cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
2198 IDE_CD_FLAG_TOCADDR_AS_BCD);
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002199 else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
2200 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
Bartlomiej Zolnierkiewicz2bc4cf22008-02-01 23:09:22 +01002201 cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
Bartlomiej Zolnierkiewicze59724c2008-02-01 23:09:22 +01002202 else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
2203 cdi->sanyo_slot = 3; /* 3 => use CD in slot 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 nslots = ide_cdrom_probe_capabilities (drive);
2206
2207 /*
2208 * set correct block size
2209 */
2210 blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
2211
2212 if (drive->autotune == IDE_TUNE_DEFAULT ||
2213 drive->autotune == IDE_TUNE_AUTO)
2214 drive->dsc_overlap = (drive->next != drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
2216 if (ide_cdrom_register(drive, nslots)) {
2217 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 +01002218 cd->devinfo.handle = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 return 1;
2220 }
2221 ide_cdrom_add_settings(drive);
2222 return 0;
2223}
2224
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +02002225#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226static
2227sector_t ide_cdrom_capacity (ide_drive_t *drive)
2228{
2229 unsigned long capacity, sectors_per_frame;
2230
2231 if (cdrom_read_capacity(drive, &capacity, &sectors_per_frame, NULL))
2232 return 0;
2233
2234 return capacity * sectors_per_frame;
2235}
Amos Waterlandd97b32142005-10-30 15:02:10 -08002236#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
Russell King4031bbe2006-01-06 11:41:00 +00002238static void ide_cd_remove(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239{
2240 struct cdrom_info *info = drive->driver_data;
2241
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002242 ide_proc_unregister_driver(drive, info->driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244 del_gendisk(info->disk);
2245
2246 ide_cd_put(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247}
2248
2249static void ide_cd_release(struct kref *kref)
2250{
2251 struct cdrom_info *info = to_ide_cd(kref);
2252 struct cdrom_device_info *devinfo = &info->devinfo;
2253 ide_drive_t *drive = info->drive;
2254 struct gendisk *g = info->disk;
2255
Jesper Juhl6044ec82005-11-07 01:01:32 -08002256 kfree(info->buffer);
2257 kfree(info->toc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 if (devinfo->handle == drive && unregister_cdrom(devinfo))
2259 printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
2260 "driver.\n", __FUNCTION__, drive->name);
2261 drive->dsc_overlap = 0;
2262 drive->driver_data = NULL;
2263 blk_queue_prep_rq(drive->queue, NULL);
2264 g->private_data = NULL;
2265 put_disk(g);
2266 kfree(info);
2267}
2268
Russell King4031bbe2006-01-06 11:41:00 +00002269static int ide_cd_probe(ide_drive_t *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Bartlomiej Zolnierkiewiczecfd80e2007-05-10 00:01:09 +02002271#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272static int proc_idecd_read_capacity
2273 (char *page, char **start, off_t off, int count, int *eof, void *data)
2274{
Jesper Juhl2a91f3e2005-10-30 15:02:45 -08002275 ide_drive_t *drive = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 int len;
2277
2278 len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
2279 PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
2280}
2281
2282static ide_proc_entry_t idecd_proc[] = {
2283 { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
2284 { NULL, 0, NULL, NULL }
2285};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286#endif
2287
2288static ide_driver_t ide_cdrom_driver = {
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002289 .gen_driver = {
Laurent Riffard4ef3b8f2005-11-18 22:15:40 +01002290 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002291 .name = "ide-cdrom",
2292 .bus = &ide_bus_type,
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002293 },
Russell King4031bbe2006-01-06 11:41:00 +00002294 .probe = ide_cd_probe,
2295 .remove = ide_cd_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 .version = IDECD_VERSION,
2297 .media = ide_cdrom,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 .supports_dsc_overlap = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 .do_request = ide_do_rw_cdrom,
2300 .end_request = ide_end_request,
2301 .error = __ide_error,
2302 .abort = __ide_abort,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002303#ifdef CONFIG_IDE_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 .proc = idecd_proc,
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002305#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306};
2307
2308static int idecd_open(struct inode * inode, struct file * file)
2309{
2310 struct gendisk *disk = inode->i_bdev->bd_disk;
2311 struct cdrom_info *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 int rc = -ENOMEM;
2313
2314 if (!(info = ide_cd_get(disk)))
2315 return -ENXIO;
2316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 if (!info->buffer)
Bartlomiej Zolnierkiewiczc94964a2007-02-17 02:40:24 +01002318 info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT);
2319
2320 if (info->buffer)
2321 rc = cdrom_open(&info->devinfo, inode, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
2323 if (rc < 0)
2324 ide_cd_put(info);
2325
2326 return rc;
2327}
2328
2329static int idecd_release(struct inode * inode, struct file * file)
2330{
2331 struct gendisk *disk = inode->i_bdev->bd_disk;
2332 struct cdrom_info *info = ide_cd_g(disk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
2334 cdrom_release (&info->devinfo, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
2336 ide_cd_put(info);
2337
2338 return 0;
2339}
2340
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002341static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg)
2342{
2343 struct packet_command cgc;
2344 char buffer[16];
2345 int stat;
2346 char spindown;
2347
2348 if (copy_from_user(&spindown, (void __user *)arg, sizeof(char)))
2349 return -EFAULT;
2350
2351 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
2352
2353 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
2354 if (stat)
2355 return stat;
2356
2357 buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
2358 return cdrom_mode_select(cdi, &cgc);
2359}
2360
2361static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
2362{
2363 struct packet_command cgc;
2364 char buffer[16];
2365 int stat;
2366 char spindown;
2367
2368 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
2369
2370 stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
2371 if (stat)
2372 return stat;
2373
2374 spindown = buffer[11] & 0x0f;
2375 if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
2376 return -EFAULT;
2377 return 0;
2378}
2379
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380static int idecd_ioctl (struct inode *inode, struct file *file,
2381 unsigned int cmd, unsigned long arg)
2382{
2383 struct block_device *bdev = inode->i_bdev;
2384 struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
2385 int err;
2386
Christoph Hellwig6a2900b2006-03-23 03:00:15 -08002387 switch (cmd) {
2388 case CDROMSETSPINDOWN:
2389 return idecd_set_spindown(&info->devinfo, arg);
2390 case CDROMGETSPINDOWN:
2391 return idecd_get_spindown(&info->devinfo, arg);
2392 default:
2393 break;
2394 }
2395
2396 err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 if (err == -EINVAL)
2398 err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
2399
2400 return err;
2401}
2402
2403static int idecd_media_changed(struct gendisk *disk)
2404{
2405 struct cdrom_info *info = ide_cd_g(disk);
2406 return cdrom_media_changed(&info->devinfo);
2407}
2408
2409static int idecd_revalidate_disk(struct gendisk *disk)
2410{
2411 struct cdrom_info *info = ide_cd_g(disk);
2412 struct request_sense sense;
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01002413
2414 ide_cd_read_toc(info->drive, &sense);
2415
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 return 0;
2417}
2418
2419static struct block_device_operations idecd_ops = {
2420 .owner = THIS_MODULE,
2421 .open = idecd_open,
2422 .release = idecd_release,
2423 .ioctl = idecd_ioctl,
2424 .media_changed = idecd_media_changed,
2425 .revalidate_disk= idecd_revalidate_disk
2426};
2427
2428/* options */
2429static char *ignore = NULL;
2430
2431module_param(ignore, charp, 0400);
2432MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
2433
Russell King4031bbe2006-01-06 11:41:00 +00002434static int ide_cd_probe(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435{
2436 struct cdrom_info *info;
2437 struct gendisk *g;
2438 struct request_sense sense;
2439
2440 if (!strstr("ide-cdrom", drive->driver_req))
2441 goto failed;
2442 if (!drive->present)
2443 goto failed;
2444 if (drive->media != ide_cdrom && drive->media != ide_optical)
2445 goto failed;
2446 /* skip drives that we were told to ignore */
2447 if (ignore != NULL) {
2448 if (strstr(ignore, drive->name)) {
2449 printk(KERN_INFO "ide-cd: ignoring drive %s\n", drive->name);
2450 goto failed;
2451 }
2452 }
2453 if (drive->scsi) {
2454 printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
2455 goto failed;
2456 }
Deepak Saxenaf5e3c2f2005-11-07 01:01:25 -08002457 info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 if (info == NULL) {
2459 printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
2460 goto failed;
2461 }
2462
2463 g = alloc_disk(1 << PARTN_BITS);
2464 if (!g)
2465 goto out_free_cd;
2466
2467 ide_init_disk(g, drive);
2468
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002469 ide_proc_register_driver(drive, &ide_cdrom_driver);
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002470
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 kref_init(&info->kref);
2472
2473 info->drive = drive;
2474 info->driver = &ide_cdrom_driver;
2475 info->disk = g;
2476
2477 g->private_data = &info->driver;
2478
2479 drive->driver_data = info;
2480
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 g->minors = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 g->driverfs_dev = &drive->gendev;
2483 g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
2484 if (ide_cdrom_setup(drive)) {
Bartlomiej Zolnierkiewicz7662d042007-05-10 00:01:10 +02002485 ide_proc_unregister_driver(drive, &ide_cdrom_driver);
Bartlomiej Zolnierkiewicz05017db2007-12-24 15:23:43 +01002486 ide_cd_release(&info->kref);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 goto failed;
2488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Bartlomiej Zolnierkiewicz139c8292008-02-01 23:09:24 +01002490 ide_cd_read_toc(drive, &sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491 g->fops = &idecd_ops;
2492 g->flags |= GENHD_FL_REMOVABLE;
2493 add_disk(g);
2494 return 0;
2495
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496out_free_cd:
2497 kfree(info);
2498failed:
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002499 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500}
2501
2502static void __exit ide_cdrom_exit(void)
2503{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002504 driver_unregister(&ide_cdrom_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505}
Bartlomiej Zolnierkiewicz17514e82005-11-19 22:24:35 +01002506
2507static int __init ide_cdrom_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508{
Bartlomiej Zolnierkiewicz8604aff2005-05-26 14:55:34 +02002509 return driver_register(&ide_cdrom_driver.gen_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510}
2511
Kay Sievers263756e2005-12-12 18:03:44 +01002512MODULE_ALIAS("ide:*m-cdrom*");
Bartlomiej Zolnierkiewicz972560f2008-02-01 23:09:23 +01002513MODULE_ALIAS("ide-cd");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514module_init(ide_cdrom_init);
2515module_exit(ide_cdrom_exit);
2516MODULE_LICENSE("GPL");