patch-2.4.19 linux-2.4.19/drivers/ide/ide-floppy.c
Next file: linux-2.4.19/drivers/ide/ide-geometry.c
Previous file: linux-2.4.19/drivers/ide/ide-features.c
Back to the patch index
Back to the overall index
- Lines: 302
- Date:
Fri Aug 2 17:39:44 2002
- Orig file:
linux-2.4.18/drivers/ide/ide-floppy.c
- Orig date:
Fri Dec 21 09:41:54 2001
diff -urN linux-2.4.18/drivers/ide/ide-floppy.c linux-2.4.19/drivers/ide/ide-floppy.c
@@ -1,8 +1,8 @@
/*
- * linux/drivers/ide/ide-floppy.c Version 0.97.sv Jan 14 2001
+ * linux/drivers/ide/ide-floppy.c Version 0.99 Feb 24 2002
*
* Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
- * Copyright (C) 2000 - 2001 Paul Bristow <paul@paulbristow.net>
+ * Copyright (C) 2000 - 2002 Paul Bristow <paul@paulbristow.net>
*/
/*
@@ -13,7 +13,7 @@
*
* This driver supports the following IDE floppy drives:
*
- * LS-120 SuperDisk
+ * LS-120/240 SuperDisk
* Iomega Zip 100/250
* Iomega PC Card Clik!/PocketZip
*
@@ -68,12 +68,19 @@
* 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
+ * including set_bit patch from Rusty Russell
* Ver 0.97 Jul 22 01 Merge 0.91-0.96 onto 0.9.sv for ac series
* Ver 0.97.sv Aug 3 01 Backported from 2.4.7-ac3
+ * Ver 0.98 Oct 26 01 Split idefloppy_transfer_pc into two pieces to
+ * fix a lost interrupt problem. It appears the busy
+ * bit was being deasserted by my IOMEGA ATAPI ZIP 100
+ * drive before the drive was actually ready.
+ * Ver 0.98a Oct 29 01 Expose delay value so we can play.
+ * Ver 0.99 Feb 24 02 Remove duplicate code, modify clik! detection code
+ * to support new PocketZip drives
*/
-#define IDEFLOPPY_VERSION "0.97.sv"
+#define IDEFLOPPY_VERSION "0.99.newide"
#include <linux/config.h>
#include <linux/module.h>
@@ -276,6 +283,7 @@
* Last error information
*/
byte sense_key, asc, ascq;
+ byte ticks; /* delay this long before sending packet command */
int progress_indication;
/*
@@ -289,6 +297,8 @@
unsigned long flags; /* Status/Action flags */
} idefloppy_floppy_t;
+#define IDEFLOPPY_TICKS_DELAY 3 /* default delay for ZIP 100 */
+
/*
* Floppy flag bits values.
*/
@@ -297,7 +307,7 @@
#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */
#define IDEFLOPPY_FORMAT_IN_PROGRESS 3 /* Format in progress */
#define IDEFLOPPY_CLIK_DRIVE 4 /* Avoid commands not supported in Clik drive */
-
+#define IDEFLOPPY_ZIP_DRIVE 5 /* Requires BH algorithm for packets */
/*
* ATAPI floppy drive packet commands
@@ -1001,6 +1011,11 @@
return ide_started;
}
+/*
+ * This is the original routine that did the packet transfer.
+ * It fails at high speeds on the Iomega ZIP drive, so there's a slower version
+ * for that drive below. The algorithm is chosen based on drive type
+ */
static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
{
ide_startstop_t startstop;
@@ -1021,6 +1036,56 @@
return ide_started;
}
+
+/*
+ * What we have here is a classic case of a top half / bottom half
+ * interrupt service routine. In interrupt mode, the device sends
+ * an interrupt to signal it's ready to receive a packet. However,
+ * we need to delay about 2-3 ticks before issuing the packet or we
+ * gets in trouble.
+ *
+ * So, follow carefully. transfer_pc1 is called as an interrupt (or
+ * directly). In either case, when the device says it's ready for a
+ * packet, we schedule the packet transfer to occur about 2-3 ticks
+ * later in transfer_pc2.
+ */
+static int idefloppy_transfer_pc2 (ide_drive_t *drive)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+
+ atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
+ return IDEFLOPPY_WAIT_CMD; /* Timeout for the packet command */
+}
+
+static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
+{
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ ide_startstop_t startstop;
+ idefloppy_ireason_reg_t ireason;
+
+ if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
+ printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
+ return startstop;
+ }
+ ireason.all=IN_BYTE (IDE_IREASON_REG);
+ if (!ireason.b.cod || ireason.b.io) {
+ printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
+ return ide_do_reset (drive);
+ }
+ /*
+ * The following delay solves a problem with ATAPI Zip 100 drives where the
+ * Busy flag was apparently being deasserted before the unit was ready to
+ * receive data. This was happening on a 1200 MHz Athlon system. 10/26/01
+ * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will
+ * not be actually used until after the packet is moved in about 50 msec.
+ */
+ ide_set_handler (drive,
+ &idefloppy_pc_intr, /* service routine for packet command */
+ floppy->ticks, /* wait this long before "failing" */
+ &idefloppy_transfer_pc2); /* fail == transfer_pc2 */
+ return ide_started;
+}
+
/*
* Issue a packet command
*/
@@ -1029,6 +1094,7 @@
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_bcount_reg_t bcount;
int dma_ok = 0;
+ ide_handler_t *pkt_xfer_routine;
#if IDEFLOPPY_DEBUG_BUGS
if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD && pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
@@ -1088,13 +1154,20 @@
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
+ /* Can we transfer the packet when we get the interrupt or wait? */
+ if (test_bit (IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) {
+ pkt_xfer_routine = &idefloppy_transfer_pc1; /* wait */
+ } else {
+ pkt_xfer_routine = &idefloppy_transfer_pc; /* immediate */
+ }
+
if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
- ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD, NULL);
+ ide_set_handler (drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL);
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */
return ide_started;
} else {
OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
- return idefloppy_transfer_pc (drive);
+ return (*pkt_xfer_routine) (drive);
}
}
@@ -1914,13 +1987,18 @@
{
int major = HWIF(drive)->major;
int minor = drive->select.b.unit << PARTN_BITS;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+/*
+ * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function
+ */
ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL);
ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
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, "ticks", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL);
}
@@ -1954,27 +2032,19 @@
if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0)
{
+ set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags);
+ /* This value will be visible in the /proc/ide/hdx/settings */
+ floppy->ticks = IDEFLOPPY_TICKS_DELAY;
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);
- }
/*
* 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)
+ if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0)
{
for (i = 0; i < 1 << PARTN_BITS; i++)
max_sectors[major][minor + i] = 64;
@@ -2019,10 +2089,7 @@
#endif /* CONFIG_PROC_FS */
-static int idefloppy_reinit (ide_drive_t *drive)
-{
- return 0;
-}
+int idefloppy_reinit(ide_drive_t *drive);
/*
* IDE subdriver functions, registered with ide.c
@@ -2035,6 +2102,8 @@
supports_dma: 1,
supports_dsc_overlap: 0,
cleanup: idefloppy_cleanup,
+ standby: NULL,
+ flushcache: NULL,
do_request: idefloppy_do_request,
end_request: idefloppy_end_request,
ioctl: idefloppy_ioctl,
@@ -2046,7 +2115,9 @@
capacity: idefloppy_capacity,
special: NULL,
proc: idefloppy_proc,
- driver_reinit: idefloppy_reinit,
+ reinit: idefloppy_reinit,
+ ata_prebuilder: NULL,
+ atapi_prebuilder: NULL,
};
int idefloppy_init (void);
@@ -2057,6 +2128,40 @@
NULL
};
+int idefloppy_reinit (ide_drive_t *drive)
+{
+ idefloppy_floppy_t *floppy;
+ int failed = 0;
+
+ MOD_INC_USE_COUNT;
+ while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) {
+ if (!idefloppy_identify_device (drive, drive->id)) {
+ printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);
+ continue;
+ }
+ if (drive->scsi) {
+ printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
+ continue;
+ }
+ if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+ printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
+ continue;
+ }
+ if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) {
+ printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
+ kfree (floppy);
+ continue;
+ }
+ DRIVER(drive)->busy++;
+ idefloppy_setup (drive, floppy);
+ DRIVER(drive)->busy--;
+ failed--;
+ }
+ ide_register_module(&idefloppy_module);
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
static void __exit idefloppy_exit (void)
@@ -2108,7 +2213,9 @@
kfree (floppy);
continue;
}
+ DRIVER(drive)->busy++;
idefloppy_setup (drive, floppy);
+ DRIVER(drive)->busy--;
failed--;
}
ide_register_module(&idefloppy_module);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)