aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/legacy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
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 000000000000..c7971061767e
--- /dev/null
+++ b/drivers/ide/legacy/Makefile
@@ -0,0 +1,13 @@
1
2obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o
3obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o
4obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o
5obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o
6obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
7
8obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
9
10# Last of all
11obj-$(CONFIG_BLK_DEV_HD) += hd.o
12
13EXTRA_CFLAGS := -Idrivers/ide
diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
new file mode 100644
index 000000000000..fb88711812e6
--- /dev/null
+++ b/drivers/ide/legacy/ali14xx.c
@@ -0,0 +1,253 @@
1/*
2 * linux/drivers/ide/legacy/ali14xx.c Version 0.03 Feb 09, 1996
3 *
4 * Copyright (C) 1996 Linus Torvalds & author (see below)
5 */
6
7/*
8 * ALI M14xx chipset EIDE controller
9 *
10 * Works for ALI M1439/1443/1445/1487/1489 chipsets.
11 *
12 * Adapted from code developed by derekn@vw.ece.cmu.edu. -ml
13 * Derek's notes follow:
14 *
15 * I think the code should be pretty understandable,
16 * but I'll be happy to (try to) answer questions.
17 *
18 * The critical part is in the setupDrive function. The initRegisters
19 * function doesn't seem to be necessary, but the DOS driver does it, so
20 * I threw it in.
21 *
22 * I've only tested this on my system, which only has one disk. I posted
23 * it to comp.sys.linux.hardware, so maybe some other people will try it
24 * out.
25 *
26 * Derek Noonburg (derekn@ece.cmu.edu)
27 * 95-sep-26
28 *
29 * Update 96-jul-13:
30 *
31 * I've since upgraded to two disks and a CD-ROM, with no trouble, and
32 * I've also heard from several others who have used it successfully.
33 * This driver appears to work with both the 1443/1445 and the 1487/1489
34 * chipsets. I've added support for PIO mode 4 for the 1487. This
35 * seems to work just fine on the 1443 also, although I'm not sure it's
36 * advertised as supporting mode 4. (I've been running a WDC AC21200 in
37 * mode 4 for a while now with no trouble.) -Derek
38 */
39
40#undef REALLY_SLOW_IO /* most systems can safely undef this */
41
42#include <linux/module.h>
43#include <linux/config.h>
44#include <linux/types.h>
45#include <linux/kernel.h>
46#include <linux/delay.h>
47#include <linux/timer.h>
48#include <linux/mm.h>
49#include <linux/ioport.h>
50#include <linux/blkdev.h>
51#include <linux/hdreg.h>
52#include <linux/ide.h>
53#include <linux/init.h>
54
55#include <asm/io.h>
56
57/* port addresses for auto-detection */
58#define ALI_NUM_PORTS 4
59static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
60
61/* register initialization data */
62typedef struct { u8 reg, data; } RegInitializer;
63
64static RegInitializer initData[] __initdata = {
65 {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
66 {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
67 {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
68 {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
69 {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
70 {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
71 {0x35, 0x03}, {0x00, 0x00}
72};
73
74#define ALI_MAX_PIO 4
75
76/* timing parameter registers for each drive */
77static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
78 {0x03, 0x26, 0x04, 0x27}, /* drive 0 */
79 {0x05, 0x28, 0x06, 0x29}, /* drive 1 */
80 {0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */
81 {0x2d, 0x32, 0x2e, 0x33}, /* drive 3 */
82};
83
84static int basePort; /* base port address */
85static int regPort; /* port for register number */
86static int dataPort; /* port for register data */
87static u8 regOn; /* output to base port to access registers */
88static u8 regOff; /* output to base port to close registers */
89
90/*------------------------------------------------------------------------*/
91
92/*
93 * Read a controller register.
94 */
95static inline u8 inReg (u8 reg)
96{
97 outb_p(reg, regPort);
98 return inb(dataPort);
99}
100
101/*
102 * Write a controller register.
103 */
104static void outReg (u8 data, u8 reg)
105{
106 outb_p(reg, regPort);
107 outb_p(data, dataPort);
108}
109
110/*
111 * Set PIO mode for the specified drive.
112 * This function computes timing parameters
113 * and sets controller registers accordingly.
114 */
115static void ali14xx_tune_drive (ide_drive_t *drive, u8 pio)
116{
117 int driveNum;
118 int time1, time2;
119 u8 param1, param2, param3, param4;
120 unsigned long flags;
121 ide_pio_data_t d;
122 int bus_speed = system_bus_clock();
123
124 pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
125
126 /* calculate timing, according to PIO mode */
127 time1 = d.cycle_time;
128 time2 = ide_pio_timings[pio].active_time;
129 param3 = param1 = (time2 * bus_speed + 999) / 1000;
130 param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
131 if (pio < 3) {
132 param3 += 8;
133 param4 += 8;
134 }
135 printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
136 drive->name, pio, time1, time2, param1, param2, param3, param4);
137
138 /* stuff timing parameters into controller registers */
139 driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
140 spin_lock_irqsave(&ide_lock, flags);
141 outb_p(regOn, basePort);
142 outReg(param1, regTab[driveNum].reg1);
143 outReg(param2, regTab[driveNum].reg2);
144 outReg(param3, regTab[driveNum].reg3);
145 outReg(param4, regTab[driveNum].reg4);
146 outb_p(regOff, basePort);
147 spin_unlock_irqrestore(&ide_lock, flags);
148}
149
150/*
151 * Auto-detect the IDE controller port.
152 */
153static int __init findPort (void)
154{
155 int i;
156 u8 t;
157 unsigned long flags;
158
159 local_irq_save(flags);
160 for (i = 0; i < ALI_NUM_PORTS; ++i) {
161 basePort = ports[i];
162 regOff = inb(basePort);
163 for (regOn = 0x30; regOn <= 0x33; ++regOn) {
164 outb_p(regOn, basePort);
165 if (inb(basePort) == regOn) {
166 regPort = basePort + 4;
167 dataPort = basePort + 8;
168 t = inReg(0) & 0xf0;
169 outb_p(regOff, basePort);
170 local_irq_restore(flags);
171 if (t != 0x50)
172 return 0;
173 return 1; /* success */
174 }
175 }
176 outb_p(regOff, basePort);
177 }
178 local_irq_restore(flags);
179 return 0;
180}
181
182/*
183 * Initialize controller registers with default values.
184 */
185static int __init initRegisters (void) {
186 RegInitializer *p;
187 u8 t;
188 unsigned long flags;
189
190 local_irq_save(flags);
191 outb_p(regOn, basePort);
192 for (p = initData; p->reg != 0; ++p)
193 outReg(p->data, p->reg);
194 outb_p(0x01, regPort);
195 t = inb(regPort) & 0x01;
196 outb_p(regOff, basePort);
197 local_irq_restore(flags);
198 return t;
199}
200
201static int __init ali14xx_probe(void)
202{
203 ide_hwif_t *hwif, *mate;
204
205 printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
206 basePort, regOn);
207
208 /* initialize controller registers */
209 if (!initRegisters()) {
210 printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
211 return 1;
212 }
213
214 hwif = &ide_hwifs[0];
215 mate = &ide_hwifs[1];
216
217 hwif->chipset = ide_ali14xx;
218 hwif->tuneproc = &ali14xx_tune_drive;
219 hwif->mate = mate;
220
221 mate->chipset = ide_ali14xx;
222 mate->tuneproc = &ali14xx_tune_drive;
223 mate->mate = hwif;
224 mate->channel = 1;
225
226 probe_hwif_init(hwif);
227 probe_hwif_init(mate);
228
229 create_proc_ide_interfaces();
230
231 return 0;
232}
233
234/* Can be called directly from ide.c. */
235int __init ali14xx_init(void)
236{
237 /* auto-detect IDE controller port */
238 if (findPort()) {
239 if (ali14xx_probe())
240 return -ENODEV;
241 return 0;
242 }
243 printk(KERN_ERR "ali14xx: not found.\n");
244 return -ENODEV;
245}
246
247#ifdef MODULE
248module_init(ali14xx_init);
249#endif
250
251MODULE_AUTHOR("see local file");
252MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
253MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
new file mode 100644
index 000000000000..0391a3122878
--- /dev/null
+++ b/drivers/ide/legacy/buddha.c
@@ -0,0 +1,235 @@
1/*
2 * linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
3 *
4 * Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
5 *
6 * This driver was written based on the specifications in README.buddha and
7 * the X-Surf info from Inside_XSurf.txt available at
8 * http://www.jschoenfeld.com
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for
12 * more details.
13 *
14 * TODO:
15 * - test it :-)
16 * - tune the timings using the speed-register
17 */
18
19#include <linux/types.h>
20#include <linux/mm.h>
21#include <linux/interrupt.h>
22#include <linux/blkdev.h>
23#include <linux/hdreg.h>
24#include <linux/zorro.h>
25#include <linux/ide.h>
26#include <linux/init.h>
27
28#include <asm/amigahw.h>
29#include <asm/amigaints.h>
30
31
32 /*
33 * The Buddha has 2 IDE interfaces, the Catweasel has 3, X-Surf has 2
34 */
35
36#define BUDDHA_NUM_HWIFS 2
37#define CATWEASEL_NUM_HWIFS 3
38#define XSURF_NUM_HWIFS 2
39
40 /*
41 * Bases of the IDE interfaces (relative to the board address)
42 */
43
44#define BUDDHA_BASE1 0x800
45#define BUDDHA_BASE2 0xa00
46#define BUDDHA_BASE3 0xc00
47
48#define XSURF_BASE1 0xb000 /* 2.5" Interface */
49#define XSURF_BASE2 0xd000 /* 3.5" Interface */
50
51static u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = {
52 BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
53};
54
55static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
56 XSURF_BASE1, XSURF_BASE2
57};
58
59
60 /*
61 * Offsets from one of the above bases
62 */
63
64#define BUDDHA_DATA 0x00
65#define BUDDHA_ERROR 0x06 /* see err-bits */
66#define BUDDHA_NSECTOR 0x0a /* nr of sectors to read/write */
67#define BUDDHA_SECTOR 0x0e /* starting sector */
68#define BUDDHA_LCYL 0x12 /* starting cylinder */
69#define BUDDHA_HCYL 0x16 /* high byte of starting cyl */
70#define BUDDHA_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
71#define BUDDHA_STATUS 0x1e /* see status-bits */
72#define BUDDHA_CONTROL 0x11a
73#define XSURF_CONTROL -1 /* X-Surf has no CS1* (Control/AltStat) */
74
75static int buddha_offsets[IDE_NR_PORTS] __initdata = {
76 BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
77 BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1
78};
79
80static int xsurf_offsets[IDE_NR_PORTS] __initdata = {
81 BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
82 BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1
83};
84
85 /*
86 * Other registers
87 */
88
89#define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */
90#define BUDDHA_IRQ2 0xf40 /* interrupt */
91#define BUDDHA_IRQ3 0xf80
92
93#define XSURF_IRQ1 0x7e
94#define XSURF_IRQ2 0x7e
95
96static int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = {
97 BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
98};
99
100static int xsurf_irqports[XSURF_NUM_HWIFS] __initdata = {
101 XSURF_IRQ1, XSURF_IRQ2
102};
103
104#define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */
105
106
107 /*
108 * Board information
109 */
110
111typedef enum BuddhaType_Enum {
112 BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
113} BuddhaType;
114
115
116 /*
117 * Check and acknowledge the interrupt status
118 */
119
120static int buddha_ack_intr(ide_hwif_t *hwif)
121{
122 unsigned char ch;
123
124 ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
125 if (!(ch & 0x80))
126 return 0;
127 return 1;
128}
129
130static int xsurf_ack_intr(ide_hwif_t *hwif)
131{
132 unsigned char ch;
133
134 ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
135 /* X-Surf needs a 0 written to IRQ register to ensure ISA bit A11 stays at 0 */
136 z_writeb(0, hwif->io_ports[IDE_IRQ_OFFSET]);
137 if (!(ch & 0x80))
138 return 0;
139 return 1;
140}
141
142 /*
143 * Probe for a Buddha or Catweasel IDE interface
144 */
145
146void __init buddha_init(void)
147{
148 hw_regs_t hw;
149 ide_hwif_t *hwif;
150 int i, index;
151
152 struct zorro_dev *z = NULL;
153 u_long buddha_board = 0;
154 BuddhaType type;
155 int buddha_num_hwifs;
156
157 while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
158 unsigned long board;
159 if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
160 buddha_num_hwifs = BUDDHA_NUM_HWIFS;
161 type=BOARD_BUDDHA;
162 } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL) {
163 buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
164 type=BOARD_CATWEASEL;
165 } else if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF) {
166 buddha_num_hwifs = XSURF_NUM_HWIFS;
167 type=BOARD_XSURF;
168 } else
169 continue;
170
171 board = z->resource.start;
172
173/*
174 * FIXME: we now have selectable mmio v/s iomio transports.
175 */
176
177 if(type != BOARD_XSURF) {
178 if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
179 continue;
180 } else {
181 if (!request_mem_region(board+XSURF_BASE1, 0x1000, "IDE"))
182 continue;
183 if (!request_mem_region(board+XSURF_BASE2, 0x1000, "IDE"))
184 goto fail_base2;
185 if (!request_mem_region(board+XSURF_IRQ1, 0x8, "IDE")) {
186 release_mem_region(board+XSURF_BASE2, 0x1000);
187fail_base2:
188 release_mem_region(board+XSURF_BASE1, 0x1000);
189 continue;
190 }
191 }
192 buddha_board = ZTWO_VADDR(board);
193
194 /* write to BUDDHA_IRQ_MR to enable the board IRQ */
195 /* X-Surf doesn't have this. IRQs are always on */
196 if (type != BOARD_XSURF)
197 z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
198
199 for(i=0;i<buddha_num_hwifs;i++) {
200 if(type != BOARD_XSURF) {
201 ide_setup_ports(&hw, (buddha_board+buddha_bases[i]),
202 buddha_offsets, 0,
203 (buddha_board+buddha_irqports[i]),
204 buddha_ack_intr,
205// budda_iops,
206 IRQ_AMIGA_PORTS);
207 } else {
208 ide_setup_ports(&hw, (buddha_board+xsurf_bases[i]),
209 xsurf_offsets, 0,
210 (buddha_board+xsurf_irqports[i]),
211 xsurf_ack_intr,
212// xsurf_iops,
213 IRQ_AMIGA_PORTS);
214 }
215
216 index = ide_register_hw(&hw, &hwif);
217 if (index != -1) {
218 hwif->mmio = 2;
219 printk("ide%d: ", index);
220 switch(type) {
221 case BOARD_BUDDHA:
222 printk("Buddha");
223 break;
224 case BOARD_CATWEASEL:
225 printk("Catweasel");
226 break;
227 case BOARD_XSURF:
228 printk("X-Surf");
229 break;
230 }
231 printk(" IDE interface\n");
232 }
233 }
234 }
235}
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
new file mode 100644
index 000000000000..20eb5b872ca9
--- /dev/null
+++ b/drivers/ide/legacy/dtc2278.c
@@ -0,0 +1,165 @@
1/*
2 * linux/drivers/ide/legacy/dtc2278.c Version 0.02 Feb 10, 1996
3 *
4 * Copyright (C) 1996 Linus Torvalds & author (see below)
5 */
6
7#undef REALLY_SLOW_IO /* most systems can safely undef this */
8
9#include <linux/module.h>
10#include <linux/config.h>
11#include <linux/types.h>
12#include <linux/kernel.h>
13#include <linux/delay.h>
14#include <linux/timer.h>
15#include <linux/mm.h>
16#include <linux/ioport.h>
17#include <linux/blkdev.h>
18#include <linux/hdreg.h>
19#include <linux/ide.h>
20#include <linux/init.h>
21
22#include <asm/io.h>
23
24/*
25 * Changing this #undef to #define may solve start up problems in some systems.
26 */
27#undef ALWAYS_SET_DTC2278_PIO_MODE
28
29/*
30 * From: andy@cercle.cts.com (Dyan Wile)
31 *
32 * Below is a patch for DTC-2278 - alike software-programmable controllers
33 * The code enables the secondary IDE controller and the PIO4 (3?) timings on
34 * the primary (EIDE). You may probably have to enable the 32-bit support to
35 * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
36 * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
37 * filesystem corrupted with -u1, but under heavy disk load only :-)
38 *
39 * This card is now forced to use the "serialize" feature,
40 * and irq-unmasking is disallowed. If io_32bit is enabled,
41 * it must be done for BOTH drives on each interface.
42 *
43 * This code was written for the DTC2278E, but might work with any of these:
44 *
45 * DTC2278S has only a single IDE interface.
46 * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
47 * DTC2278E also has serial ports and a printer port
48 * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
49 *
50 * There may be a fourth controller type. The S and D versions use the
51 * Winbond chip, and I think the E version does also.
52 *
53 */
54
55static void sub22 (char b, char c)
56{
57 int i;
58
59 for(i = 0; i < 3; ++i) {
60 inb(0x3f6);
61 outb_p(b,0xb0);
62 inb(0x3f6);
63 outb_p(c,0xb4);
64 inb(0x3f6);
65 if(inb(0xb4) == c) {
66 outb_p(7,0xb0);
67 inb(0x3f6);
68 return; /* success */
69 }
70 }
71}
72
73static void tune_dtc2278 (ide_drive_t *drive, u8 pio)
74{
75 unsigned long flags;
76
77 pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
78
79 if (pio >= 3) {
80 spin_lock_irqsave(&ide_lock, flags);
81 /*
82 * This enables PIO mode4 (3?) on the first interface
83 */
84 sub22(1,0xc3);
85 sub22(0,0xa0);
86 spin_unlock_irqrestore(&ide_lock, flags);
87 } else {
88 /* we don't know how to set it back again.. */
89 }
90
91 /*
92 * 32bit I/O has to be enabled for *both* drives at the same time.
93 */
94 drive->io_32bit = 1;
95 HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
96}
97
98static int __init probe_dtc2278(void)
99{
100 unsigned long flags;
101 ide_hwif_t *hwif, *mate;
102
103 hwif = &ide_hwifs[0];
104 mate = &ide_hwifs[1];
105
106 if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown)
107 return 1;
108
109 local_irq_save(flags);
110 /*
111 * This enables the second interface
112 */
113 outb_p(4,0xb0);
114 inb(0x3f6);
115 outb_p(0x20,0xb4);
116 inb(0x3f6);
117#ifdef ALWAYS_SET_DTC2278_PIO_MODE
118 /*
119 * This enables PIO mode4 (3?) on the first interface
120 * and may solve start-up problems for some people.
121 */
122 sub22(1,0xc3);
123 sub22(0,0xa0);
124#endif
125 local_irq_restore(flags);
126
127 hwif->serialized = 1;
128 hwif->chipset = ide_dtc2278;
129 hwif->tuneproc = &tune_dtc2278;
130 hwif->drives[0].no_unmask = 1;
131 hwif->drives[1].no_unmask = 1;
132 hwif->mate = mate;
133
134 mate->serialized = 1;
135 mate->chipset = ide_dtc2278;
136 mate->drives[0].no_unmask = 1;
137 mate->drives[1].no_unmask = 1;
138 mate->mate = hwif;
139 mate->channel = 1;
140
141 probe_hwif_init(hwif);
142 probe_hwif_init(mate);
143
144 create_proc_ide_interfaces();
145
146 return 0;
147}
148
149/* Can be called directly from ide.c. */
150int __init dtc2278_init(void)
151{
152 if (probe_dtc2278()) {
153 printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
154 return -EBUSY;
155 }
156 return 0;
157}
158
159#ifdef MODULE
160module_init(dtc2278_init);
161#endif
162
163MODULE_AUTHOR("See Local File");
164MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
165MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
new file mode 100644
index 000000000000..a9f2cd5bb81e
--- /dev/null
+++ b/drivers/ide/legacy/falconide.c
@@ -0,0 +1,78 @@
1/*
2 * linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver
3 *
4 * Created 12 Jul 1997 by Geert Uytterhoeven
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 */
10
11#include <linux/types.h>
12#include <linux/mm.h>
13#include <linux/interrupt.h>
14#include <linux/blkdev.h>
15#include <linux/hdreg.h>
16#include <linux/ide.h>
17#include <linux/init.h>
18
19#include <asm/setup.h>
20#include <asm/atarihw.h>
21#include <asm/atariints.h>
22#include <asm/atari_stdma.h>
23
24
25 /*
26 * Base of the IDE interface
27 */
28
29#define ATA_HD_BASE 0xfff00000
30
31 /*
32 * Offsets from the above base
33 */
34
35#define ATA_HD_DATA 0x00
36#define ATA_HD_ERROR 0x05 /* see err-bits */
37#define ATA_HD_NSECTOR 0x09 /* nr of sectors to read/write */
38#define ATA_HD_SECTOR 0x0d /* starting sector */
39#define ATA_HD_LCYL 0x11 /* starting cylinder */
40#define ATA_HD_HCYL 0x15 /* high byte of starting cyl */
41#define ATA_HD_SELECT 0x19 /* 101dhhhh , d=drive, hhhh=head */
42#define ATA_HD_STATUS 0x1d /* see status-bits */
43#define ATA_HD_CONTROL 0x39
44
45static int falconide_offsets[IDE_NR_PORTS] __initdata = {
46 ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL,
47 ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1
48};
49
50
51 /*
52 * falconide_intr_lock is used to obtain access to the IDE interrupt,
53 * which is shared between several drivers.
54 */
55
56int falconide_intr_lock;
57
58
59 /*
60 * Probe for a Falcon IDE interface
61 */
62
63void __init falconide_init(void)
64{
65 if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
66 hw_regs_t hw;
67 int index;
68
69 ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets,
70 0, 0, NULL,
71// falconide_iops,
72 IRQ_MFP_IDE);
73 index = ide_register_hw(&hw, NULL);
74
75 if (index != -1)
76 printk("ide%d: Falcon IDE interface\n", index);
77 }
78}
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
new file mode 100644
index 000000000000..3fac3e9ec47d
--- /dev/null
+++ b/drivers/ide/legacy/gayle.c
@@ -0,0 +1,186 @@
1/*
2 * linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
3 *
4 * Created 9 Jul 1997 by Geert Uytterhoeven
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 */
10
11#include <linux/config.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/interrupt.h>
15#include <linux/blkdev.h>
16#include <linux/hdreg.h>
17#include <linux/ide.h>
18#include <linux/init.h>
19#include <linux/zorro.h>
20
21#include <asm/setup.h>
22#include <asm/amigahw.h>
23#include <asm/amigaints.h>
24#include <asm/amigayle.h>
25
26
27 /*
28 * Bases of the IDE interfaces
29 */
30
31#define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
32#define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */
33
34 /*
35 * Offsets from one of the above bases
36 */
37
38#define GAYLE_DATA 0x00
39#define GAYLE_ERROR 0x06 /* see err-bits */
40#define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */
41#define GAYLE_SECTOR 0x0e /* starting sector */
42#define GAYLE_LCYL 0x12 /* starting cylinder */
43#define GAYLE_HCYL 0x16 /* high byte of starting cyl */
44#define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
45#define GAYLE_STATUS 0x1e /* see status-bits */
46#define GAYLE_CONTROL 0x101a
47
48static int gayle_offsets[IDE_NR_PORTS] __initdata = {
49 GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
50 GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
51};
52
53
54 /*
55 * These are at different offsets from the base
56 */
57
58#define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */
59#define GAYLE_IRQ_1200 0xda9000 /* interrupt */
60
61
62 /*
63 * Offset of the secondary port for IDE doublers
64 * Note that GAYLE_CONTROL is NOT available then!
65 */
66
67#define GAYLE_NEXT_PORT 0x1000
68
69#ifndef CONFIG_BLK_DEV_IDEDOUBLER
70#define GAYLE_NUM_HWIFS 1
71#define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS
72#define GAYLE_HAS_CONTROL_REG 1
73#define GAYLE_IDEREG_SIZE 0x2000
74#else /* CONFIG_BLK_DEV_IDEDOUBLER */
75#define GAYLE_NUM_HWIFS 2
76#define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \
77 GAYLE_NUM_HWIFS-1)
78#define GAYLE_HAS_CONTROL_REG (!ide_doubler)
79#define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
80int ide_doubler = 0; /* support IDE doublers? */
81#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
82
83
84 /*
85 * Check and acknowledge the interrupt status
86 */
87
88static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
89{
90 unsigned char ch;
91
92 ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
93 if (!(ch & GAYLE_IRQ_IDE))
94 return 0;
95 return 1;
96}
97
98static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
99{
100 unsigned char ch;
101
102 ch = z_readb(hwif->io_ports[IDE_IRQ_OFFSET]);
103 if (!(ch & GAYLE_IRQ_IDE))
104 return 0;
105 (void)z_readb(hwif->io_ports[IDE_STATUS_OFFSET]);
106 z_writeb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
107 return 1;
108}
109
110 /*
111 * Probe for a Gayle IDE interface (and optionally for an IDE doubler)
112 */
113
114void __init gayle_init(void)
115{
116 int a4000, i;
117
118 if (!MACH_IS_AMIGA)
119 return;
120
121 if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
122 goto found;
123
124#ifdef CONFIG_ZORRO
125 if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE,
126 NULL))
127 goto found;
128#endif
129 return;
130
131found:
132 for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
133 unsigned long base, ctrlport, irqport;
134 ide_ack_intr_t *ack_intr;
135 hw_regs_t hw;
136 ide_hwif_t *hwif;
137 int index;
138 unsigned long phys_base, res_start, res_n;
139
140 if (a4000) {
141 phys_base = GAYLE_BASE_4000;
142 irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
143 ack_intr = gayle_ack_intr_a4000;
144 } else {
145 phys_base = GAYLE_BASE_1200;
146 irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200);
147 ack_intr = gayle_ack_intr_a1200;
148 }
149/*
150 * FIXME: we now have selectable modes between mmio v/s iomio
151 */
152
153 phys_base += i*GAYLE_NEXT_PORT;
154
155 res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
156 res_n = GAYLE_IDEREG_SIZE;
157
158 if (!request_mem_region(res_start, res_n, "IDE"))
159 continue;
160
161 base = (unsigned long)ZTWO_VADDR(phys_base);
162 ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
163
164 ide_setup_ports(&hw, base, gayle_offsets,
165 ctrlport, irqport, ack_intr,
166// &gayle_iops,
167 IRQ_AMIGA_PORTS);
168
169 index = ide_register_hw(&hw, &hwif);
170 if (index != -1) {
171 hwif->mmio = 2;
172 switch (i) {
173 case 0:
174 printk("ide%d: Gayle IDE interface (A%d style)\n", index,
175 a4000 ? 4000 : 1200);
176 break;
177#ifdef CONFIG_BLK_DEV_IDEDOUBLER
178 case 1:
179 printk("ide%d: IDE doubler\n", index);
180 break;
181#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
182 }
183 } else
184 release_mem_region(res_start, res_n);
185 }
186}
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
new file mode 100644
index 000000000000..c4090550ec13
--- /dev/null
+++ b/drivers/ide/legacy/hd.c
@@ -0,0 +1,864 @@
1/*
2 * Copyright (C) 1991, 1992 Linus Torvalds
3 *
4 * This is the low-level hd interrupt support. It traverses the
5 * request-list, using interrupts to jump between functions. As
6 * all the functions are called within interrupts, we may not
7 * sleep. Special care is recommended.
8 *
9 * modified by Drew Eckhardt to check nr of hd's from the CMOS.
10 *
11 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
12 * in the early extended-partition checks and added DM partitions
13 *
14 * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
15 * and general streamlining by Mark Lord.
16 *
17 * Removed 99% of above. Use Mark's ide driver for those options.
18 * This is now a lightweight ST-506 driver. (Paul Gortmaker)
19 *
20 * Modified 1995 Russell King for ARM processor.
21 *
22 * Bugfix: max_sectors must be <= 255 or the wheels tend to come
23 * off in a hurry once you queue things up - Paul G. 02/2001
24 */
25
26/* Uncomment the following if you want verbose error reports. */
27/* #define VERBOSE_ERRORS */
28
29#include <linux/blkdev.h>
30#include <linux/errno.h>
31#include <linux/signal.h>
32#include <linux/interrupt.h>
33#include <linux/timer.h>
34#include <linux/fs.h>
35#include <linux/kernel.h>
36#include <linux/genhd.h>
37#include <linux/slab.h>
38#include <linux/string.h>
39#include <linux/ioport.h>
40#include <linux/mc146818rtc.h> /* CMOS defines */
41#include <linux/init.h>
42#include <linux/blkpg.h>
43#include <linux/hdreg.h>
44
45#define REALLY_SLOW_IO
46#include <asm/system.h>
47#include <asm/io.h>
48#include <asm/uaccess.h>
49
50#ifdef __arm__
51#undef HD_IRQ
52#endif
53#include <asm/irq.h>
54#ifdef __arm__
55#define HD_IRQ IRQ_HARDDISK
56#endif
57
58/* Hd controller regster ports */
59
60#define HD_DATA 0x1f0 /* _CTL when writing */
61#define HD_ERROR 0x1f1 /* see err-bits */
62#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
63#define HD_SECTOR 0x1f3 /* starting sector */
64#define HD_LCYL 0x1f4 /* starting cylinder */
65#define HD_HCYL 0x1f5 /* high byte of starting cyl */
66#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
67#define HD_STATUS 0x1f7 /* see status-bits */
68#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
69#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
70#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
71
72#define HD_CMD 0x3f6 /* used for resets */
73#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
74
75/* Bits of HD_STATUS */
76#define ERR_STAT 0x01
77#define INDEX_STAT 0x02
78#define ECC_STAT 0x04 /* Corrected error */
79#define DRQ_STAT 0x08
80#define SEEK_STAT 0x10
81#define SERVICE_STAT SEEK_STAT
82#define WRERR_STAT 0x20
83#define READY_STAT 0x40
84#define BUSY_STAT 0x80
85
86/* Bits for HD_ERROR */
87#define MARK_ERR 0x01 /* Bad address mark */
88#define TRK0_ERR 0x02 /* couldn't find track 0 */
89#define ABRT_ERR 0x04 /* Command aborted */
90#define MCR_ERR 0x08 /* media change request */
91#define ID_ERR 0x10 /* ID field not found */
92#define MC_ERR 0x20 /* media changed */
93#define ECC_ERR 0x40 /* Uncorrectable ECC error */
94#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
95#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
96
97static DEFINE_SPINLOCK(hd_lock);
98static struct request_queue *hd_queue;
99
100#define MAJOR_NR HD_MAJOR
101#define QUEUE (hd_queue)
102#define CURRENT elv_next_request(hd_queue)
103
104#define TIMEOUT_VALUE (6*HZ)
105#define HD_DELAY 0
106
107#define MAX_ERRORS 16 /* Max read/write errors/sector */
108#define RESET_FREQ 8 /* Reset controller every 8th retry */
109#define RECAL_FREQ 4 /* Recalibrate every 4th retry */
110#define MAX_HD 2
111
112#define STAT_OK (READY_STAT|SEEK_STAT)
113#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK)
114
115static void recal_intr(void);
116static void bad_rw_intr(void);
117
118static int reset;
119static int hd_error;
120
121/*
122 * This struct defines the HD's and their types.
123 */
124struct hd_i_struct {
125 unsigned int head,sect,cyl,wpcom,lzone,ctl;
126 int unit;
127 int recalibrate;
128 int special_op;
129};
130
131#ifdef HD_TYPE
132static struct hd_i_struct hd_info[] = { HD_TYPE };
133static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
134#else
135static struct hd_i_struct hd_info[MAX_HD];
136static int NR_HD;
137#endif
138
139static struct gendisk *hd_gendisk[MAX_HD];
140
141static struct timer_list device_timer;
142
143#define TIMEOUT_VALUE (6*HZ)
144
145#define SET_TIMER \
146 do { \
147 mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \
148 } while (0)
149
150static void (*do_hd)(void) = NULL;
151#define SET_HANDLER(x) \
152if ((do_hd = (x)) != NULL) \
153 SET_TIMER; \
154else \
155 del_timer(&device_timer);
156
157
158#if (HD_DELAY > 0)
159unsigned long last_req;
160
161unsigned long read_timer(void)
162{
163 extern spinlock_t i8253_lock;
164 unsigned long t, flags;
165 int i;
166
167 spin_lock_irqsave(&i8253_lock, flags);
168 t = jiffies * 11932;
169 outb_p(0, 0x43);
170 i = inb_p(0x40);
171 i |= inb(0x40) << 8;
172 spin_unlock_irqrestore(&i8253_lock, flags);
173 return(t - i);
174}
175#endif
176
177static void __init hd_setup(char *str, int *ints)
178{
179 int hdind = 0;
180
181 if (ints[0] != 3)
182 return;
183 if (hd_info[0].head != 0)
184 hdind=1;
185 hd_info[hdind].head = ints[2];
186 hd_info[hdind].sect = ints[3];
187 hd_info[hdind].cyl = ints[1];
188 hd_info[hdind].wpcom = 0;
189 hd_info[hdind].lzone = ints[1];
190 hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0);
191 NR_HD = hdind+1;
192}
193
194static void dump_status (const char *msg, unsigned int stat)
195{
196 char *name = "hd?";
197 if (CURRENT)
198 name = CURRENT->rq_disk->disk_name;
199
200#ifdef VERBOSE_ERRORS
201 printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
202 if (stat & BUSY_STAT) printk("Busy ");
203 if (stat & READY_STAT) printk("DriveReady ");
204 if (stat & WRERR_STAT) printk("WriteFault ");
205 if (stat & SEEK_STAT) printk("SeekComplete ");
206 if (stat & DRQ_STAT) printk("DataRequest ");
207 if (stat & ECC_STAT) printk("CorrectedError ");
208 if (stat & INDEX_STAT) printk("Index ");
209 if (stat & ERR_STAT) printk("Error ");
210 printk("}\n");
211 if ((stat & ERR_STAT) == 0) {
212 hd_error = 0;
213 } else {
214 hd_error = inb(HD_ERROR);
215 printk("%s: %s: error=0x%02x { ", name, msg, hd_error & 0xff);
216 if (hd_error & BBD_ERR) printk("BadSector ");
217 if (hd_error & ECC_ERR) printk("UncorrectableError ");
218 if (hd_error & ID_ERR) printk("SectorIdNotFound ");
219 if (hd_error & ABRT_ERR) printk("DriveStatusError ");
220 if (hd_error & TRK0_ERR) printk("TrackZeroNotFound ");
221 if (hd_error & MARK_ERR) printk("AddrMarkNotFound ");
222 printk("}");
223 if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) {
224 printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL),
225 inb(HD_CURRENT) & 0xf, inb(HD_SECTOR));
226 if (CURRENT)
227 printk(", sector=%ld", CURRENT->sector);
228 }
229 printk("\n");
230 }
231#else
232 printk("%s: %s: status=0x%02x.\n", name, msg, stat & 0xff);
233 if ((stat & ERR_STAT) == 0) {
234 hd_error = 0;
235 } else {
236 hd_error = inb(HD_ERROR);
237 printk("%s: %s: error=0x%02x.\n", name, msg, hd_error & 0xff);
238 }
239#endif
240}
241
242static void check_status(void)
243{
244 int i = inb_p(HD_STATUS);
245
246 if (!OK_STATUS(i)) {
247 dump_status("check_status", i);
248 bad_rw_intr();
249 }
250}
251
252static int controller_busy(void)
253{
254 int retries = 100000;
255 unsigned char status;
256
257 do {
258 status = inb_p(HD_STATUS);
259 } while ((status & BUSY_STAT) && --retries);
260 return status;
261}
262
263static int status_ok(void)
264{
265 unsigned char status = inb_p(HD_STATUS);
266
267 if (status & BUSY_STAT)
268 return 1; /* Ancient, but does it make sense??? */
269 if (status & WRERR_STAT)
270 return 0;
271 if (!(status & READY_STAT))
272 return 0;
273 if (!(status & SEEK_STAT))
274 return 0;
275 return 1;
276}
277
278static int controller_ready(unsigned int drive, unsigned int head)
279{
280 int retry = 100;
281
282 do {
283 if (controller_busy() & BUSY_STAT)
284 return 0;
285 outb_p(0xA0 | (drive<<4) | head, HD_CURRENT);
286 if (status_ok())
287 return 1;
288 } while (--retry);
289 return 0;
290}
291
292
293static void hd_out(struct hd_i_struct *disk,
294 unsigned int nsect,
295 unsigned int sect,
296 unsigned int head,
297 unsigned int cyl,
298 unsigned int cmd,
299 void (*intr_addr)(void))
300{
301 unsigned short port;
302
303#if (HD_DELAY > 0)
304 while (read_timer() - last_req < HD_DELAY)
305 /* nothing */;
306#endif
307 if (reset)
308 return;
309 if (!controller_ready(disk->unit, head)) {
310 reset = 1;
311 return;
312 }
313 SET_HANDLER(intr_addr);
314 outb_p(disk->ctl,HD_CMD);
315 port=HD_DATA;
316 outb_p(disk->wpcom>>2,++port);
317 outb_p(nsect,++port);
318 outb_p(sect,++port);
319 outb_p(cyl,++port);
320 outb_p(cyl>>8,++port);
321 outb_p(0xA0|(disk->unit<<4)|head,++port);
322 outb_p(cmd,++port);
323}
324
325static void hd_request (void);
326
327static int drive_busy(void)
328{
329 unsigned int i;
330 unsigned char c;
331
332 for (i = 0; i < 500000 ; i++) {
333 c = inb_p(HD_STATUS);
334 if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK)
335 return 0;
336 }
337 dump_status("reset timed out", c);
338 return 1;
339}
340
341static void reset_controller(void)
342{
343 int i;
344
345 outb_p(4,HD_CMD);
346 for(i = 0; i < 1000; i++) barrier();
347 outb_p(hd_info[0].ctl & 0x0f,HD_CMD);
348 for(i = 0; i < 1000; i++) barrier();
349 if (drive_busy())
350 printk("hd: controller still busy\n");
351 else if ((hd_error = inb(HD_ERROR)) != 1)
352 printk("hd: controller reset failed: %02x\n",hd_error);
353}
354
355static void reset_hd(void)
356{
357 static int i;
358
359repeat:
360 if (reset) {
361 reset = 0;
362 i = -1;
363 reset_controller();
364 } else {
365 check_status();
366 if (reset)
367 goto repeat;
368 }
369 if (++i < NR_HD) {
370 struct hd_i_struct *disk = &hd_info[i];
371 disk->special_op = disk->recalibrate = 1;
372 hd_out(disk,disk->sect,disk->sect,disk->head-1,
373 disk->cyl,WIN_SPECIFY,&reset_hd);
374 if (reset)
375 goto repeat;
376 } else
377 hd_request();
378}
379
380/*
381 * Ok, don't know what to do with the unexpected interrupts: on some machines
382 * doing a reset and a retry seems to result in an eternal loop. Right now I
383 * ignore it, and just set the timeout.
384 *
385 * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
386 * drive enters "idle", "standby", or "sleep" mode, so if the status looks
387 * "good", we just ignore the interrupt completely.
388 */
389static void unexpected_hd_interrupt(void)
390{
391 unsigned int stat = inb_p(HD_STATUS);
392
393 if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) {
394 dump_status ("unexpected interrupt", stat);
395 SET_TIMER;
396 }
397}
398
399/*
400 * bad_rw_intr() now tries to be a bit smarter and does things
401 * according to the error returned by the controller.
402 * -Mika Liljeberg (liljeber@cs.Helsinki.FI)
403 */
404static void bad_rw_intr(void)
405{
406 struct request *req = CURRENT;
407 if (req != NULL) {
408 struct hd_i_struct *disk = req->rq_disk->private_data;
409 if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
410 end_request(req, 0);
411 disk->special_op = disk->recalibrate = 1;
412 } else if (req->errors % RESET_FREQ == 0)
413 reset = 1;
414 else if ((hd_error & TRK0_ERR) || req->errors % RECAL_FREQ == 0)
415 disk->special_op = disk->recalibrate = 1;
416 /* Otherwise just retry */
417 }
418}
419
420static inline int wait_DRQ(void)
421{
422 int retries = 100000, stat;
423
424 while (--retries > 0)
425 if ((stat = inb_p(HD_STATUS)) & DRQ_STAT)
426 return 0;
427 dump_status("wait_DRQ", stat);
428 return -1;
429}
430
431static void read_intr(void)
432{
433 struct request *req;
434 int i, retries = 100000;
435
436 do {
437 i = (unsigned) inb_p(HD_STATUS);
438 if (i & BUSY_STAT)
439 continue;
440 if (!OK_STATUS(i))
441 break;
442 if (i & DRQ_STAT)
443 goto ok_to_read;
444 } while (--retries > 0);
445 dump_status("read_intr", i);
446 bad_rw_intr();
447 hd_request();
448 return;
449ok_to_read:
450 req = CURRENT;
451 insw(HD_DATA,req->buffer,256);
452 req->sector++;
453 req->buffer += 512;
454 req->errors = 0;
455 i = --req->nr_sectors;
456 --req->current_nr_sectors;
457#ifdef DEBUG
458 printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
459 req->rq_disk->disk_name, req->sector, req->nr_sectors,
460 req->buffer+512));
461#endif
462 if (req->current_nr_sectors <= 0)
463 end_request(req, 1);
464 if (i > 0) {
465 SET_HANDLER(&read_intr);
466 return;
467 }
468 (void) inb_p(HD_STATUS);
469#if (HD_DELAY > 0)
470 last_req = read_timer();
471#endif
472 if (elv_next_request(QUEUE))
473 hd_request();
474 return;
475}
476
477static void write_intr(void)
478{
479 struct request *req = CURRENT;
480 int i;
481 int retries = 100000;
482
483 do {
484 i = (unsigned) inb_p(HD_STATUS);
485 if (i & BUSY_STAT)
486 continue;
487 if (!OK_STATUS(i))
488 break;
489 if ((req->nr_sectors <= 1) || (i & DRQ_STAT))
490 goto ok_to_write;
491 } while (--retries > 0);
492 dump_status("write_intr", i);
493 bad_rw_intr();
494 hd_request();
495 return;
496ok_to_write:
497 req->sector++;
498 i = --req->nr_sectors;
499 --req->current_nr_sectors;
500 req->buffer += 512;
501 if (!i || (req->bio && req->current_nr_sectors <= 0))
502 end_request(req, 1);
503 if (i > 0) {
504 SET_HANDLER(&write_intr);
505 outsw(HD_DATA,req->buffer,256);
506 local_irq_enable();
507 } else {
508#if (HD_DELAY > 0)
509 last_req = read_timer();
510#endif
511 hd_request();
512 }
513 return;
514}
515
516static void recal_intr(void)
517{
518 check_status();
519#if (HD_DELAY > 0)
520 last_req = read_timer();
521#endif
522 hd_request();
523}
524
525/*
526 * This is another of the error-routines I don't know what to do with. The
527 * best idea seems to just set reset, and start all over again.
528 */
529static void hd_times_out(unsigned long dummy)
530{
531 char *name;
532
533 do_hd = NULL;
534
535 if (!CURRENT)
536 return;
537
538 disable_irq(HD_IRQ);
539 local_irq_enable();
540 reset = 1;
541 name = CURRENT->rq_disk->disk_name;
542 printk("%s: timeout\n", name);
543 if (++CURRENT->errors >= MAX_ERRORS) {
544#ifdef DEBUG
545 printk("%s: too many errors\n", name);
546#endif
547 end_request(CURRENT, 0);
548 }
549 local_irq_disable();
550 hd_request();
551 enable_irq(HD_IRQ);
552}
553
554static int do_special_op(struct hd_i_struct *disk, struct request *req)
555{
556 if (disk->recalibrate) {
557 disk->recalibrate = 0;
558 hd_out(disk,disk->sect,0,0,0,WIN_RESTORE,&recal_intr);
559 return reset;
560 }
561 if (disk->head > 16) {
562 printk ("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name);
563 end_request(req, 0);
564 }
565 disk->special_op = 0;
566 return 1;
567}
568
569/*
570 * The driver enables interrupts as much as possible. In order to do this,
571 * (a) the device-interrupt is disabled before entering hd_request(),
572 * and (b) the timeout-interrupt is disabled before the sti().
573 *
574 * Interrupts are still masked (by default) whenever we are exchanging
575 * data/cmds with a drive, because some drives seem to have very poor
576 * tolerance for latency during I/O. The IDE driver has support to unmask
577 * interrupts for non-broken hardware, so use that driver if required.
578 */
579static void hd_request(void)
580{
581 unsigned int block, nsect, sec, track, head, cyl;
582 struct hd_i_struct *disk;
583 struct request *req;
584
585 if (do_hd)
586 return;
587repeat:
588 del_timer(&device_timer);
589 local_irq_enable();
590
591 req = CURRENT;
592 if (!req) {
593 do_hd = NULL;
594 return;
595 }
596
597 if (reset) {
598 local_irq_disable();
599 reset_hd();
600 return;
601 }
602 disk = req->rq_disk->private_data;
603 block = req->sector;
604 nsect = req->nr_sectors;
605 if (block >= get_capacity(req->rq_disk) ||
606 ((block+nsect) > get_capacity(req->rq_disk))) {
607 printk("%s: bad access: block=%d, count=%d\n",
608 req->rq_disk->disk_name, block, nsect);
609 end_request(req, 0);
610 goto repeat;
611 }
612
613 if (disk->special_op) {
614 if (do_special_op(disk, req))
615 goto repeat;
616 return;
617 }
618 sec = block % disk->sect + 1;
619 track = block / disk->sect;
620 head = track % disk->head;
621 cyl = track / disk->head;
622#ifdef DEBUG
623 printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
624 req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
625 cyl, head, sec, nsect, req->buffer);
626#endif
627 if (req->flags & REQ_CMD) {
628 switch (rq_data_dir(req)) {
629 case READ:
630 hd_out(disk,nsect,sec,head,cyl,WIN_READ,&read_intr);
631 if (reset)
632 goto repeat;
633 break;
634 case WRITE:
635 hd_out(disk,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
636 if (reset)
637 goto repeat;
638 if (wait_DRQ()) {
639 bad_rw_intr();
640 goto repeat;
641 }
642 outsw(HD_DATA,req->buffer,256);
643 break;
644 default:
645 printk("unknown hd-command\n");
646 end_request(req, 0);
647 break;
648 }
649 }
650}
651
652static void do_hd_request (request_queue_t * q)
653{
654 disable_irq(HD_IRQ);
655 hd_request();
656 enable_irq(HD_IRQ);
657}
658
659static int hd_ioctl(struct inode * inode, struct file * file,
660 unsigned int cmd, unsigned long arg)
661{
662 struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
663 struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
664 struct hd_geometry g;
665
666 if (cmd != HDIO_GETGEO)
667 return -EINVAL;
668 if (!loc)
669 return -EINVAL;
670 g.heads = disk->head;
671 g.sectors = disk->sect;
672 g.cylinders = disk->cyl;
673 g.start = get_start_sect(inode->i_bdev);
674 return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
675}
676
677/*
678 * Releasing a block device means we sync() it, so that it can safely
679 * be forgotten about...
680 */
681
682static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
683{
684 void (*handler)(void) = do_hd;
685
686 do_hd = NULL;
687 del_timer(&device_timer);
688 if (!handler)
689 handler = unexpected_hd_interrupt;
690 handler();
691 local_irq_enable();
692 return IRQ_HANDLED;
693}
694
695static struct block_device_operations hd_fops = {
696 .ioctl = hd_ioctl,
697};
698
699/*
700 * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
701 * means we run the IRQ-handler with interrupts disabled: this is bad for
702 * interrupt latency, but anything else has led to problems on some
703 * machines.
704 *
705 * We enable interrupts in some of the routines after making sure it's
706 * safe.
707 */
708
709static int __init hd_init(void)
710{
711 int drive;
712
713 if (register_blkdev(MAJOR_NR,"hd"))
714 return -1;
715
716 hd_queue = blk_init_queue(do_hd_request, &hd_lock);
717 if (!hd_queue) {
718 unregister_blkdev(MAJOR_NR,"hd");
719 return -ENOMEM;
720 }
721
722 blk_queue_max_sectors(hd_queue, 255);
723 init_timer(&device_timer);
724 device_timer.function = hd_times_out;
725 blk_queue_hardsect_size(hd_queue, 512);
726
727#ifdef __i386__
728 if (!NR_HD) {
729 extern struct drive_info drive_info;
730 unsigned char *BIOS = (unsigned char *) &drive_info;
731 unsigned long flags;
732 int cmos_disks;
733
734 for (drive=0 ; drive<2 ; drive++) {
735 hd_info[drive].cyl = *(unsigned short *) BIOS;
736 hd_info[drive].head = *(2+BIOS);
737 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
738 hd_info[drive].ctl = *(8+BIOS);
739 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
740 hd_info[drive].sect = *(14+BIOS);
741#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
742 if (hd_info[drive].cyl && NR_HD == drive)
743 NR_HD++;
744#endif
745 BIOS += 16;
746 }
747
748 /*
749 We query CMOS about hard disks : it could be that
750 we have a SCSI/ESDI/etc controller that is BIOS
751 compatible with ST-506, and thus showing up in our
752 BIOS table, but not register compatible, and therefore
753 not present in CMOS.
754
755 Furthermore, we will assume that our ST-506 drives
756 <if any> are the primary drives in the system, and
757 the ones reflected as drive 1 or 2.
758
759 The first drive is stored in the high nibble of CMOS
760 byte 0x12, the second in the low nibble. This will be
761 either a 4 bit drive type or 0xf indicating use byte 0x19
762 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
763
764 Needless to say, a non-zero value means we have
765 an AT controller hard disk for that drive.
766
767 Currently the rtc_lock is a bit academic since this
768 driver is non-modular, but someday... ? Paul G.
769 */
770
771 spin_lock_irqsave(&rtc_lock, flags);
772 cmos_disks = CMOS_READ(0x12);
773 spin_unlock_irqrestore(&rtc_lock, flags);
774
775 if (cmos_disks & 0xf0) {
776 if (cmos_disks & 0x0f)
777 NR_HD = 2;
778 else
779 NR_HD = 1;
780 }
781 }
782#endif /* __i386__ */
783#ifdef __arm__
784 if (!NR_HD) {
785 /* We don't know anything about the drive. This means
786 * that you *MUST* specify the drive parameters to the
787 * kernel yourself.
788 */
789 printk("hd: no drives specified - use hd=cyl,head,sectors"
790 " on kernel command line\n");
791 }
792#endif
793 if (!NR_HD)
794 goto out;
795
796 for (drive=0 ; drive < NR_HD ; drive++) {
797 struct gendisk *disk = alloc_disk(64);
798 struct hd_i_struct *p = &hd_info[drive];
799 if (!disk)
800 goto Enomem;
801 disk->major = MAJOR_NR;
802 disk->first_minor = drive << 6;
803 disk->fops = &hd_fops;
804 sprintf(disk->disk_name, "hd%c", 'a'+drive);
805 disk->private_data = p;
806 set_capacity(disk, p->head * p->sect * p->cyl);
807 disk->queue = hd_queue;
808 p->unit = drive;
809 hd_gendisk[drive] = disk;
810 printk ("%s: %luMB, CHS=%d/%d/%d\n",
811 disk->disk_name, (unsigned long)get_capacity(disk)/2048,
812 p->cyl, p->head, p->sect);
813 }
814
815 if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
816 printk("hd: unable to get IRQ%d for the hard disk driver\n",
817 HD_IRQ);
818 goto out1;
819 }
820 if (!request_region(HD_DATA, 8, "hd")) {
821 printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
822 goto out2;
823 }
824 if (!request_region(HD_CMD, 1, "hd(cmd)")) {
825 printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
826 goto out3;
827 }
828
829 /* Let them fly */
830 for(drive=0; drive < NR_HD; drive++)
831 add_disk(hd_gendisk[drive]);
832
833 return 0;
834
835out3:
836 release_region(HD_DATA, 8);
837out2:
838 free_irq(HD_IRQ, NULL);
839out1:
840 for (drive = 0; drive < NR_HD; drive++)
841 put_disk(hd_gendisk[drive]);
842 NR_HD = 0;
843out:
844 del_timer(&device_timer);
845 unregister_blkdev(MAJOR_NR,"hd");
846 blk_cleanup_queue(hd_queue);
847 return -1;
848Enomem:
849 while (drive--)
850 put_disk(hd_gendisk[drive]);
851 goto out;
852}
853
854static int parse_hd_setup (char *line) {
855 int ints[6];
856
857 (void) get_options(line, ARRAY_SIZE(ints), ints);
858 hd_setup(NULL, ints);
859
860 return 1;
861}
862__setup("hd=", parse_hd_setup);
863
864module_init(hd_init);
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
new file mode 100644
index 000000000000..a77fb249d5cf
--- /dev/null
+++ b/drivers/ide/legacy/ht6560b.c
@@ -0,0 +1,370 @@
1/*
2 * linux/drivers/ide/legacy/ht6560b.c Version 0.07 Feb 1, 2000
3 *
4 * Copyright (C) 1995-2000 Linus Torvalds & author (see below)
5 */
6
7/*
8 *
9 * Version 0.01 Initial version hacked out of ide.c
10 *
11 * Version 0.02 Added support for PIO modes, auto-tune
12 *
13 * Version 0.03 Some cleanups
14 *
15 * Version 0.05 PIO mode cycle timings auto-tune using bus-speed
16 *
17 * Version 0.06 Prefetch mode now defaults no OFF. To set
18 * prefetch mode OFF/ON use "hdparm -p8/-p9".
19 * Unmask irq is disabled when prefetch mode
20 * is enabled.
21 *
22 * Version 0.07 Trying to fix CD-ROM detection problem.
23 * "Prefetch" mode bit OFF for ide disks and
24 * ON for anything else.
25 *
26 *
27 * HT-6560B EIDE-controller support
28 * To activate controller support use kernel parameter "ide0=ht6560b".
29 * Use hdparm utility to enable PIO mode support.
30 *
31 * Author: Mikko Ala-Fossi <maf@iki.fi>
32 * Jan Evert van Grootheest <janevert@iae.nl>
33 *
34 * Try: http://www.maf.iki.fi/~maf/ht6560b/
35 */
36
37#define HT6560B_VERSION "v0.07"
38
39#undef REALLY_SLOW_IO /* most systems can safely undef this */
40
41#include <linux/module.h>
42#include <linux/config.h>
43#include <linux/types.h>
44#include <linux/kernel.h>
45#include <linux/delay.h>
46#include <linux/timer.h>
47#include <linux/mm.h>
48#include <linux/ioport.h>
49#include <linux/blkdev.h>
50#include <linux/hdreg.h>
51#include <linux/ide.h>
52#include <linux/init.h>
53
54#include <asm/io.h>
55
56/* #define DEBUG */ /* remove comments for DEBUG messages */
57
58/*
59 * The special i/o-port that HT-6560B uses to configuration:
60 * bit0 (0x01): "1" selects secondary interface
61 * bit2 (0x04): "1" enables FIFO function
62 * bit5 (0x20): "1" enables prefetched data read function (???)
63 *
64 * The special i/o-port that HT-6560A uses to configuration:
65 * bit0 (0x01): "1" selects secondary interface
66 * bit1 (0x02): "1" enables prefetched data read function
67 * bit2 (0x04): "0" enables multi-master system (?)
68 * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?)
69 */
70#define HT_CONFIG_PORT 0x3e6
71#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
72/*
73 * FIFO + PREFETCH (both a/b-model)
74 */
75#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
76/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
77#define HT_SECONDARY_IF 0x01
78#define HT_PREFETCH_MODE 0x20
79
80/*
81 * ht6560b Timing values:
82 *
83 * I reviewed some assembler source listings of htide drivers and found
84 * out how they setup those cycle time interfacing values, as they at Holtek
85 * call them. IDESETUP.COM that is supplied with the drivers figures out
86 * optimal values and fetches those values to drivers. I found out that
87 * they use IDE_SELECT_REG to fetch timings to the ide board right after
88 * interface switching. After that it was quite easy to add code to
89 * ht6560b.c.
90 *
91 * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
92 * for hda and hdc. But hdb needed higher values to work, so I guess
93 * that sometimes it is necessary to give higher value than IDESETUP
94 * gives. [see cmd640.c for an extreme example of this. -ml]
95 *
96 * Perhaps I should explain something about these timing values:
97 * The higher nibble of value is the Recovery Time (rt) and the lower nibble
98 * of the value is the Active Time (at). Minimum value 2 is the fastest and
99 * the maximum value 15 is the slowest. Default values should be 15 for both.
100 * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
101 * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
102 * similar. If value is too small there will be all sorts of failures.
103 *
104 * Timing byte consists of
105 * High nibble: Recovery Cycle Time (rt)
106 * The valid values range from 2 to 15. The default is 15.
107 *
108 * Low nibble: Active Cycle Time (at)
109 * The valid values range from 2 to 15. The default is 15.
110 *
111 * You can obtain optimized timing values by running Holtek IDESETUP.COM
112 * for DOS. DOS drivers get their timing values from command line, where
113 * the first value is the Recovery Time and the second value is the
114 * Active Time for each drive. Smaller value gives higher speed.
115 * In case of failures you should probably fall back to a higher value.
116 */
117#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
118#define HT_TIMING_DEFAULT 0xff
119
120/*
121 * This routine handles interface switching for the peculiar hardware design
122 * on the F.G.I./Holtek HT-6560B VLB IDE interface.
123 * The HT-6560B can only enable one IDE port at a time, and requires a
124 * silly sequence (below) whenever we switch between primary and secondary.
125 */
126
127/*
128 * This routine is invoked from ide.c to prepare for access to a given drive.
129 */
130static void ht6560b_selectproc (ide_drive_t *drive)
131{
132 unsigned long flags;
133 static u8 current_select = 0;
134 static u8 current_timing = 0;
135 u8 select, timing;
136
137 local_irq_save(flags);
138
139 select = HT_CONFIG(drive);
140 timing = HT_TIMING(drive);
141
142 if (select != current_select || timing != current_timing) {
143 current_select = select;
144 current_timing = timing;
145 if (drive->media != ide_disk || !drive->present)
146 select |= HT_PREFETCH_MODE;
147 (void) HWIF(drive)->INB(HT_CONFIG_PORT);
148 (void) HWIF(drive)->INB(HT_CONFIG_PORT);
149 (void) HWIF(drive)->INB(HT_CONFIG_PORT);
150 (void) HWIF(drive)->INB(HT_CONFIG_PORT);
151 HWIF(drive)->OUTB(select, HT_CONFIG_PORT);
152 /*
153 * Set timing for this drive:
154 */
155 HWIF(drive)->OUTB(timing, IDE_SELECT_REG);
156 (void) HWIF(drive)->INB(IDE_STATUS_REG);
157#ifdef DEBUG
158 printk("ht6560b: %s: select=%#x timing=%#x\n",
159 drive->name, select, timing);
160#endif
161 }
162 local_irq_restore(flags);
163}
164
165/*
166 * Autodetection and initialization of ht6560b
167 */
168static int __init try_to_init_ht6560b(void)
169{
170 u8 orig_value;
171 int i;
172
173 /* Autodetect ht6560b */
174 if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
175 return 0;
176
177 for (i=3;i>0;i--) {
178 outb(0x00, HT_CONFIG_PORT);
179 if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
180 outb(orig_value, HT_CONFIG_PORT);
181 return 0;
182 }
183 }
184 outb(0x00, HT_CONFIG_PORT);
185 if ((~inb(HT_CONFIG_PORT))& 0x3f) {
186 outb(orig_value, HT_CONFIG_PORT);
187 return 0;
188 }
189 /*
190 * Ht6560b autodetected
191 */
192 outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
193 outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */
194 (void) inb(0x1f7); /* IDE_STATUS_REG */
195
196 printk("\nht6560b " HT6560B_VERSION
197 ": chipset detected and initialized"
198#ifdef DEBUG
199 " with debug enabled"
200#endif
201 );
202 return 1;
203}
204
205static u8 ht_pio2timings(ide_drive_t *drive, u8 pio)
206{
207 int active_time, recovery_time;
208 int active_cycles, recovery_cycles;
209 ide_pio_data_t d;
210 int bus_speed = system_bus_clock();
211
212 if (pio) {
213 pio = ide_get_best_pio_mode(drive, pio, 5, &d);
214
215 /*
216 * Just like opti621.c we try to calculate the
217 * actual cycle time for recovery and activity
218 * according system bus speed.
219 */
220 active_time = ide_pio_timings[pio].active_time;
221 recovery_time = d.cycle_time
222 - active_time
223 - ide_pio_timings[pio].setup_time;
224 /*
225 * Cycle times should be Vesa bus cycles
226 */
227 active_cycles = (active_time * bus_speed + 999) / 1000;
228 recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
229 /*
230 * Upper and lower limits
231 */
232 if (active_cycles < 2) active_cycles = 2;
233 if (recovery_cycles < 2) recovery_cycles = 2;
234 if (active_cycles > 15) active_cycles = 15;
235 if (recovery_cycles > 15) recovery_cycles = 0; /* 0==16 */
236
237#ifdef DEBUG
238 printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
239#endif
240
241 return (u8)((recovery_cycles << 4) | active_cycles);
242 } else {
243
244#ifdef DEBUG
245 printk("ht6560b: drive %s setting pio=0\n", drive->name);
246#endif
247
248 return HT_TIMING_DEFAULT; /* default setting */
249 }
250}
251
252/*
253 * Enable/Disable so called prefetch mode
254 */
255static void ht_set_prefetch(ide_drive_t *drive, u8 state)
256{
257 unsigned long flags;
258 int t = HT_PREFETCH_MODE << 8;
259
260 spin_lock_irqsave(&ide_lock, flags);
261
262 /*
263 * Prefetch mode and unmask irq seems to conflict
264 */
265 if (state) {
266 drive->drive_data |= t; /* enable prefetch mode */
267 drive->no_unmask = 1;
268 drive->unmask = 0;
269 } else {
270 drive->drive_data &= ~t; /* disable prefetch mode */
271 drive->no_unmask = 0;
272 }
273
274 spin_unlock_irqrestore(&ide_lock, flags);
275
276#ifdef DEBUG
277 printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
278#endif
279}
280
281static void tune_ht6560b (ide_drive_t *drive, u8 pio)
282{
283 unsigned long flags;
284 u8 timing;
285
286 switch (pio) {
287 case 8: /* set prefetch off */
288 case 9: /* set prefetch on */
289 ht_set_prefetch(drive, pio & 1);
290 return;
291 }
292
293 timing = ht_pio2timings(drive, pio);
294
295 spin_lock_irqsave(&ide_lock, flags);
296
297 drive->drive_data &= 0xff00;
298 drive->drive_data |= timing;
299
300 spin_unlock_irqrestore(&ide_lock, flags);
301
302#ifdef DEBUG
303 printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
304#endif
305}
306
307/* Can be called directly from ide.c. */
308int __init ht6560b_init(void)
309{
310 ide_hwif_t *hwif, *mate;
311 int t;
312
313 hwif = &ide_hwifs[0];
314 mate = &ide_hwifs[1];
315
316 if (!request_region(HT_CONFIG_PORT, 1, hwif->name)) {
317 printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
318 __FUNCTION__);
319 return -ENODEV;
320 }
321
322 if (!try_to_init_ht6560b()) {
323 printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
324 goto release_region;
325 }
326
327 hwif->chipset = ide_ht6560b;
328 hwif->selectproc = &ht6560b_selectproc;
329 hwif->tuneproc = &tune_ht6560b;
330 hwif->serialized = 1; /* is this needed? */
331 hwif->mate = mate;
332
333 mate->chipset = ide_ht6560b;
334 mate->selectproc = &ht6560b_selectproc;
335 mate->tuneproc = &tune_ht6560b;
336 mate->serialized = 1; /* is this needed? */
337 mate->mate = hwif;
338 mate->channel = 1;
339
340 /*
341 * Setting default configurations for drives
342 */
343 t = (HT_CONFIG_DEFAULT << 8);
344 t |= HT_TIMING_DEFAULT;
345 hwif->drives[0].drive_data = t;
346 hwif->drives[1].drive_data = t;
347
348 t |= (HT_SECONDARY_IF << 8);
349 mate->drives[0].drive_data = t;
350 mate->drives[1].drive_data = t;
351
352 probe_hwif_init(hwif);
353 probe_hwif_init(mate);
354
355 create_proc_ide_interfaces();
356
357 return 0;
358
359release_region:
360 release_region(HT_CONFIG_PORT, 1);
361 return -ENODEV;
362}
363
364#ifdef MODULE
365module_init(ht6560b_init);
366#endif
367
368MODULE_AUTHOR("See Local File");
369MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
370MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
new file mode 100644
index 000000000000..e20327e54b1a
--- /dev/null
+++ b/drivers/ide/legacy/ide-cs.c
@@ -0,0 +1,481 @@
1/*======================================================================
2
3 A driver for PCMCIA IDE/ATA disk cards
4
5 ide-cs.c 1.3 2002/10/26 05:45:31
6
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
11
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
16
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
20
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in
23 which case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
31
32======================================================================*/
33
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <linux/sched.h>
38#include <linux/ptrace.h>
39#include <linux/slab.h>
40#include <linux/string.h>
41#include <linux/timer.h>
42#include <linux/ioport.h>
43#include <linux/ide.h>
44#include <linux/hdreg.h>
45#include <linux/major.h>
46#include <asm/io.h>
47#include <asm/system.h>
48
49#include <pcmcia/version.h>
50#include <pcmcia/cs_types.h>
51#include <pcmcia/cs.h>
52#include <pcmcia/cistpl.h>
53#include <pcmcia/ds.h>
54#include <pcmcia/cisreg.h>
55#include <pcmcia/ciscode.h>
56
57/*====================================================================*/
58
59/* Module parameters */
60
61MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
62MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");
63MODULE_LICENSE("Dual MPL/GPL");
64
65#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
66
67#ifdef PCMCIA_DEBUG
68INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
69#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
70static char *version =
71"ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
72#else
73#define DEBUG(n, args...)
74#endif
75
76/*====================================================================*/
77
78static const char ide_major[] = {
79 IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
80 IDE4_MAJOR, IDE5_MAJOR
81};
82
83typedef struct ide_info_t {
84 dev_link_t link;
85 int ndev;
86 dev_node_t node;
87 int hd;
88} ide_info_t;
89
90static void ide_release(dev_link_t *);
91static int ide_event(event_t event, int priority,
92 event_callback_args_t *args);
93
94static dev_info_t dev_info = "ide-cs";
95
96static dev_link_t *ide_attach(void);
97static void ide_detach(dev_link_t *);
98
99static dev_link_t *dev_list = NULL;
100
101/*======================================================================
102
103 ide_attach() creates an "instance" of the driver, allocating
104 local data structures for one device. The device is registered
105 with Card Services.
106
107======================================================================*/
108
109static dev_link_t *ide_attach(void)
110{
111 ide_info_t *info;
112 dev_link_t *link;
113 client_reg_t client_reg;
114 int ret;
115
116 DEBUG(0, "ide_attach()\n");
117
118 /* Create new ide device */
119 info = kmalloc(sizeof(*info), GFP_KERNEL);
120 if (!info) return NULL;
121 memset(info, 0, sizeof(*info));
122 link = &info->link; link->priv = info;
123
124 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
125 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
126 link->io.IOAddrLines = 3;
127 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
128 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
129 link->conf.Attributes = CONF_ENABLE_IRQ;
130 link->conf.Vcc = 50;
131 link->conf.IntType = INT_MEMORY_AND_IO;
132
133 /* Register with Card Services */
134 link->next = dev_list;
135 dev_list = link;
136 client_reg.dev_info = &dev_info;
137 client_reg.EventMask =
138 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
139 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
140 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
141 client_reg.event_handler = &ide_event;
142 client_reg.Version = 0x0210;
143 client_reg.event_callback_args.client_data = link;
144 ret = pcmcia_register_client(&link->handle, &client_reg);
145 if (ret != CS_SUCCESS) {
146 cs_error(link->handle, RegisterClient, ret);
147 ide_detach(link);
148 return NULL;
149 }
150
151 return link;
152} /* ide_attach */
153
154/*======================================================================
155
156 This deletes a driver "instance". The device is de-registered
157 with Card Services. If it has been released, all local data
158 structures are freed. Otherwise, the structures will be freed
159 when the device is released.
160
161======================================================================*/
162
163static void ide_detach(dev_link_t *link)
164{
165 dev_link_t **linkp;
166 int ret;
167
168 DEBUG(0, "ide_detach(0x%p)\n", link);
169
170 /* Locate device structure */
171 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
172 if (*linkp == link) break;
173 if (*linkp == NULL)
174 return;
175
176 if (link->state & DEV_CONFIG)
177 ide_release(link);
178
179 if (link->handle) {
180 ret = pcmcia_deregister_client(link->handle);
181 if (ret != CS_SUCCESS)
182 cs_error(link->handle, DeregisterClient, ret);
183 }
184
185 /* Unlink, free device structure */
186 *linkp = link->next;
187 kfree(link->priv);
188
189} /* ide_detach */
190
191static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq)
192{
193 hw_regs_t hw;
194 memset(&hw, 0, sizeof(hw));
195 ide_init_hwif_ports(&hw, io, ctl, NULL);
196 hw.irq = irq;
197 hw.chipset = ide_pci;
198 return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
199}
200
201/*======================================================================
202
203 ide_config() is scheduled to run after a CARD_INSERTION event
204 is received, to configure the PCMCIA socket, and to make the
205 ide device available to the system.
206
207======================================================================*/
208
209#define CS_CHECK(fn, ret) \
210do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
211
212static void ide_config(dev_link_t *link)
213{
214 client_handle_t handle = link->handle;
215 ide_info_t *info = link->priv;
216 tuple_t tuple;
217 struct {
218 u_short buf[128];
219 cisparse_t parse;
220 config_info_t conf;
221 cistpl_cftable_entry_t dflt;
222 } *stk = NULL;
223 cistpl_cftable_entry_t *cfg;
224 int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0;
225 unsigned long io_base, ctl_base;
226
227 DEBUG(0, "ide_config(0x%p)\n", link);
228
229 stk = kmalloc(sizeof(*stk), GFP_KERNEL);
230 if (!stk) goto err_mem;
231 memset(stk, 0, sizeof(*stk));
232 cfg = &stk->parse.cftable_entry;
233
234 tuple.TupleData = (cisdata_t *)&stk->buf;
235 tuple.TupleOffset = 0;
236 tuple.TupleDataMax = 255;
237 tuple.Attributes = 0;
238 tuple.DesiredTuple = CISTPL_CONFIG;
239 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
240 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
241 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse));
242 link->conf.ConfigBase = stk->parse.config.base;
243 link->conf.Present = stk->parse.config.rmask[0];
244
245 tuple.DesiredTuple = CISTPL_MANFID;
246 if (!pcmcia_get_first_tuple(handle, &tuple) &&
247 !pcmcia_get_tuple_data(handle, &tuple) &&
248 !pcmcia_parse_tuple(handle, &tuple, &stk->parse))
249 is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
250 ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
251 (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
252
253 /* Configure card */
254 link->state |= DEV_CONFIG;
255
256 /* Not sure if this is right... look up the current Vcc */
257 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf));
258 link->conf.Vcc = stk->conf.Vcc;
259
260 pass = io_base = ctl_base = 0;
261 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
262 tuple.Attributes = 0;
263 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
264 while (1) {
265 if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry;
266 if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry;
267
268 /* Check for matching Vcc, unless we're desperate */
269 if (!pass) {
270 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
271 if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
272 goto next_entry;
273 } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
274 if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
275 goto next_entry;
276 }
277 }
278
279 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
280 link->conf.Vpp1 = link->conf.Vpp2 =
281 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
282 else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
283 link->conf.Vpp1 = link->conf.Vpp2 =
284 stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
285
286 if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
287 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
288 link->conf.ConfigIndex = cfg->index;
289 link->io.BasePort1 = io->win[0].base;
290 link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
291 if (!(io->flags & CISTPL_IO_16BIT))
292 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
293 if (io->nwin == 2) {
294 link->io.NumPorts1 = 8;
295 link->io.BasePort2 = io->win[1].base;
296 link->io.NumPorts2 = (is_kme) ? 2 : 1;
297 if (pcmcia_request_io(link->handle, &link->io) != 0)
298 goto next_entry;
299 io_base = link->io.BasePort1;
300 ctl_base = link->io.BasePort2;
301 } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
302 link->io.NumPorts1 = io->win[0].len;
303 link->io.NumPorts2 = 0;
304 if (pcmcia_request_io(link->handle, &link->io) != 0)
305 goto next_entry;
306 io_base = link->io.BasePort1;
307 ctl_base = link->io.BasePort1 + 0x0e;
308 } else goto next_entry;
309 /* If we've got this far, we're done */
310 break;
311 }
312
313 next_entry:
314 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
315 memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
316 if (pass) {
317 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
318 } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) {
319 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
320 memset(&stk->dflt, 0, sizeof(stk->dflt));
321 pass++;
322 }
323 }
324
325 CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
326 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
327
328 /* disable drive interrupts during IDE probe */
329 outb(0x02, ctl_base);
330
331 /* special setup for KXLC005 card */
332 if (is_kme)
333 outb(0x81, ctl_base+1);
334
335 /* retry registration in case device is still spinning up */
336 for (hd = -1, i = 0; i < 10; i++) {
337 hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
338 if (hd >= 0) break;
339 if (link->io.NumPorts1 == 0x20) {
340 outb(0x02, ctl_base + 0x10);
341 hd = idecs_register(io_base + 0x10, ctl_base + 0x10,
342 link->irq.AssignedIRQ);
343 if (hd >= 0) {
344 io_base += 0x10;
345 ctl_base += 0x10;
346 break;
347 }
348 }
349 __set_current_state(TASK_UNINTERRUPTIBLE);
350 schedule_timeout(HZ/10);
351 }
352
353 if (hd < 0) {
354 printk(KERN_NOTICE "ide-cs: ide_register() at 0x%3lx & 0x%3lx"
355 ", irq %u failed\n", io_base, ctl_base,
356 link->irq.AssignedIRQ);
357 goto failed;
358 }
359
360 info->ndev = 1;
361 sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2));
362 info->node.major = ide_major[hd];
363 info->node.minor = 0;
364 info->hd = hd;
365 link->dev = &info->node;
366 printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n",
367 info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10,
368 link->conf.Vpp1 / 10, link->conf.Vpp1 % 10);
369
370 link->state &= ~DEV_CONFIG_PENDING;
371 kfree(stk);
372 return;
373
374err_mem:
375 printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
376 goto failed;
377
378cs_failed:
379 cs_error(link->handle, last_fn, last_ret);
380failed:
381 kfree(stk);
382 ide_release(link);
383 link->state &= ~DEV_CONFIG_PENDING;
384} /* ide_config */
385
386/*======================================================================
387
388 After a card is removed, ide_release() will unregister the net
389 device, and release the PCMCIA configuration. If the device is
390 still open, this will be postponed until it is closed.
391
392======================================================================*/
393
394void ide_release(dev_link_t *link)
395{
396 ide_info_t *info = link->priv;
397
398 DEBUG(0, "ide_release(0x%p)\n", link);
399
400 if (info->ndev) {
401 /* FIXME: if this fails we need to queue the cleanup somehow
402 -- need to investigate the required PCMCIA magic */
403 ide_unregister(info->hd);
404 }
405 info->ndev = 0;
406 link->dev = NULL;
407
408 pcmcia_release_configuration(link->handle);
409 pcmcia_release_io(link->handle, &link->io);
410 pcmcia_release_irq(link->handle, &link->irq);
411
412 link->state &= ~DEV_CONFIG;
413
414} /* ide_release */
415
416/*======================================================================
417
418 The card status event handler. Mostly, this schedules other
419 stuff to run after an event is received. A CARD_REMOVAL event
420 also sets some flags to discourage the ide drivers from
421 talking to the ports.
422
423======================================================================*/
424
425int ide_event(event_t event, int priority,
426 event_callback_args_t *args)
427{
428 dev_link_t *link = args->client_data;
429
430 DEBUG(1, "ide_event(0x%06x)\n", event);
431
432 switch (event) {
433 case CS_EVENT_CARD_REMOVAL:
434 link->state &= ~DEV_PRESENT;
435 if (link->state & DEV_CONFIG)
436 ide_release(link);
437 break;
438 case CS_EVENT_CARD_INSERTION:
439 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
440 ide_config(link);
441 break;
442 case CS_EVENT_PM_SUSPEND:
443 link->state |= DEV_SUSPEND;
444 /* Fall through... */
445 case CS_EVENT_RESET_PHYSICAL:
446 if (link->state & DEV_CONFIG)
447 pcmcia_release_configuration(link->handle);
448 break;
449 case CS_EVENT_PM_RESUME:
450 link->state &= ~DEV_SUSPEND;
451 /* Fall through... */
452 case CS_EVENT_CARD_RESET:
453 if (DEV_OK(link))
454 pcmcia_request_configuration(link->handle, &link->conf);
455 break;
456 }
457 return 0;
458} /* ide_event */
459
460static struct pcmcia_driver ide_cs_driver = {
461 .owner = THIS_MODULE,
462 .drv = {
463 .name = "ide-cs",
464 },
465 .attach = ide_attach,
466 .detach = ide_detach,
467};
468
469static int __init init_ide_cs(void)
470{
471 return pcmcia_register_driver(&ide_cs_driver);
472}
473
474static void __exit exit_ide_cs(void)
475{
476 pcmcia_unregister_driver(&ide_cs_driver);
477 BUG_ON(dev_list != NULL);
478}
479
480module_init(init_ide_cs);
481module_exit(exit_ide_cs);
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
new file mode 100644
index 000000000000..90cac609d9cf
--- /dev/null
+++ b/drivers/ide/legacy/macide.c
@@ -0,0 +1,155 @@
1/*
2 * linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver
3 *
4 * Copyright (C) 1998 by Michael Schmitz
5 *
6 * This driver was written based on information obtained from the MacOS IDE
7 * driver binary by Mikael Forselius
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
11 * more details.
12 */
13
14#include <linux/config.h>
15#include <linux/types.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18#include <linux/blkdev.h>
19#include <linux/hdreg.h>
20#include <linux/delay.h>
21#include <linux/ide.h>
22
23#include <asm/machw.h>
24#include <asm/macintosh.h>
25#include <asm/macints.h>
26#include <asm/mac_baboon.h>
27
28#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */
29
30/*
31 * Generic IDE registers as offsets from the base
32 * These match MkLinux so they should be correct.
33 */
34
35#define IDE_DATA 0x00
36#define IDE_ERROR 0x04 /* see err-bits */
37#define IDE_NSECTOR 0x08 /* nr of sectors to read/write */
38#define IDE_SECTOR 0x0c /* starting sector */
39#define IDE_LCYL 0x10 /* starting cylinder */
40#define IDE_HCYL 0x14 /* high byte of starting cyl */
41#define IDE_SELECT 0x18 /* 101dhhhh , d=drive, hhhh=head */
42#define IDE_STATUS 0x1c /* see status-bits */
43#define IDE_CONTROL 0x38 /* control/altstatus */
44
45/*
46 * Mac-specific registers
47 */
48
49/*
50 * this register is odd; it doesn't seem to do much and it's
51 * not word-aligned like virtually every other hardware register
52 * on the Mac...
53 */
54
55#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra:
56 *
57 * Bit 0+1: some interrupt flags
58 * Bit 2+3: some interrupt enable
59 * Bit 4: ??
60 * Bit 5: IDE interrupt flag (any hwif)
61 * Bit 6: maybe IDE interrupt enable (any hwif) ??
62 * Bit 7: Any interrupt condition
63 */
64
65volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR);
66
67static int macide_offsets[IDE_NR_PORTS] = {
68 IDE_DATA, IDE_ERROR, IDE_NSECTOR, IDE_SECTOR, IDE_LCYL,
69 IDE_HCYL, IDE_SELECT, IDE_STATUS, IDE_CONTROL
70};
71
72int macide_ack_intr(ide_hwif_t* hwif)
73{
74 if (*ide_ifr & 0x20) {
75 *ide_ifr &= ~0x20;
76 return 1;
77 }
78 return 0;
79}
80
81#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
82static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *regs)
83{
84 int state = baboon->mb_status & 0x04;
85
86 printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
87}
88#endif
89
90/*
91 * Probe for a Macintosh IDE interface
92 */
93
94void macide_init(void)
95{
96 hw_regs_t hw;
97 ide_hwif_t *hwif;
98 int index = -1;
99
100 switch (macintosh_config->ide_type) {
101 case MAC_IDE_QUADRA:
102 ide_setup_ports(&hw, IDE_BASE, macide_offsets,
103 0, 0, macide_ack_intr,
104// quadra_ide_iops,
105 IRQ_NUBUS_F);
106 index = ide_register_hw(&hw, &hwif);
107 break;
108 case MAC_IDE_PB:
109 ide_setup_ports(&hw, IDE_BASE, macide_offsets,
110 0, 0, macide_ack_intr,
111// macide_pb_iops,
112 IRQ_NUBUS_C);
113 index = ide_register_hw(&hw, &hwif);
114 break;
115 case MAC_IDE_BABOON:
116 ide_setup_ports(&hw, BABOON_BASE, macide_offsets,
117 0, 0, NULL,
118// macide_baboon_iops,
119 IRQ_BABOON_1);
120 index = ide_register_hw(&hw, &hwif);
121 if (index == -1) break;
122 if (macintosh_config->ident == MAC_MODEL_PB190) {
123
124 /* Fix breakage in ide-disk.c: drive capacity */
125 /* is not initialized for drives without a */
126 /* hardware ID, and we can't get that without */
127 /* probing the drive which freezes a 190. */
128
129 ide_drive_t *drive = &ide_hwifs[index].drives[0];
130 drive->capacity64 = drive->cyl*drive->head*drive->sect;
131
132#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
133 request_irq(IRQ_BABOON_2, macide_mediabay_interrupt,
134 IRQ_FLG_FAST, "mediabay",
135 macide_mediabay_interrupt);
136#endif
137 }
138 break;
139
140 default:
141 return;
142 }
143
144 if (index != -1) {
145 hwif->mmio = 2;
146 if (macintosh_config->ide_type == MAC_IDE_QUADRA)
147 printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
148 else if (macintosh_config->ide_type == MAC_IDE_PB)
149 printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index);
150 else if (macintosh_config->ide_type == MAC_IDE_BABOON)
151 printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index);
152 else
153 printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index);
154 }
155}
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
new file mode 100644
index 000000000000..2a78b792f7fb
--- /dev/null
+++ b/drivers/ide/legacy/q40ide.c
@@ -0,0 +1,150 @@
1/*
2 * linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver
3 *
4 * (c) Richard Zidlicky
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 *
10 *
11 */
12
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/interrupt.h>
16#include <linux/blkdev.h>
17#include <linux/hdreg.h>
18
19#include <linux/ide.h>
20
21 /*
22 * Bases of the IDE interfaces
23 */
24
25#define Q40IDE_NUM_HWIFS 2
26
27#define PCIDE_BASE1 0x1f0
28#define PCIDE_BASE2 0x170
29#define PCIDE_BASE3 0x1e8
30#define PCIDE_BASE4 0x168
31#define PCIDE_BASE5 0x1e0
32#define PCIDE_BASE6 0x160
33
34static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
35 PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5,
36 PCIDE_BASE6 */
37};
38
39
40 /*
41 * Offsets from one of the above bases
42 */
43
44/* used to do addr translation here but it is easier to do in setup ports */
45/*#define IDE_OFF_B(x) ((unsigned long)Q40_ISA_IO_B((IDE_##x##_OFFSET)))*/
46
47#define IDE_OFF_B(x) ((unsigned long)((IDE_##x##_OFFSET)))
48#define IDE_OFF_W(x) ((unsigned long)((IDE_##x##_OFFSET)))
49
50static const int pcide_offsets[IDE_NR_PORTS] = {
51 IDE_OFF_W(DATA), IDE_OFF_B(ERROR), IDE_OFF_B(NSECTOR), IDE_OFF_B(SECTOR),
52 IDE_OFF_B(LCYL), IDE_OFF_B(HCYL), 6 /*IDE_OFF_B(CURRENT)*/, IDE_OFF_B(STATUS),
53 518/*IDE_OFF(CMD)*/
54};
55
56static int q40ide_default_irq(unsigned long base)
57{
58 switch (base) {
59 case 0x1f0: return 14;
60 case 0x170: return 15;
61 case 0x1e8: return 11;
62 default:
63 return 0;
64 }
65}
66
67
68/*
69 * This is very similar to ide_setup_ports except that addresses
70 * are pretranslated for q40 ISA access
71 */
72void q40_ide_setup_ports ( hw_regs_t *hw,
73 unsigned long base, int *offsets,
74 unsigned long ctrl, unsigned long intr,
75 ide_ack_intr_t *ack_intr,
76/*
77 * ide_io_ops_t *iops,
78 */
79 int irq)
80{
81 int i;
82
83 for (i = 0; i < IDE_NR_PORTS; i++) {
84 /* BIG FAT WARNING:
85 assumption: only DATA port is ever used in 16 bit mode */
86 if ( i==0 )
87 hw->io_ports[i] = Q40_ISA_IO_W(base + offsets[i]);
88 else
89 hw->io_ports[i] = Q40_ISA_IO_B(base + offsets[i]);
90 }
91
92 hw->irq = irq;
93 hw->dma = NO_DMA;
94 hw->ack_intr = ack_intr;
95/*
96 * hw->iops = iops;
97 */
98}
99
100
101
102/*
103 * the static array is needed to have the name reported in /proc/ioports,
104 * hwif->name unfortunately isn´t available yet
105 */
106static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
107 "ide0", "ide1"
108};
109
110/*
111 * Probe for Q40 IDE interfaces
112 */
113
114void q40ide_init(void)
115{
116 int i;
117 ide_hwif_t *hwif;
118 int index;
119 const char *name;
120
121 if (!MACH_IS_Q40)
122 return ;
123
124 for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
125 hw_regs_t hw;
126
127 name = q40_ide_names[i];
128 if (!request_region(pcide_bases[i], 8, name)) {
129 printk("could not reserve ports %lx-%lx for %s\n",
130 pcide_bases[i],pcide_bases[i]+8,name);
131 continue;
132 }
133 if (!request_region(pcide_bases[i]+0x206, 1, name)) {
134 printk("could not reserve port %lx for %s\n",
135 pcide_bases[i]+0x206,name);
136 release_region(pcide_bases[i], 8);
137 continue;
138 }
139 q40_ide_setup_ports(&hw,(unsigned long) pcide_bases[i], (int *)pcide_offsets,
140 pcide_bases[i]+0x206,
141 0, NULL,
142// m68kide_iops,
143 q40ide_default_irq(pcide_bases[i]));
144 index = ide_register_hw(&hw, &hwif);
145 // **FIXME**
146 if (index != -1)
147 hwif->mmio = 2;
148 }
149}
150
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
new file mode 100644
index 000000000000..563fab0098be
--- /dev/null
+++ b/drivers/ide/legacy/qd65xx.c
@@ -0,0 +1,511 @@
1/*
2 * linux/drivers/ide/legacy/qd65xx.c Version 0.07 Sep 30, 2001
3 *
4 * Copyright (C) 1996-2001 Linus Torvalds & author (see below)
5 */
6
7/*
8 * Version 0.03 Cleaned auto-tune, added probe
9 * Version 0.04 Added second channel tuning
10 * Version 0.05 Enhanced tuning ; added qd6500 support
11 * Version 0.06 Added dos driver's list
12 * Version 0.07 Second channel bug fix
13 *
14 * QDI QD6500/QD6580 EIDE controller fast support
15 *
16 * Please set local bus speed using kernel parameter idebus
17 * for example, "idebus=33" stands for 33Mhz VLbus
18 * To activate controller support, use "ide0=qd65xx"
19 * To enable tuning, use "ide0=autotune"
20 * To enable second channel tuning (qd6580 only), use "ide1=autotune"
21 */
22
23/*
24 * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
25 * Samuel Thibault <samuel.thibault@fnac.net>
26 */
27
28#undef REALLY_SLOW_IO /* most systems can safely undef this */
29
30#include <linux/module.h>
31#include <linux/config.h>
32#include <linux/types.h>
33#include <linux/kernel.h>
34#include <linux/delay.h>
35#include <linux/timer.h>
36#include <linux/mm.h>
37#include <linux/ioport.h>
38#include <linux/blkdev.h>
39#include <linux/hdreg.h>
40#include <linux/ide.h>
41#include <linux/init.h>
42#include <asm/system.h>
43#include <asm/io.h>
44
45#include "qd65xx.h"
46
47/*
48 * I/O ports are 0x30-0x31 (and 0x32-0x33 for qd6580)
49 * or 0xb0-0xb1 (and 0xb2-0xb3 for qd6580)
50 * -- qd6500 is a single IDE interface
51 * -- qd6580 is a dual IDE interface
52 *
53 * More research on qd6580 being done by willmore@cig.mot.com (David)
54 * More Information given by Petr Soucek (petr@ryston.cz)
55 * http://www.ryston.cz/petr/vlb
56 */
57
58/*
59 * base: Timer1
60 *
61 *
62 * base+0x01: Config (R/O)
63 *
64 * bit 0: ide baseport: 1 = 0x1f0 ; 0 = 0x170 (only useful for qd6500)
65 * bit 1: qd65xx baseport: 1 = 0xb0 ; 0 = 0x30
66 * bit 2: ID3: bus speed: 1 = <=33MHz ; 0 = >33MHz
67 * bit 3: qd6500: 1 = disabled, 0 = enabled
68 * qd6580: 1
69 * upper nibble:
70 * qd6500: 1100
71 * qd6580: either 1010 or 0101
72 *
73 *
74 * base+0x02: Timer2 (qd6580 only)
75 *
76 *
77 * base+0x03: Control (qd6580 only)
78 *
79 * bits 0-3 must always be set 1
80 * bit 4 must be set 1, but is set 0 by dos driver while measuring vlb clock
81 * bit 0 : 1 = Only primary port enabled : channel 0 for hda, channel 1 for hdb
82 * 0 = Primary and Secondary ports enabled : channel 0 for hda & hdb
83 * channel 1 for hdc & hdd
84 * bit 1 : 1 = only disks on primary port
85 * 0 = disks & ATAPI devices on primary port
86 * bit 2-4 : always 0
87 * bit 5 : status, but of what ?
88 * bit 6 : always set 1 by dos driver
89 * bit 7 : set 1 for non-ATAPI devices on primary port
90 * (maybe read-ahead and post-write buffer ?)
91 */
92
93static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
94
95static void qd_write_reg (u8 content, unsigned long reg)
96{
97 unsigned long flags;
98
99 spin_lock_irqsave(&ide_lock, flags);
100 outb(content,reg);
101 spin_unlock_irqrestore(&ide_lock, flags);
102}
103
104static u8 __init qd_read_reg (unsigned long reg)
105{
106 unsigned long flags;
107 u8 read;
108
109 spin_lock_irqsave(&ide_lock, flags);
110 read = inb(reg);
111 spin_unlock_irqrestore(&ide_lock, flags);
112 return read;
113}
114
115/*
116 * qd_select:
117 *
118 * This routine is invoked from ide.c to prepare for access to a given drive.
119 */
120
121static void qd_select (ide_drive_t *drive)
122{
123 u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) |
124 (QD_TIMREG(drive) & 0x02);
125
126 if (timings[index] != QD_TIMING(drive))
127 qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
128}
129
130/*
131 * qd6500_compute_timing
132 *
133 * computes the timing value where
134 * lower nibble represents active time, in count of VLB clocks
135 * upper nibble represents recovery time, in count of VLB clocks
136 */
137
138static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
139{
140 u8 active_cycle,recovery_cycle;
141
142 if (system_bus_clock()<=33) {
143 active_cycle = 9 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 9);
144 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15);
145 } else {
146 active_cycle = 8 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 1, 8);
147 recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18);
148 }
149
150 return((recovery_cycle<<4) | 0x08 | active_cycle);
151}
152
153/*
154 * qd6580_compute_timing
155 *
156 * idem for qd6580
157 */
158
159static u8 qd6580_compute_timing (int active_time, int recovery_time)
160{
161 u8 active_cycle = 17 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 17);
162 u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15);
163
164 return((recovery_cycle<<4) | active_cycle);
165}
166
167/*
168 * qd_find_disk_type
169 *
170 * tries to find timing from dos driver's table
171 */
172
173static int qd_find_disk_type (ide_drive_t *drive,
174 int *active_time, int *recovery_time)
175{
176 struct qd65xx_timing_s *p;
177 char model[40];
178
179 if (!*drive->id->model) return 0;
180
181 strncpy(model,drive->id->model,40);
182 ide_fixstring(model,40,1); /* byte-swap */
183
184 for (p = qd65xx_timing ; p->offset != -1 ; p++) {
185 if (!strncmp(p->model, model+p->offset, 4)) {
186 printk(KERN_DEBUG "%s: listed !\n", drive->name);
187 *active_time = p->active;
188 *recovery_time = p->recovery;
189 return 1;
190 }
191 }
192 return 0;
193}
194
195/*
196 * qd_timing_ok:
197 *
198 * check whether timings don't conflict
199 */
200
201static int qd_timing_ok (ide_drive_t drives[])
202{
203 return (IDE_IMPLY(drives[0].present && drives[1].present,
204 IDE_IMPLY(QD_TIMREG(drives) == QD_TIMREG(drives+1),
205 QD_TIMING(drives) == QD_TIMING(drives+1))));
206 /* if same timing register, must be same timing */
207}
208
209/*
210 * qd_set_timing:
211 *
212 * records the timing, and enables selectproc as needed
213 */
214
215static void qd_set_timing (ide_drive_t *drive, u8 timing)
216{
217 ide_hwif_t *hwif = HWIF(drive);
218
219 drive->drive_data &= 0xff00;
220 drive->drive_data |= timing;
221 if (qd_timing_ok(hwif->drives)) {
222 qd_select(drive); /* selects once */
223 hwif->selectproc = NULL;
224 } else
225 hwif->selectproc = &qd_select;
226
227 printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
228}
229
230/*
231 * qd6500_tune_drive
232 */
233
234static void qd6500_tune_drive (ide_drive_t *drive, u8 pio)
235{
236 int active_time = 175;
237 int recovery_time = 415; /* worst case values from the dos driver */
238
239 if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)
240 && drive->id->tPIO && (drive->id->field_valid & 0x02)
241 && drive->id->eide_pio >= 240) {
242
243 printk(KERN_INFO "%s: PIO mode%d\n", drive->name,
244 drive->id->tPIO);
245 active_time = 110;
246 recovery_time = drive->id->eide_pio - 120;
247 }
248
249 qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
250}
251
252/*
253 * qd6580_tune_drive
254 */
255
256static void qd6580_tune_drive (ide_drive_t *drive, u8 pio)
257{
258 ide_pio_data_t d;
259 int base = HWIF(drive)->select_data;
260 int active_time = 175;
261 int recovery_time = 415; /* worst case values from the dos driver */
262
263 if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
264 pio = ide_get_best_pio_mode(drive, pio, 255, &d);
265 pio = min_t(u8, pio, 4);
266
267 switch (pio) {
268 case 0: break;
269 case 3:
270 if (d.cycle_time >= 110) {
271 active_time = 86;
272 recovery_time = d.cycle_time - 102;
273 } else
274 printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
275 break;
276 case 4:
277 if (d.cycle_time >= 69) {
278 active_time = 70;
279 recovery_time = d.cycle_time - 61;
280 } else
281 printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
282 break;
283 default:
284 if (d.cycle_time >= 180) {
285 active_time = 110;
286 recovery_time = d.cycle_time - 120;
287 } else {
288 active_time = ide_pio_timings[pio].active_time;
289 recovery_time = d.cycle_time
290 -active_time;
291 }
292 }
293 printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio);
294 }
295
296 if (!HWIF(drive)->channel && drive->media != ide_disk) {
297 qd_write_reg(0x5f, QD_CONTROL_PORT);
298 printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
299 "and post-write buffer on %s.\n",
300 drive->name, HWIF(drive)->name);
301 }
302
303 qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
304}
305
306/*
307 * qd_testreg
308 *
309 * tests if the given port is a register
310 */
311
312static int __init qd_testreg(int port)
313{
314 u8 savereg;
315 u8 readreg;
316 unsigned long flags;
317
318 spin_lock_irqsave(&ide_lock, flags);
319 savereg = inb_p(port);
320 outb_p(QD_TESTVAL, port); /* safe value */
321 readreg = inb_p(port);
322 outb(savereg, port);
323 spin_unlock_irqrestore(&ide_lock, flags);
324
325 if (savereg == QD_TESTVAL) {
326 printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n");
327 printk(KERN_ERR "Please contact maintainers to tell about your hardware\n");
328 printk(KERN_ERR "Assuming qd65xx is not present.\n");
329 return 1;
330 }
331
332 return (readreg != QD_TESTVAL);
333}
334
335/*
336 * qd_setup:
337 *
338 * called to setup an ata channel : adjusts attributes & links for tuning
339 */
340
341static void __init qd_setup(ide_hwif_t *hwif, int base, int config,
342 unsigned int data0, unsigned int data1,
343 void (*tuneproc) (ide_drive_t *, u8 pio))
344{
345 hwif->chipset = ide_qd65xx;
346 hwif->channel = hwif->index;
347 hwif->select_data = base;
348 hwif->config_data = config;
349 hwif->drives[0].drive_data = data0;
350 hwif->drives[1].drive_data = data1;
351 hwif->drives[0].io_32bit =
352 hwif->drives[1].io_32bit = 1;
353 hwif->tuneproc = tuneproc;
354 probe_hwif_init(hwif);
355}
356
357/*
358 * qd_unsetup:
359 *
360 * called to unsetup an ata channel : back to default values, unlinks tuning
361 */
362/*
363static void __exit qd_unsetup(ide_hwif_t *hwif)
364{
365 u8 config = hwif->config_data;
366 int base = hwif->select_data;
367 void *tuneproc = (void *) hwif->tuneproc;
368
369 if (hwif->chipset != ide_qd65xx)
370 return;
371
372 printk(KERN_NOTICE "%s: back to defaults\n", hwif->name);
373
374 hwif->selectproc = NULL;
375 hwif->tuneproc = NULL;
376
377 if (tuneproc == (void *) qd6500_tune_drive) {
378 // will do it for both
379 qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
380 } else if (tuneproc == (void *) qd6580_tune_drive) {
381 if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
382 qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
383 qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
384 } else {
385 qd_write_reg(hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
386 }
387 } else {
388 printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
389 printk(KERN_WARNING "keeping settings !\n");
390 }
391}
392*/
393
394/*
395 * qd_probe:
396 *
397 * looks at the specified baseport, and if qd found, registers & initialises it
398 * return 1 if another qd may be probed
399 */
400
401static int __init qd_probe(int base)
402{
403 ide_hwif_t *hwif;
404 u8 config;
405 u8 unit;
406
407 config = qd_read_reg(QD_CONFIG_PORT);
408
409 if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
410 return 1;
411
412 unit = ! (config & QD_CONFIG_IDE_BASEPORT);
413
414 if ((config & 0xf0) == QD_CONFIG_QD6500) {
415
416 if (qd_testreg(base)) return 1; /* bad register */
417
418 /* qd6500 found */
419
420 hwif = &ide_hwifs[unit];
421 printk(KERN_NOTICE "%s: qd6500 at %#x\n", hwif->name, base);
422 printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
423 config, QD_ID3);
424
425 if (config & QD_CONFIG_DISABLED) {
426 printk(KERN_WARNING "qd6500 is disabled !\n");
427 return 1;
428 }
429
430 qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA,
431 &qd6500_tune_drive);
432
433 create_proc_ide_interfaces();
434
435 return 1;
436 }
437
438 if (((config & 0xf0) == QD_CONFIG_QD6580_A) ||
439 ((config & 0xf0) == QD_CONFIG_QD6580_B)) {
440
441 u8 control;
442
443 if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
444 /* bad registers */
445
446 /* qd6580 found */
447
448 control = qd_read_reg(QD_CONTROL_PORT);
449
450 printk(KERN_NOTICE "qd6580 at %#x\n", base);
451 printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n",
452 config, control, QD_ID3);
453
454 if (control & QD_CONTR_SEC_DISABLED) {
455 /* secondary disabled */
456
457 hwif = &ide_hwifs[unit];
458 printk(KERN_INFO "%s: qd6580: single IDE board\n",
459 hwif->name);
460 qd_setup(hwif, base, config | (control << 8),
461 QD6580_DEF_DATA, QD6580_DEF_DATA2,
462 &qd6580_tune_drive);
463 qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
464
465 create_proc_ide_interfaces();
466
467 return 1;
468 } else {
469 ide_hwif_t *mate;
470
471 hwif = &ide_hwifs[0];
472 mate = &ide_hwifs[1];
473 /* secondary enabled */
474 printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
475 hwif->name, mate->name);
476
477 qd_setup(hwif, base, config | (control << 8),
478 QD6580_DEF_DATA, QD6580_DEF_DATA,
479 &qd6580_tune_drive);
480 qd_setup(mate, base, config | (control << 8),
481 QD6580_DEF_DATA2, QD6580_DEF_DATA2,
482 &qd6580_tune_drive);
483 qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
484
485 create_proc_ide_interfaces();
486
487 return 0; /* no other qd65xx possible */
488 }
489 }
490 /* no qd65xx found */
491 return 1;
492}
493
494/* Can be called directly from ide.c. */
495int __init qd65xx_init(void)
496{
497 if (qd_probe(0x30))
498 qd_probe(0xb0);
499 if (ide_hwifs[0].chipset != ide_qd65xx &&
500 ide_hwifs[1].chipset != ide_qd65xx)
501 return -ENODEV;
502 return 0;
503}
504
505#ifdef MODULE
506module_init(qd65xx_init);
507#endif
508
509MODULE_AUTHOR("Samuel Thibault");
510MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
511MODULE_LICENSE("GPL");
diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
new file mode 100644
index 000000000000..633a42456ef6
--- /dev/null
+++ b/drivers/ide/legacy/qd65xx.h
@@ -0,0 +1,140 @@
1/*
2 * linux/drivers/ide/legacy/qd65xx.h
3 *
4 * Copyright (c) 2000 Linus Torvalds & authors
5 */
6
7/*
8 * Authors: Petr Soucek <petr@ryston.cz>
9 * Samuel Thibault <samuel.thibault@fnac.net>
10 */
11
12/* truncates a in [b,c] */
13#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) )
14
15#define IDE_IMPLY(a,b) ((!(a)) || (b))
16
17#define QD_TIM1_PORT (base)
18#define QD_CONFIG_PORT (base+0x01)
19#define QD_TIM2_PORT (base+0x02)
20#define QD_CONTROL_PORT (base+0x03)
21
22#define QD_CONFIG_IDE_BASEPORT 0x01
23#define QD_CONFIG_BASEPORT 0x02
24#define QD_CONFIG_ID3 0x04
25#define QD_CONFIG_DISABLED 0x08
26#define QD_CONFIG_QD6500 0xc0
27#define QD_CONFIG_QD6580_A 0xa0
28#define QD_CONFIG_QD6580_B 0x50
29
30#define QD_CONTR_SEC_DISABLED 0x01
31
32#define QD_ID3 ((config & QD_CONFIG_ID3)!=0)
33
34#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff)
35#define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8)
36
37#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff)
38#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8)
39
40#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08))
41#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
42#define QD6580_DEF_DATA2 ((QD_TIM2_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
43#define QD_DEF_CONTR (0x40 | ((control & 0x02) ? 0x9f : 0x1f))
44
45#define QD_TESTVAL 0x19 /* safe value */
46
47/* Drive specific timing taken from DOS driver v3.7 */
48
49static struct qd65xx_timing_s {
50 s8 offset; /* ofset from the beginning of Model Number" */
51 char model[4]; /* 4 chars from Model number, no conversion */
52 s16 active; /* active time */
53 s16 recovery; /* recovery time */
54} qd65xx_timing [] = {
55 { 30, "2040", 110, 225 }, /* Conner CP30204 */
56 { 30, "2045", 135, 225 }, /* Conner CP30254 */
57 { 30, "1040", 155, 325 }, /* Conner CP30104 */
58 { 30, "1047", 135, 265 }, /* Conner CP30174 */
59 { 30, "5344", 135, 225 }, /* Conner CP3544 */
60 { 30, "01 4", 175, 405 }, /* Conner CP-3104 */
61 { 27, "C030", 175, 375 }, /* Conner CP3000 */
62 { 8, "PL42", 110, 295 }, /* Quantum LP240 */
63 { 8, "PL21", 110, 315 }, /* Quantum LP120 */
64 { 8, "PL25", 175, 385 }, /* Quantum LP52 */
65 { 4, "PA24", 110, 285 }, /* WD Piranha SP4200 */
66 { 6, "2200", 110, 260 }, /* WD Caviar AC2200 */
67 { 6, "3204", 110, 235 }, /* WD Caviar AC2340 */
68 { 6, "1202", 110, 265 }, /* WD Caviar AC2120 */
69 { 0, "DS3-", 135, 315 }, /* Teac SD340 */
70 { 8, "KM32", 175, 355 }, /* Toshiba MK234 */
71 { 2, "53A1", 175, 355 }, /* Seagate ST351A */
72 { 2, "4108", 175, 295 }, /* Seagate ST1480A */
73 { 2, "1344", 175, 335 }, /* Seagate ST3144A */
74 { 6, "7 12", 110, 225 }, /* Maxtor 7213A */
75 { 30, "02F4", 145, 295 }, /* Conner 3204F */
76 { 2, "1302", 175, 335 }, /* Seagate ST3120A */
77 { 2, "2334", 145, 265 }, /* Seagate ST3243A */
78 { 2, "2338", 145, 275 }, /* Seagate ST3283A */
79 { 2, "3309", 145, 275 }, /* Seagate ST3390A */
80 { 2, "5305", 145, 275 }, /* Seagate ST3550A */
81 { 2, "4100", 175, 295 }, /* Seagate ST1400A */
82 { 2, "4110", 175, 295 }, /* Seagate ST1401A */
83 { 2, "6300", 135, 265 }, /* Seagate ST3600A */
84 { 2, "5300", 135, 265 }, /* Seagate ST3500A */
85 { 6, "7 31", 135, 225 }, /* Maxtor 7131 AT */
86 { 6, "7 43", 115, 265 }, /* Maxtor 7345 AT */
87 { 6, "7 42", 110, 255 }, /* Maxtor 7245 AT */
88 { 6, "3 04", 135, 265 }, /* Maxtor 340 AT */
89 { 6, "61 0", 135, 285 }, /* WD AC160 */
90 { 6, "1107", 135, 235 }, /* WD AC1170 */
91 { 6, "2101", 110, 220 }, /* WD AC1210 */
92 { 6, "4202", 135, 245 }, /* WD AC2420 */
93 { 6, "41 0", 175, 355 }, /* WD Caviar 140 */
94 { 6, "82 0", 175, 355 }, /* WD Caviar 280 */
95 { 8, "PL01", 175, 375 }, /* Quantum LP105 */
96 { 8, "PL25", 110, 295 }, /* Quantum LP525 */
97 { 10, "4S 2", 175, 385 }, /* Quantum ELS42 */
98 { 10, "8S 5", 175, 385 }, /* Quantum ELS85 */
99 { 10, "1S72", 175, 385 }, /* Quantum ELS127 */
100 { 10, "1S07", 175, 385 }, /* Quantum ELS170 */
101 { 8, "ZE42", 135, 295 }, /* Quantum EZ240 */
102 { 8, "ZE21", 175, 385 }, /* Quantum EZ127 */
103 { 8, "ZE58", 175, 385 }, /* Quantum EZ85 */
104 { 8, "ZE24", 175, 385 }, /* Quantum EZ42 */
105 { 27, "C036", 155, 325 }, /* Conner CP30064 */
106 { 27, "C038", 155, 325 }, /* Conner CP30084 */
107 { 6, "2205", 110, 255 }, /* WDC AC2250 */
108 { 2, " CHA", 140, 415 }, /* WDC AH series; WDC AH260, WDC */
109 { 2, " CLA", 140, 415 }, /* WDC AL series: WDC AL2120, 2170, */
110 { 4, "UC41", 140, 415 }, /* WDC CU140 */
111 { 6, "1207", 130, 275 }, /* WDC AC2170 */
112 { 6, "2107", 130, 275 }, /* WDC AC1270 */
113 { 6, "5204", 130, 275 }, /* WDC AC2540 */
114 { 30, "3004", 110, 235 }, /* Conner CP30340 */
115 { 30, "0345", 135, 255 }, /* Conner CP30544 */
116 { 12, "12A3", 175, 320 }, /* MAXTOR LXT-213A */
117 { 12, "43A0", 145, 240 }, /* MAXTOR LXT-340A */
118 { 6, "7 21", 180, 290 }, /* Maxtor 7120 AT */
119 { 6, "7 71", 135, 240 }, /* Maxtor 7170 AT */
120 { 12, "45\0000", 110, 205 }, /* MAXTOR MXT-540 */
121 { 8, "PL11", 180, 290 }, /* QUANTUM LP110A */
122 { 8, "OG21", 150, 275 }, /* QUANTUM GO120 */
123 { 12, "42A5", 175, 320 }, /* MAXTOR LXT-245A */
124 { 2, "2309", 175, 295 }, /* ST3290A */
125 { 2, "3358", 180, 310 }, /* ST3385A */
126 { 2, "6355", 180, 310 }, /* ST3655A */
127 { 2, "1900", 175, 270 }, /* ST9100A */
128 { 2, "1954", 175, 270 }, /* ST9145A */
129 { 2, "1909", 175, 270 }, /* ST9190AG */
130 { 2, "2953", 175, 270 }, /* ST9235A */
131 { 2, "1359", 175, 270 }, /* ST3195A */
132 { 24, "3R11", 175, 290 }, /* ALPS ELECTRIC Co.,LTD, DR311C */
133 { 0, "2M26", 175, 215 }, /* M262XT-0Ah */
134 { 4, "2253", 175, 300 }, /* HP C2235A */
135 { 4, "-32A", 145, 245 }, /* H3133-A2 */
136 { 30, "0326", 150, 270 }, /* Samsung Electronics 120MB */
137 { 30, "3044", 110, 195 }, /* Conner CFA340A */
138 { 30, "43A0", 110, 195 }, /* Conner CFA340A */
139 { -1, " ", 175, 415 } /* unknown disk name */
140};
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
new file mode 100644
index 000000000000..cdbdb2ff9f15
--- /dev/null
+++ b/drivers/ide/legacy/umc8672.c
@@ -0,0 +1,183 @@
1/*
2 * linux/drivers/ide/legacy/umc8672.c Version 0.05 Jul 31, 1996
3 *
4 * Copyright (C) 1995-1996 Linus Torvalds & author (see below)
5 */
6
7/*
8 * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien)
9 *
10 * This file provides support for the advanced features
11 * of the UMC 8672 IDE interface.
12 *
13 * Version 0.01 Initial version, hacked out of ide.c,
14 * and #include'd rather than compiled separately.
15 * This will get cleaned up in a subsequent release.
16 *
17 * Version 0.02 now configs/compiles separate from ide.c -ml
18 * Version 0.03 enhanced auto-tune, fix display bug
19 * Version 0.05 replace sti() with restore_flags() -ml
20 * add detection of possible race condition -ml
21 */
22
23/*
24 * VLB Controller Support from
25 * Wolfram Podien
26 * Rohoefe 3
27 * D28832 Achim
28 * Germany
29 *
30 * To enable UMC8672 support there must a lilo line like
31 * append="ide0=umc8672"...
32 * To set the speed according to the abilities of the hardware there must be a
33 * line like
34 * #define UMC_DRIVE0 11
35 * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
36 * are some lines present). 0 - 11 are allowed speed values. These values are
37 * the results from the DOS speed test program supplied from UMC. 11 is the
38 * highest speed (about PIO mode 3)
39 */
40#define REALLY_SLOW_IO /* some systems can safely undef this */
41
42#include <linux/module.h>
43#include <linux/config.h>
44#include <linux/types.h>
45#include <linux/kernel.h>
46#include <linux/delay.h>
47#include <linux/timer.h>
48#include <linux/mm.h>
49#include <linux/ioport.h>
50#include <linux/blkdev.h>
51#include <linux/hdreg.h>
52#include <linux/ide.h>
53#include <linux/init.h>
54
55#include <asm/io.h>
56
57/*
58 * Default speeds. These can be changed with "auto-tune" and/or hdparm.
59 */
60#define UMC_DRIVE0 1 /* DOS measured drive speeds */
61#define UMC_DRIVE1 1 /* 0 to 11 allowed */
62#define UMC_DRIVE2 1 /* 11 = Fastest Speed */
63#define UMC_DRIVE3 1 /* In case of crash reduce speed */
64
65static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
66static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */
67
68/* 0 1 2 3 4 5 6 7 8 9 10 11 */
69static const u8 speedtab [3][12] = {
70 {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
71 {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
72 {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
73
74static void out_umc (char port,char wert)
75{
76 outb_p(port,0x108);
77 outb_p(wert,0x109);
78}
79
80static inline u8 in_umc (char port)
81{
82 outb_p(port,0x108);
83 return inb_p(0x109);
84}
85
86static void umc_set_speeds (u8 speeds[])
87{
88 int i, tmp;
89
90 outb_p(0x5A,0x108); /* enable umc */
91
92 out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4)));
93 out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4)));
94 tmp = 0;
95 for (i = 3; i >= 0; i--) {
96 tmp = (tmp << 2) | speedtab[1][speeds[i]];
97 }
98 out_umc (0xdc,tmp);
99 for (i = 0;i < 4; i++) {
100 out_umc (0xd0+i,speedtab[2][speeds[i]]);
101 out_umc (0xd8+i,speedtab[2][speeds[i]]);
102 }
103 outb_p(0xa5,0x108); /* disable umc */
104
105 printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n",
106 speeds[0], speeds[1], speeds[2], speeds[3]);
107}
108
109static void tune_umc (ide_drive_t *drive, u8 pio)
110{
111 unsigned long flags;
112 ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
113
114 pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
115 printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
116 drive->name, pio, pio_to_umc[pio]);
117 spin_lock_irqsave(&ide_lock, flags);
118 if (hwgroup && hwgroup->handler != NULL) {
119 printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
120 } else {
121 current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
122 umc_set_speeds (current_speeds);
123 }
124 spin_unlock_irqrestore(&ide_lock, flags);
125}
126
127static int __init umc8672_probe(void)
128{
129 unsigned long flags;
130 ide_hwif_t *hwif, *mate;
131
132 if (!request_region(0x108, 2, "umc8672")) {
133 printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
134 return 1;
135 }
136 local_irq_save(flags);
137 outb_p(0x5A,0x108); /* enable umc */
138 if (in_umc (0xd5) != 0xa0) {
139 local_irq_restore(flags);
140 printk(KERN_ERR "umc8672: not found\n");
141 release_region(0x108, 2);
142 return 1;
143 }
144 outb_p(0xa5,0x108); /* disable umc */
145
146 umc_set_speeds (current_speeds);
147 local_irq_restore(flags);
148
149 hwif = &ide_hwifs[0];
150 mate = &ide_hwifs[1];
151
152 hwif->chipset = ide_umc8672;
153 hwif->tuneproc = &tune_umc;
154 hwif->mate = mate;
155
156 mate->chipset = ide_umc8672;
157 mate->tuneproc = &tune_umc;
158 mate->mate = hwif;
159 mate->channel = 1;
160
161 probe_hwif_init(hwif);
162 probe_hwif_init(mate);
163
164 create_proc_ide_interfaces();
165
166 return 0;
167}
168
169/* Can be called directly from ide.c. */
170int __init umc8672_init(void)
171{
172 if (umc8672_probe())
173 return -ENODEV;
174 return 0;
175}
176
177#ifdef MODULE
178module_init(umc8672_init);
179#endif
180
181MODULE_AUTHOR("Wolfram Podien");
182MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
183MODULE_LICENSE("GPL");