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