File: /usr/src/linux/drivers/ide/ali14xx.c

1     /*
2      *  linux/drivers/ide/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/types.h>
43     #include <linux/kernel.h>
44     #include <linux/delay.h>
45     #include <linux/timer.h>
46     #include <linux/mm.h>
47     #include <linux/ioport.h>
48     #include <linux/blkdev.h>
49     #include <linux/hdreg.h>
50     #include <linux/ide.h>
51     #include <linux/init.h>
52     
53     #include <asm/io.h>
54     
55     #include "ide_modes.h"
56     
57     /* port addresses for auto-detection */
58     #define ALI_NUM_PORTS 4
59     static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
60     
61     /* register initialization data */
62     typedef struct { byte reg, data; } RegInitializer;
63     
64     static 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 */
77     static struct { byte 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     
84     static int basePort;	/* base port address */
85     static int regPort;	/* port for register number */
86     static int dataPort;	/* port for register data */
87     static byte regOn;	/* output to base port to access registers */
88     static byte regOff;	/* output to base port to close registers */
89     
90     /*------------------------------------------------------------------------*/
91     
92     /*
93      * Read a controller register.
94      */
95     static inline byte inReg (byte reg)
96     {
97     	outb_p(reg, regPort);
98     	return inb(dataPort);
99     }
100     
101     /*
102      * Write a controller register.
103      */
104     static void outReg (byte data, byte 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      */
115     static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
116     {
117     	int driveNum;
118     	int time1, time2;
119     	byte 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("%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     	save_flags(flags);	/* all CPUs */
141     	cli();			/* all CPUs */
142     	outb_p(regOn, basePort);
143     	outReg(param1, regTab[driveNum].reg1);
144     	outReg(param2, regTab[driveNum].reg2);
145     	outReg(param3, regTab[driveNum].reg3);
146     	outReg(param4, regTab[driveNum].reg4);
147     	outb_p(regOff, basePort);
148     	restore_flags(flags);	/* all CPUs */
149     }
150     
151     /*
152      * Auto-detect the IDE controller port.
153      */
154     static int __init findPort (void)
155     {
156     	int i;
157     	byte t;
158     	unsigned long flags;
159     
160     	__save_flags(flags);	/* local CPU only */
161     	__cli();		/* local CPU only */
162     	for (i = 0; i < ALI_NUM_PORTS; ++i) {
163     		basePort = ports[i];
164     		regOff = inb(basePort);
165     		for (regOn = 0x30; regOn <= 0x33; ++regOn) {
166     			outb_p(regOn, basePort);
167     			if (inb(basePort) == regOn) {
168     				regPort = basePort + 4;
169     				dataPort = basePort + 8;
170     				t = inReg(0) & 0xf0;
171     				outb_p(regOff, basePort);
172     				__restore_flags(flags);	/* local CPU only */
173     				if (t != 0x50)
174     					return 0;
175     				return 1;  /* success */
176     			}
177     		}
178     		outb_p(regOff, basePort);
179     	}
180     	__restore_flags(flags);	/* local CPU only */
181     	return 0;
182     }
183     
184     /*
185      * Initialize controller registers with default values.
186      */
187     static int __init initRegisters (void) {
188     	RegInitializer *p;
189     	byte t;
190     	unsigned long flags;
191     
192     	__save_flags(flags);	/* local CPU only */
193     	__cli();		/* local CPU only */
194     	outb_p(regOn, basePort);
195     	for (p = initData; p->reg != 0; ++p)
196     		outReg(p->data, p->reg);
197     	outb_p(0x01, regPort);
198     	t = inb(regPort) & 0x01;
199     	outb_p(regOff, basePort);
200     	__restore_flags(flags);	/* local CPU only */
201     	return t;
202     }
203     
204     void __init init_ali14xx (void)
205     {
206     	/* auto-detect IDE controller port */
207     	if (!findPort()) {
208     		printk("\nali14xx: not found");
209     		return;
210     	}
211     
212     	printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn);
213     	ide_hwifs[0].chipset = ide_ali14xx;
214     	ide_hwifs[1].chipset = ide_ali14xx;
215     	ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
216     	ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
217     	ide_hwifs[0].mate = &ide_hwifs[1];
218     	ide_hwifs[1].mate = &ide_hwifs[0];
219     	ide_hwifs[1].channel = 1;
220     
221     	/* initialize controller registers */
222     	if (!initRegisters()) {
223     		printk("\nali14xx: Chip initialization failed");
224     		return;
225     	}
226     }
227