linux/include/pcmcia/mem_op.h
<<
>>
Prefs
   1/*
   2 * mem_op.h
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * The initial developer of the original code is David A. Hinds
   9 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  10 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  11 *
  12 * (C) 1999             David A. Hinds
  13 */
  14
  15#ifndef _LINUX_MEM_OP_H
  16#define _LINUX_MEM_OP_H
  17
  18#include <asm/uaccess.h>
  19#include <asm/io.h>
  20
  21/*
  22   If UNSAFE_MEMCPY is defined, we use the (optimized) system routines
  23   to copy between a card and kernel memory.  These routines do 32-bit
  24   operations which may not work with all PCMCIA controllers.  The
  25   safe versions defined here will do only 8-bit and 16-bit accesses.
  26*/
  27
  28#ifdef UNSAFE_MEMCPY
  29
  30#define copy_from_pc memcpy_fromio
  31#define copy_to_pc memcpy_toio
  32
  33static inline void copy_pc_to_user(void *to, const void *from, size_t n)
  34{
  35    size_t odd = (n & 3);
  36    n -= odd;
  37    while (n) {
  38        put_user(__raw_readl(from), (int *)to);
  39        (char *)from += 4; (char *)to += 4; n -= 4;
  40    }
  41    while (odd--)
  42        put_user(readb((char *)from++), (char *)to++);
  43}
  44
  45static inline void copy_user_to_pc(void *to, const void *from, size_t n)
  46{
  47    int l;
  48    char c;
  49    size_t odd = (n & 3);
  50    n -= odd;
  51    while (n) {
  52        get_user(l, (int *)from);
  53        __raw_writel(l, to);
  54        (char *)to += 4; (char *)from += 4; n -= 4;
  55    }
  56    while (odd--) {
  57        get_user(c, (char *)from++);
  58        writeb(c, (char *)to++);
  59    }
  60}
  61
  62#else /* UNSAFE_MEMCPY */
  63
  64static inline void copy_from_pc(void *to, void __iomem *from, size_t n)
  65{
  66        __u16 *t = to;
  67        __u16 __iomem *f = from;
  68        size_t odd = (n & 1);
  69        for (n >>= 1; n; n--)
  70                *t++ = __raw_readw(f++);
  71        if (odd)
  72                *(__u8 *)t = readb(f);
  73}
  74
  75static inline void copy_to_pc(void __iomem *to, const void *from, size_t n)
  76{
  77        __u16 __iomem *t = to;
  78        const __u16 *f = from;
  79        size_t odd = (n & 1);
  80        for (n >>= 1; n ; n--)
  81                __raw_writew(*f++, t++);
  82        if (odd)
  83                writeb(*(__u8 *)f, t);
  84}
  85
  86static inline void copy_pc_to_user(void __user *to, void __iomem *from, size_t n)
  87{
  88        __u16 __user *t = to;
  89        __u16 __iomem *f = from;
  90        size_t odd = (n & 1);
  91        for (n >>= 1; n ; n--)
  92                put_user(__raw_readw(f++), t++);
  93        if (odd)
  94                put_user(readb(f), (char __user *)t);
  95}
  96
  97static inline void copy_user_to_pc(void __iomem *to, void __user *from, size_t n)
  98{
  99        __u16 __user *f = from;
 100        __u16 __iomem *t = to;
 101        short s;
 102        char c;
 103        size_t odd = (n & 1);
 104        for (n >>= 1; n; n--) {
 105                get_user(s, f++);
 106                __raw_writew(s, t++);
 107        }
 108        if (odd) {
 109                get_user(c, (char __user *)f);
 110                writeb(c, t);
 111        }
 112}
 113
 114#endif /* UNSAFE_MEMCPY */
 115
 116#endif /* _LINUX_MEM_OP_H */
 117