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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ide/] [legacy/] [ali14xx.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/ali14xx.c          Version 0.03    Feb 09, 1996
3
 *
4
 *  Copyright (C) 1996  Linus Torvalds & author (see below)
5
 */
6
 
7
/*
8
 * ALI M14xx chipset EIDE controller
9
 *
10
 * Works for ALI M1439/1443/1445/1487/1489 chipsets.
11
 *
12
 * Adapted from code developed by derekn@vw.ece.cmu.edu.  -ml
13
 * Derek's notes follow:
14
 *
15
 * I think the code should be pretty understandable,
16
 * but I'll be happy to (try to) answer questions.
17
 *
18
 * The critical part is in the setupDrive function.  The initRegisters
19
 * function doesn't seem to be necessary, but the DOS driver does it, so
20
 * I threw it in.
21
 *
22
 * I've only tested this on my system, which only has one disk.  I posted
23
 * it to comp.sys.linux.hardware, so maybe some other people will try it
24
 * out.
25
 *
26
 * Derek Noonburg  (derekn@ece.cmu.edu)
27
 * 95-sep-26
28
 *
29
 * Update 96-jul-13:
30
 *
31
 * I've since upgraded to two disks and a CD-ROM, with no trouble, and
32
 * I've also heard from several others who have used it successfully.
33
 * This driver appears to work with both the 1443/1445 and the 1487/1489
34
 * chipsets.  I've added support for PIO mode 4 for the 1487.  This
35
 * seems to work just fine on the 1443 also, although I'm not sure it's
36
 * advertised as supporting mode 4.  (I've been running a WDC AC21200 in
37
 * mode 4 for a while now with no trouble.)  -Derek
38
 */
39
 
40
#undef REALLY_SLOW_IO           /* most systems can safely undef this */
41
 
42
#include <linux/module.h>
43
#include <linux/config.h>
44
#include <linux/types.h>
45
#include <linux/kernel.h>
46
#include <linux/delay.h>
47
#include <linux/timer.h>
48
#include <linux/mm.h>
49
#include <linux/ioport.h>
50
#include <linux/blkdev.h>
51
#include <linux/hdreg.h>
52
#include <linux/ide.h>
53
#include <linux/init.h>
54
 
55
#include <asm/io.h>
56
 
57
#ifdef CONFIG_BLK_DEV_ALI14XX_MODULE
58
# define _IDE_C
59
# include "ide_modes.h"
60
# undef _IDE_C
61
#else
62
# include "ide_modes.h"
63
#endif /* CONFIG_BLK_DEV_ALI14XX_MODULE */
64
 
65
/* port addresses for auto-detection */
66
#define ALI_NUM_PORTS 4
67
static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
68
 
69
/* register initialization data */
70
typedef struct { u8 reg, data; } RegInitializer;
71
 
72
static RegInitializer initData[] __initdata = {
73
        {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
74
        {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
75
        {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
76
        {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
77
        {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
78
        {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
79
        {0x35, 0x03}, {0x00, 0x00}
80
};
81
 
82
#define ALI_MAX_PIO 4
83
 
84
/* timing parameter registers for each drive */
85
static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
86
        {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
87
        {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
88
        {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
89
        {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
90
};
91
 
92
static int basePort;    /* base port address */
93
static int regPort;     /* port for register number */
94
static int dataPort;    /* port for register data */
95
static u8 regOn;        /* output to base port to access registers */
96
static u8 regOff;       /* output to base port to close registers */
97
 
98
/*------------------------------------------------------------------------*/
99
 
100
/*
101
 * Read a controller register.
102
 */
103
static inline u8 inReg (u8 reg)
104
{
105
        outb_p(reg, regPort);
106
        return inb(dataPort);
107
}
108
 
109
/*
110
 * Write a controller register.
111
 */
112
static void outReg (u8 data, u8 reg)
113
{
114
        outb_p(reg, regPort);
115
        outb_p(data, dataPort);
116
}
117
 
118
/*
119
 * Set PIO mode for the specified drive.
120
 * This function computes timing parameters
121
 * and sets controller registers accordingly.
122
 */
123
static void ali14xx_tune_drive (ide_drive_t *drive, u8 pio)
124
{
125
        int driveNum;
126
        int time1, time2;
127
        u8 param1, param2, param3, param4;
128
        unsigned long flags;
129
        ide_pio_data_t d;
130
        int bus_speed = system_bus_clock();
131
 
132
        pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
133
 
134
        /* calculate timing, according to PIO mode */
135
        time1 = d.cycle_time;
136
        time2 = ide_pio_timings[pio].active_time;
137
        param3 = param1 = (time2 * bus_speed + 999) / 1000;
138
        param4 = param2 = (time1 * bus_speed + 999) / 1000 - param1;
139
        if (pio < 3) {
140
                param3 += 8;
141
                param4 += 8;
142
        }
143
        printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
144
                drive->name, pio, time1, time2, param1, param2, param3, param4);
145
 
146
        /* stuff timing parameters into controller registers */
147
        driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
148
        spin_lock_irqsave(&io_request_lock, flags);
149
        outb_p(regOn, basePort);
150
        outReg(param1, regTab[driveNum].reg1);
151
        outReg(param2, regTab[driveNum].reg2);
152
        outReg(param3, regTab[driveNum].reg3);
153
        outReg(param4, regTab[driveNum].reg4);
154
        outb_p(regOff, basePort);
155
        spin_unlock_irqrestore(&io_request_lock, flags);
156
}
157
 
158
/*
159
 * Auto-detect the IDE controller port.
160
 */
161
static int __init findPort (void)
162
{
163
        int i;
164
        u8 t;
165
        unsigned long flags;
166
 
167
        local_irq_save(flags);
168
        for (i = 0; i < ALI_NUM_PORTS; ++i) {
169
                basePort = ports[i];
170
                regOff = inb(basePort);
171
                for (regOn = 0x30; regOn <= 0x33; ++regOn) {
172
                        outb_p(regOn, basePort);
173
                        if (inb(basePort) == regOn) {
174
                                regPort = basePort + 4;
175
                                dataPort = basePort + 8;
176
                                t = inReg(0) & 0xf0;
177
                                outb_p(regOff, basePort);
178
                                local_irq_restore(flags);
179
                                if (t != 0x50)
180
                                        return 0;
181
                                return 1;  /* success */
182
                        }
183
                }
184
                outb_p(regOff, basePort);
185
        }
186
        local_irq_restore(flags);
187
        return 0;
188
}
189
 
190
/*
191
 * Initialize controller registers with default values.
192
 */
193
static int __init initRegisters (void) {
194
        RegInitializer *p;
195
        u8 t;
196
        unsigned long flags;
197
 
198
        local_irq_save(flags);
199
        outb_p(regOn, basePort);
200
        for (p = initData; p->reg != 0; ++p)
201
                outReg(p->data, p->reg);
202
        outb_p(0x01, regPort);
203
        t = inb(regPort) & 0x01;
204
        outb_p(regOff, basePort);
205
        local_irq_restore(flags);
206
        return t;
207
}
208
 
209
int __init probe_ali14xx (void)
210
{
211
        /* auto-detect IDE controller port */
212
        if (!findPort()) {
213
                printk(KERN_ERR "ali14xx: not found.\n");
214
                return 1;
215
        }
216
 
217
        printk(KERN_DEBUG "ali14xx: base= 0x%03x, regOn = 0x%02x.\n", basePort, regOn);
218
        ide_hwifs[0].chipset = ide_ali14xx;
219
        ide_hwifs[1].chipset = ide_ali14xx;
220
        ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
221
        ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
222
        ide_hwifs[0].mate = &ide_hwifs[1];
223
        ide_hwifs[1].mate = &ide_hwifs[0];
224
        ide_hwifs[1].channel = 1;
225
 
226
        /* initialize controller registers */
227
        if (!initRegisters()) {
228
                printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
229
                return 1;
230
        }
231
 
232
#ifndef HWIF_PROBE_CLASSIC_METHOD
233
        probe_hwif_init(&ide_hwifs[0]);
234
        probe_hwif_init(&ide_hwifs[1]);
235
#endif /* HWIF_PROBE_CLASSIC_METHOD */
236
 
237
        return 0;
238
}
239
 
240
void __init ali14xx_release (void)
241
{
242
        if (ide_hwifs[0].chipset != ide_ali14xx &&
243
            ide_hwifs[1].chipset != ide_ali14xx)
244
                return;
245
 
246
        ide_hwifs[0].chipset = ide_unknown;
247
        ide_hwifs[1].chipset = ide_unknown;
248
        ide_hwifs[0].tuneproc = NULL;
249
        ide_hwifs[1].tuneproc = NULL;
250
        ide_hwifs[0].mate = NULL;
251
        ide_hwifs[1].mate = NULL;
252
}
253
 
254
#ifndef MODULE
255
/*
256
 * init_ali14xx:
257
 *
258
 * called by ide.c when parsing command line
259
 */
260
 
261
void __init init_ali14xx (void)
262
{
263
        /* auto-detect IDE controller port */
264
        if (findPort())
265
                if (probe_ali14xx())
266
                        goto no_detect;
267
        return;
268
 
269
no_detect:
270
        printk(KERN_ERR "ali14xx: not found.\n");
271
        ali14xx_release();
272
}
273
 
274
#else
275
 
276
MODULE_AUTHOR("see local file");
277
MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
278
MODULE_LICENSE("GPL");
279
 
280
int __init ali14xx_mod_init(void)
281
{
282
        /* auto-detect IDE controller port */
283
        if (findPort())
284
                if (probe_ali14xx()) {
285
                        ali14xx_release();
286
                        return -ENODEV;
287
                }
288
 
289
        if (ide_hwifs[0].chipset != ide_ali14xx &&
290
            ide_hwifs[1].chipset != ide_ali14xx) {
291
                ali14xx_release();
292
                return -ENODEV;
293
        }
294
        return 0;
295
}
296
module_init(ali14xx_mod_init);
297
 
298
void __init ali14xx_mod_exit(void)
299
{
300
        ali14xx_release();
301
}
302
module_exit(ali14xx_mod_exit);
303
#endif
304
 

powered by: WebSVN 2.1.0

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