1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#define DRV_NAME "ht6560b"
17#define HT6560B_VERSION "v0.08"
18
19#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/delay.h>
23#include <linux/timer.h>
24#include <linux/mm.h>
25#include <linux/ioport.h>
26#include <linux/blkdev.h>
27#include <linux/ide.h>
28#include <linux/init.h>
29
30#include <asm/io.h>
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#define HT_CONFIG_PORT 0x3e6
47
48static inline u8 HT_CONFIG(ide_drive_t *drive)
49{
50 return ((unsigned long)ide_get_drivedata(drive) & 0xff00) >> 8;
51}
52
53
54
55
56#define HT_CONFIG_DEFAULT 0x1c
57
58#define HT_SECONDARY_IF 0x01
59#define HT_PREFETCH_MODE 0x20
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98static inline u8 HT_TIMING(ide_drive_t *drive)
99{
100 return (unsigned long)ide_get_drivedata(drive) & 0x00ff;
101}
102
103#define HT_TIMING_DEFAULT 0xff
104
105
106
107
108
109
110
111
112
113
114
115static void ht6560b_dev_select(ide_drive_t *drive)
116{
117 ide_hwif_t *hwif = drive->hwif;
118 unsigned long flags;
119 static u8 current_select = 0;
120 static u8 current_timing = 0;
121 u8 select, timing;
122
123 local_irq_save(flags);
124
125 select = HT_CONFIG(drive);
126 timing = HT_TIMING(drive);
127
128
129
130
131
132 if (drive->media != ide_disk ||
133 (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
134 select |= HT_PREFETCH_MODE;
135
136 if (select != current_select || timing != current_timing) {
137 current_select = select;
138 current_timing = timing;
139 (void)inb(HT_CONFIG_PORT);
140 (void)inb(HT_CONFIG_PORT);
141 (void)inb(HT_CONFIG_PORT);
142 (void)inb(HT_CONFIG_PORT);
143 outb(select, HT_CONFIG_PORT);
144
145
146
147 outb(timing, hwif->io_ports.device_addr);
148 (void)inb(hwif->io_ports.status_addr);
149#ifdef DEBUG
150 printk("ht6560b: %s: select=%#x timing=%#x\n",
151 drive->name, select, timing);
152#endif
153 }
154 local_irq_restore(flags);
155
156 outb(drive->select | ATA_DEVICE_OBS, hwif->io_ports.device_addr);
157}
158
159
160
161
162static int __init try_to_init_ht6560b(void)
163{
164 u8 orig_value;
165 int i;
166
167
168 if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
169 return 0;
170
171 for (i=3;i>0;i--) {
172 outb(0x00, HT_CONFIG_PORT);
173 if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
174 outb(orig_value, HT_CONFIG_PORT);
175 return 0;
176 }
177 }
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
185
186 outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
187 outb(HT_TIMING_DEFAULT, 0x1f6);
188 (void)inb(0x1f7);
189
190 printk("ht6560b " HT6560B_VERSION
191 ": chipset detected and initialized"
192#ifdef DEBUG
193 " with debug enabled"
194#endif
195 "\n"
196 );
197 return 1;
198}
199
200static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
201{
202 int active_time, recovery_time;
203 int active_cycles, recovery_cycles;
204 int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
205
206 if (pio) {
207 unsigned int cycle_time;
208 struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
209
210 cycle_time = ide_pio_cycle_time(drive, pio);
211
212
213
214
215
216
217 active_time = t->active;
218 recovery_time = cycle_time - active_time - t->setup;
219
220
221
222 active_cycles = (active_time * bus_speed + 999) / 1000;
223 recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
224
225
226
227 if (active_cycles < 2) active_cycles = 2;
228 if (recovery_cycles < 2) recovery_cycles = 2;
229 if (active_cycles > 15) active_cycles = 15;
230 if (recovery_cycles > 15) recovery_cycles = 0;
231
232#ifdef DEBUG
233 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);
234#endif
235
236 return (u8)((recovery_cycles << 4) | active_cycles);
237 } else {
238
239#ifdef DEBUG
240 printk("ht6560b: drive %s setting pio=0\n", drive->name);
241#endif
242
243 return HT_TIMING_DEFAULT;
244 }
245}
246
247static DEFINE_SPINLOCK(ht6560b_lock);
248
249
250
251
252static void ht_set_prefetch(ide_drive_t *drive, u8 state)
253{
254 unsigned long flags, config;
255 int t = HT_PREFETCH_MODE << 8;
256
257 spin_lock_irqsave(&ht6560b_lock, flags);
258
259 config = (unsigned long)ide_get_drivedata(drive);
260
261
262
263
264 if (state) {
265 config |= t;
266 drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
267 drive->dev_flags &= ~IDE_DFLAG_UNMASK;
268 } else {
269 config &= ~t;
270 drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
271 }
272
273 ide_set_drivedata(drive, (void *)config);
274
275 spin_unlock_irqrestore(&ht6560b_lock, flags);
276
277#ifdef DEBUG
278 printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
279#endif
280}
281
282static void ht6560b_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
283{
284 unsigned long flags, config;
285 const u8 pio = drive->pio_mode - XFER_PIO_0;
286 u8 timing;
287
288 switch (pio) {
289 case 8:
290 case 9:
291 ht_set_prefetch(drive, pio & 1);
292 return;
293 }
294
295 timing = ht_pio2timings(drive, pio);
296
297 spin_lock_irqsave(&ht6560b_lock, flags);
298 config = (unsigned long)ide_get_drivedata(drive);
299 config &= 0xff00;
300 config |= timing;
301 ide_set_drivedata(drive, (void *)config);
302 spin_unlock_irqrestore(&ht6560b_lock, flags);
303
304#ifdef DEBUG
305 printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
306#endif
307}
308
309static void __init ht6560b_init_dev(ide_drive_t *drive)
310{
311 ide_hwif_t *hwif = drive->hwif;
312
313 int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
314
315 if (hwif->channel)
316 t |= (HT_SECONDARY_IF << 8);
317
318 ide_set_drivedata(drive, (void *)t);
319}
320
321static bool probe_ht6560b;
322
323module_param_named(probe, probe_ht6560b, bool, 0);
324MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
325
326static const struct ide_tp_ops ht6560b_tp_ops = {
327 .exec_command = ide_exec_command,
328 .read_status = ide_read_status,
329 .read_altstatus = ide_read_altstatus,
330 .write_devctl = ide_write_devctl,
331
332 .dev_select = ht6560b_dev_select,
333 .tf_load = ide_tf_load,
334 .tf_read = ide_tf_read,
335
336 .input_data = ide_input_data,
337 .output_data = ide_output_data,
338};
339
340static const struct ide_port_ops ht6560b_port_ops = {
341 .init_dev = ht6560b_init_dev,
342 .set_pio_mode = ht6560b_set_pio_mode,
343};
344
345static const struct ide_port_info ht6560b_port_info __initconst = {
346 .name = DRV_NAME,
347 .chipset = ide_ht6560b,
348 .tp_ops = &ht6560b_tp_ops,
349 .port_ops = &ht6560b_port_ops,
350 .host_flags = IDE_HFLAG_SERIALIZE |
351 IDE_HFLAG_NO_DMA |
352 IDE_HFLAG_ABUSE_PREFETCH,
353 .pio_mask = ATA_PIO4,
354};
355
356static int __init ht6560b_init(void)
357{
358 if (probe_ht6560b == 0)
359 return -ENODEV;
360
361 if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
362 printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
363 __func__);
364 return -ENODEV;
365 }
366
367 if (!try_to_init_ht6560b()) {
368 printk(KERN_NOTICE "%s: HBA not found\n", __func__);
369 goto release_region;
370 }
371
372 return ide_legacy_device_add(&ht6560b_port_info, 0);
373
374release_region:
375 release_region(HT_CONFIG_PORT, 1);
376 return -ENODEV;
377}
378
379module_init(ht6560b_init);
380
381MODULE_AUTHOR("See Local File");
382MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
383MODULE_LICENSE("GPL");
384