Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
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 */ |