2 *-----------------------------------------------------------------------------
5 *-----------------------------------------------------------------------------
6 * Copyright (c) 2002-2010, Intel Corporation.
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 *-----------------------------------------------------------------------------
28 * This file contains OS abstracted interfaces to common memory operations.
29 *-----------------------------------------------------------------------------
35 #include <linux/slab.h>
37 unsigned long os_gart_alloc_page( void );
38 unsigned long os_gart_virt_to_phys( unsigned char *a );
39 void os_gart_free_page( unsigned char *a );
41 /* #define INSTRUMENT_KERNEL_ALLOCS */
42 #ifdef INSTRUMENT_KERNEL_ALLOCS
43 #define MAX_FUNC_NAME 64
45 typedef struct _os_allocd_mem {
48 char function[MAX_FUNC_NAME];
49 struct _os_allocd_mem *next;
52 extern os_allocd_mem *list_head;
53 extern os_allocd_mem *list_tail;
55 static inline void *_os_alloc(unsigned int size, const char *function) {
57 void *ptr = kmalloc(size, GFP_KERNEL);
58 printk(KERN_DEBUG "%s OS_ALLOC(size=%u)=0x%p\n", function, size, ptr);
59 mem = kmalloc(sizeof(os_allocd_mem), GFP_KERNEL);
60 if (!ZERO_OR_NULL_PTR(mem)) {
63 strncpy(mem->function, function, MAX_FUNC_NAME);
64 mem->function[MAX_FUNC_NAME-1] = '\0';
66 if (NULL == list_tail) {
69 list_tail->next = mem;
76 static inline void _os_free(void *ptr, const char *function) {
77 printk(KERN_DEBUG "%s OS_FREE(0x%p)\n", function, ptr);
78 if (NULL != list_head) {
79 os_allocd_mem *mem = list_head;
80 os_allocd_mem *prev = NULL;
82 if (mem->ptr == ptr) {
83 if (mem == list_head) {
84 list_head = mem->next;
85 if (mem == list_tail) {
89 prev->next = mem->next;
90 if (mem == list_tail) {
104 static inline void emgd_report_unfreed_memory(void) {
105 os_allocd_mem *mem = list_head;
108 printk(KERN_DEBUG "%s() REPORT ON NON-FREED MEMORY:\n", __FUNCTION__);
109 while (NULL != mem) {
110 printk(KERN_DEBUG " addr=0x%p, size=%u, function=\"%s\"\n",
111 mem->ptr, mem->size, mem->function);
120 * void *OS_ALLOC(size_t size)
122 * OS_ALLOC is used by OS independent code to allocate system memory and
123 * return a CPU writeable address to the allocated memory (Virtual address)
124 * The returned address has no guarenteed alignment.
125 * size should be <= 4k for larger sizes use OS_ALLOC_LARGE().
127 * Allocations returned from OS_ALLOC() should be freed with OS_FREE().
129 * All Full OAL implementations must implement the _OS_ALLOC entry point
130 * to enable use of this function.
132 * @return NULL on Failure
133 * @return Virtual or Flat address on Success
135 #define OS_ALLOC(a) _os_alloc(a, __FUNCTION__)
138 * void OS_FREE(void *p)
139 * OS_FREE should be used to free allocations returned from OS_ALLOC()
141 * All Full OAL implementations must implement the _OS_FREE entry point
142 * to enable use of this function.
144 #define OS_FREE(a) _os_free(a, __FUNCTION__)
147 * void *OS_ALLOC_LARGE(size_t size)
149 * OS_ALLOC_LARGE is used by OS independent code to allocate system memory
150 * in the same manner as OS_ALLOC except that size must be > 4k.
152 * Allocations returned from OS_ALLOC_LARGE() should be freed with
155 * All Full OAL implementations must implement the _OS_ALLOC_LARGE entry point
156 * to enable use of this function. This entry point may be implemented
157 * exactly the same as _OS_ALLOC is no diferentiation is required.
159 * @return NULL on Failure
160 * @return Virtual or Flat address on Success
162 #define OS_ALLOC_LARGE(a) _os_alloc(a, __FUNCTION__)
165 * void OS_FREE_LARGE(void *p)
166 * OS_FREE_LARGE should be used to free allocations returned from
169 * All Full OAL implementations must implement the _OS_FREE_LARGE entry point
170 * to enable use of this function. This entry point may be implemented
171 * exactly the same as _OS_FREE is no diferentiation is required.
174 #define OS_FREE_LARGE(a) _os_free(a, __FUNCTION__)
176 #else /* INSTRUMENT_KERNEL_ALLOCS */
178 #define OS_ALLOC(a) kmalloc((a), GFP_KERNEL)
179 #define OS_FREE(a) kfree(a)
180 #define OS_ALLOC_LARGE(a) kmalloc((a), GFP_KERNEL)
181 #define OS_FREE_LARGE(a) kfree(a)
183 #endif /* INSTRUMENT_KERNEL_ALLOCS */
185 #define OS_ALLOC_PAGE() NULL
187 * void *OS_VIRT_TO_PHYS( void *p )
189 * OS_VIRT_TO_PHYS is used by OS independent code to obtain the physical
190 * address referenced by the virtual address p. The virtual address must be
191 * one returned by OS_ALLOC_PAGE or OS_ALLOC_CONTIGUOUS.
193 * This entry point is OPTIONAL. Only OAL implementations that have
194 * implemented the _OS_ALLOC_PAGE or _OS_ALLOC_CONTIGUOUS macros need
195 * implement the _OS_VIRT_TO_PHYS macro. OS independent code that must
196 * function on all implementation may not use this entry point.
198 * @returns Physical Address
200 #define OS_VIRT_TO_PHYS(a) os_gart_virt_to_phys(a)
203 * void OS_FREE_PAGE(void *p)
204 * OS_FREE_PAGE should be used to free allocations returned from
207 * This entry point is OPTIONAL. Only OAL implementations that have implemented
208 * the _OS_ALLOC_PAGE macro need implement the _OS_FREE_PAGE macro.
210 #define OS_FREE_PAGE(a) os_gart_free_page(a)
212 #define OS_MEMSET(a,b,c) memset(a,b,c)
213 #define OS_MEMCPY(a,b,c) memcpy(a,b,c)
214 #define OS_MEMCMP(a,b,c) memcmp(a,b,c)
216 #define OS_OFFSETOF(t,m) offsetof(t,m)
220 * void *OS_MEMSET(void *s, int c, size_t n)
222 * OS_MEMSET sets all bytes of the memory area referenced by address s and
223 * size n to the char value c.
225 * ALL Full OAL implementations must implement the entry point _OS_MEMSET
226 * to enable use of this function.
231 #define OS_MEMSET(a,b,c) _oal_memset(a,b,c)
235 * void *OS_MEMCPY(void *dest, void *src, size_t n)
237 * OS_MEMCPY copies n bytes from the memory referenced by src to the
238 * memory referenced by dest. The areas may not overlap.
240 * ALL Full OAL implementations must implement the entry point _OS_MEMCPY
241 * to enable use of this function.
243 * @returns Address dest
246 #define OS_MEMCPY(a,b,c) _oal_memcpy(a,b,c)
250 * void *OS_MEMCMP(void *s1, void *s2, size_t n)
252 * OS_MEMCMP compares n bytes from the memory referenced by s1 to the
253 * corresponding bytes referenced by s2.
255 * This entry point is available in all full OAL implementations. An OAL
256 * may implement _OS_MEMCMP macro or the built-in version will be used.
258 * @returns < 0 if the s1 value is less than s2
259 * @returns > 0 if the s1 value is greater than s2
260 * @returns 0 if the values are equal
263 #define OS_MEMCMP(a,b,c) _oal_memcmp(a,b,c)
268 * void *OS_MEMZERO(void *s, size_t n)
270 * OS_MEMZERO sets all bytes of the memory area referenced by address s and
273 * This entry point is available in all full OAL implementations. An OAL
274 * may implement _OS_MEMZERO macro or the built-in version making use of
275 * of _OS_MEMSET will be used.
280 #define OS_MEMZERO(a,b) OS_MEMSET(a, 0, b)
284 * void *OS_MEMZERO(void *s, size_t n)
286 * OS_MEMZERO sets all bytes of the memory area referenced by address s and
289 * This entry point is available in all full OAL implementations. An OAL
290 * may implement _OS_MEMZERO macro or the built-in version making use of
291 * of _OS_MEMSET will be used.
296 #define OS_STRNCPY(d, s, n) _oal_strncpy(d, s, n)
304 * void *OS_ALLOC_CONTIGUOUS( size_t n, size_t align )
306 * OS_ALLOC_CONTIGUOUS is used by OS independent code to allocate a number
307 * of aligned system memory pages and return a CPU writeable address to the
308 * allocated memory (Virtual address) The returned address must point to
309 * physically contiguous memory aligned to the requested alignment.
311 * Allocations returned from OS_ALLOC_CONTIGUOUS() should be freed with
312 * OS_FREE_CONTIGUOUS().
314 * This entry point is OPTIONAL. Only OAL implementations that have the
315 * ability to allocate such pages need implement the _OS_ALLOC_CONTIGUOUS
316 * macro. OS independent code that must function on all implementation may
317 * not use this entry point.
319 * @return NULL on Failure
320 * @return Virtual or Flat address on Success
322 #define OS_ALLOC_CONTIGUOUS(a,b) _OS_ALLOC_CONTIGUOUS(a,b)
324 * void OS_FREE_CONTIGUOUS(void *p)
325 * OS_FREE_CONTIGUOUS should be used to free allocations returned from
326 * OS_ALLOC_CONTIGUOUS()
328 * This entry point is OPTIONAL. Only OAL implementations that have implemented
329 * the _OS_ALLOC_CONTIGUOUS macro need implement the _OS_FREE_CONTIGUOUS macro.
331 #define OS_FREE_CONTIGUOUS(a) _OS_FREE_CONTIGUOUS(a)
334 * size_t OS_OFFSETOF(type, member)
336 * OS_OFFSETOF is used by OS independent code to obtain the offset of a
337 * given member within a type.
339 * @returns size_t of the offset of member m within type t
342 #define OS_OFFSETOF(t,m) ((size_t)&(((t *)0)->m))
346 * This is a OS independent helper is case the operating environment
347 * does not supply a memcmp() function. The OAL may use this implementation.
349 static __inline int _oal_memcmp(const void *s1, const void *s2, unsigned long n)
351 const unsigned char *cs1 = (const unsigned char *) s1;
352 const unsigned char *cs2 = (const unsigned char *)s2;
354 for ( ; n-- > 0; cs1++, cs2++) {
362 static __inline void *_oal_memcpy(void *dest, const void *src, size_t n)
368 ((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
374 static __inline char *_oal_strncpy(char *dest, const char *src, size_t n)
379 if(!(dest[i] = src[i])) {
389 static __inline void *_oal_memset(void *s, int c, size_t n)
393 ((unsigned char *)s)[i] = (unsigned char)c;
399 * These macros are optional for the OAL port. They are used to do memory
400 * management for virtual apterture space process.
403 #ifdef _OS_MAP_STOLEN_MEM
404 #define OS_MAP_STOLEN_MEM(a, b, c) _OS_MAP_STOLEN_MEM(a, b, c)
406 #define OS_MAP_STOLEN_MEM(a, b, c) 0
409 #ifdef _OS_VIRT_APERT_AVAILABLE
410 #define OS_VIRT_APERT_AVAILABLE() _OS_VIRT_APERT_AVAILABLE()
412 #define OS_VIRT_APERT_AVAILABLE() 0
415 #ifdef _OS_GET_VIRT_APERT_BASE
416 #define OS_GET_VIRT_APERT_BASE() _OS_GET_VIRT_APERT_BASE()
418 #define OS_GET_VIRT_APERT_BASE() NULL