diff options
Diffstat (limited to 'drivers/block/ide-cd.c')
-rw-r--r-- | drivers/block/ide-cd.c | 188 |
1 files changed, 116 insertions, 72 deletions
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index 53ee1a13f..02f97ec6f 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -1,15 +1,46 @@ -/* #define VERBOSE_IDE_CD_ERRORS 1 */ +#define VERBOSE_IDE_CD_ERRORS 1 /* * linux/drivers/block/ide-cd.c - * ATAPI cd-rom driver. To be used with ide.c. + * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov> + * Copyright (C) 1996, 1997 Erik Andersen <andersee@debian.org> + * 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. * - * Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov> - * Copyright (C) 1996 Erik Andersen <andersee@et.byu.edu> + * 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 ATAPI standard. This document can be + * obtained by anonymous ftp from fission.dt.wdc.com in directory: + * /pub/standards/SFF_atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf * - * May be copied or modified under the terms of the GNU General Public License - * see linux/COPYING for more information. + * Drives that deviate from the ATAPI standard will be accomodated as much + * as possible via compile options. Since I only have a few drives, you you + * generally need to send me patches... * + * ---------------------------------- + * TO DO LIST: + * -Avoid printing error messages for expected errors from the drive. + * (If you are using a cd changer, you may get errors in the kernel + * logs that are completly expected. Don't complain to me about this, + * unless you have a patch to fix it. I am working on it...) + * -Implement ide_cdrom_select_speed using the generic cdrom interface + * -Fix ide_cdrom_reset so that it works (it does nothing right now) + * -When trying to mount a cdrom with the tray open, you get an billion + * "tray open or drive not ready" messages until the tray gets closed. + * This is because ide-cd does not properly return drive_status immediatly, + * but instead waits for the drive to close first (bad, bad, bad) + * and keeps on trying, and failing... This bug was revealed by the + * recent changes to the Uniform CD-ROm driver, and I havn't had a + * chance to fix it yet. + * + * MOSTLY DONE LIST: + * Query the drive to find what features are available + * before trying to use them. + * + * + * ---------------------------------- * 1.00 Oct 31, 1994 -- Initial version. * 1.01 Nov 2, 1994 -- Fixed problem with starting request in * cdrom_check_status. @@ -121,7 +152,7 @@ * * * 4.00 Nov 5, 1996 -- New ide-cd maintainer, - * Erik B. Andersen <andersee@et.byu.edu> + * Erik B. Andersen <andersee@debian.org> * -- Newer Creative drives don't always set the error * register correctly. Make sure we see media changes * regardless. @@ -147,32 +178,16 @@ * 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 * - * MOSTLY DONE LIST: - * Query the drive to find what features are available - * before trying to use them. - * - * TO DO LIST: - * Avoid printing error messages for expected errors from the drive. - * (If you are using a cd changer, you may get errors in the kernel - * logs that are completly expected. Don't complain to me about this, - * unless you have a patch to fix it. I am working on it...) - * Reset unlocks drive? - * Implement ide_cdrom_disc_status using the generic cdrom interface - * Implement ide_cdrom_select_speed using the generic cdrom interface - * Fix ide_cdrom_reset so that it works (it does nothing right now) - * - * -- 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 ATAPI standard. This document can be - * obtained by anonymous ftp from fission.dt.wdc.com in directory: - * /pub/standards/atapi/spec/SFF8020-r2.6/PDF/8020r26.pdf - * - */ - - -/***************************************************************************/ + *************************************************************************/ +#include <linux/config.h> #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -185,7 +200,6 @@ #include <linux/errno.h> #include <linux/hdreg.h> #include <linux/cdrom.h> -#include <linux/ucdrom.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/byteorder.h> @@ -463,13 +477,16 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat, because workman constantly polls the drive with this command, and we don't want to uselessly fill up the syslog. */ - if (pc->c[0] != SCMD_READ_SUBCHANNEL) + if (pc->c[0] != SCMD_READ_SUBCHANNEL) { printk ("%s: tray open or drive not ready\n", drive->name); + return 1; + } } else if (sense_key == UNIT_ATTENTION) { /* Check for media change. */ cdrom_saw_media_change (drive); - printk ("%s: media changed\n", drive->name); + printk (" %s: media changed\n", drive->name); + return 0; } else { /* Otherwise, print an error. */ ide_dump_status (drive, "packet command error", @@ -1094,8 +1111,13 @@ static void cdrom_pc_intr (ide_drive_t *drive) if (pc->buflen == 0) cdrom_end_request (1, drive); else { + /* Comment this out, because this always happins + right after a reset occurs, and it is annoying to + always print expected stuff. */ + /* printk ("%s: cdrom_pc_intr: data underrun %d\n", drive->name, pc->buflen); + */ pc->stat = 1; cdrom_end_request (1, drive); } @@ -1355,7 +1377,7 @@ void msf_from_bcd (struct atapi_msf *msf) static inline void lba_to_msf (int lba, byte *m, byte *s, byte *f) { - lba += CD_BLOCK_OFFSET; + lba += CD_MSF_OFFSET; lba &= 0xffffff; /* negative lbas use only 24 bits */ *m = lba / (CD_SECS * CD_FRAMES); lba %= (CD_SECS * CD_FRAMES); @@ -1367,7 +1389,7 @@ void lba_to_msf (int lba, byte *m, byte *s, byte *f) static inline int msf_to_lba (byte m, byte s, byte f) { - return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET; + return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; } @@ -1421,7 +1443,7 @@ cdrom_lockdoor (ide_drive_t *drive, int lockflag, probably cannot lock the door. */ if (stat != 0 && reqbuf->sense_key == ILLEGAL_REQUEST && - reqbuf->asc == 0x24) { + (reqbuf->asc == 0x24 || reqbuf->asc == 0x20)) { printk ("%s: door locking not supported\n", drive->name); CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; @@ -2325,12 +2347,17 @@ int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, return cdrom_startstop (drive, 1, NULL); case CDROMSTOP: { - int stat; - - stat = cdrom_startstop (drive, 0, NULL); - if (stat) return stat; - /* pit says the Dolphin needs this. */ - return cdrom_eject (drive, 1, NULL); +#ifdef IHAVEADOLPHIN + /* Certain Drives require this. Most don't + and will produce errors upon CDROMSTOP + pit says the Dolphin needs this. If you + own a dolphin, just define IHAVEADOLPHIN somewhere */ + int stat; + stat = cdrom_startstop (drive, 0, NULL); + if (stat) return stat; + return cdrom_eject (drive, 1, NULL); +#endif /* end of IHAVEADOLPHIN */ + return cdrom_startstop (drive, 0, NULL); } case CDROMPAUSE: @@ -2360,7 +2387,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi) return ide_do_drive_cmd (drive, &req, ide_wait); #endif -/* For now, just return 0, as if things worked... */ +/* For now, just return 0, as if things had worked... */ return 0; @@ -2399,10 +2426,8 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) int stat; int nslots, curslot; - if ( ! CDROM_CONFIG_FLAGS (drive)->is_changer) { - printk ("%s: Not a changer.", drive->name); - return -EINVAL; - } + if ( ! CDROM_CONFIG_FLAGS (drive)->is_changer) + return -EDRIVE_CANT_DO_THIS; #if ! STANDARD_ATAPI if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) { @@ -2436,7 +2461,7 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) stat = cdrom_check_status (drive, &my_reqbuf); if (stat && my_reqbuf.sense_key == NOT_READY) - return (-ENOENT); + return -ENOENT; if (slot == CDSL_NONE) { (void) cdrom_load_unload (drive, -1, NULL); @@ -2449,11 +2474,8 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot) #if ! STANDARD_ATAPI CDROM_STATE_FLAGS (drive)->sanyo_slot == 0 && #endif - info->changer_info->slots[slot].disc_present - == 0) { - printk ("%s: Requested slot does not contain a CD.\n", - drive->name); - return (-ENOENT); + info->changer_info->slots[slot].disc_present == 0) { + return -ENOMEDIUM; } stat = cdrom_load_unload (drive, slot, NULL); @@ -2519,7 +2541,6 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) } } - static int ide_cdrom_get_last_session (struct cdrom_device_info *cdi, struct cdrom_multisession *ms_info) @@ -2628,16 +2649,16 @@ void ide_cdrom_release_real (struct cdrom_device_info *cdi) /**************************************************************************** * Device initialization. */ + static struct cdrom_device_ops ide_cdrom_dops = { ide_cdrom_open_real, /* open */ ide_cdrom_release_real, /* release */ ide_cdrom_drive_status, /* drive_status */ - 0, /* disc_status */ ide_cdrom_check_media_change_real, /* media_changed */ ide_cdrom_tray_move, /* tray_move */ ide_cdrom_lock_door, /* lock_door */ - 0, /* select_speed */ + NULL, /* select_speed */ ide_cdrom_select_disc, /* select_disc */ ide_cdrom_get_last_session, /* get_last_session */ ide_cdrom_get_mcn, /* get_mcn */ @@ -2646,11 +2667,11 @@ struct cdrom_device_ops ide_cdrom_dops = { ide_cdrom_dev_ioctl, /* dev_ioctl */ CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN - | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO, /* capability */ + | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET + | CDC_IOCTLS | CDC_DRIVE_STATUS, /* capability */ 0 /* n_minors */ }; - static int ide_cdrom_register (ide_drive_t *drive, int nslots) { struct cdrom_info *info = drive->driver_data; @@ -2660,11 +2681,11 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots) devinfo->dev = MKDEV (HWIF(drive)->major, minor); devinfo->ops = &ide_cdrom_dops; devinfo->mask = 0; - *(int *)&devinfo->speed = 0; + *(int *)&devinfo->speed = CDROM_CONFIG_FLAGS (drive)->max_speed; *(int *)&devinfo->capacity = nslots; devinfo->handle = (void *) drive; - - return register_cdrom (devinfo, drive->name); + strcpy(devinfo->name, drive->name); + return register_cdrom (devinfo); } @@ -2690,6 +2711,11 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) if (buf.cap.lock == 0) CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1; + if (buf.cap.cd_r_write) + CDROM_CONFIG_FLAGS (drive)->cd_r = 1; + if (buf.cap.cd_rw_write) + CDROM_CONFIG_FLAGS (drive)->cd_rw = 1; + #if ! STANDARD_ATAPI if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) { CDROM_CONFIG_FLAGS (drive)->is_changer = 1; @@ -2711,9 +2737,23 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) } } - if (CDROM_CONFIG_FLAGS (drive)->is_changer) - printk (" %s: ATAPI CDROM changer with %d slots\n", - drive->name, nslots); + CDROM_STATE_FLAGS (drive)->curent_speed = ntohs(buf.cap.curspeed)/176; + CDROM_CONFIG_FLAGS (drive)->max_speed = ntohs(buf.cap.maxspeed)/176; + + stat=0; + printk ("%s: ATAPI %dx CDROM", + drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed); + if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) + printk (" CD%s%s", + (CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "", + (CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : ""); + if (CDROM_CONFIG_FLAGS (drive)->is_changer) + printk (" changer w/%d slots", nslots); + else + printk (" drive"); + printk (" %s/%dkB Cache\n", + (CDROM_CONFIG_FLAGS (drive)->is_changer)? "&" : "w", + ntohs(buf.cap.buffer_size) ); return nslots; } @@ -2751,6 +2791,8 @@ int ide_cdrom_setup (ide_drive_t *drive) CDROM_CONFIG_FLAGS (drive)->drq_interrupt = 0; CDROM_CONFIG_FLAGS (drive)->is_changer = 0; + CDROM_CONFIG_FLAGS (drive)->cd_r = 0; + CDROM_CONFIG_FLAGS (drive)->cd_rw = 0; CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0; #if ! STANDARD_ATAPI @@ -2802,13 +2844,15 @@ int ide_cdrom_setup (ide_drive_t *drive) CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd = 1; } - /* Sanyo 3 CD changer uses a non-standard command - for CD changing. */ - else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0)) { - /* uses CD in slot 0 when value is set to 3 */ - CDROM_STATE_FLAGS (drive)->sanyo_slot = 3; - } + /* Sanyo 3 CD changer uses a non-standard command + for CD changing */ + else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || + (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || + (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { + /* uses CD in slot 0 when value is set to 3 */ + CDROM_STATE_FLAGS (drive)->sanyo_slot = 3; + } + } #endif /* not STANDARD_ATAPI */ |