aboutsummaryrefslogtreecommitdiff
path: root/drivers/ide/legacy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/ide/legacy
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/legacy')
-rw-r--r--drivers/ide/legacy/Makefile13
-rw-r--r--drivers/ide/legacy/ali14xx.c253
-rw-r--r--drivers/ide/legacy/buddha.c235
-rw-r--r--drivers/ide/legacy/dtc2278.c165
-rw-r--r--drivers/ide/legacy/falconide.c78
-rw-r--r--drivers/ide/legacy/gayle.c186
-rw-r--r--drivers/ide/legacy/hd.c864
-rw-r--r--drivers/ide/legacy/ht6560b.c370
-rw-r--r--drivers/ide/legacy/ide-cs.c481
-rw-r--r--drivers/ide/legacy/macide.c155
-rw-r--r--drivers/ide/legacy/q40ide.c150
-rw-r--r--drivers/ide/legacy/qd65xx.c511
-rw-r--r--drivers/ide/legacy/qd65xx.h140
-rw-r--r--drivers/ide/legacy/umc8672.c183
14 files changed, 3784 insertions, 0 deletions
diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
new file mode 100644
index 00000000000..c7971061767
--- /dev/null
+++ b/drivers/ide/legacy/Makefile
@@ -0,0 +1,13 @@
+
+obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
+obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
+obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
+obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
+obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
+
+obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
+
+# Last of all
+obj-$(CONFIG_BLK_DEV_HD) += hd.o
+
+EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
new file mode 100644
index 00000000000..fb88711812e
--- /dev/null
+++ b/drivers/ide/legacy/ali14xx.c
@@ -0,0 +1,253 @@
+/*
+ * linux/drivers/ide/legacy/ali14xx.c Version 0.03 Feb 09, 1996
+ *
+ * Copyright (C) 1996 Linus Torvalds & author (see below)
+ */
+
+/*
+ * ALI M14xx chipset EIDE controller
+ *
+ * Works for ALI M1439/1443/1445/1487/1489 chipsets.
+ *
+ * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml
+ * Derek's notes follow:
+ *
+ * I think the code should be pretty understandable,
+ * but I'll be happy to (try to) answer questions.
+ *
+ * The critical part is in the setupDrive function. The initRegisters
+ * function doesn't seem to be necessary, but the DOS driver does it, so
+ * I threw it in.
+ *
+ * I've only tested this on my system, which only has one disk. I posted
+ * it to comp.sys.linux.hardware, so maybe some other people will try it
+ * out.
+ *
+ * Derek Noonburg (derekn@ece.cmu.edu)
+ * 95-sep-26
+ *
+ * Update 96-jul-13:
+ *
+ * I've since upgraded to two disks and a CD-ROM, with no trouble, and
+ * I've also heard from several others who have used it successfully.
+ * This driver appears to work with both the 1443/1445 and the 1487/1489
+ * chipsets. I've added support for PIO mode 4 for the 1487. This
+ * seems to work just fine on the 1443 also, although I'm not sure it's
+ * advertised as supporting mode 4. (I've been running a WDC AC21200 in
+ * mode 4 for a while now with no trouble.) -Derek
+ */
+
+#undef REALLY_SLOW_IO /* most systems can safely undef this */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+/* port addresses for auto-detection */
+#define ALI_NUM_PORTS 4
+static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
+
+/* register initialization data */
+typedef struct { u8 reg, data; } RegInitializer;
+
+static RegInitializer initData[] __initdata = {
+ {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
+ {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
+ {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
+ {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
+ {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
+ {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
+ {0x35, 0x03}, {0x00, 0x00}
+};
+
+#define ALI_MAX_PIO 4
+
+/* timing parameter registers for each drive */
+static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
+ {0x03, 0x26, 0x04, 0x27}, /* drive 0 */
+ {0x05, 0x28, 0x06, 0x29}, /* drive 1 */
+ {0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */
+ {0x2d, 0x32, 0x2e, 0x33}, /* drive 3 */
+};
+
+static int basePort; /* base port address */
+static int regPort; /* port for register number */
+static int dataPort; /* port for register data */
+static u8 regOn; /* output to base port to access registers */
+static u8 regOff; /* output to base port to close registers */
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * Read a controller register.
+ */
+static inline u8 inReg (u8 reg)
+{
+ outb_p(reg, regPort);
+ return inb(dataPort);
+}
+
+/*
+ * Write a controller register.
+ */
+static void outReg (u8 data, u8 reg)
+{
+ outb_p(reg, regPort);
+ outb_p(data, dataPort);
+}
+
+/*
+ * Set PIO mode for the specified drive.
+ * This function computes timing parameters
+ * and sets controller registers accordingly.
+ */
+static void ali14xx_tune_drive (ide_drive_t *drive, u8 pio)
+{
+ int driveNum;
+ int time1, time2;
+ u8 param1, param2, param3, param4;
+ unsigned long flags;
+ ide_pio_data_t d;
+ int bus_speed = system_bus_clock();
+
+ pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
+
+ /* calculate timing, according to PIO mode */
+ time1 = d.cycle_time;
+ time2 = ide_pio_timings[pio].active_time;
+ param3 = param1 = (time2 * bus_speed + 999) / 1000;
+ param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
+ if (pio < 3) {
+ param3 += 8;
+ param4 += 8;
+ }
+ printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
+ drive->name, pio, time1, time2, param1, param2, param3, param4);
+
+ /* stuff timing parameters into controller registers */
+ driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+ spin_lock_irqsave(&ide_lock, flags);
+ outb_p(regOn, basePort);
+ outReg(param1, regTab[driveNum].reg1);
+ outReg(param2, regTab[driveNum].reg2);
+ outReg(param3, regTab[driveNum].reg3);
+ outReg(param4, regTab[driveNum].reg4);
+ outb_p(regOff, basePort);
+ spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+/*
+ * Auto-detect the IDE controller port.
+ */
+static int __init findPort (void)
+{
+ int i;
+ u8 t;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ for (i = 0; i < ALI_NUM_PORTS; ++i) {
+ basePort = ports[i];
+ regOff = inb(basePort);
+ for (regOn = 0x30; regOn <= 0x33; ++regOn) {
+ outb_p(regOn, basePort);
+ if (inb(basePort) == regOn) {
+ regPort = basePort + 4;
+ dataPort = basePort + 8;
+ t = inReg(0) & 0xf0;
+ outb_p(regOff, basePort);
+ local_irq_restore(flags);
+ if (t != 0x50)
+ return 0;
+ return 1; /* success */
+ }
+ }
+ outb_p(regOff, basePort);
+ }
+ local_irq_restore(flags);
+ return 0;
+}
+
+/*
+ * Initialize controller registers with default values.
+ */
+static int __init initRegisters (void) {
+ RegInitializer *p;
+ u8 t;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ outb_p(regOn, basePort);
+ for (p = initData; p->reg != 0; ++p)
+ outReg(p->data, p->reg);
+ outb_p(0x01, regPort);
+ t = inb(regPort) & 0x01;
+ outb_p(regOff, basePort);
+ local_irq_restore(flags);
+ return t;
+}
+
+static int __init ali14xx_probe(void)
+{
+ ide_hwif_t *hwif, *mate;
+
+ printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
+ basePort, regOn);
+
+ /* initialize controller registers */
+ if (!initRegisters()) {
+ printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
+ return 1;
+ }
+
+ hwif = &ide_hwifs[0];
+ mate = &ide_hwifs[1];
+
+ hwif->chipset = ide_ali14xx;
+ hwif->tuneproc = &ali14xx_tune_drive;
+ hwif->mate = mate;
+
+ mate->chipset = ide_ali14xx;
+ mate->tuneproc = &ali14xx_tune_drive;
+ mate->mate = hwif;
+ mate->channel = 1;
+
+ probe_hwif_init(hwif);
+ probe_hwif_init(mate);
+
+ create_proc_ide_interfaces();
+
+ return 0;
+}
+
+/* Can be called directly from ide.c. */
+int __init ali14xx_init(void)
+{
+ /* auto-detect IDE controller port */
+ if (findPort()) {
+ if (ali14xx_probe())
+ return -ENODEV;
+ return 0;
+ }
+ printk(KERN_ERR "ali14xx: not found.\n");
+ return -ENODEV;
+}
+
+#ifdef MODULE
+module_init(ali14xx_init);
+#endif
+
+MODULE_AUTHOR("see local file");
+MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
new file mode 100644
index 00000000000..0391a312287
--- /dev/null
+++ b/drivers/ide/legacy/buddha.c
@@ -0,0 +1,235 @@
+/*
+ * linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
+ *
+ * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
+ *
+ * This driver was written based on the specifications in README.buddha and
+ * the X-Surf info from Inside_XSurf.txt available at
+ * http://www.jschoenfeld.com
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * TODO:
+ * - test it :-)
+ * - tune the timings using the speed-register
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/zorro.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+ /*
+ * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2
+ */
+
+#define BUDDHA_NUM_HWIFS 2
+#define CATWEASEL_NUM_HWIFS 3
+#define XSURF_NUM_HWIFS 2
+
+ /*
+ * Bases of the IDE interfaces (relative to the board address)
+ */
+
+#define BUDDHA_BASE1 0x800
+#define BUDDHA_BASE2 0xa00
+#define BUDDHA_BASE3 0xc00
+
+#define XSURF_BASE1 0xb000 /* 2.5" Interface */
+#define XSURF_BASE2 0xd000 /* 3.5" Interface */
+
+static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
+ BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
+};
+
+static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
+ XSURF_BASE1, XSURF_BASE2
+};
+
+
+ /*
+ * Offsets from one of the above bases
+ */
+
+#define BUDDHA_DATA 0x00
+#define BUDDHA_ERROR 0x06 /* see err-bits */
+#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */
+#define BUDDHA_SECTOR 0x0e /* starting sector */
+#define BUDDHA_LCYL 0x12 /* starting cylinder */
+#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */
+#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
+#define BUDDHA_STATUS 0x1e /* see status-bits */
+#define BUDDHA_CONTROL 0x11a
+#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */
+
+static int buddha_offsets[IDE_NR_PORTS] __initdata = {
+ BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+ BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1
+};
+
+static int xsurf_offsets[IDE_NR_PORTS] __initdata = {
+ BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+ BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1
+};
+
+ /*
+ * Other registers
+ */
+
+#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */
+#define BUDDHA_IRQ2 0xf40 /* interrupt */
+#define BUDDHA_IRQ3 0xf80
+
+#define XSURF_IRQ1 0x7e
+#define XSURF_IRQ2 0x7e
+
+static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
+ BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
+};
+
+static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = {
+ XSURF_IRQ1, XSURF_IRQ2
+};
+
+#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */
+
+
+ /*
+ * Board information
+ */
+
+typedef enum BuddhaType_Enum {
+ BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
+} BuddhaType;
+
+
+ /*
+ * Check and acknowledge the interrupt status
+ */
+
+static int buddha_ack_intr(ide_hwif_t *hwif)
+{
+ unsigned char ch;
+
+ ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+ if (!(ch & 0x80))
+ return 0;
+ return 1;
+}
+
+static int xsurf_ack_intr(ide_hwif_t *hwif)
+{
+ unsigned char ch;
+
+ ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+ /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
+ z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]);
+ if (!(ch & 0x80))
+ return 0;
+ return 1;
+}
+
+ /*
+ * Probe for a Buddha or Catweasel IDE interface
+ */
+
+void __init buddha_init(void)
+{
+ hw_regs_t hw;
+ ide_hwif_t *hwif;
+ int i, index;
+
+ struct zorro_dev *z = NULL;
+ u_long buddha_board = 0;
+ BuddhaType type;
+ int buddha_num_hwifs;
+
+ while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+ unsigned long board;
+ if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
+ buddha_num_hwifs = BUDDHA_NUM_HWIFS;
+ type=BOARD_BUDDHA;
+ } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) {
+ buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
+ type=BOARD_CATWEASEL;
+ } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) {
+ buddha_num_hwifs = XSURF_NUM_HWIFS;
+ type=BOARD_XSURF;
+ } else
+ continue;
+
+ board = z->resource.start;
+
+/*
+ * FIXME: we now have selectable mmio v/s iomio transports.
+ */
+
+ if(type != BOARD_XSURF) {
+ if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
+ continue;
+ } else {
+ if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE"))
+ continue;
+ if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE"))
+ goto fail_base2;
+ if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) {
+ release_mem_region(board+XSURF_BASE2, 0x1000);
+fail_base2:
+ release_mem_region(board+XSURF_BASE1, 0x1000);
+ continue;
+ }
+ }
+ buddha_board = ZTWO_VADDR(board);
+
+ /* write to BUDDHA_IRQ_MR to enable the board IRQ */
+ /* X-Surf doesn't have this. IRQs are always on */
+ if (type != BOARD_XSURF)
+ z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
+
+ for(i=0;i<buddha_num_hwifs;i++) {
+ if(type != BOARD_XSURF) {
+ ide_setup_ports(&hw, (buddha_board+buddha_bases[i]),
+ buddha_offsets, 0,
+ (buddha_board+buddha_irqports[i]),
+ buddha_ack_intr,
+// budda_iops,
+ IRQ_AMIGA_PORTS);
+ } else {
+ ide_setup_ports(&hw, (buddha_board+xsurf_bases[i]),
+ xsurf_offsets, 0,
+ (buddha_board+xsurf_irqports[i]),
+ xsurf_ack_intr,
+// xsurf_iops,
+ IRQ_AMIGA_PORTS);
+ }
+
+ index = ide_register_hw(&hw, &hwif);
+ if (index != -1) {
+ hwif->mmio = 2;
+ printk("ide%d: ", index);
+ switch(type) {
+ case BOARD_BUDDHA:
+ printk("Buddha");
+ break;
+ case BOARD_CATWEASEL:
+ printk("Catweasel");
+ break;
+ case BOARD_XSURF:
+ printk("X-Surf");
+ break;
+ }
+ printk(" IDE interface\n");
+ }
+ }
+ }
+}
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
new file mode 100644
index 00000000000..20eb5b872ca
--- /dev/null
+++ b/drivers/ide/legacy/dtc2278.c
@@ -0,0 +1,165 @@
+/*
+ * linux/drivers/ide/legacy/dtc2278.c Version 0.02 Feb 10, 1996
+ *
+ * Copyright (C) 1996 Linus Torvalds & author (see below)
+ */
+
+#undef REALLY_SLOW_IO /* most systems can safely undef this */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+/*
+ * Changing this #undef to #define may solve start up problems in some systems.
+ */
+#undef ALWAYS_SET_DTC2278_PIO_MODE
+
+/*
+ * From: andy@cercle.cts.com (Dyan Wile)
+ *
+ * Below is a patch for DTC-2278 - alike software-programmable controllers
+ * The code enables the secondary IDE controller and the PIO4 (3?) timings on
+ * the primary (EIDE). You may probably have to enable the 32-bit support to
+ * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
+ * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
+ * filesystem corrupted with -u1, but under heavy disk load only :-)
+ *
+ * This card is now forced to use the "serialize" feature,
+ * and irq-unmasking is disallowed. If io_32bit is enabled,
+ * it must be done for BOTH drives on each interface.
+ *
+ * This code was written for the DTC2278E, but might work with any of these:
+ *
+ * DTC2278S has only a single IDE interface.
+ * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
+ * DTC2278E also has serial ports and a printer port
+ * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
+ *
+ * There may be a fourth controller type. The S and D versions use the
+ * Winbond chip, and I think the E version does also.
+ *
+ */
+
+static void sub22 (char b, char c)
+{
+ int i;
+
+ for(i = 0; i < 3; ++i) {
+ inb(0x3f6);
+ outb_p(b,0xb0);
+ inb(0x3f6);
+ outb_p(c,0xb4);
+ inb(0x3f6);
+ if(inb(0xb4) == c) {
+ outb_p(7,0xb0);
+ inb(0x3f6);
+ return; /* success */
+ }
+ }
+}
+
+static void tune_dtc2278 (ide_drive_t *drive, u8 pio)
+{
+ unsigned long flags;
+
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+
+ if (pio >= 3) {
+ spin_lock_irqsave(&ide_lock, flags);
+ /*
+ * This enables PIO mode4 (3?) on the first interface
+ */
+ sub22(1,0xc3);
+ sub22(0,0xa0);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ } else {
+ /* we don't know how to set it back again.. */
+ }
+
+ /*
+ * 32bit I/O has to be enabled for *both* drives at the same time.
+ */
+ drive->io_32bit = 1;
+ HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
+}
+
+static int __init probe_dtc2278(void)
+{
+ unsigned long flags;
+ ide_hwif_t *hwif, *mate;
+
+ hwif = &ide_hwifs[0];
+ mate = &ide_hwifs[1];
+
+ if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
+ return 1;
+
+ local_irq_save(flags);
+ /*
+ * This enables the second interface
+ */
+ outb_p(4,0xb0);
+ inb(0x3f6);
+ outb_p(0x20,0xb4);
+ inb(0x3f6);
+#ifdef ALWAYS_SET_DTC2278_PIO_MODE
+ /*
+ * This enables PIO mode4 (3?) on the first interface
+ * and may solve start-up problems for some people.
+ */
+ sub22(1,0xc3);
+ sub22(0,0xa0);
+#endif
+ local_irq_restore(flags);
+
+ hwif->serialized = 1;
+ hwif->chipset = ide_dtc2278;
+ hwif->tuneproc = &tune_dtc2278;
+ hwif->drives[0].no_unmask = 1;
+ hwif->drives[1].no_unmask = 1;
+ hwif->mate = mate;
+
+ mate->serialized = 1;
+ mate->chipset = ide_dtc2278;
+ mate->drives[0].no_unmask = 1;
+ mate->drives[1].no_unmask = 1;
+ mate->mate = hwif;
+ mate->channel = 1;
+
+ probe_hwif_init(hwif);
+ probe_hwif_init(mate);
+
+ create_proc_ide_interfaces();
+
+ return 0;
+}
+
+/* Can be called directly from ide.c. */
+int __init dtc2278_init(void)
+{
+ if (probe_dtc2278()) {
+ printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
+ return -EBUSY;
+ }
+ return 0;
+}
+
+#ifdef MODULE
+module_init(dtc2278_init);
+#endif
+
+MODULE_AUTHOR("See Local File");
+MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
new file mode 100644
index 00000000000..a9f2cd5bb81
--- /dev/null
+++ b/drivers/ide/legacy/falconide.c
@@ -0,0 +1,78 @@
+/*
+ * linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver
+ *
+ * Created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atari_stdma.h>
+
+
+ /*
+ * Base of the IDE interface
+ */
+
+#define ATA_HD_BASE 0xfff00000
+
+ /*
+ * Offsets from the above base
+ */
+
+#define ATA_HD_DATA 0x00
+#define ATA_HD_ERROR 0x05 /* see err-bits */
+#define ATA_HD_NSECTOR 0x09 /* nr of sectors to read/write */
+#define ATA_HD_SECTOR 0x0d /* starting sector */
+#define ATA_HD_LCYL 0x11 /* starting cylinder */
+#define ATA_HD_HCYL 0x15 /* high byte of starting cyl */
+#define ATA_HD_SELECT 0x19 /* 101dhhhh , d=drive, hhhh=head */
+#define ATA_HD_STATUS 0x1d /* see status-bits */
+#define ATA_HD_CONTROL 0x39
+
+static int falconide_offsets[IDE_NR_PORTS] __initdata = {
+ ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL,
+ ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1
+};
+
+
+ /*
+ * falconide_intr_lock is used to obtain access to the IDE interrupt,
+ * which is shared between several drivers.
+ */
+
+int falconide_intr_lock;
+
+
+ /*
+ * Probe for a Falcon IDE interface
+ */
+
+void __init falconide_init(void)
+{
+ if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
+ hw_regs_t hw;
+ int index;
+
+ ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets,
+ 0, 0, NULL,
+// falconide_iops,
+ IRQ_MFP_IDE);
+ index = ide_register_hw(&hw, NULL);
+
+ if (index != -1)
+ printk("ide%d: Falcon IDE interface\n", index);
+ }
+}
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
new file mode 100644
index 00000000000..3fac3e9ec47
--- /dev/null
+++ b/drivers/ide/legacy/gayle.c
@@ -0,0 +1,186 @@
+/*
+ * linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
+ *
+ * Created 9 Jul 1997 by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+#include <linux/zorro.h>
+
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amigayle.h>
+
+
+ /*
+ * Bases of the IDE interfaces
+ */
+
+#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
+#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
+
+ /*
+ * Offsets from one of the above bases
+ */
+
+#define GAYLE_DATA 0x00
+#define GAYLE_ERROR 0x06 /* see err-bits */
+#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */
+#define GAYLE_SECTOR 0x0e /* starting sector */
+#define GAYLE_LCYL 0x12 /* starting cylinder */
+#define GAYLE_HCYL 0x16 /* high byte of starting cyl */
+#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
+#define GAYLE_STATUS 0x1e /* see status-bits */
+#define GAYLE_CONTROL 0x101a
+
+static int gayle_offsets[IDE_NR_PORTS] __initdata = {
+ GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
+ GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
+};
+
+
+ /*
+ * These are at different offsets from the base
+ */
+
+#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */
+#define GAYLE_IRQ_1200 0xda9000 /* interrupt */
+
+
+ /*
+ * Offset of the secondary port for IDE doublers
+ * Note that GAYLE_CONTROL is NOT available then!
+ */
+
+#define GAYLE_NEXT_PORT 0x1000
+
+#ifndef CONFIG_BLK_DEV_IDEDOUBLER
+#define GAYLE_NUM_HWIFS 1
+#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS
+#define GAYLE_HAS_CONTROL_REG 1
+#define GAYLE_IDEREG_SIZE 0x2000
+#else /* CONFIG_BLK_DEV_IDEDOUBLER */
+#define GAYLE_NUM_HWIFS 2
+#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \
+ GAYLE_NUM_HWIFS-1)
+#define GAYLE_HAS_CONTROL_REG (!ide_doubler)
+#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
+int ide_doubler = 0; /* support IDE doublers? */
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+
+ /*
+ * Check and acknowledge the interrupt status
+ */
+
+static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+{
+ unsigned char ch;
+
+ ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+ if (!(ch & GAYLE_IRQ_IDE))
+ return 0;
+ return 1;
+}
+
+static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+{
+ unsigned char ch;
+
+ ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
+ if (!(ch & GAYLE_IRQ_IDE))
+ return 0;
+ (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]);
+ z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
+ return 1;
+}
+
+ /*
+ * Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+ */
+
+void __init gayle_init(void)
+{
+ int a4000, i;
+
+ if (!MACH_IS_AMIGA)
+ return;
+
+ if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
+ goto found;
+
+#ifdef CONFIG_ZORRO
+ if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
+ NULL))
+ goto found;
+#endif
+ return;
+
+found:
+ for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+ unsigned long base, ctrlport, irqport;
+ ide_ack_intr_t *ack_intr;
+ hw_regs_t hw;
+ ide_hwif_t *hwif;
+ int index;
+ unsigned long phys_base, res_start, res_n;
+
+ if (a4000) {
+ phys_base = GAYLE_BASE_4000;
+ irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
+ ack_intr = gayle_ack_intr_a4000;
+ } else {
+ phys_base = GAYLE_BASE_1200;
+ irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
+ ack_intr = gayle_ack_intr_a1200;
+ }
+/*
+ * FIXME: we now have selectable modes between mmio v/s iomio
+ */
+
+ phys_base += i*GAYLE_NEXT_PORT;
+
+ res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
+ res_n = GAYLE_IDEREG_SIZE;
+
+ if (!request_mem_region(res_start, res_n, "IDE"))
+ continue;
+
+ base = (unsigned long)ZTWO_VADDR(phys_base);
+ ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
+
+ ide_setup_ports(&hw, base, gayle_offsets,
+ ctrlport, irqport, ack_intr,
+// &gayle_iops,
+ IRQ_AMIGA_PORTS);
+
+ index = ide_register_hw(&hw, &hwif);
+ if (index != -1) {
+ hwif->mmio = 2;
+ switch (i) {
+ case 0:
+ printk("ide%d: Gayle IDE interface (A%d style)\n", index,
+ a4000 ? 4000 : 1200);
+ break;
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+ case 1:
+ printk("ide%d: IDE doubler\n", index);
+ break;
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+ }
+ } else
+ release_mem_region(res_start, res_n);
+ }
+}
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
new file mode 100644
index 00000000000..c4090550ec1
--- /dev/null
+++ b/drivers/ide/legacy/hd.c
@@ -0,0 +1,864 @@
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This is the low-level hd interrupt support. It traverses the
+ * request-list, using interrupts to jump between functions. As
+ * all the functions are called within interrupts, we may not
+ * sleep. Special care is recommended.
+ *
+ * modified by Drew Eckhardt to check nr of hd's from the CMOS.
+ *
+ * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ * in the early extended-partition checks and added DM partitions
+ *
+ * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
+ * and general streamlining by Mark Lord.
+ *
+ * Removed 99% of above. Use Mark's ide driver for those options.
+ * This is now a lightweight ST-506 driver. (Paul Gortmaker)
+ *
+ * Modified 1995 Russell King for ARM processor.
+ *
+ * Bugfix: max_sectors must be <= 255 or the wheels tend to come
+ * off in a hurry once you queue things up - Paul G. 02/2001
+ */
+
+/* Uncomment the following if you want verbose error reports. */
+/* #define VERBOSE_ERRORS */
+
+#include <linux/blkdev.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/mc146818rtc.h> /* CMOS defines */
+#include <linux/init.h>
+#include <linux/blkpg.h>
+#include <linux/hdreg.h>
+
+#define REALLY_SLOW_IO
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#ifdef __arm__
+#undef HD_IRQ
+#endif
+#include <asm/irq.h>
+#ifdef __arm__
+#define HD_IRQ IRQ_HARDDISK
+#endif
+
+/* Hd controller regster ports */
+
+#define HD_DATA 0x1f0 /* _CTL when writing */
+#define HD_ERROR 0x1f1 /* see err-bits */
+#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
+#define HD_SECTOR 0x1f3 /* starting sector */
+#define HD_LCYL 0x1f4 /* starting cylinder */
+#define HD_HCYL 0x1f5 /* high byte of starting cyl */
+#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS 0x1f7 /* see status-bits */
+#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
+#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
+#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
+
+#define HD_CMD 0x3f6 /* used for resets */
+#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
+
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define SERVICE_STAT SEEK_STAT
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */