]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - include/pcmcia/mem_op.h
pcmcia: simplify locking
[linux-2.6.git] / include / pcmcia / mem_op.h
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 <linux/io.h>
19 #include <asm/uaccess.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
33 static 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
45 static 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
64 static 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
75 static 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
86 static 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
97 static 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 */