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