linux/arch/alpha/kernel/io.c
<<
>>
Prefs
   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
  15unsigned int
  16ioread8(void __iomem *addr)
  17{
  18        unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
  19        mb();
  20        return ret;
  21}
  22
  23unsigned int ioread16(void __iomem *addr)
  24{
  25        unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
  26        mb();
  27        return ret;
  28}
  29
  30unsigned int ioread32(void __iomem *addr)
  31{
  32        unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
  33        mb();
  34        return ret;
  35}
  36
  37void iowrite8(u8 b, void __iomem *addr)
  38{
  39        IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
  40        mb();
  41}
  42
  43void iowrite16(u16 b, void __iomem *addr)
  44{
  45        IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
  46        mb();
  47}
  48
  49void iowrite32(u32 b, void __iomem *addr)
  50{
  51        IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
  52        mb();
  53}
  54
  55EXPORT_SYMBOL(ioread8);
  56EXPORT_SYMBOL(ioread16);
  57EXPORT_SYMBOL(ioread32);
  58EXPORT_SYMBOL(iowrite8);
  59EXPORT_SYMBOL(iowrite16);
  60EXPORT_SYMBOL(iowrite32);
  61
  62u8 inb(unsigned long port)
  63{
  64        return ioread8(ioport_map(port, 1));
  65}
  66
  67u16 inw(unsigned long port)
  68{
  69        return ioread16(ioport_map(port, 2));
  70}
  71
  72u32 inl(unsigned long port)
  73{
  74        return ioread32(ioport_map(port, 4));
  75}
  76
  77void outb(u8 b, unsigned long port)
  78{
  79        iowrite8(b, ioport_map(port, 1));
  80}
  81
  82void outw(u16 b, unsigned long port)
  83{
  84        iowrite16(b, ioport_map(port, 2));
  85}
  86
  87void outl(u32 b, unsigned long port)
  88{
  89        iowrite32(b, ioport_map(port, 4));
  90}
  91
  92EXPORT_SYMBOL(inb);
  93EXPORT_SYMBOL(inw);
  94EXPORT_SYMBOL(inl);
  95EXPORT_SYMBOL(outb);
  96EXPORT_SYMBOL(outw);
  97EXPORT_SYMBOL(outl);
  98
  99u8 __raw_readb(const volatile void __iomem *addr)
 100{
 101        return IO_CONCAT(__IO_PREFIX,readb)(addr);
 102}
 103
 104u16 __raw_readw(const volatile void __iomem *addr)
 105{
 106        return IO_CONCAT(__IO_PREFIX,readw)(addr);
 107}
 108
 109u32 __raw_readl(const volatile void __iomem *addr)
 110{
 111        return IO_CONCAT(__IO_PREFIX,readl)(addr);
 112}
 113
 114u64 __raw_readq(const volatile void __iomem *addr)
 115{
 116        return IO_CONCAT(__IO_PREFIX,readq)(addr);
 117}
 118
 119void __raw_writeb(u8 b, volatile void __iomem *addr)
 120{
 121        IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
 122}
 123
 124void __raw_writew(u16 b, volatile void __iomem *addr)
 125{
 126        IO_CONCAT(__IO_PREFIX,writew)(b, addr);
 127}
 128
 129void __raw_writel(u32 b, volatile void __iomem *addr)
 130{
 131        IO_CONCAT(__IO_PREFIX,writel)(b, addr);
 132}
 133
 134void __raw_writeq(u64 b, volatile void __iomem *addr)
 135{
 136        IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
 137}
 138
 139EXPORT_SYMBOL(__raw_readb); 
 140EXPORT_SYMBOL(__raw_readw); 
 141EXPORT_SYMBOL(__raw_readl); 
 142EXPORT_SYMBOL(__raw_readq); 
 143EXPORT_SYMBOL(__raw_writeb); 
 144EXPORT_SYMBOL(__raw_writew); 
 145EXPORT_SYMBOL(__raw_writel); 
 146EXPORT_SYMBOL(__raw_writeq); 
 147
 148u8 readb(const volatile void __iomem *addr)
 149{
 150        u8 ret = __raw_readb(addr);
 151        mb();
 152        return ret;
 153}
 154
 155u16 readw(const volatile void __iomem *addr)
 156{
 157        u16 ret = __raw_readw(addr);
 158        mb();
 159        return ret;
 160}
 161
 162u32 readl(const volatile void __iomem *addr)
 163{
 164        u32 ret = __raw_readl(addr);
 165        mb();
 166        return ret;
 167}
 168
 169u64 readq(const volatile void __iomem *addr)
 170{
 171        u64 ret = __raw_readq(addr);
 172        mb();
 173        return ret;
 174}
 175
 176void writeb(u8 b, volatile void __iomem *addr)
 177{
 178        __raw_writeb(b, addr);
 179        mb();
 180}
 181
 182void writew(u16 b, volatile void __iomem *addr)
 183{
 184        __raw_writew(b, addr);
 185        mb();
 186}
 187
 188void writel(u32 b, volatile void __iomem *addr)
 189{
 190        __raw_writel(b, addr);
 191        mb();
 192}
 193
 194void writeq(u64 b, volatile void __iomem *addr)
 195{
 196        __raw_writeq(b, addr);
 197        mb();
 198}
 199
 200EXPORT_SYMBOL(readb);
 201EXPORT_SYMBOL(readw);
 202EXPORT_SYMBOL(readl);
 203EXPORT_SYMBOL(readq);
 204EXPORT_SYMBOL(writeb);
 205EXPORT_SYMBOL(writew);
 206EXPORT_SYMBOL(writel);
 207EXPORT_SYMBOL(writeq);
 208
 209
 210/*
 211 * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
 212 */
 213void 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
 241void insb(unsigned long port, void *dst, unsigned long count)
 242{
 243        ioread8_rep(ioport_map(port, 1), dst, count);
 244}
 245
 246EXPORT_SYMBOL(ioread8_rep);
 247EXPORT_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 */
 256void 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
 281void insw(unsigned long port, void *dst, unsigned long count)
 282{
 283        ioread16_rep(ioport_map(port, 2), dst, count);
 284}
 285
 286EXPORT_SYMBOL(ioread16_rep);
 287EXPORT_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 */
 296void 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
 313void insl(unsigned long port, void *dst, unsigned long count)
 314{
 315        ioread32_rep(ioport_map(port, 4), dst, count);
 316}
 317
 318EXPORT_SYMBOL(ioread32_rep);
 319EXPORT_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 */
 328void 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
 335void outsb(unsigned long port, const void *src, unsigned long count)
 336{
 337        iowrite8_rep(ioport_map(port, 1), src, count);
 338}
 339
 340EXPORT_SYMBOL(iowrite8_rep);
 341EXPORT_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 */
 350void 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
 375void outsw(unsigned long port, const void *src, unsigned long count)
 376{
 377        iowrite16_rep(ioport_map(port, 2), src, count);
 378}
 379
 380EXPORT_SYMBOL(iowrite16_rep);
 381EXPORT_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 */
 390void 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
 407void outsl(unsigned long port, const void *src, unsigned long count)
 408{
 409        iowrite32_rep(ioport_map(port, 4), src, count);
 410}
 411
 412EXPORT_SYMBOL(iowrite32_rep);
 413EXPORT_SYMBOL(outsl);
 414
 415
 416/*
 417 * Copy data from IO memory space to "real" memory space.
 418 * This needs to be optimized.
 419 */
 420void 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
 467EXPORT_SYMBOL(memcpy_fromio);
 468
 469
 470/*
 471 * Copy data from "real" memory space to IO memory space.
 472 * This needs to be optimized.
 473 */
 474void 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
 522EXPORT_SYMBOL(memcpy_toio);
 523
 524
 525/*
 526 * "memset" on IO memory space.
 527 */
 528void _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
 584EXPORT_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
 589void
 590scr_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
 618EXPORT_SYMBOL(scr_memcpyw);
 619
 620void __iomem *ioport_map(unsigned long port, unsigned int size)
 621{
 622        return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
 623}
 624
 625void ioport_unmap(void __iomem *addr)
 626{
 627}
 628
 629EXPORT_SYMBOL(ioport_map);
 630EXPORT_SYMBOL(ioport_unmap);
 631