| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* $Id: PeeCeeI.c,v 1.4 1999/09/06 01:17:35 davem Exp $ | 
|  | 2 | * PeeCeeI.c: The emerging standard... | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) | 
|  | 5 | */ | 
|  | 6 |  | 
|  | 7 | #include <asm/io.h> | 
|  | 8 | #include <asm/byteorder.h> | 
|  | 9 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 10 | void outsb(unsigned long __addr, const void *src, unsigned long count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 11 | { | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 12 | void __iomem *addr = (void __iomem *) __addr; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 13 | const u8 *p = src; | 
|  | 14 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 15 | while (count--) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 16 | outb(*p++, addr); | 
|  | 17 | } | 
|  | 18 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 19 | void outsw(unsigned long __addr, const void *src, unsigned long count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 20 | { | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 21 | void __iomem *addr = (void __iomem *) __addr; | 
|  | 22 |  | 
|  | 23 | if (count) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 24 | u16 *ps = (u16 *)src; | 
|  | 25 | u32 *pi; | 
|  | 26 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 27 | if (((u64)src) & 0x2) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 28 | u16 val = le16_to_cpup(ps); | 
|  | 29 | outw(val, addr); | 
|  | 30 | ps++; | 
|  | 31 | count--; | 
|  | 32 | } | 
|  | 33 | pi = (u32 *)ps; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 34 | while (count >= 2) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 35 | u32 w = le32_to_cpup(pi); | 
|  | 36 |  | 
|  | 37 | pi++; | 
|  | 38 | outw(w >> 0, addr); | 
|  | 39 | outw(w >> 16, addr); | 
|  | 40 | count -= 2; | 
|  | 41 | } | 
|  | 42 | ps = (u16 *)pi; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 43 | if (count) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | u16 val = le16_to_cpup(ps); | 
|  | 45 | outw(val, addr); | 
|  | 46 | } | 
|  | 47 | } | 
|  | 48 | } | 
|  | 49 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 50 | void outsl(unsigned long __addr, const void *src, unsigned long count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 51 | { | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 52 | void __iomem *addr = (void __iomem *) __addr; | 
|  | 53 |  | 
|  | 54 | if (count) { | 
|  | 55 | if ((((u64)src) & 0x3) == 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 56 | u32 *p = (u32 *)src; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 57 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 58 | u32 val = cpu_to_le32p(p); | 
|  | 59 | outl(val, addr); | 
|  | 60 | p++; | 
|  | 61 | } | 
|  | 62 | } else { | 
|  | 63 | u8 *pb; | 
|  | 64 | u16 *ps = (u16 *)src; | 
|  | 65 | u32 l = 0, l2; | 
|  | 66 | u32 *pi; | 
|  | 67 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 68 | switch (((u64)src) & 0x3) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 69 | case 0x2: | 
|  | 70 | count -= 1; | 
|  | 71 | l = cpu_to_le16p(ps) << 16; | 
|  | 72 | ps++; | 
|  | 73 | pi = (u32 *)ps; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 74 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 | l2 = cpu_to_le32p(pi); | 
|  | 76 | pi++; | 
|  | 77 | outl(((l >> 16) | (l2 << 16)), addr); | 
|  | 78 | l = l2; | 
|  | 79 | } | 
|  | 80 | ps = (u16 *)pi; | 
|  | 81 | l2 = cpu_to_le16p(ps); | 
|  | 82 | outl(((l >> 16) | (l2 << 16)), addr); | 
|  | 83 | break; | 
|  | 84 |  | 
|  | 85 | case 0x1: | 
|  | 86 | count -= 1; | 
|  | 87 | pb = (u8 *)src; | 
|  | 88 | l = (*pb++ << 8); | 
|  | 89 | ps = (u16 *)pb; | 
|  | 90 | l2 = cpu_to_le16p(ps); | 
|  | 91 | ps++; | 
|  | 92 | l |= (l2 << 16); | 
|  | 93 | pi = (u32 *)ps; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 94 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 95 | l2 = cpu_to_le32p(pi); | 
|  | 96 | pi++; | 
|  | 97 | outl(((l >> 8) | (l2 << 24)), addr); | 
|  | 98 | l = l2; | 
|  | 99 | } | 
|  | 100 | pb = (u8 *)pi; | 
|  | 101 | outl(((l >> 8) | (*pb << 24)), addr); | 
|  | 102 | break; | 
|  | 103 |  | 
|  | 104 | case 0x3: | 
|  | 105 | count -= 1; | 
|  | 106 | pb = (u8 *)src; | 
|  | 107 | l = (*pb++ << 24); | 
|  | 108 | pi = (u32 *)pb; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 109 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 110 | l2 = cpu_to_le32p(pi); | 
|  | 111 | pi++; | 
|  | 112 | outl(((l >> 24) | (l2 << 8)), addr); | 
|  | 113 | l = l2; | 
|  | 114 | } | 
|  | 115 | ps = (u16 *)pi; | 
|  | 116 | l2 = cpu_to_le16p(ps); | 
|  | 117 | ps++; | 
|  | 118 | pb = (u8 *)ps; | 
|  | 119 | l2 |= (*pb << 16); | 
|  | 120 | outl(((l >> 24) | (l2 << 8)), addr); | 
|  | 121 | break; | 
|  | 122 | } | 
|  | 123 | } | 
|  | 124 | } | 
|  | 125 | } | 
|  | 126 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 127 | void insb(unsigned long __addr, void *dst, unsigned long count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 128 | { | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 129 | void __iomem *addr = (void __iomem *) __addr; | 
|  | 130 |  | 
|  | 131 | if (count) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | u32 *pi; | 
|  | 133 | u8 *pb = dst; | 
|  | 134 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 135 | while ((((unsigned long)pb) & 0x3) && count--) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 136 | *pb++ = inb(addr); | 
|  | 137 | pi = (u32 *)pb; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 138 | while (count >= 4) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 139 | u32 w; | 
|  | 140 |  | 
|  | 141 | w  = (inb(addr) << 24); | 
|  | 142 | w |= (inb(addr) << 16); | 
|  | 143 | w |= (inb(addr) << 8); | 
|  | 144 | w |= (inb(addr) << 0); | 
|  | 145 | *pi++ = w; | 
|  | 146 | count -= 4; | 
|  | 147 | } | 
|  | 148 | pb = (u8 *)pi; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 149 | while (count--) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 150 | *pb++ = inb(addr); | 
|  | 151 | } | 
|  | 152 | } | 
|  | 153 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 154 | void insw(unsigned long __addr, void *dst, unsigned long count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 155 | { | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 156 | void __iomem *addr = (void __iomem *) __addr; | 
|  | 157 |  | 
|  | 158 | if (count) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 159 | u16 *ps = dst; | 
|  | 160 | u32 *pi; | 
|  | 161 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 162 | if (((unsigned long)ps) & 0x2) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 163 | *ps++ = le16_to_cpu(inw(addr)); | 
|  | 164 | count--; | 
|  | 165 | } | 
|  | 166 | pi = (u32 *)ps; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 167 | while (count >= 2) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 168 | u32 w; | 
|  | 169 |  | 
|  | 170 | w  = (le16_to_cpu(inw(addr)) << 16); | 
|  | 171 | w |= (le16_to_cpu(inw(addr)) << 0); | 
|  | 172 | *pi++ = w; | 
|  | 173 | count -= 2; | 
|  | 174 | } | 
|  | 175 | ps = (u16 *)pi; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 176 | if (count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 177 | *ps = le16_to_cpu(inw(addr)); | 
|  | 178 | } | 
|  | 179 | } | 
|  | 180 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 181 | void insl(unsigned long __addr, void *dst, unsigned long count) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 182 | { | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 183 | void __iomem *addr = (void __iomem *) __addr; | 
|  | 184 |  | 
|  | 185 | if (count) { | 
|  | 186 | if ((((unsigned long)dst) & 0x3) == 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 187 | u32 *pi = dst; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 188 | while (count--) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 189 | *pi++ = le32_to_cpu(inl(addr)); | 
|  | 190 | } else { | 
|  | 191 | u32 l = 0, l2, *pi; | 
|  | 192 | u16 *ps; | 
|  | 193 | u8 *pb; | 
|  | 194 |  | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 195 | switch (((unsigned long)dst) & 3) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 196 | case 0x2: | 
|  | 197 | ps = dst; | 
|  | 198 | count -= 1; | 
|  | 199 | l = le32_to_cpu(inl(addr)); | 
|  | 200 | *ps++ = l; | 
|  | 201 | pi = (u32 *)ps; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 202 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 203 | l2 = le32_to_cpu(inl(addr)); | 
|  | 204 | *pi++ = (l << 16) | (l2 >> 16); | 
|  | 205 | l = l2; | 
|  | 206 | } | 
|  | 207 | ps = (u16 *)pi; | 
|  | 208 | *ps = l; | 
|  | 209 | break; | 
|  | 210 |  | 
|  | 211 | case 0x1: | 
|  | 212 | pb = dst; | 
|  | 213 | count -= 1; | 
|  | 214 | l = le32_to_cpu(inl(addr)); | 
|  | 215 | *pb++ = l >> 24; | 
|  | 216 | ps = (u16 *)pb; | 
|  | 217 | *ps++ = ((l >> 8) & 0xffff); | 
|  | 218 | pi = (u32 *)ps; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 219 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 220 | l2 = le32_to_cpu(inl(addr)); | 
|  | 221 | *pi++ = (l << 24) | (l2 >> 8); | 
|  | 222 | l = l2; | 
|  | 223 | } | 
|  | 224 | pb = (u8 *)pi; | 
|  | 225 | *pb = l; | 
|  | 226 | break; | 
|  | 227 |  | 
|  | 228 | case 0x3: | 
|  | 229 | pb = (u8 *)dst; | 
|  | 230 | count -= 1; | 
|  | 231 | l = le32_to_cpu(inl(addr)); | 
|  | 232 | *pb++ = l >> 24; | 
|  | 233 | pi = (u32 *)pb; | 
| David S. Miller | 8a36895 | 2005-08-31 15:01:33 -0700 | [diff] [blame] | 234 | while (count--) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 235 | l2 = le32_to_cpu(inl(addr)); | 
|  | 236 | *pi++ = (l << 8) | (l2 >> 24); | 
|  | 237 | l = l2; | 
|  | 238 | } | 
|  | 239 | ps = (u16 *)pi; | 
|  | 240 | *ps++ = ((l >> 8) & 0xffff); | 
|  | 241 | pb = (u8 *)ps; | 
|  | 242 | *pb = l; | 
|  | 243 | break; | 
|  | 244 | } | 
|  | 245 | } | 
|  | 246 | } | 
|  | 247 | } | 
|  | 248 |  |