summaryrefslogtreecommitdiffstats
path: root/drivers/block/ide-cd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/ide-cd.c')
-rw-r--r--drivers/block/ide-cd.c96
1 files changed, 64 insertions, 32 deletions
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 3a8e48722..24f00c950 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -3,13 +3,14 @@
* linux/drivers/block/ide-cd.c
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-1998 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.
*
- * Suggestions are welcome. Patches that work are more welcome though.
+ * 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:
@@ -27,10 +28,8 @@
* 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)
- *
- * MOSTLY DONE LIST:
- * Query the drive to find what features are available
- * before trying to use them.
+ * -Query the drive to find what features are available before trying to
+ * use them (like trying to close the tray in drives that can't).
*
*
* ----------------------------------
@@ -180,12 +179,21 @@
*
* 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.
*
*************************************************************************/
-#define IDECD_VERSION "4.07"
+#define IDECD_VERSION "4.10"
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -243,6 +251,15 @@ void cdrom_analyze_sense_data (ide_drive_t *drive,
failed_command->c[0] == SCMD_READ_SUBCHANNEL)
return;
}
+ if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02
+ && reqbuf->asc == 0x3a && reqbuf->ascq == 0x00)
+ {
+ /*
+ * No disc in drive ("Medium not present"),
+ * so keep the noise level down to a dull roar.
+ */
+ return;
+ }
#if VERBOSE_IDE_CD_ERRORS
{
@@ -466,7 +483,7 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
/* Check for tray open. */
if (sense_key == NOT_READY) {
cdrom_saw_media_change (drive);
-
+#if 0 /* let the upper layers do the complaining */
/* Print an error message to the syslog.
Exception: don't print anything if this
is a read subchannel command. This is
@@ -474,12 +491,13 @@ static int cdrom_decode_status (ide_drive_t *drive, int good_stat,
with this command, and we don't want
to uselessly fill up the syslog. */
if (pc->c[0] != SCMD_READ_SUBCHANNEL)
- printk ("%s: tray open or drive not ready\n",
- drive->name);
+ printk ("%s: tray open or drive not ready\n", drive->name);
+#endif
} 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 {
/* Otherwise, print an error. */
ide_dump_status (drive, "packet command error",
@@ -1297,7 +1315,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
/****************************************************************************
* cdrom driver request routine.
*/
-
+static
void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
{
if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND)
@@ -1651,7 +1669,7 @@ cdrom_read_toc (ide_drive_t *drive,
if (stat) toc->capacity = 0x1fffff;
HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]
- = toc->capacity * SECTORS_PER_FRAME;
+ = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
/* Remember that we've read this stuff. */
@@ -2455,10 +2473,6 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
if (drive->usage > 1)
return -EBUSY;
- stat = cdrom_check_status (drive, &my_reqbuf);
- if (stat && my_reqbuf.sense_key == NOT_READY)
- return -ENOENT;
-
if (slot == CDSL_NONE) {
(void) cdrom_load_unload (drive, -1, NULL);
cdrom_saw_media_change (drive);
@@ -2734,12 +2748,13 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
}
}
- if (drive->id && drive->id->model[0]) {
- CDROM_STATE_FLAGS (drive)->current_speed = (ntohs(buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed = (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
- } else { /* no-name ACERs (AOpen) have it backwards */
+ /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
+ if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
CDROM_CONFIG_FLAGS (drive)->max_speed = (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
+ } else {
+ CDROM_STATE_FLAGS (drive)->current_speed = (ntohs(buf.cap.curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS (drive)->max_speed = (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
}
printk ("%s: ATAPI %dX CDROM",
@@ -2752,13 +2767,23 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
printk (" changer w/%d slots", nslots);
else
printk (" drive");
- printk (" %s/%dkB Cache\n",
- (CDROM_CONFIG_FLAGS (drive)->is_changer)? "&" : "w",
+ printk (", %dkB Cache\n",
ntohs(buf.cap.buffer_size) );
return nslots;
}
+static void ide_cdrom_add_settings(ide_drive_t *drive)
+{
+ int major = HWIF(drive)->major;
+ int minor = drive->select.b.unit << PARTN_BITS;
+
+ ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
+ ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
+ ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
+ ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
+}
+
static
int ide_cdrom_setup (ide_drive_t *drive)
{
@@ -2871,11 +2896,12 @@ int ide_cdrom_setup (ide_drive_t *drive)
info->devinfo.handle = NULL;
return 1;
}
+ ide_cdrom_add_settings(drive);
return 0;
}
/* Forwarding functions to generic routines. */
-
+static
int ide_cdrom_ioctl (ide_drive_t *drive,
struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
@@ -2883,6 +2909,7 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
return cdrom_fops.ioctl (inode, file, cmd, arg);
}
+static
int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
{
int rc;
@@ -2896,6 +2923,7 @@ int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
return rc;
}
+static
void ide_cdrom_release (struct inode *inode, struct file *file,
ide_drive_t *drive)
{
@@ -2903,6 +2931,7 @@ void ide_cdrom_release (struct inode *inode, struct file *file,
MOD_DEC_USE_COUNT;
}
+static
int ide_cdrom_check_media_change (ide_drive_t *drive)
{
return cdrom_fops.check_media_change
@@ -2911,6 +2940,7 @@ int ide_cdrom_check_media_change (ide_drive_t *drive)
}
+static
int ide_cdrom_cleanup(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
@@ -2922,6 +2952,8 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
kfree (info->sector_buffer);
if (info->toc != NULL)
kfree (info->toc);
+ if (info->changer_info != NULL)
+ kfree (info->changer_info);
if (devinfo->handle == drive && unregister_cdrom (devinfo))
printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
kfree (info);
@@ -2929,13 +2961,6 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
return 0;
}
-int ide_cdrom_init (void);
-static ide_module_t ide_cdrom_module = {
- IDE_DRIVER_MODULE,
- ide_cdrom_init,
- NULL
-};
-
static ide_driver_t ide_cdrom_driver = {
"ide-cdrom", /* name */
IDECD_VERSION, /* version */
@@ -2956,6 +2981,13 @@ static ide_driver_t ide_cdrom_driver = {
NULL /* proc */
};
+int ide_cdrom_init (void);
+static ide_module_t ide_cdrom_module = {
+ IDE_DRIVER_MODULE,
+ ide_cdrom_init,
+ &ide_cdrom_driver,
+ NULL
+};
#ifdef MODULE
int init_module (void)
@@ -2968,7 +3000,7 @@ void cleanup_module(void)
ide_drive_t *drive;
int failed = 0;
- while ((drive = ide_scan_devices (ide_cdrom, &ide_cdrom_driver, failed)) != NULL)
+ while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, &ide_cdrom_driver, failed)) != NULL)
if (ide_cdrom_cleanup (drive)) {
printk ("%s: cleanup_module() called while still busy\n", drive->name);
failed++;
@@ -2984,7 +3016,7 @@ int ide_cdrom_init (void)
int failed = 0;
MOD_INC_USE_COUNT;
- while ((drive = ide_scan_devices (ide_cdrom, NULL, failed++)) != NULL) {
+ while ((drive = ide_scan_devices (ide_cdrom, ide_cdrom_driver.name, NULL, failed++)) != NULL) {
info = (struct cdrom_info *) kmalloc (sizeof (struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk ("%s: Can't allocate a cdrom structure\n", drive->name);