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