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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [block/] [ali14xx.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/drivers/block/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/types.h>
43
#include <linux/kernel.h>
44
#include <linux/delay.h>
45
#include <linux/timer.h>
46
#include <linux/mm.h>
47
#include <linux/ioport.h>
48
#include <linux/blkdev.h>
49
#include <linux/hdreg.h>
50
#include <asm/io.h>
51
#include "ide.h"
52
#include "ide_modes.h"
53
 
54
/* port addresses for auto-detection */
55
#define ALI_NUM_PORTS 4
56
static int ports[ALI_NUM_PORTS] = {0x074, 0x0f4, 0x034, 0x0e4};
57
 
58
/* register initialization data */
59
typedef struct { byte reg, data; } RegInitializer;
60
 
61
static RegInitializer initData[] = {
62
        {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
63
        {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
64
        {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
65
        {0x29, 0x00}, {0x2a, 0x00}, {0x2f, 0x00}, {0x2b, 0x00},
66
        {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x30, 0x00},
67
        {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0xff},
68
        {0x35, 0x03}, {0x00, 0x00}
69
};
70
 
71
#define ALI_MAX_PIO 4
72
 
73
/* timing parameter registers for each drive */
74
static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
75
        {0x03, 0x26, 0x04, 0x27},     /* drive 0 */
76
        {0x05, 0x28, 0x06, 0x29},     /* drive 1 */
77
        {0x2b, 0x30, 0x2c, 0x31},     /* drive 2 */
78
        {0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
79
};
80
 
81
static int basePort = 0; /* base port address */
82
static int regPort = 0;          /* port for register number */
83
static int dataPort = 0; /* port for register data */
84
static byte regOn;      /* output to base port to access registers */
85
static byte regOff;     /* output to base port to close registers */
86
 
87
/*------------------------------------------------------------------------*/
88
 
89
/*
90
 * Read a controller register.
91
 */
92
static inline byte inReg (byte reg)
93
{
94
        outb_p(reg, regPort);
95
        return inb(dataPort);
96
}
97
 
98
/*
99
 * Write a controller register.
100
 */
101
static void outReg (byte data, byte reg)
102
{
103
        outb_p(reg, regPort);
104
        outb_p(data, dataPort);
105
}
106
 
107
/*
108
 * Set PIO mode for the specified drive.
109
 * This function computes timing parameters
110
 * and sets controller registers accordingly.
111
 */
112
static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
113
{
114
        int driveNum;
115
        int time1, time2;
116
        byte param1, param2, param3, param4;
117
        unsigned long flags;
118
        ide_pio_data_t d;
119
        int bus_speed = ide_system_bus_speed();
120
 
121
        pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
122
 
123
        /* calculate timing, according to PIO mode */
124
        time1 = d.cycle_time;
125
        time2 = ide_pio_timings[pio].active_time;
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("%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
        /* stuff timing parameters into controller registers */
136
        driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
137
        save_flags(flags);
138
        cli();
139
        outb_p(regOn, basePort);
140
        outReg(param1, regTab[driveNum].reg1);
141
        outReg(param2, regTab[driveNum].reg2);
142
        outReg(param3, regTab[driveNum].reg3);
143
        outReg(param4, regTab[driveNum].reg4);
144
        outb_p(regOff, basePort);
145
        restore_flags(flags);
146
}
147
 
148
/*
149
 * Auto-detect the IDE controller port.
150
 */
151
static int findPort (void)
152
{
153
        int i;
154
        byte t;
155
        unsigned long flags;
156
 
157
        save_flags(flags);
158
        cli();
159
        for (i = 0; i < ALI_NUM_PORTS; ++i) {
160
                basePort = ports[i];
161
                regOff = inb(basePort);
162
                for (regOn = 0x30; regOn <= 0x33; ++regOn) {
163
                        outb_p(regOn, basePort);
164
                        if (inb(basePort) == regOn) {
165
                                regPort = basePort + 4;
166
                                dataPort = basePort + 8;
167
                                t = inReg(0) & 0xf0;
168
                                outb_p(regOff, basePort);
169
                                restore_flags(flags);
170
                                if (t != 0x50)
171
                                        return 0;
172
                                return 1;  /* success */
173
                        }
174
                }
175
                outb_p(regOff, basePort);
176
        }
177
        restore_flags(flags);
178
        return 0;
179
}
180
 
181
/*
182
 * Initialize controller registers with default values.
183
 */
184
static int initRegisters (void) {
185
        RegInitializer *p;
186
        byte t;
187
        unsigned long flags;
188
 
189
        save_flags(flags);
190
        cli();
191
        outb_p(regOn, basePort);
192
        for (p = initData; p->reg != 0; ++p)
193
                outReg(p->data, p->reg);
194
        outb_p(0x01, regPort);
195
        t = inb(regPort) & 0x01;
196
        outb_p(regOff, basePort);
197
        restore_flags(flags);
198
        return t;
199
}
200
 
201
void init_ali14xx (void)
202
{
203
        /* auto-detect IDE controller port */
204
        if (!findPort()) {
205
                printk("ali14xx: not found\n");
206
                return;
207
        }
208
 
209
        printk("ali14xx: base= 0x%03x, regOn = 0x%02x\n", basePort, regOn);
210
        ide_hwifs[0].chipset = ide_ali14xx;
211
        ide_hwifs[1].chipset = ide_ali14xx;
212
        ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
213
        ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
214
 
215
        /* initialize controller registers */
216
        if (!initRegisters()) {
217
                printk("ali14xx: Chip initialization failed\n");
218
                return;
219
        }
220
}

powered by: WebSVN 2.1.0

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