12
12
#include <linux/module.h>
13
13
#include <asm/io.h>
14
14
15
- /*
16
- ** Copies a block of memory from a device in an efficient manner.
17
- ** Assumes the device can cope with 32-bit transfers. If it can't,
18
- ** don't use this function.
19
- **
20
- ** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
21
- ** 27341/64 = 427 cyc per int
22
- ** 61311/128 = 478 cyc per short
23
- ** 122637/256 = 479 cyc per byte
24
- ** Ergo bus latencies dominant (not transfer size).
25
- ** Minimize total number of transfers at cost of CPU cycles.
26
- ** TODO: only look at src alignment and adjust the stores to dest.
27
- */
28
- void memcpy_fromio (void * dst , const volatile void __iomem * src , int count )
29
- {
30
- /* first compare alignment of src/dst */
31
- if ( (((unsigned long )dst ^ (unsigned long )src ) & 1 ) || (count < 2 ) )
32
- goto bytecopy ;
33
-
34
- if ( (((unsigned long )dst ^ (unsigned long )src ) & 2 ) || (count < 4 ) )
35
- goto shortcopy ;
36
-
37
- /* Then check for misaligned start address */
38
- if ((unsigned long )src & 1 ) {
39
- * (u8 * )dst = readb (src );
40
- src ++ ;
41
- dst ++ ;
42
- count -- ;
43
- if (count < 2 ) goto bytecopy ;
44
- }
45
-
46
- if ((unsigned long )src & 2 ) {
47
- * (u16 * )dst = __raw_readw (src );
48
- src += 2 ;
49
- dst += 2 ;
50
- count -= 2 ;
51
- }
52
-
53
- while (count > 3 ) {
54
- * (u32 * )dst = __raw_readl (src );
55
- dst += 4 ;
56
- src += 4 ;
57
- count -= 4 ;
58
- }
59
-
60
- shortcopy :
61
- while (count > 1 ) {
62
- * (u16 * )dst = __raw_readw (src );
63
- src += 2 ;
64
- dst += 2 ;
65
- count -= 2 ;
66
- }
67
-
68
- bytecopy :
69
- while (count -- ) {
70
- * (char * )dst = readb (src );
71
- src ++ ;
72
- dst ++ ;
73
- }
74
- }
75
-
76
15
/*
77
16
* Read COUNT 8-bit bytes from port PORT into memory starting at
78
17
* SRC.
@@ -123,15 +62,15 @@ void insw (unsigned long port, void *dst, unsigned long count)
123
62
unsigned char * p ;
124
63
125
64
p = (unsigned char * )dst ;
126
-
65
+
127
66
if (!count )
128
67
return ;
129
-
68
+
130
69
switch (((unsigned long )p ) & 0x3 )
131
70
{
132
71
case 0x00 : /* Buffer 32-bit aligned */
133
72
while (count >=2 ) {
134
-
73
+
135
74
count -= 2 ;
136
75
l = cpu_to_le16 (inw (port )) << 16 ;
137
76
l |= cpu_to_le16 (inw (port ));
@@ -142,13 +81,13 @@ void insw (unsigned long port, void *dst, unsigned long count)
142
81
* (unsigned short * )p = cpu_to_le16 (inw (port ));
143
82
}
144
83
break ;
145
-
84
+
146
85
case 0x02 : /* Buffer 16-bit aligned */
147
86
* (unsigned short * )p = cpu_to_le16 (inw (port ));
148
87
p += 2 ;
149
88
count -- ;
150
89
while (count >=2 ) {
151
-
90
+
152
91
count -= 2 ;
153
92
l = cpu_to_le16 (inw (port )) << 16 ;
154
93
l |= cpu_to_le16 (inw (port ));
@@ -159,13 +98,13 @@ void insw (unsigned long port, void *dst, unsigned long count)
159
98
* (unsigned short * )p = cpu_to_le16 (inw (port ));
160
99
}
161
100
break ;
162
-
101
+
163
102
case 0x01 : /* Buffer 8-bit aligned */
164
103
case 0x03 :
165
104
/* I don't bother with 32bit transfers
166
105
* in this case, 16bit will have to do -- DE */
167
106
-- count ;
168
-
107
+
169
108
l = cpu_to_le16 (inw (port ));
170
109
* p = l >> 8 ;
171
110
p ++ ;
@@ -195,10 +134,10 @@ void insl (unsigned long port, void *dst, unsigned long count)
195
134
unsigned char * p ;
196
135
197
136
p = (unsigned char * )dst ;
198
-
137
+
199
138
if (!count )
200
139
return ;
201
-
140
+
202
141
switch (((unsigned long ) dst ) & 0x3 )
203
142
{
204
143
case 0x00 : /* Buffer 32-bit aligned */
@@ -208,14 +147,14 @@ void insl (unsigned long port, void *dst, unsigned long count)
208
147
p += 4 ;
209
148
}
210
149
break ;
211
-
150
+
212
151
case 0x02 : /* Buffer 16-bit aligned */
213
152
-- count ;
214
-
153
+
215
154
l = cpu_to_le32 (inl (port ));
216
155
* (unsigned short * )p = l >> 16 ;
217
156
p += 2 ;
218
-
157
+
219
158
while (count -- )
220
159
{
221
160
l2 = cpu_to_le32 (inl (port ));
@@ -227,7 +166,7 @@ void insl (unsigned long port, void *dst, unsigned long count)
227
166
break ;
228
167
case 0x01 : /* Buffer 8-bit aligned */
229
168
-- count ;
230
-
169
+
231
170
l = cpu_to_le32 (inl (port ));
232
171
* (unsigned char * )p = l >> 24 ;
233
172
p ++ ;
@@ -244,7 +183,7 @@ void insl (unsigned long port, void *dst, unsigned long count)
244
183
break ;
245
184
case 0x03 : /* Buffer 8-bit aligned */
246
185
-- count ;
247
-
186
+
248
187
l = cpu_to_le32 (inl (port ));
249
188
* p = l >> 24 ;
250
189
p ++ ;
@@ -293,10 +232,10 @@ void outsw (unsigned long port, const void *src, unsigned long count)
293
232
const unsigned char * p ;
294
233
295
234
p = (const unsigned char * )src ;
296
-
235
+
297
236
if (!count )
298
237
return ;
299
-
238
+
300
239
switch (((unsigned long )p ) & 0x3 )
301
240
{
302
241
case 0x00 : /* Buffer 32-bit aligned */
@@ -311,13 +250,13 @@ void outsw (unsigned long port, const void *src, unsigned long count)
311
250
outw (le16_to_cpu (* (unsigned short * )p ), port );
312
251
}
313
252
break ;
314
-
253
+
315
254
case 0x02 : /* Buffer 16-bit aligned */
316
-
255
+
317
256
outw (le16_to_cpu (* (unsigned short * )p ), port );
318
257
p += 2 ;
319
258
count -- ;
320
-
259
+
321
260
while (count >=2 ) {
322
261
count -= 2 ;
323
262
l = * (unsigned int * )p ;
@@ -329,11 +268,11 @@ void outsw (unsigned long port, const void *src, unsigned long count)
329
268
outw (le16_to_cpu (* (unsigned short * )p ), port );
330
269
}
331
270
break ;
332
-
333
- case 0x01 : /* Buffer 8-bit aligned */
271
+
272
+ case 0x01 : /* Buffer 8-bit aligned */
334
273
/* I don't bother with 32bit transfers
335
274
* in this case, 16bit will have to do -- DE */
336
-
275
+
337
276
l = * p << 8 ;
338
277
p ++ ;
339
278
count -- ;
@@ -348,7 +287,7 @@ void outsw (unsigned long port, const void *src, unsigned long count)
348
287
l2 = * (unsigned char * )p ;
349
288
outw (le16_to_cpu (l | l2 >>8 ), port );
350
289
break ;
351
-
290
+
352
291
}
353
292
}
354
293
@@ -365,10 +304,10 @@ void outsl (unsigned long port, const void *src, unsigned long count)
365
304
const unsigned char * p ;
366
305
367
306
p = (const unsigned char * )src ;
368
-
307
+
369
308
if (!count )
370
309
return ;
371
-
310
+
372
311
switch (((unsigned long )p ) & 0x3 )
373
312
{
374
313
case 0x00 : /* Buffer 32-bit aligned */
@@ -378,13 +317,13 @@ void outsl (unsigned long port, const void *src, unsigned long count)
378
317
p += 4 ;
379
318
}
380
319
break ;
381
-
320
+
382
321
case 0x02 : /* Buffer 16-bit aligned */
383
322
-- count ;
384
-
323
+
385
324
l = * (unsigned short * )p ;
386
325
p += 2 ;
387
-
326
+
388
327
while (count -- )
389
328
{
390
329
l2 = * (unsigned int * )p ;
@@ -415,7 +354,7 @@ void outsl (unsigned long port, const void *src, unsigned long count)
415
354
break ;
416
355
case 0x03 : /* Buffer 8-bit aligned */
417
356
-- count ;
418
-
357
+
419
358
l = * p << 24 ;
420
359
p ++ ;
421
360
0 commit comments