Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PeeCeeI.c: The emerging standard...
0004  *
0005  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
0006  */
0007 
0008 #include <linux/module.h>
0009 
0010 #include <asm/io.h>
0011 #include <asm/byteorder.h>
0012 
0013 void outsb(unsigned long __addr, const void *src, unsigned long count)
0014 {
0015     void __iomem *addr = (void __iomem *) __addr;
0016     const u8 *p = src;
0017 
0018     while (count--)
0019         __raw_writeb(*p++, addr);
0020 }
0021 EXPORT_SYMBOL(outsb);
0022 
0023 void outsw(unsigned long __addr, const void *src, unsigned long count)
0024 {
0025     void __iomem *addr = (void __iomem *) __addr;
0026 
0027     while (count--) {
0028         __raw_writew(*(u16 *)src, addr);
0029         src += sizeof(u16);
0030     }
0031 }
0032 EXPORT_SYMBOL(outsw);
0033 
0034 void outsl(unsigned long __addr, const void *src, unsigned long count)
0035 {
0036     void __iomem *addr = (void __iomem *) __addr;
0037     u32 l, l2;
0038 
0039     if (!count)
0040         return;
0041 
0042     switch (((unsigned long)src) & 0x3) {
0043     case 0x0:
0044         /* src is naturally aligned */
0045         while (count--) {
0046             __raw_writel(*(u32 *)src, addr);
0047             src += sizeof(u32);
0048         }
0049         break;
0050     case 0x2:
0051         /* 2-byte alignment */
0052         while (count--) {
0053             l = (*(u16 *)src) << 16;
0054             l |= *(u16 *)(src + sizeof(u16));
0055             __raw_writel(l, addr);
0056             src += sizeof(u32);
0057         }
0058         break;
0059     case 0x1:
0060         /* Hold three bytes in l each time, grab a byte from l2 */
0061         l = (*(u8 *)src) << 24;
0062         l |= (*(u16 *)(src + sizeof(u8))) << 8;
0063         src += sizeof(u8) + sizeof(u16);
0064         while (count--) {
0065             l2 = *(u32 *)src;
0066             l |= (l2 >> 24);
0067             __raw_writel(l, addr);
0068             l = l2 << 8;
0069             src += sizeof(u32);
0070         }
0071         break;
0072     case 0x3:
0073         /* Hold a byte in l each time, grab 3 bytes from l2 */
0074         l = (*(u8 *)src) << 24;
0075         src += sizeof(u8);
0076         while (count--) {
0077             l2 = *(u32 *)src;
0078             l |= (l2 >> 8);
0079             __raw_writel(l, addr);
0080             l = l2 << 24;
0081             src += sizeof(u32);
0082         }
0083         break;
0084     }
0085 }
0086 EXPORT_SYMBOL(outsl);
0087 
0088 void insb(unsigned long __addr, void *dst, unsigned long count)
0089 {
0090     void __iomem *addr = (void __iomem *) __addr;
0091 
0092     if (count) {
0093         u32 *pi;
0094         u8 *pb = dst;
0095 
0096         while ((((unsigned long)pb) & 0x3) && count--)
0097             *pb++ = __raw_readb(addr);
0098         pi = (u32 *)pb;
0099         while (count >= 4) {
0100             u32 w;
0101 
0102             w  = (__raw_readb(addr) << 24);
0103             w |= (__raw_readb(addr) << 16);
0104             w |= (__raw_readb(addr) << 8);
0105             w |= (__raw_readb(addr) << 0);
0106             *pi++ = w;
0107             count -= 4;
0108         }
0109         pb = (u8 *)pi;
0110         while (count--)
0111             *pb++ = __raw_readb(addr);
0112     }
0113 }
0114 EXPORT_SYMBOL(insb);
0115 
0116 void insw(unsigned long __addr, void *dst, unsigned long count)
0117 {
0118     void __iomem *addr = (void __iomem *) __addr;
0119 
0120     if (count) {
0121         u16 *ps = dst;
0122         u32 *pi;
0123 
0124         if (((unsigned long)ps) & 0x2) {
0125             *ps++ = __raw_readw(addr);
0126             count--;
0127         }
0128         pi = (u32 *)ps;
0129         while (count >= 2) {
0130             u32 w;
0131 
0132             w  = __raw_readw(addr) << 16;
0133             w |= __raw_readw(addr) << 0;
0134             *pi++ = w;
0135             count -= 2;
0136         }
0137         ps = (u16 *)pi;
0138         if (count)
0139             *ps = __raw_readw(addr);
0140     }
0141 }
0142 EXPORT_SYMBOL(insw);
0143 
0144 void insl(unsigned long __addr, void *dst, unsigned long count)
0145 {
0146     void __iomem *addr = (void __iomem *) __addr;
0147 
0148     if (count) {
0149         if ((((unsigned long)dst) & 0x3) == 0) {
0150             u32 *pi = dst;
0151             while (count--)
0152                 *pi++ = __raw_readl(addr);
0153         } else {
0154             u32 l = 0, l2, *pi;
0155             u16 *ps;
0156             u8 *pb;
0157 
0158             switch (((unsigned long)dst) & 3) {
0159             case 0x2:
0160                 ps = dst;
0161                 count -= 1;
0162                 l = __raw_readl(addr);
0163                 *ps++ = l;
0164                 pi = (u32 *)ps;
0165                 while (count--) {
0166                     l2 = __raw_readl(addr);
0167                     *pi++ = (l << 16) | (l2 >> 16);
0168                     l = l2;
0169                 }
0170                 ps = (u16 *)pi;
0171                 *ps = l;
0172                 break;
0173 
0174             case 0x1:
0175                 pb = dst;
0176                 count -= 1;
0177                 l = __raw_readl(addr);
0178                 *pb++ = l >> 24;
0179                 ps = (u16 *)pb;
0180                 *ps++ = ((l >> 8) & 0xffff);
0181                 pi = (u32 *)ps;
0182                 while (count--) {
0183                     l2 = __raw_readl(addr);
0184                     *pi++ = (l << 24) | (l2 >> 8);
0185                     l = l2;
0186                 }
0187                 pb = (u8 *)pi;
0188                 *pb = l;
0189                 break;
0190 
0191             case 0x3:
0192                 pb = (u8 *)dst;
0193                 count -= 1;
0194                 l = __raw_readl(addr);
0195                 *pb++ = l >> 24;
0196                 pi = (u32 *)pb;
0197                 while (count--) {
0198                     l2 = __raw_readl(addr);
0199                     *pi++ = (l << 8) | (l2 >> 24);
0200                     l = l2;
0201                 }
0202                 ps = (u16 *)pi;
0203                 *ps++ = ((l >> 8) & 0xffff);
0204                 pb = (u8 *)ps;
0205                 *pb = l;
0206                 break;
0207             }
0208         }
0209     }
0210 }
0211 EXPORT_SYMBOL(insl);
0212