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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [alpha/] [lib/] [io.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Alpha IO and memory functions.. Just expand the inlines in the header
3
 * files..
4
 */
5
 
6
#include <linux/kernel.h>
7
#include <linux/types.h>
8
#include <linux/string.h>
9
 
10
#include <asm/io.h>
11
 
12
u8 _inb(unsigned long addr)
13
{
14
        return __inb(addr);
15
}
16
 
17
u16 _inw(unsigned long addr)
18
{
19
        return __inw(addr);
20
}
21
 
22
u32 _inl(unsigned long addr)
23
{
24
        return __inl(addr);
25
}
26
 
27
 
28
void _outb(u8 b, unsigned long addr)
29
{
30
        __outb(b, addr);
31
}
32
 
33
void _outw(u16 b, unsigned long addr)
34
{
35
        __outw(b, addr);
36
}
37
 
38
void _outl(u32 b, unsigned long addr)
39
{
40
        __outl(b, addr);
41
}
42
 
43
u8 ___raw_readb(unsigned long addr)
44
{
45
        return __readb(addr);
46
}
47
 
48
u16 ___raw_readw(unsigned long addr)
49
{
50
        return __readw(addr);
51
}
52
 
53
u32 ___raw_readl(unsigned long addr)
54
{
55
        return __readl(addr);
56
}
57
 
58
u64 ___raw_readq(unsigned long addr)
59
{
60
        return __readq(addr);
61
}
62
 
63
u8 _readb(unsigned long addr)
64
{
65
        unsigned long r = __readb(addr);
66
        mb();
67
        return r;
68
}
69
 
70
u16 _readw(unsigned long addr)
71
{
72
        unsigned long r = __readw(addr);
73
        mb();
74
        return r;
75
}
76
 
77
u32 _readl(unsigned long addr)
78
{
79
        unsigned long r = __readl(addr);
80
        mb();
81
        return r;
82
}
83
 
84
u64 _readq(unsigned long addr)
85
{
86
        unsigned long r = __readq(addr);
87
        mb();
88
        return r;
89
}
90
 
91
void ___raw_writeb(u8 b, unsigned long addr)
92
{
93
        __writeb(b, addr);
94
}
95
 
96
void ___raw_writew(u16 b, unsigned long addr)
97
{
98
        __writew(b, addr);
99
}
100
 
101
void ___raw_writel(u32 b, unsigned long addr)
102
{
103
        __writel(b, addr);
104
}
105
 
106
void ___raw_writeq(u64 b, unsigned long addr)
107
{
108
        __writeq(b, addr);
109
}
110
 
111
void _writeb(u8 b, unsigned long addr)
112
{
113
        __writeb(b, addr);
114
        mb();
115
}
116
 
117
void _writew(u16 b, unsigned long addr)
118
{
119
        __writew(b, addr);
120
        mb();
121
}
122
 
123
void _writel(u32 b, unsigned long addr)
124
{
125
        __writel(b, addr);
126
        mb();
127
}
128
 
129
void _writeq(u64 b, unsigned long addr)
130
{
131
        __writeq(b, addr);
132
        mb();
133
}
134
 
135
/*
136
 * Read COUNT 8-bit bytes from port PORT into memory starting at
137
 * SRC.
138
 */
139
void insb (unsigned long port, void *dst, unsigned long count)
140
{
141
        while (((unsigned long)dst) & 0x3) {
142
                if (!count)
143
                        return;
144
                count--;
145
                *(unsigned char *) dst = inb(port);
146
                ((unsigned char *) dst)++;
147
        }
148
 
149
        while (count >= 4) {
150
                unsigned int w;
151
                count -= 4;
152
                w = inb(port);
153
                w |= inb(port) << 8;
154
                w |= inb(port) << 16;
155
                w |= inb(port) << 24;
156
                *(unsigned int *) dst = w;
157
                ((unsigned int *) dst)++;
158
        }
159
 
160
        while (count) {
161
                --count;
162
                *(unsigned char *) dst = inb(port);
163
                ((unsigned char *) dst)++;
164
        }
165
}
166
 
167
 
168
/*
169
 * Read COUNT 16-bit words from port PORT into memory starting at
170
 * SRC.  SRC must be at least short aligned.  This is used by the
171
 * IDE driver to read disk sectors.  Performance is important, but
172
 * the interfaces seems to be slow: just using the inlined version
173
 * of the inw() breaks things.
174
 */
175
void insw (unsigned long port, void *dst, unsigned long count)
176
{
177
        if (((unsigned long)dst) & 0x3) {
178
                if (((unsigned long)dst) & 0x1) {
179
                        panic("insw: memory not short aligned");
180
                }
181
                if (!count)
182
                        return;
183
                count--;
184
                *(unsigned short* ) dst = inw(port);
185
                ((unsigned short *) dst)++;
186
        }
187
 
188
        while (count >= 2) {
189
                unsigned int w;
190
                count -= 2;
191
                w = inw(port);
192
                w |= inw(port) << 16;
193
                *(unsigned int *) dst = w;
194
                ((unsigned int *) dst)++;
195
        }
196
 
197
        if (count) {
198
                *(unsigned short*) dst = inw(port);
199
        }
200
}
201
 
202
 
203
/*
204
 * Read COUNT 32-bit words from port PORT into memory starting at
205
 * SRC. Now works with any alignment in SRC. Performance is important,
206
 * but the interfaces seems to be slow: just using the inlined version
207
 * of the inl() breaks things.
208
 */
209
void insl (unsigned long port, void *dst, unsigned long count)
210
{
211
        unsigned int l = 0, l2;
212
 
213
        if (!count)
214
                return;
215
 
216
        switch (((unsigned long) dst) & 0x3)
217
        {
218
         case 0x00:                     /* Buffer 32-bit aligned */
219
                while (count--)
220
                {
221
                        *(unsigned int *) dst = inl(port);
222
                        ((unsigned int *) dst)++;
223
                }
224
                break;
225
 
226
        /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
227
 
228
         case 0x02:                     /* Buffer 16-bit aligned */
229
                --count;
230
 
231
                l = inl(port);
232
                *(unsigned short *) dst = l;
233
                ((unsigned short *) dst)++;
234
 
235
                while (count--)
236
                {
237
                        l2 = inl(port);
238
                        *(unsigned int *) dst = l >> 16 | l2 << 16;
239
                        ((unsigned int *) dst)++;
240
                        l = l2;
241
                }
242
                *(unsigned short *) dst = l >> 16;
243
                break;
244
         case 0x01:                     /* Buffer 8-bit aligned */
245
                --count;
246
 
247
                l = inl(port);
248
                *(unsigned char *) dst = l;
249
                ((unsigned char *) dst)++;
250
                *(unsigned short *) dst = l >> 8;
251
                ((unsigned short *) dst)++;
252
                while (count--)
253
                {
254
                        l2 = inl(port);
255
                        *(unsigned int *) dst = l >> 24 | l2 << 8;
256
                        ((unsigned int *) dst)++;
257
                        l = l2;
258
                }
259
                *(unsigned char *) dst = l >> 24;
260
                break;
261
         case 0x03:                     /* Buffer 8-bit aligned */
262
                --count;
263
 
264
                l = inl(port);
265
                *(unsigned char *) dst = l;
266
                ((unsigned char *) dst)++;
267
                while (count--)
268
                {
269
                        l2 = inl(port);
270
                        *(unsigned int *) dst = l << 24 | l2 >> 8;
271
                        ((unsigned int *) dst)++;
272
                        l = l2;
273
                }
274
                *(unsigned short *) dst = l >> 8;
275
                ((unsigned short *) dst)++;
276
                *(unsigned char *) dst = l >> 24;
277
                break;
278
        }
279
}
280
 
281
 
282
/*
283
 * Like insb but in the opposite direction.
284
 * Don't worry as much about doing aligned memory transfers:
285
 * doing byte reads the "slow" way isn't nearly as slow as
286
 * doing byte writes the slow way (no r-m-w cycle).
287
 */
288
void outsb(unsigned long port, const void * src, unsigned long count)
289
{
290
        while (count) {
291
                count--;
292
                outb(*(char *)src, port);
293
                ((char *) src)++;
294
        }
295
}
296
 
297
/*
298
 * Like insw but in the opposite direction.  This is used by the IDE
299
 * driver to write disk sectors.  Performance is important, but the
300
 * interfaces seems to be slow: just using the inlined version of the
301
 * outw() breaks things.
302
 */
303
void outsw (unsigned long port, const void *src, unsigned long count)
304
{
305
        if (((unsigned long)src) & 0x3) {
306
                if (((unsigned long)src) & 0x1) {
307
                        panic("outsw: memory not short aligned");
308
                }
309
                outw(*(unsigned short*)src, port);
310
                ((unsigned short *) src)++;
311
                --count;
312
        }
313
 
314
        while (count >= 2) {
315
                unsigned int w;
316
                count -= 2;
317
                w = *(unsigned int *) src;
318
                ((unsigned int *) src)++;
319
                outw(w >>  0, port);
320
                outw(w >> 16, port);
321
        }
322
 
323
        if (count) {
324
                outw(*(unsigned short *) src, port);
325
        }
326
}
327
 
328
 
329
/*
330
 * Like insl but in the opposite direction.  This is used by the IDE
331
 * driver to write disk sectors.  Works with any alignment in SRC.
332
 *  Performance is important, but the interfaces seems to be slow:
333
 * just using the inlined version of the outl() breaks things.
334
 */
335
void outsl (unsigned long port, const void *src, unsigned long count)
336
{
337
        unsigned int l = 0, l2;
338
 
339
        if (!count)
340
                return;
341
 
342
        switch (((unsigned long) src) & 0x3)
343
        {
344
         case 0x00:                     /* Buffer 32-bit aligned */
345
                while (count--)
346
                {
347
                        outl(*(unsigned int *) src, port);
348
                        ((unsigned int *) src)++;
349
                }
350
                break;
351
 
352
        /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */
353
 
354
         case 0x02:                     /* Buffer 16-bit aligned */
355
                --count;
356
 
357
                l = *(unsigned short *) src << 16;
358
                ((unsigned short *) src)++;
359
 
360
                while (count--)
361
                {
362
                        l2 = *(unsigned int *) src;
363
                        ((unsigned int *) src)++;
364
                        outl (l >> 16 | l2 << 16, port);
365
                        l = l2;
366
                }
367
                l2 = *(unsigned short *) src;
368
                outl (l >> 16 | l2 << 16, port);
369
                break;
370
         case 0x01:                     /* Buffer 8-bit aligned */
371
                --count;
372
 
373
                l  = *(unsigned char *) src << 8;
374
                ((unsigned char *) src)++;
375
                l |= *(unsigned short *) src << 16;
376
                ((unsigned short *) src)++;
377
                while (count--)
378
                {
379
                        l2 = *(unsigned int *) src;
380
                        ((unsigned int *) src)++;
381
                        outl (l >> 8 | l2 << 24, port);
382
                        l = l2;
383
                }
384
                l2 = *(unsigned char *) src;
385
                outl (l >> 8 | l2 << 24, port);
386
                break;
387
         case 0x03:                     /* Buffer 8-bit aligned */
388
                --count;
389
 
390
                l  = *(unsigned char *) src << 24;
391
                ((unsigned char *) src)++;
392
                while (count--)
393
                {
394
                        l2 = *(unsigned int *) src;
395
                        ((unsigned int *) src)++;
396
                        outl (l >> 24 | l2 << 8, port);
397
                        l = l2;
398
                }
399
                l2  = *(unsigned short *) src;
400
                ((unsigned short *) src)++;
401
                l2 |= *(unsigned char *) src << 16;
402
                outl (l >> 24 | l2 << 8, port);
403
                break;
404
        }
405
}
406
 
407
 
408
/*
409
 * Copy data from IO memory space to "real" memory space.
410
 * This needs to be optimized.
411
 */
412
void _memcpy_fromio(void * to, unsigned long from, long count)
413
{
414
        /* Optimize co-aligned transfers.  Everything else gets handled
415
           a byte at a time. */
416
 
417
        if (count >= 8 && ((long)to & 7) == (from & 7)) {
418
                count -= 8;
419
                do {
420
                        *(u64 *)to = __raw_readq(from);
421
                        count -= 8;
422
                        to += 8;
423
                        from += 8;
424
                } while (count >= 0);
425
                count += 8;
426
        }
427
 
428
        if (count >= 4 && ((long)to & 3) == (from & 3)) {
429
                count -= 4;
430
                do {
431
                        *(u32 *)to = __raw_readl(from);
432
                        count -= 4;
433
                        to += 4;
434
                        from += 4;
435
                } while (count >= 0);
436
                count += 4;
437
        }
438
 
439
        if (count >= 2 && ((long)to & 1) == (from & 1)) {
440
                count -= 2;
441
                do {
442
                        *(u16 *)to = __raw_readw(from);
443
                        count -= 2;
444
                        to += 2;
445
                        from += 2;
446
                } while (count >= 0);
447
                count += 2;
448
        }
449
 
450
        while (count > 0) {
451
                *(u8 *) to = __raw_readb(from);
452
                count--;
453
                to++;
454
                from++;
455
        }
456
}
457
 
458
/*
459
 * Copy data from "real" memory space to IO memory space.
460
 * This needs to be optimized.
461
 */
462
void _memcpy_toio(unsigned long to, const void * from, long count)
463
{
464
        /* Optimize co-aligned transfers.  Everything else gets handled
465
           a byte at a time. */
466
        /* FIXME -- align FROM.  */
467
 
468
        if (count >= 8 && (to & 7) == ((long)from & 7)) {
469
                count -= 8;
470
                do {
471
                        __raw_writeq(*(const u64 *)from, to);
472
                        count -= 8;
473
                        to += 8;
474
                        from += 8;
475
                } while (count >= 0);
476
                count += 8;
477
        }
478
 
479
        if (count >= 4 && (to & 3) == ((long)from & 3)) {
480
                count -= 4;
481
                do {
482
                        __raw_writel(*(const u32 *)from, to);
483
                        count -= 4;
484
                        to += 4;
485
                        from += 4;
486
                } while (count >= 0);
487
                count += 4;
488
        }
489
 
490
        if (count >= 2 && (to & 1) == ((long)from & 1)) {
491
                count -= 2;
492
                do {
493
                        __raw_writew(*(const u16 *)from, to);
494
                        count -= 2;
495
                        to += 2;
496
                        from += 2;
497
                } while (count >= 0);
498
                count += 2;
499
        }
500
 
501
        while (count > 0) {
502
                __raw_writeb(*(const u8 *) from, to);
503
                count--;
504
                to++;
505
                from++;
506
        }
507
        mb();
508
}
509
 
510
/*
511
 * "memset" on IO memory space.
512
 */
513
void _memset_c_io(unsigned long to, unsigned long c, long count)
514
{
515
        /* Handle any initial odd byte */
516
        if (count > 0 && (to & 1)) {
517
                __raw_writeb(c, to);
518
                to++;
519
                count--;
520
        }
521
 
522
        /* Handle any initial odd halfword */
523
        if (count >= 2 && (to & 2)) {
524
                __raw_writew(c, to);
525
                to += 2;
526
                count -= 2;
527
        }
528
 
529
        /* Handle any initial odd word */
530
        if (count >= 4 && (to & 4)) {
531
                __raw_writel(c, to);
532
                to += 4;
533
                count -= 4;
534
        }
535
 
536
        /* Handle all full-sized quadwords: we're aligned
537
           (or have a small count) */
538
        count -= 8;
539
        if (count >= 0) {
540
                do {
541
                        __raw_writeq(c, to);
542
                        to += 8;
543
                        count -= 8;
544
                } while (count >= 0);
545
        }
546
        count += 8;
547
 
548
        /* The tail is word-aligned if we still have count >= 4 */
549
        if (count >= 4) {
550
                __raw_writel(c, to);
551
                to += 4;
552
                count -= 4;
553
        }
554
 
555
        /* The tail is half-word aligned if we have count >= 2 */
556
        if (count >= 2) {
557
                __raw_writew(c, to);
558
                to += 2;
559
                count -= 2;
560
        }
561
 
562
        /* And finally, one last byte.. */
563
        if (count) {
564
                __raw_writeb(c, to);
565
        }
566
        mb();
567
}
568
 
569
void
570
scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
571
{
572
        if (! __is_ioaddr((unsigned long) s)) {
573
                /* Source is memory.  */
574
                if (! __is_ioaddr((unsigned long) d))
575
                        memcpy(d, s, count);
576
                else
577
                        memcpy_toio(d, s, count);
578
        } else {
579
                /* Source is screen.  */
580
                if (! __is_ioaddr((unsigned long) d))
581
                        memcpy_fromio(d, s, count);
582
                else {
583
                        /* FIXME: Should handle unaligned ops and
584
                           operation widening.  */
585
                        count /= 2;
586
                        while (count--) {
587
                                u16 tmp = __raw_readw((unsigned long)(s++));
588
                                __raw_writew(tmp, (unsigned long)(d++));
589
                        }
590
                }
591
        }
592
}

powered by: WebSVN 2.1.0

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