]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/uaccess_dsp.h
a2ac7b62446f8676682023beb70ee3d9919e5e6d
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / 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 "dsp_common.h"
29
30 #define HAVE_ASM_COPY_FROM_USER_DSP_2B
31
32 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
33 extern unsigned long __copy_from_user_dsp_2b(void *to,
34                                                   const void __user *from);
35 extern unsigned long __copy_to_user_dsp_2b(void __user *to,
36                                                 const void *from);
37 #endif
38
39 #ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
40 static __inline__ unsigned long copy_from_user_dsp_2b(void *to,
41                                                       const void *from)
42 {
43         unsigned short tmp;
44
45         if (__copy_from_user(&tmp, from, 2))
46                 return 2;
47         /* expecting compiler to generate "strh" instruction */
48         *((unsigned short *)to) = tmp;
49         return 0;
50 }
51 #endif
52
53 /*
54  * @n must be multiple of 2
55  */
56 static __inline__ unsigned long copy_from_user_dsp(void *to, const void *from,
57                                                    unsigned long n)
58 {
59         if (access_ok(VERIFY_READ, from, n)) {
60                 if ((is_dsp_internal_mem(to)) &&
61                     (((unsigned long)to & 2) || (n & 2))) {
62                         /*
63                          * DARAM/SARAM with odd word alignment
64                          */
65                         unsigned long n4;
66                         unsigned long last_n;
67
68                         /* dest not aligned -- copy 2 bytes */
69                         if (((unsigned long)to & 2) && (n >= 2)) {
70 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
71                                 if (__copy_from_user_dsp_2b(to, from))
72 #else
73                                 if (copy_from_user_dsp_2b(to, from))
74 #endif
75                                         return n;
76                                 to += 2;
77                                 from += 2;
78                                 n -= 2;
79                         }
80                         /* middle 4*n bytes */
81                         last_n = n & 2;
82                         n4 = n - last_n;
83                         if ((n = __copy_from_user(to, from, n4)) != 0)
84                                 return n + last_n;
85                         /* last 2 bytes */
86                         if (last_n) {
87                                 to += n4;
88                                 from += n4;
89 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
90                                 if (__copy_from_user_dsp_2b(to, from))
91 #else
92                                 if (copy_from_user_dsp_2b(to, from))
93 #endif
94                                         return 2;
95                                 n = 0;
96                         }
97                 } else {
98                         /*
99                          * DARAM/SARAM with 4-byte alignment or
100                          * external memory
101                          */
102                         n = __copy_from_user(to, from, n);
103                 }
104         }
105         else    /* security hole - plug it */
106                 memzero(to, n);
107         return n;
108 }
109
110 #ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B
111 static __inline__ unsigned long copy_to_user_dsp_2b(void *to, const void *from)
112 {
113         /* expecting compiler to generate "strh" instruction */
114         unsigned short tmp = *(unsigned short *)from;
115
116         return __copy_to_user(to, &tmp, 2);
117 }
118 #endif
119
120 /*
121  * @n must be multiple of 2
122  */
123 static __inline__ unsigned long copy_to_user_dsp(void *to, const void *from,
124                                                  unsigned long n)
125 {
126         if (access_ok(VERIFY_WRITE, to, n)) {
127                 if ((is_dsp_internal_mem(from)) &&
128                     (((unsigned long)to & 2) || (n & 2))) {
129                         /*
130                          * DARAM/SARAM with odd word alignment
131                          */
132                         unsigned long n4;
133                         unsigned long last_n;
134
135                         /* dest not aligned -- copy 2 bytes */
136                         if (((unsigned long)to & 2) && (n >= 2)) {
137 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
138                                 if (__copy_to_user_dsp_2b(to, from))
139 #else
140                                 if (copy_to_user_dsp_2b(to, from))
141 #endif
142                                         return n;
143                                 to += 2;
144                                 from += 2;
145                                 n -= 2;
146                         }
147                         /* middle 4*n bytes */
148                         last_n = n & 2;
149                         n4 = n - last_n;
150                         if ((n = __copy_to_user(to, from, n4)) != 0)
151                                 return n + last_n;
152                         /* last 2 bytes */
153                         if (last_n) {
154                                 to += n4;
155                                 from += n4;
156 #ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B
157                                 if (__copy_to_user_dsp_2b(to, from))
158 #else
159                                 if (copy_to_user_dsp_2b(to, from))
160 #endif
161                                         return 2;
162                                 n = 0;
163                         }
164                 } else {
165                         /*
166                          * DARAM/SARAM with 4-byte alignment or
167                          * external memory
168                          */
169                         n = __copy_to_user(to, from, n);
170                 }
171         }
172         return n;
173 }
174
175 #endif /* _OMAP_DSP_UACCESS_DSP_H */