Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / drivers / dsp / dspgateway / uaccess_dsp.h
1 /*
2  * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
3  *
4  * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #ifndef _OMAP_DSP_UACCESS_DSP_H
25 #define _OMAP_DSP_UACCESS_DSP_H
26
27 #include <asm/uaccess.h>
28 #include <mach/dsp_common.h>
29 #include "dsp.h"
30
31 #define HAVE_ASM_COPY_FROM_USER_DSP_2B
32
33 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
34 extern unsigned long __copy_from_user_dsp_2b(void *to,
35                                                   const void __user *from);
36 extern unsigned long __copy_to_user_dsp_2b(void __user *to,
37                                                 const void *from);
38 #endif
39
40 #ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
41 static inline unsigned long copy_from_user_dsp_2b(void *to,
42                                                       const void *from)
43 {
44         unsigned short tmp;
45
46         if (__copy_from_user(&tmp, from, 2))
47                 return 2;
48         /* expecting compiler to generate "strh" instruction */
49         *((unsigned short *)to) = tmp;
50         return 0;
51 }
52 #endif
53
54 /*
55  * @n must be multiple of 2
56  */
57 static inline unsigned long copy_from_user_dsp(void *to, const void *from,
58                                                    unsigned long n)
59 {
60         if (access_ok(VERIFY_READ, from, n)) {
61                 if ((is_dsp_internal_mem(to)) &&
62                     (((unsigned long)to & 2) || (n & 2))) {
63                         /*
64                          * DARAM/SARAM with odd word alignment
65                          */
66                         unsigned long n4;
67                         unsigned long last_n;
68
69                         /* dest not aligned -- copy 2 bytes */
70                         if (((unsigned long)to & 2) && (n >= 2)) {
71 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
72                                 if (__copy_from_user_dsp_2b(to, from))
73 #else
74                                 if (copy_from_user_dsp_2b(to, from))
75 #endif
76                                         return n;
77                                 to += 2;
78                                 from += 2;
79                                 n -= 2;
80                         }
81                         /* middle 4*n bytes */
82                         last_n = n & 2;
83                         n4 = n - last_n;
84                         if ((n = __copy_from_user(to, from, n4)) != 0)
85                                 return n + last_n;
86                         /* last 2 bytes */
87                         if (last_n) {
88                                 to += n4;
89                                 from += n4;
90 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
91                                 if (__copy_from_user_dsp_2b(to, from))
92 #else
93                                 if (copy_from_user_dsp_2b(to, from))
94 #endif
95                                         return 2;
96                                 n = 0;
97                         }
98                 } else {
99                         /*
100                          * DARAM/SARAM with 4-byte alignment or
101                          * external memory
102                          */
103                         n = __copy_from_user(to, from, n);
104                 }
105         }
106         else    /* security hole - plug it */
107                 memzero(to, n);
108         return n;
109 }
110
111 #ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
112 static inline unsigned long copy_to_user_dsp_2b(void *to, const void *from)
113 {
114         /* expecting compiler to generate "strh" instruction */
115         unsigned short tmp = *(unsigned short *)from;
116
117         return __copy_to_user(to, &tmp, 2);
118 }
119 #endif
120
121 /*
122  * @n must be multiple of 2
123  */
124 static inline unsigned long copy_to_user_dsp(void *to, const void *from,
125                                                  unsigned long n)
126 {
127         if (access_ok(VERIFY_WRITE, to, n)) {
128                 if ((is_dsp_internal_mem(from)) &&
129                     (((unsigned long)to & 2) || (n & 2))) {
130                         /*
131                          * DARAM/SARAM with odd word alignment
132                          */
133                         unsigned long n4;
134                         unsigned long last_n;
135
136                         /* dest not aligned -- copy 2 bytes */
137                         if (((unsigned long)to & 2) && (n >= 2)) {
138 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
139                                 if (__copy_to_user_dsp_2b(to, from))
140 #else
141                                 if (copy_to_user_dsp_2b(to, from))
142 #endif
143                                         return n;
144                                 to += 2;
145                                 from += 2;
146                                 n -= 2;
147                         }
148                         /* middle 4*n bytes */
149                         last_n = n & 2;
150                         n4 = n - last_n;
151                         if ((n = __copy_to_user(to, from, n4)) != 0)
152                                 return n + last_n;
153                         /* last 2 bytes */
154                         if (last_n) {
155                                 to += n4;
156                                 from += n4;
157 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
158                                 if (__copy_to_user_dsp_2b(to, from))
159 #else
160                                 if (copy_to_user_dsp_2b(to, from))
161 #endif
162                                         return 2;
163                                 n = 0;
164                         }
165                 } else {
166                         /*
167                          * DARAM/SARAM with 4-byte alignment or
168                          * external memory
169                          */
170                         n = __copy_to_user(to, from, n);
171                 }
172         }
173         return n;
174 }
175
176 #endif /* _OMAP_DSP_UACCESS_DSP_H */