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/] [paride/] [epia.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
        epia.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
3
                              Under the terms of the GNU public license.
4
 
5
        epia.c is a low-level protocol driver for Shuttle Technologies
6
        EPIA parallel to IDE adapter chip.  This device is now obsolete
7
        and has been replaced with the EPAT chip, which is supported
8
        by epat.c, however, some devices based on EPIA are still
9
        available.
10
 
11
*/
12
 
13
/* Changes:
14
 
15
        1.01    GRG 1998.05.06 init_proto, release_proto
16
        1.02    GRG 1998.06.17 support older versions of EPIA
17
 
18
*/
19
 
20
#define EPIA_VERSION      "1.02"
21
 
22
#include <linux/module.h>
23
#include <linux/delay.h>
24
#include <linux/kernel.h>
25
#include <linux/types.h>
26
#include <asm/io.h>
27
 
28
#include "paride.h"
29
 
30
/* mode codes:  0  nybble reads on port 1, 8-bit writes
31
                1  5/3 reads on ports 1 & 2, 8-bit writes
32
                2  8-bit reads and writes
33
                3  8-bit EPP mode
34
                4  16-bit EPP
35
                5  32-bit EPP
36
*/
37
 
38
#define j44(a,b)                (((a>>4)&0x0f)+(b&0xf0))
39
#define j53(a,b)                (((a>>3)&0x1f)+((b<<4)&0xe0))
40
 
41
/* cont =  0   IDE register file
42
   cont =  1   IDE control registers
43
*/
44
 
45
static int cont_map[2] = { 0, 0x80 };
46
 
47
static int epia_read_regr( PIA *pi, int cont, int regr )
48
 
49
{       int     a, b, r;
50
 
51
        regr += cont_map[cont];
52
 
53
        switch (pi->mode)  {
54
 
55
        case 0: r = regr^0x39;
56
                w0(r); w2(1); w2(3); w0(r);
57
                a = r1(); w2(1); b = r1(); w2(4);
58
                return j44(a,b);
59
 
60
        case 1: r = regr^0x31;
61
                w0(r); w2(1); w0(r&0x37);
62
                w2(3); w2(5); w0(r|0xf0);
63
                a = r1(); b = r2(); w2(4);
64
                return j53(a,b);
65
 
66
        case 2: r = regr^0x29;
67
                w0(r); w2(1); w2(0X21); w2(0x23);
68
                a = r0(); w2(4);
69
                return a;
70
 
71
        case 3:
72
        case 4:
73
        case 5: w3(regr); w2(0x24); a = r4(); w2(4);
74
                return a;
75
 
76
        }
77
        return -1;
78
}
79
 
80
static void epia_write_regr( PIA *pi, int cont, int regr, int val)
81
 
82
{       int  r;
83
 
84
        regr += cont_map[cont];
85
 
86
        switch (pi->mode)  {
87
 
88
        case 0:
89
        case 1:
90
        case 2: r = regr^0x19;
91
                w0(r); w2(1); w0(val); w2(3); w2(4);
92
                break;
93
 
94
        case 3:
95
        case 4:
96
        case 5: r = regr^0x40;
97
                w3(r); w4(val); w2(4);
98
                break;
99
        }
100
}
101
 
102
#define WR(r,v)         epia_write_regr(pi,0,r,v)
103
#define RR(r)           (epia_read_regr(pi,0,r))
104
 
105
/* The use of register 0x84 is entirely unclear - it seems to control
106
   some EPP counters ...  currently we know about 3 different block
107
   sizes:  the standard 512 byte reads and writes, 12 byte writes and
108
   2048 byte reads (the last two being used in the CDrom drivers.
109
*/
110
 
111
static void epia_connect ( PIA *pi  )
112
 
113
{       pi->saved_r0 = r0();
114
        pi->saved_r2 = r2();
115
 
116
        w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
117
        w2(1); w2(4);
118
        if (pi->mode >= 3) {
119
                w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
120
                w2(0x24); w2(0x26); w2(4);
121
        }
122
        WR(0x86,8);
123
}
124
 
125
static void epia_disconnect ( PIA *pi )
126
 
127
{       /* WR(0x84,0x10); */
128
        w0(pi->saved_r0);
129
        w2(1); w2(4);
130
        w0(pi->saved_r0);
131
        w2(pi->saved_r2);
132
}
133
 
134
static void epia_read_block( PIA *pi, char * buf, int count )
135
 
136
{       int     k, ph, a, b;
137
 
138
        switch (pi->mode) {
139
 
140
        case 0: w0(0x81); w2(1); w2(3); w0(0xc1);
141
                ph = 1;
142
                for (k=0;k<count;k++) {
143
                        w2(2+ph); a = r1();
144
                        w2(4+ph); b = r1();
145
                        buf[k] = j44(a,b);
146
                        ph = 1 - ph;
147
                }
148
                w0(0); w2(4);
149
                break;
150
 
151
        case 1: w0(0x91); w2(1); w0(0x10); w2(3);
152
                w0(0x51); w2(5); w0(0xd1);
153
                ph = 1;
154
                for (k=0;k<count;k++) {
155
                        w2(4+ph);
156
                        a = r1(); b = r2();
157
                        buf[k] = j53(a,b);
158
                        ph = 1 - ph;
159
                }
160
                w0(0); w2(4);
161
                break;
162
 
163
        case 2: w0(0x89); w2(1); w2(0x23); w2(0x21);
164
                ph = 1;
165
                for (k=0;k<count;k++) {
166
                        w2(0x24+ph);
167
                        buf[k] = r0();
168
                        ph = 1 - ph;
169
                }
170
                w2(6); w2(4);
171
                break;
172
 
173
        case 3: if (count > 512) WR(0x84,3);
174
                w3(0); w2(0x24);
175
                for (k=0;k<count;k++) buf[k] = r4();
176
                w2(4); WR(0x84,0);
177
                break;
178
 
179
        case 4: if (count > 512) WR(0x84,3);
180
                w3(0); w2(0x24);
181
                for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
182
                w2(4); WR(0x84,0);
183
                break;
184
 
185
        case 5: if (count > 512) WR(0x84,3);
186
                w3(0); w2(0x24);
187
                for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
188
                w2(4); WR(0x84,0);
189
                break;
190
 
191
        }
192
}
193
 
194
static void epia_write_block( PIA *pi, char * buf, int count )
195
 
196
{       int     ph, k, last, d;
197
 
198
        switch (pi->mode) {
199
 
200
        case 0:
201
        case 1:
202
        case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5);
203
                ph = 0;  last = 0x8000;
204
                for (k=0;k<count;k++) {
205
                        d = buf[k];
206
                        if (d != last) { last = d; w0(d); }
207
                        w2(4+ph);
208
                        ph = 1 - ph;
209
                }
210
                w2(7); w2(4);
211
                break;
212
 
213
        case 3: if (count < 512) WR(0x84,1);
214
                w3(0x40);
215
                for (k=0;k<count;k++) w4(buf[k]);
216
                if (count < 512) WR(0x84,0);
217
                break;
218
 
219
        case 4: if (count < 512) WR(0x84,1);
220
                w3(0x40);
221
                for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
222
                if (count < 512) WR(0x84,0);
223
                break;
224
 
225
        case 5: if (count < 512) WR(0x84,1);
226
                w3(0x40);
227
                for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
228
                if (count < 512) WR(0x84,0);
229
                break;
230
 
231
        }
232
 
233
}
234
 
235
static int epia_test_proto( PIA *pi, char * scratch, int verbose )
236
 
237
{       int     j, k, f;
238
        int     e[2] = {0,0};
239
 
240
        epia_connect(pi);
241
        for (j=0;j<2;j++) {
242
            WR(6,0xa0+j*0x10);
243
            for (k=0;k<256;k++) {
244
                WR(2,k^0xaa);
245
                WR(3,k^0x55);
246
                if (RR(2) != (k^0xaa)) e[j]++;
247
            }
248
            WR(2,1); WR(3,1);
249
        }
250
        epia_disconnect(pi);
251
 
252
        f = 0;
253
        epia_connect(pi);
254
        WR(0x84,8);
255
        epia_read_block(pi,scratch,512);
256
        for (k=0;k<256;k++) {
257
            if ((scratch[2*k] & 0xff) != ((k+1) & 0xff)) f++;
258
            if ((scratch[2*k+1] & 0xff) != ((-2-k) & 0xff)) f++;
259
        }
260
        WR(0x84,0);
261
        epia_disconnect(pi);
262
 
263
        if (verbose)  {
264
            printk("%s: epia: port 0x%x, mode %d, test=(%d,%d,%d)\n",
265
                   pi->device,pi->port,pi->mode,e[0],e[1],f);
266
        }
267
 
268
        return (e[0] && e[1]) || f;
269
 
270
}
271
 
272
 
273
static void epia_log_adapter( PIA *pi, char * scratch, int verbose )
274
 
275
{       char    *mode_string[6] = {"4-bit","5/3","8-bit",
276
                                   "EPP-8","EPP-16","EPP-32"};
277
 
278
        printk("%s: epia %s, Shuttle EPIA at 0x%x, ",
279
                pi->device,EPIA_VERSION,pi->port);
280
        printk("mode %d (%s), delay %d\n",pi->mode,
281
                mode_string[pi->mode],pi->delay);
282
 
283
}
284
 
285
static void epia_init_proto( PIA *pi)
286
 
287
{       MOD_INC_USE_COUNT;
288
}
289
 
290
static void epia_release_proto( PIA *pi)
291
 
292
{       MOD_DEC_USE_COUNT;
293
}
294
 
295
struct pi_protocol epia = {"epia",0,6,3,1,1,
296
                           epia_write_regr,
297
                           epia_read_regr,
298
                           epia_write_block,
299
                           epia_read_block,
300
                           epia_connect,
301
                           epia_disconnect,
302
                           0,
303
                           0,
304
                           epia_test_proto,
305
                           epia_log_adapter,
306
                           epia_init_proto,
307
                           epia_release_proto
308
                          };
309
 
310
 
311
#ifdef MODULE
312
 
313
int     init_module(void)
314
 
315
{       return pi_register( &epia ) - 1;
316
}
317
 
318
void    cleanup_module(void)
319
 
320
{       pi_unregister( &epia );
321
}
322
 
323
#endif
324
 
325
/* end of epia.c */
326
 

powered by: WebSVN 2.1.0

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