diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/ide/ide-cd.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 3524 |
1 files changed, 3524 insertions, 0 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c new file mode 100644 index 00000000000..33a020faeab --- /dev/null +++ b/drivers/ide/ide-cd.c @@ -0,0 +1,3524 @@ +/* + * linux/drivers/ide/ide-cd.c + * + * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov> + * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> + * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * ATAPI CD-ROM driver. To be used with ide.c. + * See Documentation/cdrom/ide-cd for usage information. + * + * Suggestions are welcome. Patches that work are more welcome though. ;-) + * For those wishing to work on this driver, please be sure you download + * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI + * (SFF-8020i rev 2.6) standards. These documents can be obtained by + * anonymous ftp from: + * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps + * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf + * + * Drives that deviate from these standards will be accommodated as much + * as possible via compile time or command-line options. Since I only have + * a few drives, you generally need to send me patches... + * + * ---------------------------------- + * TO DO LIST: + * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on + * boot + * + * ---------------------------------- + * 1.00 Oct 31, 1994 -- Initial version. + * 1.01 Nov 2, 1994 -- Fixed problem with starting request in + * cdrom_check_status. + * 1.03 Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks) + * (from mlord) -- minor changes to cdrom_setup() + * -- renamed ide_dev_s to ide_drive_t, enable irq on command + * 2.00 Nov 27, 1994 -- Generalize packet command interface; + * add audio ioctls. + * 2.01 Dec 3, 1994 -- Rework packet command interface to handle devices + * which send an interrupt when ready for a command. + * 2.02 Dec 11, 1994 -- Cache the TOC in the driver. + * Don't use SCMD_PLAYAUDIO_TI; it's not included + * in the current version of ATAPI. + * Try to use LBA instead of track or MSF addressing + * when possible. + * Don't wait for READY_STAT. + * 2.03 Jan 10, 1995 -- Rewrite block read routines to handle block sizes + * other than 2k and to move multiple sectors in a + * single transaction. + * 2.04 Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives. + * Thanks to Nick Saw <cwsaw@pts7.pts.mot.com> for + * help in figuring this out. Ditto for Acer and + * Aztech drives, which seem to have the same problem. + * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml + * 2.05 Jun 8, 1995 -- Don't attempt to retry after an illegal request + * or data protect error. + * Use HWIF and DEV_HWIF macros as in ide.c. + * Always try to do a request_sense after + * a failed command. + * Include an option to give textual descriptions + * of ATAPI errors. + * Fix a bug in handling the sector cache which + * showed up if the drive returned data in 512 byte + * blocks (like Pioneer drives). Thanks to + * Richard Hirst <srh@gpt.co.uk> for diagnosing this. + * Properly supply the page number field in the + * MODE_SELECT command. + * PLAYAUDIO12 is broken on the Aztech; work around it. + * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c + * (my apologies to Scott, but now ide-cd.c is independent) + * 3.00 Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl. + * Implement CDROMREADAUDIO ioctl (UNTESTED). + * Use input_ide_data() and output_ide_data(). + * Add door locking. + * Fix usage count leak in cdrom_open, which happened + * when a read-write mount was attempted. + * Try to load the disk on open. + * Implement CDROMEJECT_SW ioctl (off by default). + * Read total cdrom capacity during open. + * Rearrange logic in cdrom_decode_status. Issue + * request sense commands for failed packet commands + * from here instead of from cdrom_queue_packet_command. + * Fix a race condition in retrieving error information. + * Suppress printing normal unit attention errors and + * some drive not ready errors. + * Implement CDROMVOLREAD ioctl. + * Implement CDROMREADMODE1/2 ioctls. + * Fix race condition in setting up interrupt handlers + * when the `serialize' option is used. + * 3.01 Sep 2, 1995 -- Fix ordering of reenabling interrupts in + * cdrom_queue_request. + * Another try at using ide_[input,output]_data. + * 3.02 Sep 16, 1995 -- Stick total disk capacity in partition table as well. + * Make VERBOSE_IDE_CD_ERRORS dump failed command again. + * Dump out more information for ILLEGAL REQUEST errs. + * Fix handling of errors occurring before the + * packet command is transferred. + * Fix transfers with odd bytelengths. + * 3.03 Oct 27, 1995 -- Some Creative drives have an id of just `CD'. + * `DCI-2S10' drives are broken too. + * 3.04 Nov 20, 1995 -- So are Vertos drives. + * 3.05 Dec 1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c + * 3.06 Dec 16, 1995 -- Add support needed for partitions. + * More workarounds for Vertos bugs (based on patches + * from Holger Dietze <dietze@aix520.informatik.uni-leipzig.de>). + * Try to eliminate byteorder assumptions. + * Use atapi_cdrom_subchnl struct definition. + * Add STANDARD_ATAPI compilation option. + * 3.07 Jan 29, 1996 -- More twiddling for broken drives: Sony 55D, + * Vertos 300. + * Add NO_DOOR_LOCKING configuration option. + * Handle drive_cmd requests w/NULL args (for hdparm -t). + * Work around sporadic Sony55e audio play problem. + * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix + * problem with "hde=cdrom" with no drive present. -ml + * 3.08 Mar 6, 1996 -- More Vertos workarounds. + * 3.09 Apr 5, 1996 -- Add CDROMCLOSETRAY ioctl. + * Switch to using MSF addressing for audio commands. + * Reformat to match kernel tabbing style. + * Add CDROM_GET_UPC ioctl. + * 3.10 Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI. + * 3.11 Apr 29, 1996 -- Patch from Heiko Eissfeldt <heiko@colossus.escape.de> + * to remove redundant verify_area calls. + * 3.12 May 7, 1996 -- Rudimentary changer support. Based on patches + * from Gerhard Zuber <zuber@berlin.snafu.de>. + * Let open succeed even if there's no loaded disc. + * 3.13 May 19, 1996 -- Fixes for changer code. + * 3.14 May 29, 1996 -- Add work-around for Vertos 600. + * (From Hennus Bergman <hennus@sky.ow.nl>.) + * 3.15 July 2, 1996 -- Added support for Sanyo 3 CD changers + * from Ben Galliart <bgallia@luc.edu> with + * special help from Jeff Lightfoot + * <jeffml@pobox.com> + * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification + * 3.16 Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl. + * 3.17 Sep 17, 1996 -- Tweak audio reads for some drives. + * Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC. + * 3.18 Oct 31, 1996 -- Added module and DMA support. + * + * + * 4.00 Nov 5, 1996 -- New ide-cd maintainer, + * Erik B. Andersen <andersee@debian.org> + * -- Newer Creative drives don't always set the error + * register correctly. Make sure we see media changes + * regardless. + * -- Integrate with generic cdrom driver. + * -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on + * a patch from Ciro Cattuto <>. + * -- Call set_device_ro. + * -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE + * ioctls, based on patch by Erik Andersen + * -- Add some probes of drive capability during setup. + * + * 4.01 Nov 11, 1996 -- Split into ide-cd.c and ide-cd.h + * -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE + * ioctls in favor of a generalized approach + * using the generic cdrom driver. + * -- Fully integrated with the 2.1.X kernel. + * -- Other stuff that I forgot (lots of changes) + * + * 4.02 Dec 01, 1996 -- Applied patch from Gadi Oxman <gadio@netvision.net.il> + * to fix the drive door locking problems. + * + * 4.03 Dec 04, 1996 -- Added DSC overlap support. + * 4.04 Dec 29, 1996 -- Added CDROMREADRAW ioclt based on patch + * by Ales Makarov (xmakarov@sun.felk.cvut.cz) + * + * 4.05 Nov 20, 1997 -- Modified to print more drive info on init + * Minor other changes + * Fix errors on CDROMSTOP (If you have a "Dolphin", + * you must define IHAVEADOLPHIN) + * Added identifier so new Sanyo CD-changer works + * Better detection if door locking isn't supported + * + * 4.06 Dec 17, 1997 -- fixed endless "tray open" messages -ml + * 4.07 Dec 17, 1997 -- fallback to set pc->stat on "tray open" + * 4.08 Dec 18, 1997 -- spew less noise when tray is empty + * -- fix speed display for ACER 24X, 18X + * 4.09 Jan 04, 1998 -- fix handling of the last block so we return + * an end of file instead of an I/O error (Gadi) + * 4.10 Jan 24, 1998 -- fixed a bug so now changers can change to a new + * slot when there is no disc in the current slot. + * -- Fixed a memory leak where info->changer_info was + * malloc'ed but never free'd when closing the device. + * -- Cleaned up the global namespace a bit by making more + * functions static that should already have been. + * 4.11 Mar 12, 1998 -- Added support for the CDROM_SELECT_SPEED ioctl + * based on a patch for 2.0.33 by Jelle Foks + * <jelle@scintilla.utwente.nl>, a patch for 2.0.33 + * by Toni Giorgino <toni@pcape2.pi.infn.it>, the SCSI + * version, and my own efforts. -erik + * -- Fixed a stupid bug which egcs was kind enough to + * inform me of where "Illegal mode for this track" + * was never returned due to a comparison on data + * types of limited range. + * 4.12 Mar 29, 1998 -- Fixed bug in CDROM_SELECT_SPEED so write speed is + * now set ionly for CD-R and CD-RW drives. I had + * removed this support because it produced errors. + * It produced errors _only_ for non-writers. duh. + * 4.13 May 05, 1998 -- Suppress useless "in progress of becoming ready" + * messages, since this is not an error. + * -- Change error messages to be const + * -- Remove a "\t" which looks ugly in the syslogs + * 4.14 July 17, 1998 -- Change to pointing to .ps version of ATAPI spec + * since the .pdf version doesn't seem to work... + * -- Updated the TODO list to something more current. + * + * 4.15 Aug 25, 1998 -- Updated ide-cd.h to respect mechine endianess, + * patch thanks to "Eddie C. Dost" <ecd@skynet.be> + * + * 4.50 Oct 19, 1998 -- New maintainers! + * Jens Axboe <axboe@image.dk> + * Chris Zwilling <chris@cloudnet.com> + * + * 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk> + * - ide_cdrom_reset enabled since the ide subsystem + * handles resets fine now. <axboe@image.dk> + * - Transfer size fix for Samsung CD-ROMs, thanks to + * "Ville Hallik" <ville.hallik@mail.ee>. + * - other minor stuff. + * + * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk> + * - Detect DVD-ROM/RAM drives + * + * 4.53 Feb 22, 1999 - Include other model Samsung and one Goldstar + * drive in transfer size limit. + * - Fix the I/O error when doing eject without a medium + * loaded on some drives. + * - CDROMREADMODE2 is now implemented through + * CDROMREADRAW, since many drives don't support + * MODE2 (even though ATAPI 2.6 says they must). + * - Added ignore parameter to ide-cd (as a module), eg + * insmod ide-cd ignore='hda hdb' + * Useful when using ide-cd in conjunction with + * ide-scsi. TODO: non-modular way of doing the + * same. + * + * 4.54 Aug 5, 1999 - Support for MMC2 class commands through the generic + * packet interface to cdrom.c. + * - Unified audio ioctl support, most of it. + * - cleaned up various deprecated verify_area(). + * - Added ide_cdrom_packet() as the interface for + * the Uniform generic_packet(). + * - bunch of other stuff, will fill in logs later. + * - report 1 slot for non-changers, like the other + * cd-rom drivers. don't report select disc for + * non-changers as well. + * - mask out audio playing, if the device can't do it. + * + * 4.55 Sep 1, 1999 - Eliminated the rest of the audio ioctls, except + * for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers + * use this independently of the actual audio handling. + * They will disappear later when I get the time to + * do it cleanly. + * - Minimize the TOC reading - only do it when we + * know a media change has occurred. + * - Moved all the CDROMREADx ioctls to the Uniform layer. + * - Heiko Eissfeldt <heiko@colossus.escape.de> supplied + * some fixes for CDI. + * - CD-ROM leaving door locked fix from Andries + * Brouwer <Andries.Brouwer@cwi.nl> + * - Erik Andersen <andersen@xmission.com> unified + * commands across the various drivers and how + * sense errors are handled. + * + * 4.56 Sep 12, 1999 - Removed changer support - it is now in the + * Uniform layer. + * - Added partition based multisession handling. + * - Mode sense and mode select moved to the + * Uniform layer. + * - Fixed a problem with WPI CDS-32X drive - it + * failed the capabilities + * + * 4.57 Apr 7, 2000 - Fixed sense reporting. + * - Fixed possible oops in ide_cdrom_get_last_session() + * - Fix locking mania and make ide_cdrom_reset relock + * - Stop spewing errors to log when magicdev polls with + * TEST_UNIT_READY on some drives. + * - Various fixes from Tobias Ringstrom: + * tray if it was locked prior to the reset. + * - cdrom_read_capacity returns one frame too little. + * - Fix real capacity reporting. + * + * 4.58 May 1, 2000 - Clean up ACER50 stuff. + * - Fix small problem with ide_cdrom_capacity + * + * 4.59 Aug 11, 2000 - Fix changer problem in cdrom_read_toc, we weren't + * correctly sensing a disc change. + * - Rearranged some code + * - Use extended sense on drives that support it for + * correctly reporting tray status -- from + * Michael D Johnson <johnsom@orst.edu> + * 4.60 Dec 17, 2003 - Add mt rainier support + * - Bump timeout for packet commands, matches sr + * - Odd stuff + * 4.61 Jan 22, 2004 - support hardware sector sizes other than 2kB, + * Pascal Schmidt <der.eremit@email.de> + * + *************************************************************************/ + +#define IDECD_VERSION "4.61" + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/cdrom.h> +#include <linux/ide.h> +#include <linux/completion.h> + +#include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */ + +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <asm/uaccess.h> +#include <asm/unaligned.h> + +#include "ide-cd.h" + +static DECLARE_MUTEX(idecd_ref_sem); + +#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref) + +#define ide_cd_g(disk) \ + container_of((disk)->private_data, struct cdrom_info, driver) + +static struct cdrom_info *ide_cd_get(struct gendisk *disk) +{ + struct cdrom_info *cd = NULL; + + down(&idecd_ref_sem); + cd = ide_cd_g(disk); + if (cd) + kref_get(&cd->kref); + up(&idecd_ref_sem); + return cd; +} + +static void ide_cd_release(struct kref *); + +static void ide_cd_put(struct cdrom_info *cd) +{ + down(&idecd_ref_sem); + kref_put(&cd->kref, ide_cd_release); + up(&idecd_ref_sem); +} + +/**************************************************************************** + * Generic packet command support and error handling routines. + */ + +/* Mark that we've seen a media change, and invalidate our internal + buffers. */ +static void cdrom_saw_media_change (ide_drive_t *drive) +{ + struct cdrom_info *info = drive->driver_data; + + CDROM_STATE_FLAGS (drive)->media_changed = 1; + CDROM_STATE_FLAGS (drive)->toc_valid = 0; + info->nsectors_buffered = 0; +} + +static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, + struct request_sense *sense) +{ + int log = 0; + + if (!sense || !rq || (rq->flags & REQ_QUIET)) + return 0; + + switch (sense->sense_key) { + case NO_SENSE: case RECOVERED_ERROR: + break; + case NOT_READY: + /* + * don't care about tray state messages for + * e.g. capacity commands or in-progress or + * becoming ready + */ + if (sense->asc == 0x3a || sense->asc == 0x04) + break; + log = 1; + break; + case ILLEGAL_REQUEST: + /* + * don't log START_STOP unit with LoEj set, since + * we cannot reliably check if drive can auto-close + */ + if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) + log = 0; + break; + case UNIT_ATTENTION: + /* + * Make good and sure we've seen this potential media + * change. Some drives (i.e. Creative) fail to present + * the correct sense key in the error register. + */ + cdrom_saw_media_change(drive); + break; + default: + log = 1; + break; + } + return log; +} + +static +void cdrom_analyze_sense_data(ide_drive_t *drive, + struct request *failed_command, + struct request_sense *sense) +{ + if (!cdrom_log_sense(drive, failed_command, sense)) + return; + + /* + * If a read toc is executed for a CD-R or CD-RW medium where + * the first toc has not been recorded yet, it will fail with + * 05/24/00 (which is a confusing error) + */ + if (failed_command && failed_command->cmd[0] == GPCMD_READ_TOC_PMA_ATIP) + if (sense->sense_key == 0x05 && sense->asc == 0x24) + return; + +#if VERBOSE_IDE_CD_ERRORS + { + int i; + const char *s; + char buf[80]; + + printk ("ATAPI device %s:\n", drive->name); + if (sense->error_code==0x70) + printk(" Error: "); + else if (sense->error_code==0x71) + printk(" Deferred Error: "); + else if (sense->error_code == 0x7f) + printk(" Vendor-specific Error: "); + else + printk(" Unknown Error Type: "); + + if (sense->sense_key < ARY_LEN(sense_key_texts)) + s = sense_key_texts[sense->sense_key]; + else + s = "bad sense key!"; + + printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key); + + if (sense->asc == 0x40) { + sprintf(buf, "Diagnostic failure on component 0x%02x", + sense->ascq); + s = buf; + } else { + int lo = 0, mid, hi = ARY_LEN(sense_data_texts); + unsigned long key = (sense->sense_key << 16); + key |= (sense->asc << 8); + if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd)) + key |= sense->ascq; + s = NULL; + + while (hi > lo) { + mid = (lo + hi) / 2; + if (sense_data_texts[mid].asc_ascq == key || + sense_data_texts[mid].asc_ascq == (0xff0000|key)) { + s = sense_data_texts[mid].text; + break; + } + else if (sense_data_texts[mid].asc_ascq > key) + hi = mid; + else + lo = mid+1; + } + } + + if (s == NULL) { + if (sense->asc > 0x80) + s = "(vendor-specific error)"; + else + s = "(reserved error code)"; + } + + printk(KERN_ERR " %s -- (asc=0x%02x, ascq=0x%02x)\n", + s, sense->asc, sense->ascq); + + if (failed_command != NULL) { + + int lo=0, mid, hi= ARY_LEN (packet_command_texts); + s = NULL; + + while (hi > lo) { + mid = (lo + hi) / 2; + if (packet_command_texts[mid].packet_command == + failed_command->cmd[0]) { + s = packet_command_texts[mid].text; + break; + } + if (packet_command_texts[mid].packet_command > + failed_command->cmd[0]) + hi = mid; + else + lo = mid+1; + } + + printk (KERN_ERR " The failed \"%s\" packet command was: \n \"", s); + for (i=0; i<sizeof (failed_command->cmd); i++) + printk ("%02x ", failed_command->cmd[i]); + printk ("\"\n"); + } + + /* The SKSV bit specifies validity of the sense_key_specific + * in the next two commands. It is bit 7 of the first byte. + * In the case of NOT_READY, if SKSV is set the drive can + * give us nice ETA readings. + */ + if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) { + int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100; + printk(KERN_ERR " Command is %02d%% complete\n", progress / 0xffff); + + } + + if (sense->sense_key == ILLEGAL_REQUEST && + (sense->sks[0] & 0x80) != 0) { + printk(KERN_ERR " Error in %s byte %d", + (sense->sks[0] & 0x40) != 0 ? + "command packet" : "command data", + (sense->sks[1] << 8) + sense->sks[2]); + + if ((sense->sks[0] & 0x40) != 0) + printk (" bit %d", sense->sks[0] & 0x07); + + printk ("\n"); + } + } + +#else /* not VERBOSE_IDE_CD_ERRORS */ + + /* Suppress printing unit attention and `in progress of becoming ready' + errors when we're not being verbose. */ + + if (sense->sense_key == UNIT_ATTENTION || + (sense->sense_key == NOT_READY && (sense->asc == 4 || + sense->asc == 0x3a))) + return; + + printk(KERN_ERR "%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n", + drive->name, + sense->error_code, sense->sense_key, + sense->asc, sense->ascq); +#endif /* not VERBOSE_IDE_CD_ERRORS */ +} + +/* + * Initialize a ide-cd packet command request + */ +static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq) +{ + struct cdrom_info *cd = drive->driver_data; + + ide_init_drive_cmd(rq); + rq->flags = REQ_PC; + rq->rq_disk = cd->disk; +} + +static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, + struct request *failed_command) +{ + struct cdrom_info *info = drive->driver_data; + struct request *rq = &info->request_sense_request; + + if (sense == NULL) + sense = &info->sense_data; + + /* stuff the sense request in front of our current request */ + cdrom_prepare_request(drive, rq); + + rq->data = sense; + rq->cmd[0] = GPCMD_REQUEST_SENSE; + rq->cmd[4] = rq->data_len = 18; + + rq->flags = REQ_SENSE; + + /* NOTE! Save the failed command in "rq->buffer" */ + rq->buffer = (void *) failed_command; + + (void) ide_do_drive_cmd(drive, rq, ide_preempt); +} + +static void cdrom_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq = HWGROUP(drive)->rq; + int nsectors = rq->hard_cur_sectors; + + if ((rq->flags & REQ_SENSE) && uptodate) { + /* + * For REQ_SENSE, "rq->buffer" points to the original failed + * request + */ + struct request *failed = (struct request *) rq->buffer; + struct cdrom_info *info = drive->driver_data; + void *sense = &info->sense_data; + unsigned long flags; + + if (failed) { + if (failed->sense) { + sense = failed->sense; + failed->sense_len = rq->sense_len; + } + + /* + * now end failed request + */ + spin_lock_irqsave(&ide_lock, flags); + end_that_request_chunk(failed, 0, failed->data_len); + end_that_request_last(failed); + spin_unlock_irqrestore(&ide_lock, flags); + } + + cdrom_analyze_sense_data(drive, failed, sense); + } + + if (!rq->current_nr_sectors && blk_fs_request(rq)) + uptodate = 1; + /* make sure it's fully ended */ + if (blk_pc_request(rq)) + nsectors = (rq->data_len + 511) >> 9; + if (!nsectors) + nsectors = 1; + + ide_end_request(drive, uptodate, nsectors); +} + +/* Returns 0 if the request should be continued. + Returns 1 if the request was ended. */ +static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) +{ + struct request *rq = HWGROUP(drive)->rq; + int stat, err, sense_key; + + /* Check for errors. */ + stat = HWIF(drive)->INB(IDE_STATUS_REG); + if (stat_ret) + *stat_ret = stat; + + if (OK_STAT(stat, good_stat, BAD_R_STAT)) + return 0; + + /* Get the IDE error register. */ + err = HWIF(drive)->INB(IDE_ERROR_REG); + sense_key = err >> 4; + + if (rq == NULL) { + printk("%s: missing rq in cdrom_decode_status\n", drive->name); + return 1; + } + + if (rq->flags & REQ_SENSE) { + /* We got an error trying to get sense info + from the drive (probably while trying + to recover from a former error). Just give up. */ + + rq->flags |= REQ_FAILED; + cdrom_end_request(drive, 0); + ide_error(drive, "request sense failure", stat); + return 1; + + } else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) { + /* All other functions, except for READ. */ + unsigned long flags; + + /* + * if we have an error, pass back CHECK_CONDITION as the + * scsi status byte + */ + if ((rq->flags & REQ_BLOCK_PC) && !rq->errors) + rq->errors = SAM_STAT_CHECK_CONDITION; + + /* Check for tray open. */ + if (sense_key == NOT_READY) { + cdrom_saw_media_change (drive); + } else if (sense_key == UNIT_ATTENTION) { + /* Check for media change. */ + cdrom_saw_media_change (drive); + /*printk("%s: media changed\n",drive->name);*/ + return 0; + } else if (!(rq->flags & REQ_QUIET)) { + /* Otherwise, print an error. */ + ide_dump_status(drive, "packet command error", stat); + } + + rq->flags |= REQ_FAILED; + + /* + * instead of playing games with moving completions around, + * remove failed request completely and end it when the + * request sense has completed + */ + if (stat & ERR_STAT) { + spin_lock_irqsave(&ide_lock, flags); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + spin_unlock_irqrestore(&ide_lock, flags); + + cdrom_queue_request_sense(drive, rq->sense, rq); + } else + cdrom_end_request(drive, 0); + + } else if (blk_fs_request(rq)) { + int do_end_request = 0; + + /* Handle errors from READ and WRITE requests. */ + + if (blk_noretry_request(rq)) + do_end_request = 1; + + if (sense_key == NOT_READY) { + /* Tray open. */ + if (rq_data_dir(rq) == READ) { + cdrom_saw_media_change (drive); + + /* Fail the request. */ + printk ("%s: tray open\n", drive->name); + do_end_request = 1; + } else { + struct cdrom_info *info = drive->driver_data; + + /* allow the drive 5 seconds to recover, some + * devices will return this error while flushing + * data from cache */ + if (!rq->errors) + info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY; + rq->errors = 1; + if (time_after(jiffies, info->write_timeout)) + do_end_request = 1; + else { + unsigned long flags; + + /* + * take a breather relying on the + * unplug timer to kick us again + */ + spin_lock_irqsave(&ide_lock, flags); + blk_plug_device(drive->queue); + spin_unlock_irqrestore(&ide_lock,flags); + return 1; + } + } + } else if (sense_key == UNIT_ATTENTION) { + /* Media change. */ + cdrom_saw_media_change (drive); + + /* Arrange to retry the request. + But be sure to give up if we've retried + too many times. */ + if (++rq->errors > ERROR_MAX) + do_end_request = 1; + } else if (sense_key == ILLEGAL_REQUEST || + sense_key == DATA_PROTECT) { + /* No point in retrying after an illegal + request or data protect error.*/ + ide_dump_status (drive, "command error", stat); + do_end_request = 1; + } else if (sense_key == MEDIUM_ERROR) { + /* No point in re-trying a zillion times on a bad + * sector... If we got here the error is not correctable */ + ide_dump_status (drive, "media error (bad sector)", stat); + do_end_request = 1; + } else if (sense_key == BLANK_CHECK) { + /* Disk appears blank ?? */ + ide_dump_status (drive, "media error (blank)", stat); + do_end_request = 1; + } else if ((err & ~ABRT_ERR) != 0) { + /* Go to the default handler + for other errors. */ + ide_error(drive, "cdrom_decode_status", stat); + return 1; + } else if ((++rq->errors > ERROR_MAX)) { + /* We've racked up too many retries. Abort. */ + do_end_request = 1; + } + + if (do_end_request) + cdrom_end_request(drive, 0); + + /* If we got a CHECK_CONDITION status, + queue a request sense command. */ + if ((stat & ERR_STAT) != 0) + cdrom_queue_request_sense(drive, NULL, NULL); + } else { + blk_dump_rq_flags(rq, "ide-cd: bad rq"); + cdrom_end_request(drive, 0); + } + + /* Retry, or handle the next request. */ + return 1; +} + +static int cdrom_timer_expiry(ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + unsigned long wait = 0; + + /* + * Some commands are *slow* and normally take a long time to + * complete. Usually we can use the ATAPI "disconnect" to bypass + * this, but not all commands/drives support that. Let + * ide_timer_expiry keep polling us for these. + */ + switch (rq->cmd[0]) { + case GPCMD_BLANK: + case GPCMD_FORMAT_UNIT: + case GPCMD_RESERVE_RZONE_TRACK: + case GPCMD_CLOSE_TRACK: + case GPCMD_FLUSH_CACHE: + wait = ATAPI_WAIT_PC; + break; + default: + if (!(rq->flags & REQ_QUIET)) + printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]); + wait = 0; + break; + } + return wait; +} + +/* Set up the device registers for transferring a packet command on DEV, + expecting to later transfer XFERLEN bytes. HANDLER is the routine + which actually transfers the command to the drive. If this is a + drq_interrupt device, this routine will arrange for HANDLER to be + called when the interrupt from the drive arrives. Otherwise, HANDLER + will be called immediately after the drive is prepared for the transfer. */ + +static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, + int xferlen, + ide_handler_t *handler) +{ + ide_startstop_t startstop; + struct cdrom_info *info = drive->driver_data; + ide_hwif_t *hwif = drive->hwif; + + /* Wait for the controller to be idle. */ + if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) + return startstop; + + if (info->dma) + info->dma = !hwif->dma_setup(drive); + + /* Set up the controller registers. */ + /* FIXME: for Virtual DMA we must check harder */ + HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG); + HWIF(drive)->OUTB(0, IDE_IREASON_REG); + HWIF(drive)->OUTB(0, IDE_SECTOR_REG); + + HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG); + HWIF(drive)->OUTB(xferlen >> 8 , IDE_BCOUNTH_REG); + if (IDE_CONTROL_REG) + HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); + + if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { + /* packet command */ + ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); + return ide_started; + } else { + unsigned long flags; + + /* packet command */ + spin_lock_irqsave(&ide_lock, flags); + hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG); + ndelay(400); + spin_unlock_irqrestore(&ide_lock, flags); + + return (*handler) (drive); + } +} + +/* Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. + The device registers must have already been prepared + by cdrom_start_packet_command. + HANDLER is the interrupt handler to call when the command completes + or there's data ready. */ +/* + * changed 5 parameters to 3 for dvd-ram + * struct packet_command *pc; now packet_command_t *pc; + */ +#define ATAPI_MIN_CDB_BYTES 12 +static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, + struct request *rq, + ide_handler_t *handler) +{ + ide_hwif_t *hwif = drive->hwif; + int cmd_len; + struct cdrom_info *info = drive->driver_data; + ide_startstop_t startstop; + + if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) { + /* Here we should have been called after receiving an interrupt + from the device. DRQ should how be set. */ + + /* Check for errors. */ + if (cdrom_decode_status(drive, DRQ_STAT, NULL)) + return ide_stopped; + } else { + /* Otherwise, we must wait for DRQ to get set. */ + if (ide_wait_stat(&startstop, drive, DRQ_STAT, + BUSY_STAT, WAIT_READY)) + return startstop; + } + + /* Arm the interrupt handler. */ + ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry); + + /* ATAPI commands get padded out to 12 bytes minimum */ + cmd_len = COMMAND_SIZE(rq->cmd[0]); + if (cmd_len < ATAPI_MIN_CDB_BYTES) + cmd_len = ATAPI_MIN_CDB_BYTES; + + /* Send the command to the device. */ + HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len); + + /* Start the DMA if need be */ + if (info->dma) + hwif->dma_start(drive); + + return ide_started; +} + +/**************************************************************************** + * Block read functions. + */ + +/* + * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector + * buffer. Once the first sector is added, any subsequent sectors are + * assumed to be continuous (until the buffer is cleared). For the first + * sector added, SECTOR is its sector number. (SECTOR is then ignored until + * the buffer is cleared.) + */ +static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, + int sectors_to_transfer) +{ + struct cdrom_info *info = drive->driver_data; + + /* Number of sectors to read into the buffer. */ + int sectors_to_buffer = min_t(int, sectors_to_transfer, + (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - + info->nsectors_buffered); + + char *dest; + + /* If we couldn't get a buffer, don't try to buffer anything... */ + if (info->buffer == NULL) + sectors_to_buffer = 0; + + /* If this is the first sector in the buffer, remember its number. */ + if (info->nsectors_buffered == 0) + info->sector_buffered = sector; + + /* Read the data into the buffer. */ + dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; + while (sectors_to_buffer > 0) { |