From: Gunther.Mayer@t-online.de (Gunther Mayer)
To: torvalds@transmeta.com
Cc: paul@paulbristow.net, linux-kernel@vger.kernel.org
Subject: (patch-2.4.6) Fix oops with Iomega Clik! (ide-floppy)
Date: Sat, 14 Jul 2001 12:38:51 +0200 [thread overview]
Message-ID: <3B50213B.A826C259@t-online.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 20234 bytes --]
Hi,
this fixes an Oops when accessing an IOMEGA PC card Clik! drive
(NULL pointer in get_flexible_disk_page).
Linus, please include if you like.
This is the original patch from the MAINTAINER
but he seems defunct since three weeks.
Regards, Gunther
--- linux246-orig/drivers/ide/ide-floppy.c Fri Feb 9 20:30:23 2001
+++ linux/drivers/ide/ide-floppy.c Sat Jul 14 12:07:40 2001
@@ -1,7 +1,8 @@
/*
- * linux/drivers/ide/ide-floppy.c Version 0.9 Jul 4, 1999
+ * linux/drivers/ide/ide-floppy.c Version 0.96 Jan 7, 2001
*
* Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2000 - 2001 Paul Bristow <paul@paulbristow.net>
*/
/*
@@ -10,6 +11,12 @@
* The driver currently doesn't have any fancy features, just the bare
* minimum read/write support.
*
+ * This driver supports the following IDE floppy drives:
+ *
+ * LS-120 SuperDisk
+ * Iomega Zip 100/250
+ * Iomega PC Card Clik!/PocketZip
+ *
* Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many
* ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
*
@@ -29,9 +36,20 @@
* Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of
* bytes requested on each interrupt to be zero.
* Thanks to <shanos@es.co.nz> for pointing this out.
+ * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by
+ * <paul@paulbristow.net>
+ * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this
+ * driver. Included Powerbook internal zip kludge.
+ * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive
+ * no disk on insert and disk change now works
+ * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere
+ * Ver 0.95 Nov 7 00 Brought across to kernel 2.4
+ * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0
+ * including set_bit patch from Rusty Russel
+ *
*/
-#define IDEFLOPPY_VERSION "0.9"
+#define IDEFLOPPY_VERSION "0.96"
#include <linux/config.h>
#include <linux/module.h>
@@ -45,7 +63,7 @@
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
-#include <linux/slab.h>
+#include <linux/malloc.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
@@ -56,12 +74,14 @@
#include <asm/unaligned.h>
#include <asm/bitops.h>
+
/*
* The following are used to debug the driver.
*/
-#define IDEFLOPPY_DEBUG_LOG 0
#define IDEFLOPPY_DEBUG_INFO 0
#define IDEFLOPPY_DEBUG_BUGS 1
+/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
+#define IDEFLOPPY_DEBUG( fmt, args... )
/*
* Some drives require a longer irq timeout.
@@ -104,7 +124,7 @@
byte *current_position; /* Pointer into the above buffer */
void (*callback) (ide_drive_t *); /* Called when this packet command is completed */
byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */
- unsigned long flags; /* Status/Action bit flags: long for set_bit */
+ unsigned long flags; /* Status/Action bit flags : long for set_bit() */
} idefloppy_pc_t;
/*
@@ -181,6 +201,7 @@
u8 reserved30[2];
} idefloppy_flexible_disk_page_t;
+
/*
* Format capacity
*/
@@ -237,7 +258,7 @@
idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */
int wp; /* Write protect */
- unsigned int flags; /* Status/Action flags */
+ unsigned long flags; /* Status/Action flags : long for set_bit() */
} idefloppy_floppy_t;
/*
@@ -246,6 +267,8 @@
#define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */
#define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */
#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */
+#define IDEFLOPPY_CLIK_DRIVE 3 /* Avoid commands not supported in Clik drive */
+#define IDEFLOPPY_POWERBOOK_ZIP 4 /* Kludge for Apple Powerbook Zip drive */
/*
* ATAPI floppy drive packet commands
@@ -621,9 +644,7 @@
struct request *rq = hwgroup->rq;
int error;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_end_request\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Reached idefloppy_end_request\n");
switch (uptodate) {
case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
@@ -746,21 +767,19 @@
idefloppy_floppy_t *floppy = drive->driver_data;
floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq;
-#if IDEFLOPPY_DEBUG_LOG
- if (floppy->failed_pc)
- printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq);
- else
- printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ if (floppy->failed_pc) {
+ IDEFLOPPY_DEBUG("ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq);
+ }
+ else {
+ IDEFLOPPY_DEBUG("ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq);
+ }
}
static void idefloppy_request_sense_callback (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_request_sense_callback\n");
if (!floppy->pc->error) {
idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);
idefloppy_end_request (1,HWGROUP (drive));
@@ -777,9 +796,7 @@
{
idefloppy_floppy_t *floppy = drive->driver_data;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_callback\n");
idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive));
}
@@ -840,9 +857,7 @@
struct request *rq = pc->rq;
unsigned int temp;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n");
#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
@@ -852,26 +867,20 @@
pc->actually_transferred=pc->request_transfer;
idefloppy_update_buffers (drive, pc);
}
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: DMA finished\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: DMA finished\n");
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
status.all = GET_STAT(); /* Clear the interrupt */
if (!status.b.drq) { /* No more interrupts */
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
ide__sti(); /* local CPU only */
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error\n",drive->name);
rq->errors++;
if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
printk (KERN_ERR "ide-floppy: I/O error in request sense command\n");
@@ -915,9 +924,7 @@
ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
return ide_started;
}
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n");
}
}
if (test_bit (PC_WRITING, &pc->flags)) {
@@ -983,7 +990,7 @@
* a legitimate error code was received.
*/
if (!test_bit (PC_ABORT, &pc->flags)) {
- printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n",
+ IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n",
drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq);
pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */
}
@@ -991,9 +998,7 @@
pc->callback(drive);
return ide_stopped;
}
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Retry number - %d\n",pc->retries);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Retry number - %d\n",pc->retries);
pc->retries++;
pc->actually_transferred=0; /* We haven't transferred any data yet */
@@ -1034,9 +1039,7 @@
static void idefloppy_rw_callback (ide_drive_t *drive)
{
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_rw_callback\n");
idefloppy_end_request(1, HWGROUP(drive));
return;
@@ -1044,9 +1047,7 @@
static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent)
{
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: creating prevent removal command, prevent = %d\n", prevent);
idefloppy_init_pc (pc);
pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;
@@ -1106,10 +1107,8 @@
int block = sector / floppy->bs_factor;
int blocks = rq->nr_sectors / floppy->bs_factor;
-#if IDEFLOPPY_DEBUG_LOG
- printk ("create_rw1%d_cmd: block == %d, blocks == %d\n",
+ IDEFLOPPY_DEBUG( "create_rw1%d_cmd: block == %d, blocks == %d\n",
2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks);
-#endif /* IDEFLOPPY_DEBUG_LOG */
idefloppy_init_pc (pc);
if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) {
@@ -1139,10 +1138,8 @@
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t *pc;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
- printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
+ IDEFLOPPY_DEBUG( "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
if (rq->errors >= ERROR_MAX) {
if (floppy->failed_pc != NULL)
@@ -1235,6 +1232,7 @@
return 0;
}
+
/*
* Determine if a media is present in the floppy drive, and if so,
* its LBA capacity.
@@ -1263,48 +1261,68 @@
for (i = 0; i < descriptors; i++, descriptor++) {
blocks = descriptor->blocks = ntohl (descriptor->blocks);
length = descriptor->length = ntohs (descriptor->length);
- if (!i && descriptor->dc == CAPACITY_CURRENT) {
- if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) {
- printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n",
- drive->name, blocks * length / 1024, blocks, length,
- drive->using_dma ? ", DMA":"");
- }
- floppy->capacity = *descriptor;
+ if (!i) {
+ switch (descriptor->dc) {
+ case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+ break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */
+ case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */
+ if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
+ printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length);
+ floppy->capacity = *descriptor;
if (!length || length % 512)
- printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length);
+ printk (KERN_NOTICE "%s: %d bytes block size not supported\n", drive->name, length);
else {
floppy->blocks = blocks;
floppy->block_size = length;
if ((floppy->bs_factor = length / 512) != 1)
printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name);
- rc = 0;
- }
+ rc = 0;
+ }
+ break;
+ case CAPACITY_NO_CARTRIDGE:
+ /* This is a KERN_ERR so it appears on screen for the user to see */
+ printk (KERN_ERR "%s: No disk in drive\n", drive->name);
+ break;
+ case CAPACITY_INVALID:
+ printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name);
+ break;
}
-#if IDEFLOPPY_DEBUG_INFO
- if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc);
- printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
-#endif /* IDEFLOPPY_DEBUG_INFO */
}
+ if (!i) {
+ IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc);
+ }
+ IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
+ }
+
+ /* Clik! disk does not support get_flexible_disk_page */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
(void) idefloppy_get_flexible_disk_page (drive);
+
drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor;
return rc;
}
+
/*
* Our special ide-floppy ioctl's.
*
- * Currently there aren't any ioctl's.
+ * Supports eject command
*/
static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
idefloppy_pc_t pc;
+ idefloppy_floppy_t *floppy = drive->driver_data;
if (cmd == CDROMEJECT) {
if (drive->usage > 1)
return -EBUSY;
+ /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 0);
(void) idefloppy_queue_pc_tail (drive, &pc);
+ }
idefloppy_create_start_stop_cmd (&pc, 2);
(void) idefloppy_queue_pc_tail (drive, &pc);
return 0;
@@ -1320,20 +1338,24 @@
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t pc;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_open\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Reached idefloppy_open\n");
MOD_INC_USE_COUNT;
if (drive->usage == 1) {
+ IDEFLOPPY_DEBUG( "Testing if unit is ready...\n");
idefloppy_create_test_unit_ready_cmd(&pc);
if (idefloppy_queue_pc_tail(drive, &pc)) {
+ IDEFLOPPY_DEBUG( "Not ready, issuing start command\n");
idefloppy_create_start_stop_cmd (&pc, 1);
(void) idefloppy_queue_pc_tail (drive, &pc);
+ } else
+ {
+ IDEFLOPPY_DEBUG( "Yes unit is ready\n");
}
if (idefloppy_get_capacity (drive)) {
drive->usage--;
MOD_DEC_USE_COUNT;
+ IDEFLOPPY_DEBUG( "I/O Error Getting Capacity\n");
return -EIO;
}
if (floppy->wp && (filp->f_mode & 2)) {
@@ -1342,8 +1364,11 @@
return -EROFS;
}
set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
+ /* IOMEGA Clik! drives do not support lock/unlock commands - no room for mechanism */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 1);
(void) idefloppy_queue_pc_tail (drive, &pc);
+ }
check_disk_change(inode->i_rdev);
}
return 0;
@@ -1352,16 +1377,18 @@
static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
{
idefloppy_pc_t pc;
+ idefloppy_floppy_t *floppy = drive->driver_data;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_release\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Reached idefloppy_release\n");
if (!drive->usage) {
invalidate_buffers (inode->i_rdev);
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 0);
(void) idefloppy_queue_pc_tail (drive, &pc);
}
+ }
MOD_DEC_USE_COUNT;
}
@@ -1559,6 +1586,17 @@
for (i = 0; i < 1 << PARTN_BITS; i++)
max_sectors[major][minor + i] = 64;
}
+ /*
+ * Guess what? The IOMEGA Clik! drive also needs the
+ * above fix. It makes nasty clicking noises without
+ * it, so please don't remove this.
+ */
+ if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0)
+ {
+ for (i = 0; i < 1 << PARTN_BITS; i++)
+ max_sectors[major][minor + i] = 64;
+ set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
+ }
(void) idefloppy_get_capacity (drive);
idefloppy_add_settings(drive);
@@ -1597,6 +1635,7 @@
#endif /* CONFIG_PROC_FS */
+
/*
* IDE subdriver functions, registered with ide.c
*/
@@ -1629,6 +1668,7 @@
NULL
};
+
/*
* idefloppy_init will register the driver for each floppy.
*/
@@ -1665,12 +1705,16 @@
return 0;
}
+
#ifdef MODULE
+/* Initialisation code for loading the driver as a modules */
int init_module (void)
{
return idefloppy_init ();
}
+
+/* Cleanup code for removing the driver module */
void cleanup_module (void)
{
ide_drive_t *drive;
[-- Attachment #2: gmpatch-245+idefloppy-clik-bristow --]
[-- Type: application/octet-stream, Size: 17191 bytes --]
--- linux246-orig/drivers/ide/ide-floppy.c Fri Feb 9 20:30:23 2001
+++ linux/drivers/ide/ide-floppy.c Sat Jul 14 12:07:40 2001
@@ -1,7 +1,8 @@
/*
- * linux/drivers/ide/ide-floppy.c Version 0.9 Jul 4, 1999
+ * linux/drivers/ide/ide-floppy.c Version 0.96 Jan 7, 2001
*
* Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 2000 - 2001 Paul Bristow <paul@paulbristow.net>
*/
/*
@@ -10,6 +11,12 @@
* The driver currently doesn't have any fancy features, just the bare
* minimum read/write support.
*
+ * This driver supports the following IDE floppy drives:
+ *
+ * LS-120 SuperDisk
+ * Iomega Zip 100/250
+ * Iomega PC Card Clik!/PocketZip
+ *
* Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many
* ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
*
@@ -29,9 +36,20 @@
* Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of
* bytes requested on each interrupt to be zero.
* Thanks to <shanos@es.co.nz> for pointing this out.
+ * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by
+ * <paul@paulbristow.net>
+ * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this
+ * driver. Included Powerbook internal zip kludge.
+ * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive
+ * no disk on insert and disk change now works
+ * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere
+ * Ver 0.95 Nov 7 00 Brought across to kernel 2.4
+ * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0
+ * including set_bit patch from Rusty Russel
+ *
*/
-#define IDEFLOPPY_VERSION "0.9"
+#define IDEFLOPPY_VERSION "0.96"
#include <linux/config.h>
#include <linux/module.h>
@@ -45,7 +63,7 @@
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
-#include <linux/slab.h>
+#include <linux/malloc.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
@@ -56,12 +74,14 @@
#include <asm/unaligned.h>
#include <asm/bitops.h>
+
/*
* The following are used to debug the driver.
*/
-#define IDEFLOPPY_DEBUG_LOG 0
#define IDEFLOPPY_DEBUG_INFO 0
#define IDEFLOPPY_DEBUG_BUGS 1
+/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
+#define IDEFLOPPY_DEBUG( fmt, args... )
/*
* Some drives require a longer irq timeout.
@@ -104,7 +124,7 @@
byte *current_position; /* Pointer into the above buffer */
void (*callback) (ide_drive_t *); /* Called when this packet command is completed */
byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */
- unsigned long flags; /* Status/Action bit flags: long for set_bit */
+ unsigned long flags; /* Status/Action bit flags : long for set_bit() */
} idefloppy_pc_t;
/*
@@ -181,6 +201,7 @@
u8 reserved30[2];
} idefloppy_flexible_disk_page_t;
+
/*
* Format capacity
*/
@@ -237,7 +258,7 @@
idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */
int wp; /* Write protect */
- unsigned int flags; /* Status/Action flags */
+ unsigned long flags; /* Status/Action flags : long for set_bit() */
} idefloppy_floppy_t;
/*
@@ -246,6 +267,8 @@
#define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */
#define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */
#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */
+#define IDEFLOPPY_CLIK_DRIVE 3 /* Avoid commands not supported in Clik drive */
+#define IDEFLOPPY_POWERBOOK_ZIP 4 /* Kludge for Apple Powerbook Zip drive */
/*
* ATAPI floppy drive packet commands
@@ -621,9 +644,7 @@
struct request *rq = hwgroup->rq;
int error;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_end_request\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Reached idefloppy_end_request\n");
switch (uptodate) {
case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
@@ -746,21 +767,19 @@
idefloppy_floppy_t *floppy = drive->driver_data;
floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq;
-#if IDEFLOPPY_DEBUG_LOG
- if (floppy->failed_pc)
- printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq);
- else
- printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ if (floppy->failed_pc) {
+ IDEFLOPPY_DEBUG("ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq);
+ }
+ else {
+ IDEFLOPPY_DEBUG("ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq);
+ }
}
static void idefloppy_request_sense_callback (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_request_sense_callback\n");
if (!floppy->pc->error) {
idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);
idefloppy_end_request (1,HWGROUP (drive));
@@ -777,9 +796,7 @@
{
idefloppy_floppy_t *floppy = drive->driver_data;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_callback\n");
idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive));
}
@@ -840,9 +857,7 @@
struct request *rq = pc->rq;
unsigned int temp;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n");
#ifdef CONFIG_BLK_DEV_IDEDMA
if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
@@ -852,26 +867,20 @@
pc->actually_transferred=pc->request_transfer;
idefloppy_update_buffers (drive, pc);
}
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: DMA finished\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: DMA finished\n");
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
status.all = GET_STAT(); /* Clear the interrupt */
if (!status.b.drq) { /* No more interrupts */
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
ide__sti(); /* local CPU only */
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error\n",drive->name);
rq->errors++;
if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
printk (KERN_ERR "ide-floppy: I/O error in request sense command\n");
@@ -915,9 +924,7 @@
ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
return ide_started;
}
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n");
}
}
if (test_bit (PC_WRITING, &pc->flags)) {
@@ -983,7 +990,7 @@
* a legitimate error code was received.
*/
if (!test_bit (PC_ABORT, &pc->flags)) {
- printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n",
+ IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n",
drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq);
pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */
}
@@ -991,9 +998,7 @@
pc->callback(drive);
return ide_stopped;
}
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Retry number - %d\n",pc->retries);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Retry number - %d\n",pc->retries);
pc->retries++;
pc->actually_transferred=0; /* We haven't transferred any data yet */
@@ -1034,9 +1039,7 @@
static void idefloppy_rw_callback (ide_drive_t *drive)
{
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_rw_callback\n");
idefloppy_end_request(1, HWGROUP(drive));
return;
@@ -1044,9 +1047,7 @@
static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent)
{
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "ide-floppy: creating prevent removal command, prevent = %d\n", prevent);
idefloppy_init_pc (pc);
pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;
@@ -1106,10 +1107,8 @@
int block = sector / floppy->bs_factor;
int blocks = rq->nr_sectors / floppy->bs_factor;
-#if IDEFLOPPY_DEBUG_LOG
- printk ("create_rw1%d_cmd: block == %d, blocks == %d\n",
+ IDEFLOPPY_DEBUG( "create_rw1%d_cmd: block == %d, blocks == %d\n",
2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks);
-#endif /* IDEFLOPPY_DEBUG_LOG */
idefloppy_init_pc (pc);
if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) {
@@ -1139,10 +1138,8 @@
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t *pc;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
- printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
+ IDEFLOPPY_DEBUG( "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
if (rq->errors >= ERROR_MAX) {
if (floppy->failed_pc != NULL)
@@ -1235,6 +1232,7 @@
return 0;
}
+
/*
* Determine if a media is present in the floppy drive, and if so,
* its LBA capacity.
@@ -1263,48 +1261,68 @@
for (i = 0; i < descriptors; i++, descriptor++) {
blocks = descriptor->blocks = ntohl (descriptor->blocks);
length = descriptor->length = ntohs (descriptor->length);
- if (!i && descriptor->dc == CAPACITY_CURRENT) {
- if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) {
- printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size, %s \n",
- drive->name, blocks * length / 1024, blocks, length,
- drive->using_dma ? ", DMA":"");
- }
- floppy->capacity = *descriptor;
+ if (!i) {
+ switch (descriptor->dc) {
+ case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+ break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */
+ case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */
+ if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
+ printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length);
+ floppy->capacity = *descriptor;
if (!length || length % 512)
- printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length);
+ printk (KERN_NOTICE "%s: %d bytes block size not supported\n", drive->name, length);
else {
floppy->blocks = blocks;
floppy->block_size = length;
if ((floppy->bs_factor = length / 512) != 1)
printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name);
- rc = 0;
- }
+ rc = 0;
+ }
+ break;
+ case CAPACITY_NO_CARTRIDGE:
+ /* This is a KERN_ERR so it appears on screen for the user to see */
+ printk (KERN_ERR "%s: No disk in drive\n", drive->name);
+ break;
+ case CAPACITY_INVALID:
+ printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name);
+ break;
}
-#if IDEFLOPPY_DEBUG_INFO
- if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc);
- printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
-#endif /* IDEFLOPPY_DEBUG_INFO */
}
+ if (!i) {
+ IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc);
+ }
+ IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);
+ }
+
+ /* Clik! disk does not support get_flexible_disk_page */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
(void) idefloppy_get_flexible_disk_page (drive);
+
drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor;
return rc;
}
+
/*
* Our special ide-floppy ioctl's.
*
- * Currently there aren't any ioctl's.
+ * Supports eject command
*/
static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
idefloppy_pc_t pc;
+ idefloppy_floppy_t *floppy = drive->driver_data;
if (cmd == CDROMEJECT) {
if (drive->usage > 1)
return -EBUSY;
+ /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 0);
(void) idefloppy_queue_pc_tail (drive, &pc);
+ }
idefloppy_create_start_stop_cmd (&pc, 2);
(void) idefloppy_queue_pc_tail (drive, &pc);
return 0;
@@ -1320,20 +1338,24 @@
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t pc;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_open\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Reached idefloppy_open\n");
MOD_INC_USE_COUNT;
if (drive->usage == 1) {
+ IDEFLOPPY_DEBUG( "Testing if unit is ready...\n");
idefloppy_create_test_unit_ready_cmd(&pc);
if (idefloppy_queue_pc_tail(drive, &pc)) {
+ IDEFLOPPY_DEBUG( "Not ready, issuing start command\n");
idefloppy_create_start_stop_cmd (&pc, 1);
(void) idefloppy_queue_pc_tail (drive, &pc);
+ } else
+ {
+ IDEFLOPPY_DEBUG( "Yes unit is ready\n");
}
if (idefloppy_get_capacity (drive)) {
drive->usage--;
MOD_DEC_USE_COUNT;
+ IDEFLOPPY_DEBUG( "I/O Error Getting Capacity\n");
return -EIO;
}
if (floppy->wp && (filp->f_mode & 2)) {
@@ -1342,8 +1364,11 @@
return -EROFS;
}
set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
+ /* IOMEGA Clik! drives do not support lock/unlock commands - no room for mechanism */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 1);
(void) idefloppy_queue_pc_tail (drive, &pc);
+ }
check_disk_change(inode->i_rdev);
}
return 0;
@@ -1352,16 +1377,18 @@
static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
{
idefloppy_pc_t pc;
+ idefloppy_floppy_t *floppy = drive->driver_data;
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_release\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
+ IDEFLOPPY_DEBUG( "Reached idefloppy_release\n");
if (!drive->usage) {
invalidate_buffers (inode->i_rdev);
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd (&pc, 0);
(void) idefloppy_queue_pc_tail (drive, &pc);
}
+ }
MOD_DEC_USE_COUNT;
}
@@ -1559,6 +1586,17 @@
for (i = 0; i < 1 << PARTN_BITS; i++)
max_sectors[major][minor + i] = 64;
}
+ /*
+ * Guess what? The IOMEGA Clik! drive also needs the
+ * above fix. It makes nasty clicking noises without
+ * it, so please don't remove this.
+ */
+ if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0)
+ {
+ for (i = 0; i < 1 << PARTN_BITS; i++)
+ max_sectors[major][minor + i] = 64;
+ set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
+ }
(void) idefloppy_get_capacity (drive);
idefloppy_add_settings(drive);
@@ -1597,6 +1635,7 @@
#endif /* CONFIG_PROC_FS */
+
/*
* IDE subdriver functions, registered with ide.c
*/
@@ -1629,6 +1668,7 @@
NULL
};
+
/*
* idefloppy_init will register the driver for each floppy.
*/
@@ -1665,12 +1705,16 @@
return 0;
}
+
#ifdef MODULE
+/* Initialisation code for loading the driver as a modules */
int init_module (void)
{
return idefloppy_init ();
}
+
+/* Cleanup code for removing the driver module */
void cleanup_module (void)
{
ide_drive_t *drive;
next reply other threads:[~2001-07-14 10:38 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-07-14 10:38 Gunther Mayer [this message]
2001-07-14 12:15 ` (patch-2.4.6) Fix oops with Iomega Clik! (ide-floppy) Alan Cox
2001-07-14 15:00 ` Paul Bristow
2001-07-14 14:14 ` Christoph Hellwig
2001-07-14 15:18 ` Chris Wedgwood
2001-07-14 16:41 ` David Woodhouse
2001-07-14 16:47 ` David Woodhouse
2001-07-14 16:58 ` Chris Wedgwood
2001-07-14 17:02 ` Alan Cox
2001-07-14 17:11 ` Chris Wedgwood
2001-07-14 17:29 ` Jeff Garzik
2001-07-14 17:33 ` Alan Cox
2001-07-14 17:38 ` Jeff Garzik
2001-07-14 17:44 ` Alan Cox
2001-07-14 18:04 ` __KERNEL__ removal Jonathan Lundell
2001-07-14 18:19 ` Jeff Garzik
2001-07-14 18:30 ` Mo McKinlay
2001-07-15 11:53 ` Kai Henningsen
2001-07-15 13:12 ` Chris Wedgwood
2001-07-15 14:21 ` Horst von Brand
2001-07-16 9:16 ` Chris Wedgwood
2001-07-14 18:12 ` (patch-2.4.6) Fix oops with Iomega Clik! (ide-floppy) Wichert Akkerman
2001-07-15 3:40 ` Chris Wedgwood
2001-07-15 3:46 ` Jeff Garzik
2001-07-15 3:56 ` Chris Wedgwood
2001-07-14 18:09 ` David Woodhouse
2001-07-14 18:21 ` Jeff Garzik
2001-07-14 18:49 ` David Woodhouse
[not found] ` <mailman.995129400.8760.linux-kernel2news@redhat.com>
2001-07-14 18:36 ` Pete Zaitcev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3B50213B.A826C259@t-online.de \
--to=gunther.mayer@t-online.de \
--cc=linux-kernel@vger.kernel.org \
--cc=paul@paulbristow.net \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.