This source file includes following definitions.
- inReg
- outReg
- ali14xx_tune_drive
- findPort
- initRegisters
- init_ali14xx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #undef REALLY_SLOW_IO
29
30 #include <linux/types.h>
31 #include <linux/kernel.h>
32 #include <linux/delay.h>
33 #include <linux/timer.h>
34 #include <linux/mm.h>
35 #include <linux/ioport.h>
36 #include <linux/blkdev.h>
37 #include <linux/hdreg.h>
38 #include <asm/io.h>
39 #include "ide.h"
40
41 #define ALI_14xx_BUS_SPEED 40
42
43
44 #define ALI_NUM_PORTS 4
45 static int ports[ALI_NUM_PORTS] = {0x074, 0x0f4, 0x034, 0x0e4};
46
47
48 typedef struct { byte reg, data; } RegInitializer;
49
50 static RegInitializer initData[] = {
51 {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
52 {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
53 {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
54 {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
55 {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
56 {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
57 {0x35, 0x03}, {0x00, 0x00}
58 };
59
60
61 static struct { int time1, time2; } timeTab[4] = {
62 {600, 165},
63 {383, 125},
64 {240, 100},
65 {180, 80}
66 };
67
68
69 static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
70 {0x03, 0x26, 0x04, 0x27},
71 {0x05, 0x28, 0x06, 0x29},
72 {0x2b, 0x30, 0x2c, 0x31},
73 {0x2d, 0x32, 0x2e, 0x33},
74 };
75
76 static int basePort = 0;
77 static int regPort = 0;
78 static int dataPort = 0;
79 static byte regOn;
80 static byte regOff;
81
82
83
84
85
86
87 static inline byte inReg (byte reg)
88 {
89 outb_p(reg, regPort);
90 return inb(dataPort);
91 }
92
93
94
95
96 static void outReg (byte data, byte reg)
97 {
98 outb_p(reg, regPort);
99 outb_p(data, dataPort);
100 }
101
102
103
104
105
106
107 static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
108 {
109 int driveNum;
110 int time1, time2, time1a;
111 byte param1, param2, param3, param4;
112 struct hd_driveid *id = drive->id;
113 unsigned long flags;
114
115 if (pio == 255) {
116 pio = id->tPIO;
117 if ((id->field_valid & 0x02) && (id->eide_pio_modes & 0x01))
118 pio = 3;
119 }
120
121 time1 = timeTab[pio].time1;
122 time2 = timeTab[pio].time2;
123 if (pio == 3) {
124 time1a = (id->capability & 0x08) ? id->eide_pio_iordy : id->eide_pio;
125 if (time1a != 0 && time1a < time1)
126 time1 = time1a;
127 }
128 param3 = param1 = (time2 * ALI_14xx_BUS_SPEED + 999) / 1000;
129 param4 = param2 = (time1 * ALI_14xx_BUS_SPEED + 999) / 1000 - param1;
130 if (pio != 3) {
131 param3 += 8;
132 param4 += 8;
133 }
134 printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
135 drive->name, pio, time1, time2, param1, param2, param3, param4);
136
137
138 driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
139 save_flags(flags);
140 cli();
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 restore_flags(flags);
148 }
149
150
151
152
153 static int findPort (void)
154 {
155 int i;
156 byte t;
157 unsigned long flags;
158
159 save_flags(flags);
160 cli();
161 for (i = 0; i < ALI_NUM_PORTS; ++i) {
162 basePort = ports[i];
163 regOff = inb(basePort);
164 for (regOn = 0x30; regOn <= 0x33; ++regOn) {
165 outb_p(regOn, basePort);
166 if (inb(basePort) == regOn) {
167 regPort = basePort + 4;
168 dataPort = basePort + 8;
169 t = inReg(0) & 0xf0;
170 outb_p(regOff, basePort);
171 restore_flags(flags);
172 if (t != 0x50)
173 return 0;
174 return 1;
175 }
176 }
177 outb_p(regOff, basePort);
178 }
179 restore_flags(flags);
180 return 0;
181 }
182
183
184
185
186 static int initRegisters (void) {
187 RegInitializer *p;
188 byte t;
189 unsigned long flags;
190
191 save_flags(flags);
192 cli();
193 outb_p(regOn, basePort);
194 for (p = initData; p->reg != 0; ++p)
195 outReg(p->data, p->reg);
196 outb_p(0x01, regPort);
197 t = inb(regPort) & 0x01;
198 outb_p(regOff, basePort);
199 restore_flags(flags);
200 return t;
201 }
202
203 void init_ali14xx (void)
204 {
205
206 if (!findPort()) {
207 printk("ali14xx: not found\n");
208 return;
209 }
210
211 printk("ali14xx: base= 0x%03x, regOn = 0x%02x\n", basePort, regOn);
212 ide_hwifs[0].chipset = ide_ali14xx;
213 ide_hwifs[1].chipset = ide_ali14xx;
214 ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
215 ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
216
217
218 if (!initRegisters()) {
219 printk("ali14xx: Chip initialization failed\n");
220 return;
221 }
222 }