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
29
30
31
32
33
34
35
36
37
38
39#include <linux/module.h>
40#include <linux/types.h>
41#include <linux/kernel.h>
42#include <linux/delay.h>
43#include <linux/timer.h>
44#include <linux/mm.h>
45#include <linux/ioport.h>
46#include <linux/blkdev.h>
47#include <linux/ide.h>
48#include <linux/init.h>
49
50#include <asm/io.h>
51
52#define DRV_NAME "ali14xx"
53
54
55#define ALI_NUM_PORTS 4
56static const int ports[ALI_NUM_PORTS] __initconst =
57 { 0x074, 0x0f4, 0x034, 0x0e4 };
58
59
60typedef struct { u8 reg, data; } RegInitializer;
61
62static const RegInitializer initData[] __initconst = {
63 {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
64 {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
65 {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
66 {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
67 {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
68 {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
69 {0x35, 0x03}, {0x00, 0x00}
70};
71
72
73static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
74 {0x03, 0x26, 0x04, 0x27},
75 {0x05, 0x28, 0x06, 0x29},
76 {0x2b, 0x30, 0x2c, 0x31},
77 {0x2d, 0x32, 0x2e, 0x33},
78};
79
80static int basePort;
81static int regPort;
82static int dataPort;
83static u8 regOn;
84static u8 regOff;
85
86
87
88
89
90
91static inline u8 inReg(u8 reg)
92{
93 outb_p(reg, regPort);
94 return inb(dataPort);
95}
96
97
98
99
100static void outReg(u8 data, u8 reg)
101{
102 outb_p(reg, regPort);
103 outb_p(data, dataPort);
104}
105
106static DEFINE_SPINLOCK(ali14xx_lock);
107
108
109
110
111
112
113static void ali14xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
114{
115 int driveNum;
116 int time1, time2;
117 u8 param1, param2, param3, param4;
118 unsigned long flags;
119 int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
120 const u8 pio = drive->pio_mode - XFER_PIO_0;
121 struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
122
123
124 time1 = ide_pio_cycle_time(drive, pio);
125 time2 = t->active;
126 param3 = param1 = (time2 * bus_speed + 999) / 1000;
127 param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
128 if (pio < 3) {
129 param3 += 8;
130 param4 += 8;
131 }
132 printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
133 drive->name, pio, time1, time2, param1, param2, param3, param4);
134
135
136 driveNum = (drive->hwif->index << 1) + (drive->dn & 1);
137 spin_lock_irqsave(&ali14xx_lock, flags);
138 outb_p(regOn, basePort);
139 outReg(param1, regTab[driveNum].reg1);
140 outReg(param2, regTab[driveNum].reg2);
141 outReg(param3, regTab[driveNum].reg3);
142 outReg(param4, regTab[driveNum].reg4);
143 outb_p(regOff, basePort);
144 spin_unlock_irqrestore(&ali14xx_lock, flags);
145}
146
147
148
149
150static int __init findPort(void)
151{
152 int i;
153 u8 t;
154 unsigned long flags;
155
156 local_irq_save(flags);
157 for (i = 0; i < ALI_NUM_PORTS; ++i) {
158 basePort = ports[i];
159 regOff = inb(basePort);
160 for (regOn = 0x30; regOn <= 0x33; ++regOn) {
161 outb_p(regOn, basePort);
162 if (inb(basePort) == regOn) {
163 regPort = basePort + 4;
164 dataPort = basePort + 8;
165 t = inReg(0) & 0xf0;
166 outb_p(regOff, basePort);
167 local_irq_restore(flags);
168 if (t != 0x50)
169 return 0;
170 return 1;
171 }
172 }
173 outb_p(regOff, basePort);
174 }
175 local_irq_restore(flags);
176 return 0;
177}
178
179
180
181
182static int __init initRegisters(void)
183{
184 const RegInitializer *p;
185 u8 t;
186 unsigned long flags;
187
188 local_irq_save(flags);
189 outb_p(regOn, basePort);
190 for (p = initData; p->reg != 0; ++p)
191 outReg(p->data, p->reg);
192 outb_p(0x01, regPort);
193 t = inb(regPort) & 0x01;
194 outb_p(regOff, basePort);
195 local_irq_restore(flags);
196 return t;
197}
198
199static const struct ide_port_ops ali14xx_port_ops = {
200 .set_pio_mode = ali14xx_set_pio_mode,
201};
202
203static const struct ide_port_info ali14xx_port_info = {
204 .name = DRV_NAME,
205 .chipset = ide_ali14xx,
206 .port_ops = &ali14xx_port_ops,
207 .host_flags = IDE_HFLAG_NO_DMA,
208 .pio_mask = ATA_PIO4,
209};
210
211static int __init ali14xx_probe(void)
212{
213 printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
214 basePort, regOn);
215
216
217 if (!initRegisters()) {
218 printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
219 return 1;
220 }
221
222 return ide_legacy_device_add(&ali14xx_port_info, 0);
223}
224
225static bool probe_ali14xx;
226
227module_param_named(probe, probe_ali14xx, bool, 0);
228MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
229
230static int __init ali14xx_init(void)
231{
232 if (probe_ali14xx == 0)
233 goto out;
234
235
236 if (findPort()) {
237 if (ali14xx_probe())
238 return -ENODEV;
239 return 0;
240 }
241 printk(KERN_ERR "ali14xx: not found.\n");
242out:
243 return -ENODEV;
244}
245
246module_init(ali14xx_init);
247
248MODULE_AUTHOR("see local file");
249MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
250MODULE_LICENSE("GPL");
251