linux/arch/sparc/lib/PeeCeeI.c
<<
>>
Prefs
   1/*
   2 * PeeCeeI.c: The emerging standard...
   3 *
   4 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   5 */
   6
   7#include <linux/module.h>
   8
   9#include <asm/io.h>
  10#include <asm/byteorder.h>
  11
  12void outsb(unsigned long __addr, const void *src, unsigned long count)
  13{
  14        void __iomem *addr = (void __iomem *) __addr;
  15        const u8 *p = src;
  16
  17        while (count--)
  18                outb(*p++, addr);
  19}
  20EXPORT_SYMBOL(outsb);
  21
  22void outsw(unsigned long __addr, const void *src, unsigned long count)
  23{
  24        void __iomem *addr = (void __iomem *) __addr;
  25
  26        while (count--) {
  27                __raw_writew(*(u16 *)src, addr);
  28                src += sizeof(u16);
  29        }
  30}
  31EXPORT_SYMBOL(outsw);
  32
  33void outsl(unsigned long __addr, const void *src, unsigned long count)
  34{
  35        void __iomem *addr = (void __iomem *) __addr;
  36        u32 l, l2;
  37
  38        if (!count)
  39                return;
  40
  41        switch (((unsigned long)src) & 0x3) {
  42        case 0x0:
  43                /* src is naturally aligned */
  44                while (count--) {
  45                        __raw_writel(*(u32 *)src, addr);
  46                        src += sizeof(u32);
  47                }
  48                break;
  49        case 0x2:
  50                /* 2-byte alignment */
  51                while (count--) {
  52                        l = (*(u16 *)src) << 16;
  53                        l |= *(u16 *)(src + sizeof(u16));
  54                        __raw_writel(l, addr);
  55                        src += sizeof(u32);
  56                }
  57                break;
  58        case 0x1:
  59                /* Hold three bytes in l each time, grab a byte from l2 */
  60                l = (*(u8 *)src) << 24;
  61                l |= (*(u16 *)(src + sizeof(u8))) << 8;
  62                src += sizeof(u8) + sizeof(u16);
  63                while (count--) {
  64                        l2 = *(u32 *)src;
  65                        l |= (l2 >> 24);
  66                        __raw_writel(l, addr);
  67                        l = l2 << 8;
  68                        src += sizeof(u32);
  69                }
  70                break;
  71        case 0x3:
  72                /* Hold a byte in l each time, grab 3 bytes from l2 */
  73                l = (*(u8 *)src) << 24;
  74                src += sizeof(u8);
  75                while (count--) {
  76                        l2 = *(u32 *)src;
  77                        l |= (l2 >> 8);
  78                        __raw_writel(l, addr);
  79                        l = l2 << 24;
  80                        src += sizeof(u32);
  81                }
  82                break;
  83        }
  84}
  85EXPORT_SYMBOL(outsl);
  86
  87void insb(unsigned long __addr, void *dst, unsigned long count)
  88{
  89        void __iomem *addr = (void __iomem *) __addr;
  90
  91        if (count) {
  92                u32 *pi;
  93                u8 *pb = dst;
  94
  95                while ((((unsigned long)pb) & 0x3) && count--)
  96                        *pb++ = inb(addr);
  97                pi = (u32 *)pb;
  98                while (count >= 4) {
  99                        u32 w;
 100
 101                        w  = (inb(addr) << 24);
 102                        w |= (inb(addr) << 16);
 103                        w |= (inb(addr) << 8);
 104                        w |= (inb(addr) << 0);
 105                        *pi++ = w;
 106                        count -= 4;
 107                }
 108                pb = (u8 *)pi;
 109                while (count--)
 110                        *pb++ = inb(addr);
 111        }
 112}
 113EXPORT_SYMBOL(insb);
 114
 115void insw(unsigned long __addr, void *dst, unsigned long count)
 116{
 117        void __iomem *addr = (void __iomem *) __addr;
 118
 119        if (count) {
 120                u16 *ps = dst;
 121                u32 *pi;
 122
 123                if (((unsigned long)ps) & 0x2) {
 124                        *ps++ = le16_to_cpu(inw(addr));
 125                        count--;
 126                }
 127                pi = (u32 *)ps;
 128                while (count >= 2) {
 129                        u32 w;
 130
 131                        w  = (le16_to_cpu(inw(addr)) << 16);
 132                        w |= (le16_to_cpu(inw(addr)) << 0);
 133                        *pi++ = w;
 134                        count -= 2;
 135                }
 136                ps = (u16 *)pi;
 137                if (count)
 138                        *ps = le16_to_cpu(inw(addr));
 139        }
 140}
 141EXPORT_SYMBOL(insw);
 142
 143void insl(unsigned long __addr, void *dst, unsigned long count)
 144{
 145        void __iomem *addr = (void __iomem *) __addr;
 146
 147        if (count) {
 148                if ((((unsigned long)dst) & 0x3) == 0) {
 149                        u32 *pi = dst;
 150                        while (count--)
 151                                *pi++ = le32_to_cpu(inl(addr));
 152                } else {
 153                        u32 l = 0, l2, *pi;
 154                        u16 *ps;
 155                        u8 *pb;
 156
 157                        switch (((unsigned long)dst) & 3) {
 158                        case 0x2:
 159                                ps = dst;
 160                                count -= 1;
 161                                l = le32_to_cpu(inl(addr));
 162                                *ps++ = l;
 163                                pi = (u32 *)ps;
 164                                while (count--) {
 165                                        l2 = le32_to_cpu(inl(addr));
 166                                        *pi++ = (l << 16) | (l2 >> 16);
 167                                        l = l2;
 168                                }
 169                                ps = (u16 *)pi;
 170                                *ps = l;
 171                                break;
 172
 173                        case 0x1:
 174                                pb = dst;
 175                                count -= 1;
 176                                l = le32_to_cpu(inl(addr));
 177                                *pb++ = l >> 24;
 178                                ps = (u16 *)pb;
 179                                *ps++ = ((l >> 8) & 0xffff);
 180                                pi = (u32 *)ps;
 181                                while (count--) {
 182                                        l2 = le32_to_cpu(inl(addr));
 183                                        *pi++ = (l << 24) | (l2 >> 8);
 184                                        l = l2;
 185                                }
 186                                pb = (u8 *)pi;
 187                                *pb = l;
 188                                break;
 189
 190                        case 0x3:
 191                                pb = (u8 *)dst;
 192                                count -= 1;
 193                                l = le32_to_cpu(inl(addr));
 194                                *pb++ = l >> 24;
 195                                pi = (u32 *)pb;
 196                                while (count--) {
 197                                        l2 = le32_to_cpu(inl(addr));
 198                                        *pi++ = (l << 8) | (l2 >> 24);
 199                                        l = l2;
 200                                }
 201                                ps = (u16 *)pi;
 202                                *ps++ = ((l >> 8) & 0xffff);
 203                                pb = (u8 *)ps;
 204                                *pb = l;
 205                                break;
 206                        }
 207                }
 208        }
 209}
 210EXPORT_SYMBOL(insl);
 211
 212