OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ide/] [legacy/] [ht6560b.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/ide/legacy/ht6560b.c          Version 0.07    Feb  1, 2000
3
 *
4
 *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
5
 */
6
 
7
/*
8
 *
9
 *  Version 0.01        Initial version hacked out of ide.c
10
 *
11
 *  Version 0.02        Added support for PIO modes, auto-tune
12
 *
13
 *  Version 0.03        Some cleanups
14
 *
15
 *  Version 0.05        PIO mode cycle timings auto-tune using bus-speed
16
 *
17
 *  Version 0.06        Prefetch mode now defaults no OFF. To set
18
 *                      prefetch mode OFF/ON use "hdparm -p8/-p9".
19
 *                      Unmask irq is disabled when prefetch mode
20
 *                      is enabled.
21
 *
22
 *  Version 0.07        Trying to fix CD-ROM detection problem.
23
 *                      "Prefetch" mode bit OFF for ide disks and
24
 *                      ON for anything else.
25
 *
26
 *
27
 *  HT-6560B EIDE-controller support
28
 *  To activate controller support use kernel parameter "ide0=ht6560b".
29
 *  Use hdparm utility to enable PIO mode support.
30
 *
31
 *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
32
 *             Jan Evert van Grootheest   <janevert@iae.nl>
33
 *
34
 *  Try:  http://www.maf.iki.fi/~maf/ht6560b/
35
 */
36
 
37
#define HT6560B_VERSION "v0.07"
38
 
39
#undef REALLY_SLOW_IO           /* most systems can safely undef this */
40
 
41
#include <linux/module.h>
42
#include <linux/config.h>
43
#include <linux/types.h>
44
#include <linux/kernel.h>
45
#include <linux/delay.h>
46
#include <linux/timer.h>
47
#include <linux/mm.h>
48
#include <linux/ioport.h>
49
#include <linux/blkdev.h>
50
#include <linux/hdreg.h>
51
#include <linux/ide.h>
52
#include <linux/init.h>
53
 
54
#include <asm/io.h>
55
 
56
#ifdef CONFIG_BLK_DEV_HT6560B_MODULE
57
# define _IDE_C
58
# include "ide_modes.h"
59
# undef _IDE_C
60
#else
61
# include "ide_modes.h"
62
#endif /* CONFIG_BLK_DEV_HT6560B_MODULE */
63
 
64
/* #define DEBUG */  /* remove comments for DEBUG messages */
65
 
66
/*
67
 * The special i/o-port that HT-6560B uses to configuration:
68
 *    bit0 (0x01): "1" selects secondary interface
69
 *    bit2 (0x04): "1" enables FIFO function
70
 *    bit5 (0x20): "1" enables prefetched data read function  (???)
71
 *
72
 * The special i/o-port that HT-6560A uses to configuration:
73
 *    bit0 (0x01): "1" selects secondary interface
74
 *    bit1 (0x02): "1" enables prefetched data read function
75
 *    bit2 (0x04): "0" enables multi-master system             (?)
76
 *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time          (?)
77
 */
78
#define HT_CONFIG_PORT    0x3e6
79
#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
80
/*
81
 * FIFO + PREFETCH (both a/b-model)
82
 */
83
#define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
84
/* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
85
#define HT_SECONDARY_IF   0x01
86
#define HT_PREFETCH_MODE  0x20
87
 
88
/*
89
 * ht6560b Timing values:
90
 *
91
 * I reviewed some assembler source listings of htide drivers and found
92
 * out how they setup those cycle time interfacing values, as they at Holtek
93
 * call them. IDESETUP.COM that is supplied with the drivers figures out
94
 * optimal values and fetches those values to drivers. I found out that
95
 * they use IDE_SELECT_REG to fetch timings to the ide board right after
96
 * interface switching. After that it was quite easy to add code to
97
 * ht6560b.c.
98
 *
99
 * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
100
 * for hda and hdc. But hdb needed higher values to work, so I guess
101
 * that sometimes it is necessary to give higher value than IDESETUP
102
 * gives.   [see cmd640.c for an extreme example of this. -ml]
103
 *
104
 * Perhaps I should explain something about these timing values:
105
 * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
106
 * of the value is the Active Time  (at). Minimum value 2 is the fastest and
107
 * the maximum value 15 is the slowest. Default values should be 15 for both.
108
 * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
109
 * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
110
 * similar. If value is too small there will be all sorts of failures.
111
 *
112
 * Timing byte consists of
113
 *      High nibble:  Recovery Cycle Time  (rt)
114
 *           The valid values range from 2 to 15. The default is 15.
115
 *
116
 *      Low nibble:   Active Cycle Time    (at)
117
 *           The valid values range from 2 to 15. The default is 15.
118
 *
119
 * You can obtain optimized timing values by running Holtek IDESETUP.COM
120
 * for DOS. DOS drivers get their timing values from command line, where
121
 * the first value is the Recovery Time and the second value is the
122
 * Active Time for each drive. Smaller value gives higher speed.
123
 * In case of failures you should probably fall back to a higher value.
124
 */
125
#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
126
#define HT_TIMING_DEFAULT 0xff
127
 
128
/*
129
 * This routine handles interface switching for the peculiar hardware design
130
 * on the F.G.I./Holtek HT-6560B VLB IDE interface.
131
 * The HT-6560B can only enable one IDE port at a time, and requires a
132
 * silly sequence (below) whenever we switch between primary and secondary.
133
 */
134
 
135
/*
136
 * This routine is invoked from ide.c to prepare for access to a given drive.
137
 */
138
static void ht6560b_selectproc (ide_drive_t *drive)
139
{
140
        unsigned long flags;
141
        static u8 current_select = 0;
142
        static u8 current_timing = 0;
143
        u8 select, timing;
144
 
145
        local_irq_save(flags);
146
 
147
        select = HT_CONFIG(drive);
148
        timing = HT_TIMING(drive);
149
 
150
        if (select != current_select || timing != current_timing) {
151
                current_select = select;
152
                current_timing = timing;
153
                if (drive->media != ide_disk || !drive->present)
154
                        select |= HT_PREFETCH_MODE;
155
                (void) HWIF(drive)->INB(HT_CONFIG_PORT);
156
                (void) HWIF(drive)->INB(HT_CONFIG_PORT);
157
                (void) HWIF(drive)->INB(HT_CONFIG_PORT);
158
                (void) HWIF(drive)->INB(HT_CONFIG_PORT);
159
                HWIF(drive)->OUTB(select, HT_CONFIG_PORT);
160
                /*
161
                 * Set timing for this drive:
162
                 */
163
                HWIF(drive)->OUTB(timing, IDE_SELECT_REG);
164
                (void) HWIF(drive)->INB(IDE_STATUS_REG);
165
#ifdef DEBUG
166
                printk("ht6560b: %s: select=%#x timing=%#x\n",
167
                        drive->name, select, timing);
168
#endif
169
        }
170
        local_irq_restore(flags);
171
}
172
 
173
/*
174
 * Autodetection and initialization of ht6560b
175
 */
176
static int __init try_to_init_ht6560b(void)
177
{
178
        u8 orig_value;
179
        int i;
180
 
181
        /* Autodetect ht6560b */
182
        if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
183
                return 0;
184
 
185
        for (i=3;i>0;i--) {
186
                outb(0x00, HT_CONFIG_PORT);
187
                if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
188
                        outb(orig_value, HT_CONFIG_PORT);
189
                        return 0;
190
                }
191
        }
192
        outb(0x00, HT_CONFIG_PORT);
193
        if ((~inb(HT_CONFIG_PORT))& 0x3f) {
194
                outb(orig_value, HT_CONFIG_PORT);
195
                return 0;
196
        }
197
        /*
198
         * Ht6560b autodetected
199
         */
200
        outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
201
        outb(HT_TIMING_DEFAULT, 0x1f6);  /* IDE_SELECT_REG */
202
        (void) inb(0x1f7);               /* IDE_STATUS_REG */
203
 
204
        printk("\nht6560b " HT6560B_VERSION
205
               ": chipset detected and initialized"
206
#ifdef DEBUG
207
               " with debug enabled"
208
#endif
209
                );
210
        return 1;
211
}
212
 
213
static u8 ht_pio2timings(ide_drive_t *drive, u8 pio)
214
{
215
        int active_time, recovery_time;
216
        int active_cycles, recovery_cycles;
217
        ide_pio_data_t d;
218
        int bus_speed = system_bus_clock();
219
 
220
        if (pio) {
221
                pio = ide_get_best_pio_mode(drive, pio, 5, &d);
222
 
223
                /*
224
                 *  Just like opti621.c we try to calculate the
225
                 *  actual cycle time for recovery and activity
226
                 *  according system bus speed.
227
                 */
228
                active_time = ide_pio_timings[pio].active_time;
229
                recovery_time = d.cycle_time
230
                        - active_time
231
                        - ide_pio_timings[pio].setup_time;
232
                /*
233
                 *  Cycle times should be Vesa bus cycles
234
                 */
235
                active_cycles   = (active_time   * bus_speed + 999) / 1000;
236
                recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
237
                /*
238
                 *  Upper and lower limits
239
                 */
240
                if (active_cycles   < 2)  active_cycles   = 2;
241
                if (recovery_cycles < 2)  recovery_cycles = 2;
242
                if (active_cycles   > 15) active_cycles   = 15;
243
                if (recovery_cycles > 15) recovery_cycles = 0;  /* 0==16 */
244
 
245
#ifdef DEBUG
246
                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);
247
#endif
248
 
249
                return (u8)((recovery_cycles << 4) | active_cycles);
250
        } else {
251
 
252
#ifdef DEBUG
253
                printk("ht6560b: drive %s setting pio=0\n", drive->name);
254
#endif
255
 
256
                return HT_TIMING_DEFAULT;    /* default setting */
257
        }
258
}
259
 
260
/*
261
 *  Enable/Disable so called prefetch mode
262
 */
263
static void ht_set_prefetch(ide_drive_t *drive, u8 state)
264
{
265
        unsigned long flags;
266
        int t = HT_PREFETCH_MODE << 8;
267
 
268
        spin_lock_irqsave(&io_request_lock, flags);
269
 
270
        /*
271
         *  Prefetch mode and unmask irq seems to conflict
272
         */
273
        if (state) {
274
                drive->drive_data |= t;   /* enable prefetch mode */
275
                drive->no_unmask = 1;
276
                drive->unmask = 0;
277
        } else {
278
                drive->drive_data &= ~t;  /* disable prefetch mode */
279
                drive->no_unmask = 0;
280
        }
281
 
282
        spin_unlock_irqrestore(&io_request_lock, flags);
283
 
284
#ifdef DEBUG
285
        printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
286
#endif
287
}
288
 
289
static void tune_ht6560b (ide_drive_t *drive, u8 pio)
290
{
291
        unsigned long flags;
292
        u8 timing;
293
 
294
        switch (pio) {
295
        case 8:         /* set prefetch off */
296
        case 9:         /* set prefetch on */
297
                ht_set_prefetch(drive, pio & 1);
298
                return;
299
        }
300
 
301
        timing = ht_pio2timings(drive, pio);
302
 
303
        spin_lock_irqsave(&io_request_lock, flags);
304
 
305
        drive->drive_data &= 0xff00;
306
        drive->drive_data |= timing;
307
 
308
        spin_unlock_irqrestore(&io_request_lock, flags);
309
 
310
#ifdef DEBUG
311
        printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
312
#endif
313
}
314
 
315
void __init probe_ht6560b (void)
316
{
317
        int t;
318
 
319
        request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name);
320
        ide_hwifs[0].chipset = ide_ht6560b;
321
        ide_hwifs[1].chipset = ide_ht6560b;
322
        ide_hwifs[0].selectproc = &ht6560b_selectproc;
323
        ide_hwifs[1].selectproc = &ht6560b_selectproc;
324
        ide_hwifs[0].tuneproc = &tune_ht6560b;
325
        ide_hwifs[1].tuneproc = &tune_ht6560b;
326
        ide_hwifs[0].serialized = 1;  /* is this needed? */
327
        ide_hwifs[1].serialized = 1;  /* is this needed? */
328
        ide_hwifs[0].mate = &ide_hwifs[1];
329
        ide_hwifs[1].mate = &ide_hwifs[0];
330
        ide_hwifs[1].channel = 1;
331
 
332
        /*
333
         * Setting default configurations for drives
334
         */
335
        t = (HT_CONFIG_DEFAULT << 8);
336
        t |= HT_TIMING_DEFAULT;
337
        ide_hwifs[0].drives[0].drive_data = t;
338
        ide_hwifs[0].drives[1].drive_data = t;
339
        t |= (HT_SECONDARY_IF << 8);
340
        ide_hwifs[1].drives[0].drive_data = t;
341
        ide_hwifs[1].drives[1].drive_data = t;
342
 
343
#ifndef HWIF_PROBE_CLASSIC_METHOD
344
        probe_hwif_init(&ide_hwifs[0]);
345
        probe_hwif_init(&ide_hwifs[1]);
346
#endif /* HWIF_PROBE_CLASSIC_METHOD */
347
 
348
}
349
 
350
void __init ht6560b_release (void)
351
{
352
        if (ide_hwifs[0].chipset != ide_ht6560b &&
353
            ide_hwifs[1].chipset != ide_ht6560b)
354
                return;
355
 
356
        ide_hwifs[0].chipset = ide_unknown;
357
        ide_hwifs[1].chipset = ide_unknown;
358
        ide_hwifs[0].tuneproc = NULL;
359
        ide_hwifs[1].tuneproc = NULL;
360
        ide_hwifs[0].selectproc = NULL;
361
        ide_hwifs[1].selectproc = NULL;
362
        ide_hwifs[0].serialized = 0;
363
        ide_hwifs[1].serialized = 0;
364
        ide_hwifs[0].mate = NULL;
365
        ide_hwifs[1].mate = NULL;
366
 
367
        ide_hwifs[0].drives[0].drive_data = 0;
368
        ide_hwifs[0].drives[1].drive_data = 0;
369
        ide_hwifs[1].drives[0].drive_data = 0;
370
        ide_hwifs[1].drives[1].drive_data = 0;
371
        release_region(HT_CONFIG_PORT, 1);
372
}
373
 
374
#ifndef MODULE
375
/*
376
 * init_ht6560b:
377
 *
378
 * called by ide.c when parsing command line
379
 */
380
 
381
void __init init_ht6560b (void)
382
{
383
        if (check_region(HT_CONFIG_PORT,1)) {
384
                printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
385
                        __FUNCTION__);
386
                return;
387
        }
388
        if (!try_to_init_ht6560b()) {
389
                printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
390
                return;
391
        }
392
        probe_ht6560b();
393
}
394
 
395
#else
396
 
397
MODULE_AUTHOR("See Local File");
398
MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
399
MODULE_LICENSE("GPL");
400
 
401
int __init ht6560b_mod_init(void)
402
{
403
        if (check_region(HT_CONFIG_PORT,1)) {
404
                printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
405
                        __FUNCTION__);
406
                return -ENODEV;
407
        }
408
 
409
        if (!try_to_init_ht6560b()) {
410
                printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
411
                return -ENODEV;
412
        }
413
 
414
        probe_ht6560b();
415
        if (ide_hwifs[0].chipset != ide_ht6560b &&
416
            ide_hwifs[1].chipset != ide_ht6560b) {
417
                ht6560b_release();
418
                return -ENODEV;
419
        }
420
        return 0;
421
}
422
module_init(ht6560b_mod_init);
423
 
424
void __init ht6560b_mod_exit(void)
425
{
426
        ht6560b_release();
427
}
428
module_exit(ht6560b_mod_exit);
429
#endif
430
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.