1 /****************************************************************************
3 * Copyright (C) 2005 - 2013 by Vivante Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the license, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *****************************************************************************/
22 #include "gc_hal_kernel_linux.h"
24 #include <linux/pagemap.h>
25 #include <linux/seq_file.h>
27 #include <linux/mman.h>
28 #include <linux/sched.h>
29 #include <asm/atomic.h>
30 #include <linux/dma-mapping.h>
31 #include <linux/slab.h>
32 #include <linux/idr.h>
33 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
34 #include <mach/hardware.h>
36 #include <linux/workqueue.h>
37 #include <linux/idr.h>
38 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
39 #include <linux/math64.h>
41 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
42 #include <mach/common.h>
44 #include <linux/delay.h>
45 #include <linux/pm_runtime.h>
48 #define _GC_OBJ_ZONE gcvZONE_OS
50 /*******************************************************************************
51 ***** Version Signature *******************************************************/
54 const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
56 const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
59 #define USER_SIGNAL_TABLE_LEN_INIT 64
60 #define gcdSUPPRESS_OOM_MESSAGE 1
62 #define MEMORY_LOCK(os) \
63 gcmkVERIFY_OK(gckOS_AcquireMutex( \
68 #define MEMORY_UNLOCK(os) \
69 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
71 #define MEMORY_MAP_LOCK(os) \
72 gcmkVERIFY_OK(gckOS_AcquireMutex( \
74 (os)->memoryMapLock, \
77 #define MEMORY_MAP_UNLOCK(os) \
78 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
80 /* Protection bit when mapping memroy to user sapce */
81 #define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
83 #if gcdNONPAGED_MEMORY_BUFFERABLE
84 #define gcmkIOREMAP ioremap_wc
85 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
86 #elif !gcdNONPAGED_MEMORY_CACHEABLE
87 #define gcmkIOREMAP ioremap_nocache
88 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
91 #if gcdSUPPRESS_OOM_MESSAGE
92 #define gcdNOWARN __GFP_NOWARN
97 #define gcdINFINITE_TIMEOUT (60 * 1000)
98 #define gcdDETECT_TIMEOUT 0
99 #define gcdDETECT_DMA_ADDRESS 1
100 #define gcdDETECT_DMA_STATE 1
102 #define gcdUSE_NON_PAGED_MEMORY_CACHE 10
104 /******************************************************************************\
105 ********************************** Structures **********************************
106 \******************************************************************************/
107 #if gcdUSE_NON_PAGED_MEMORY_CACHE
108 typedef struct _gcsNonPagedMemoryCache
110 #ifndef NO_DMA_COHERENT
113 dma_addr_t dmaHandle;
119 struct _gcsNonPagedMemoryCache * prev;
120 struct _gcsNonPagedMemoryCache * next;
122 gcsNonPagedMemoryCache;
123 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
125 typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
126 typedef struct _gcsUSER_MAPPING
128 /* Pointer to next mapping structure. */
129 gcsUSER_MAPPING_PTR next;
131 /* Physical address of this mapping. */
134 /* Logical address of this mapping. */
137 /* Number of bytes of this mapping. */
140 /* Starting address of this mapping. */
143 /* Ending address of this mapping. */
148 typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
149 typedef struct _gcsINTEGER_DB
164 /* Pointer to device */
167 /* Memory management */
168 gctPOINTER memoryLock;
169 gctPOINTER memoryMapLock;
171 struct _LINUX_MDL *mdlHead;
172 struct _LINUX_MDL *mdlTail;
174 /* Kernel process ID. */
175 gctUINT32 kernelProcessID;
177 /* Signal management. */
180 gctPOINTER signalMutex;
182 /* signal id database. */
183 gcsINTEGER_DB signalDB;
185 gcsUSER_MAPPING_PTR userMap;
186 gctPOINTER debugLock;
188 #if gcdUSE_NON_PAGED_MEMORY_CACHE
190 gcsNonPagedMemoryCache * cacheHead;
191 gcsNonPagedMemoryCache * cacheTail;
194 /* workqueue for os timer. */
195 struct workqueue_struct * workqueue;
198 typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
199 typedef struct _gcsSIGNAL
201 /* Kernel sync primitive. */
202 struct completion obj;
204 /* Manual reset flag. */
207 /* The reference counter. */
210 /* The owner of the signal. */
213 gckHARDWARE hardware;
220 typedef struct _gcsPageInfo * gcsPageInfo_PTR;
221 typedef struct _gcsPageInfo
224 gctUINT32_PTR pageTable;
228 typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
229 typedef struct _gcsOSTIMER
231 struct delayed_work work;
232 gctTIMERFUNCTION function;
236 /******************************************************************************\
237 ******************************* Private Functions ******************************
238 \******************************************************************************/
245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
246 return task_tgid_vnr(current);
248 return current->tgid;
257 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
258 return task_pid_vnr(current);
271 gcmkHEADER_ARG("ProcessID=%d", ProcessID);
273 mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
280 mdl->pid = ProcessID;
285 gcmkFOOTER_ARG("0x%X", mdl);
292 IN PLINUX_MDL_MAP MdlMap
300 PLINUX_MDL_MAP mdlMap, next;
302 gcmkHEADER_ARG("Mdl=0x%X", Mdl);
304 /* Verify the arguments. */
305 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
309 while (mdlMap != gcvNULL)
313 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
324 static PLINUX_MDL_MAP
330 PLINUX_MDL_MAP mdlMap;
332 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
334 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
335 if (mdlMap == gcvNULL)
341 mdlMap->pid = ProcessID;
342 mdlMap->vmaAddr = gcvNULL;
343 mdlMap->vma = gcvNULL;
345 mdlMap->next = Mdl->maps;
348 gcmkFOOTER_ARG("0x%X", mdlMap);
355 IN PLINUX_MDL_MAP MdlMap
358 PLINUX_MDL_MAP prevMdlMap;
360 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
362 /* Verify the arguments. */
363 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
364 gcmkASSERT(Mdl->maps != gcvNULL);
366 if (Mdl->maps == MdlMap)
368 Mdl->maps = MdlMap->next;
372 prevMdlMap = Mdl->maps;
374 while (prevMdlMap->next != MdlMap)
376 prevMdlMap = prevMdlMap->next;
378 gcmkASSERT(prevMdlMap != gcvNULL);
381 prevMdlMap->next = MdlMap->next;
390 extern PLINUX_MDL_MAP
396 PLINUX_MDL_MAP mdlMap;
398 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
406 while (mdlMap != gcvNULL)
408 if (mdlMap->pid == ProcessID)
410 gcmkFOOTER_ARG("0x%X", mdlMap);
414 mdlMap = mdlMap->next;
429 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
435 unsigned long addr = (unsigned long)Addr;
437 return addr >= VMALLOC_START && addr < VMALLOC_END;
443 IN struct page ** Pages,
444 IN gctUINT32 NumPages
449 gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
451 gcmkASSERT(Pages != gcvNULL);
453 for (i = 0; i < NumPages; i++)
455 __free_page(Pages[i]);
458 if (is_vmalloc_addr(Pages))
470 static struct page **
472 IN gctUINT32 NumPages
475 struct page ** pages;
479 gcmkHEADER_ARG("NumPages=%lu", NumPages);
481 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
482 if (NumPages > totalram_pages)
484 if (NumPages > num_physpages)
491 size = NumPages * sizeof(struct page *);
493 pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
497 pages = vmalloc(size);
506 for (i = 0; i < NumPages; i++)
508 p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
512 _NonContiguousFree(pages, i);
520 gcmkFOOTER_ARG("pages=0x%X", pages);
524 static inline struct page *
525 _NonContiguousToPage(
526 IN struct page ** Pages,
530 gcmkASSERT(Pages != gcvNULL);
534 static inline unsigned long
536 IN struct page ** Pages,
540 gcmkASSERT(Pages != gcvNULL);
541 return page_to_pfn(_NonContiguousToPage(Pages, Index));
544 static inline unsigned long
545 _NonContiguousToPhys(
546 IN struct page ** Pages,
550 gcmkASSERT(Pages != gcvNULL);
551 return page_to_phys(_NonContiguousToPage(Pages, Index));
555 #if gcdUSE_NON_PAGED_MEMORY_CACHE
558 _AddNonPagedMemoryCache(
560 #ifndef NO_DMA_COHERENT
570 gcsNonPagedMemoryCache *cache;
572 if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
577 /* Allocate the cache record */
578 cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
580 if (cache == gcvNULL) return gcvFALSE;
582 #ifndef NO_DMA_COHERENT
585 cache->dmaHandle = DmaHandle;
587 cache->order = Order;
592 if (Os->cacheHead == gcvNULL)
594 cache->prev = gcvNULL;
595 cache->next = gcvNULL;
597 Os->cacheTail = cache;
601 /* Add to the tail. */
602 cache->prev = Os->cacheTail;
603 cache->next = gcvNULL;
604 Os->cacheTail->next = cache;
605 Os->cacheTail = cache;
613 #ifndef NO_DMA_COHERENT
615 _GetNonPagedMemoryCache(
618 dma_addr_t * DmaHandle
622 _GetNonPagedMemoryCache(
628 gcsNonPagedMemoryCache *cache;
629 #ifndef NO_DMA_COHERENT
635 if (Os->cacheHead == gcvNULL) return gcvNULL;
637 /* Find the right cache */
638 cache = Os->cacheHead;
640 while (cache != gcvNULL)
642 #ifndef NO_DMA_COHERENT
643 if (cache->size == Size) break;
645 if (cache->order == Order) break;
651 if (cache == gcvNULL) return gcvNULL;
653 /* Remove the cache from list */
654 if (cache == Os->cacheHead)
656 Os->cacheHead = cache->next;
658 if (Os->cacheHead == gcvNULL)
660 Os->cacheTail = gcvNULL;
665 cache->prev->next = cache->next;
667 if (cache == Os->cacheTail)
669 Os->cacheTail = cache->prev;
673 cache->next->prev = cache->prev;
678 #ifndef NO_DMA_COHERENT
680 *DmaHandle = cache->dmaHandle;
689 #ifndef NO_DMA_COHERENT
697 _FreeAllNonPagedMemoryCache(
701 gcsNonPagedMemoryCache *cache, *nextCache;
705 cache = Os->cacheHead;
707 while (cache != gcvNULL)
709 if (cache != Os->cacheTail)
711 nextCache = cache->next;
718 /* Remove the cache from list */
719 if (cache == Os->cacheHead)
721 Os->cacheHead = cache->next;
723 if (Os->cacheHead == gcvNULL)
725 Os->cacheTail = gcvNULL;
730 cache->prev->next = cache->next;
732 if (cache == Os->cacheTail)
734 Os->cacheTail = cache->prev;
738 cache->next->prev = cache->prev;
742 #ifndef NO_DMA_COHERENT
743 dma_free_coherent(gcvNULL,
748 free_pages((unsigned long)page_address(cache->page), cache->order);
759 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
761 /*******************************************************************************
762 ** Integer Id Management.
766 IN gcsINTEGER_DB_PTR Database,
767 IN gctPOINTER KernelPointer,
774 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
776 return gcvSTATUS_OUT_OF_MEMORY;
779 spin_lock(&Database->lock);
781 /* Try to get a id greater than 0. */
782 result = idr_get_new_above(&Database->idr, KernelPointer, 1, Id);
784 spin_unlock(&Database->lock);
786 if (result == -EAGAIN)
793 return gcvSTATUS_OUT_OF_RESOURCES;
801 IN gcsINTEGER_DB_PTR Database,
803 OUT gctPOINTER * KernelPointer
808 spin_lock(&Database->lock);
810 pointer = idr_find(&Database->idr, Id);
812 spin_unlock(&Database->lock);
816 *KernelPointer = pointer;
822 gcvLEVEL_ERROR, gcvZONE_OS,
823 "%s(%d) Id = %d is not found",
824 __FUNCTION__, __LINE__, Id);
826 return gcvSTATUS_NOT_FOUND;
832 IN gcsINTEGER_DB_PTR Database,
836 spin_lock(&Database->lock);
838 idr_remove(&Database->idr, Id);
840 spin_unlock(&Database->lock);
848 IN gctPOINTER Logical,
852 if (unlikely(current->mm == gcvNULL))
854 /* Do nothing if process is exiting. */
858 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
859 if (vm_munmap((unsigned long)Logical, Size) < 0)
862 gcvLEVEL_WARNING, gcvZONE_OS,
863 "%s(%d): vm_munmap failed",
864 __FUNCTION__, __LINE__
868 down_write(¤t->mm->mmap_sem);
869 if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
872 gcvLEVEL_WARNING, gcvZONE_OS,
873 "%s(%d): do_munmap failed",
874 __FUNCTION__, __LINE__
877 up_write(¤t->mm->mmap_sem);
882 _QueryProcessPageTable(
883 IN gctPOINTER Logical,
884 OUT gctUINT32 * Address
888 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
896 return gcvSTATUS_NOT_FOUND;
899 pgd = pgd_offset(current->mm, logical);
900 if (pgd_none(*pgd) || pgd_bad(*pgd))
902 return gcvSTATUS_NOT_FOUND;
905 pud = pud_offset(pgd, logical);
906 if (pud_none(*pud) || pud_bad(*pud))
908 return gcvSTATUS_NOT_FOUND;
911 pmd = pmd_offset(pud, logical);
912 if (pmd_none(*pmd) || pmd_bad(*pmd))
914 return gcvSTATUS_NOT_FOUND;
917 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
920 return gcvSTATUS_NOT_FOUND;
923 if (!pte_present(*pte))
925 pte_unmap_unlock(pte, lock);
926 return gcvSTATUS_NOT_FOUND;
929 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
930 pte_unmap_unlock(pte, lock);
935 /*******************************************************************************
939 ** Construct a new gckOS object.
943 ** gctPOINTER Context
944 ** Pointer to the gckGALDEVICE class.
949 ** Pointer to a variable that will hold the pointer to the gckOS object.
953 IN gctPOINTER Context,
960 gcmkHEADER_ARG("Context=0x%X", Context);
962 /* Verify the arguments. */
963 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
965 /* Allocate the gckOS object. */
966 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
971 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
972 return gcvSTATUS_OUT_OF_MEMORY;
975 /* Zero the memory. */
976 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
978 /* Initialize the gckOS object. */
979 os->object.type = gcvOBJ_OS;
981 /* Set device device. */
982 os->device = Context;
984 /* IMPORTANT! No heap yet. */
987 /* Initialize the memory lock. */
988 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
989 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
991 /* Create debug lock mutex. */
992 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
995 os->mdlHead = os->mdlTail = gcvNULL;
997 /* Get the kernel process ID. */
998 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
1001 * Initialize the signal manager.
1004 /* Initialize mutex. */
1005 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
1007 /* Initialize signal id database lock. */
1008 spin_lock_init(&os->signalDB.lock);
1010 /* Initialize signal id database. */
1011 idr_init(&os->signalDB.idr);
1013 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1015 os->cacheHead = gcvNULL;
1016 os->cacheTail = gcvNULL;
1019 /* Create a workqueue for os timer. */
1020 os->workqueue = create_singlethread_workqueue("galcore workqueue");
1022 if (os->workqueue == gcvNULL)
1024 /* Out of memory. */
1025 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1028 /* Return pointer to the gckOS object. */
1032 gcmkFOOTER_ARG("*Os=0x%X", *Os);
1033 return gcvSTATUS_OK;
1036 if (os->signalMutex != gcvNULL)
1039 gckOS_DeleteMutex(os, os->signalMutex));
1042 if (os->heap != gcvNULL)
1045 gckHEAP_Destroy(os->heap));
1048 if (os->memoryMapLock != gcvNULL)
1051 gckOS_DeleteMutex(os, os->memoryMapLock));
1054 if (os->memoryLock != gcvNULL)
1057 gckOS_DeleteMutex(os, os->memoryLock));
1060 if (os->debugLock != gcvNULL)
1063 gckOS_DeleteMutex(os, os->debugLock));
1066 if (os->workqueue != gcvNULL)
1068 destroy_workqueue(os->workqueue);
1073 /* Return the error. */
1078 /*******************************************************************************
1082 ** Destroy an gckOS object.
1087 ** Pointer to an gckOS object that needs to be destroyed.
1100 gcmkHEADER_ARG("Os=0x%X", Os);
1102 /* Verify the arguments. */
1103 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1105 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1106 _FreeAllNonPagedMemoryCache(Os);
1110 * Destroy the signal manager.
1113 /* Destroy the mutex. */
1114 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
1116 if (Os->heap != gcvNULL)
1118 /* Mark gckHEAP as gone. */
1122 /* Destroy the gckHEAP object. */
1123 gcmkVERIFY_OK(gckHEAP_Destroy(heap));
1126 /* Destroy the memory lock. */
1127 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
1128 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
1130 /* Destroy debug lock mutex. */
1131 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
1133 /* Wait for all works done. */
1134 flush_workqueue(Os->workqueue);
1136 /* Destory work queue. */
1137 destroy_workqueue(Os->workqueue);
1139 /* Flush the debug cache. */
1140 gcmkDEBUGFLUSH(~0U);
1142 /* Mark the gckOS object as unknown. */
1143 Os->object.type = gcvOBJ_UNKNOWN;
1145 /* Free the gckOS object. */
1150 return gcvSTATUS_OK;
1154 _CreateKernelVirtualMapping(
1159 gctINT numPages = Mdl->numPages;
1161 #if gcdNONPAGED_MEMORY_CACHEABLE
1162 if (Mdl->contiguous)
1164 addr = page_address(Mdl->u.contiguousPages);
1168 addr = vmap(Mdl->u.nonContiguousPages,
1173 /* Trigger a page fault. */
1174 memset(addr, 0, numPages * PAGE_SIZE);
1177 struct page ** pages;
1178 gctBOOL free = gcvFALSE;
1181 if (Mdl->contiguous)
1183 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
1190 for (i = 0; i < numPages; i++)
1192 pages[i] = nth_page(Mdl->u.contiguousPages, i);
1199 pages = Mdl->u.nonContiguousPages;
1202 /* ioremap() can't work on system memory since 2.6.38. */
1203 addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
1205 /* Trigger a page fault. */
1206 memset(addr, 0, numPages * PAGE_SIZE);
1219 _DestoryKernelVirtualMapping(
1223 #if !gcdNONPAGED_MEMORY_CACHEABLE
1229 gckOS_CreateKernelVirtualMapping(
1230 IN gctPHYS_ADDR Physical,
1231 OUT gctSIZE_T * PageCount,
1232 OUT gctPOINTER * Logical
1235 *PageCount = ((PLINUX_MDL)Physical)->numPages;
1236 *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
1238 return gcvSTATUS_OK;
1242 gckOS_DestroyKernelVirtualMapping(
1243 IN gctPOINTER Logical
1246 _DestoryKernelVirtualMapping((gctSTRING)Logical);
1247 return gcvSTATUS_OK;
1250 /*******************************************************************************
1259 ** Pointer to an gckOS object.
1262 ** Number of bytes to allocate.
1266 ** gctPOINTER * Memory
1267 ** Pointer to a variable that will hold the allocated memory location.
1273 OUT gctPOINTER * Memory
1278 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1280 /* Verify the arguments. */
1281 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1282 gcmkVERIFY_ARGUMENT(Bytes > 0);
1283 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1285 /* Do we have a heap? */
1286 if (Os->heap != gcvNULL)
1288 /* Allocate from the heap. */
1289 gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
1293 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
1297 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1298 return gcvSTATUS_OK;
1301 /* Return the status. */
1306 /*******************************************************************************
1310 ** Free allocated memory.
1315 ** Pointer to an gckOS object.
1317 ** gctPOINTER Memory
1318 ** Pointer to memory allocation to free.
1327 IN gctPOINTER Memory
1332 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
1334 /* Verify the arguments. */
1335 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1336 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1338 /* Do we have a heap? */
1339 if (Os->heap != gcvNULL)
1341 /* Free from the heap. */
1342 gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
1346 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1351 return gcvSTATUS_OK;
1354 /* Return the status. */
1359 /*******************************************************************************
1361 ** gckOS_AllocateMemory
1363 ** Allocate memory wrapper.
1368 ** Number of bytes to allocate.
1372 ** gctPOINTER * Memory
1373 ** Pointer to a variable that will hold the allocated memory location.
1376 gckOS_AllocateMemory(
1379 OUT gctPOINTER * Memory
1385 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1387 /* Verify the arguments. */
1388 gcmkVERIFY_ARGUMENT(Bytes > 0);
1389 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1391 if (Bytes > PAGE_SIZE)
1393 memory = (gctPOINTER) vmalloc(Bytes);
1397 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1400 if (memory == gcvNULL)
1402 /* Out of memory. */
1403 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1406 /* Return pointer to the memory allocation. */
1410 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1411 return gcvSTATUS_OK;
1414 /* Return the status. */
1419 /*******************************************************************************
1423 ** Free allocated memory wrapper.
1427 ** gctPOINTER Memory
1428 ** Pointer to memory allocation to free.
1437 IN gctPOINTER Memory
1440 gcmkHEADER_ARG("Memory=0x%X", Memory);
1442 /* Verify the arguments. */
1443 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1445 /* Free the memory from the OS pool. */
1446 if (is_vmalloc_addr(Memory))
1457 return gcvSTATUS_OK;
1460 /*******************************************************************************
1464 ** Map physical memory into the current process.
1469 ** Pointer to an gckOS object.
1471 ** gctPHYS_ADDR Physical
1472 ** Start of physical address memory.
1475 ** Number of bytes to map.
1479 ** gctPOINTER * Memory
1480 ** Pointer to a variable that will hold the logical address of the
1486 IN gctPHYS_ADDR Physical,
1488 OUT gctPOINTER * Logical
1491 PLINUX_MDL_MAP mdlMap;
1492 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1494 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1496 /* Verify the arguments. */
1497 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1498 gcmkVERIFY_ARGUMENT(Physical != 0);
1499 gcmkVERIFY_ARGUMENT(Bytes > 0);
1500 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1504 mdlMap = FindMdlMap(mdl, _GetProcessID());
1506 if (mdlMap == gcvNULL)
1508 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1510 if (mdlMap == gcvNULL)
1514 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1515 return gcvSTATUS_OUT_OF_MEMORY;
1519 if (mdlMap->vmaAddr == gcvNULL)
1521 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1522 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1524 mdl->numPages * PAGE_SIZE,
1525 PROT_READ | PROT_WRITE,
1529 down_write(¤t->mm->mmap_sem);
1531 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1533 mdl->numPages * PAGE_SIZE,
1534 PROT_READ | PROT_WRITE,
1538 up_write(¤t->mm->mmap_sem);
1541 if (IS_ERR(mdlMap->vmaAddr))
1545 "%s(%d): do_mmap_pgoff error",
1546 __FUNCTION__, __LINE__
1551 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1552 __FUNCTION__, __LINE__,
1557 mdlMap->vmaAddr = gcvNULL;
1561 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1562 return gcvSTATUS_OUT_OF_MEMORY;
1565 down_write(¤t->mm->mmap_sem);
1567 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1573 "%s(%d): find_vma error.",
1574 __FUNCTION__, __LINE__
1577 mdlMap->vmaAddr = gcvNULL;
1579 up_write(¤t->mm->mmap_sem);
1583 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1584 return gcvSTATUS_OUT_OF_RESOURCES;
1587 #ifndef NO_DMA_COHERENT
1588 if (dma_mmap_coherent(gcvNULL,
1592 mdl->numPages * PAGE_SIZE) < 0)
1594 up_write(¤t->mm->mmap_sem);
1598 "%s(%d): dma_mmap_coherent error.",
1599 __FUNCTION__, __LINE__
1602 mdlMap->vmaAddr = gcvNULL;
1606 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1607 return gcvSTATUS_OUT_OF_RESOURCES;
1610 #if !gcdPAGED_MEMORY_CACHEABLE
1611 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1612 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1614 mdlMap->vma->vm_pgoff = 0;
1616 if (remap_pfn_range(mdlMap->vma,
1617 mdlMap->vma->vm_start,
1618 mdl->dmaHandle >> PAGE_SHIFT,
1619 mdl->numPages*PAGE_SIZE,
1620 mdlMap->vma->vm_page_prot) < 0)
1622 up_write(¤t->mm->mmap_sem);
1626 "%s(%d): remap_pfn_range error.",
1627 __FUNCTION__, __LINE__
1630 mdlMap->vmaAddr = gcvNULL;
1634 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1635 return gcvSTATUS_OUT_OF_RESOURCES;
1639 up_write(¤t->mm->mmap_sem);
1644 *Logical = mdlMap->vmaAddr;
1646 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1647 return gcvSTATUS_OK;
1650 /*******************************************************************************
1652 ** gckOS_UnmapMemory
1654 ** Unmap physical memory out of the current process.
1659 ** Pointer to an gckOS object.
1661 ** gctPHYS_ADDR Physical
1662 ** Start of physical address memory.
1665 ** Number of bytes to unmap.
1667 ** gctPOINTER Memory
1668 ** Pointer to a previously mapped memory region.
1677 IN gctPHYS_ADDR Physical,
1679 IN gctPOINTER Logical
1682 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1683 Os, Physical, Bytes, Logical);
1685 /* Verify the arguments. */
1686 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1687 gcmkVERIFY_ARGUMENT(Physical != 0);
1688 gcmkVERIFY_ARGUMENT(Bytes > 0);
1689 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1691 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1695 return gcvSTATUS_OK;
1699 /*******************************************************************************
1701 ** gckOS_UnmapMemoryEx
1703 ** Unmap physical memory in the specified process.
1708 ** Pointer to an gckOS object.
1710 ** gctPHYS_ADDR Physical
1711 ** Start of physical address memory.
1714 ** Number of bytes to unmap.
1716 ** gctPOINTER Memory
1717 ** Pointer to a previously mapped memory region.
1720 ** Pid of the process that opened the device and mapped this memory.
1727 gckOS_UnmapMemoryEx(
1729 IN gctPHYS_ADDR Physical,
1731 IN gctPOINTER Logical,
1735 PLINUX_MDL_MAP mdlMap;
1736 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1738 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1739 Os, Physical, Bytes, Logical, PID);
1741 /* Verify the arguments. */
1742 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1743 gcmkVERIFY_ARGUMENT(Physical != 0);
1744 gcmkVERIFY_ARGUMENT(Bytes > 0);
1745 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1746 gcmkVERIFY_ARGUMENT(PID != 0);
1752 mdlMap = FindMdlMap(mdl, PID);
1754 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1758 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1759 return gcvSTATUS_INVALID_ARGUMENT;
1762 _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1764 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1771 return gcvSTATUS_OK;
1774 /*******************************************************************************
1776 ** gckOS_UnmapUserLogical
1778 ** Unmap user logical memory out of physical memory.
1783 ** Pointer to an gckOS object.
1785 ** gctPHYS_ADDR Physical
1786 ** Start of physical address memory.
1789 ** Number of bytes to unmap.
1791 ** gctPOINTER Memory
1792 ** Pointer to a previously mapped memory region.
1799 gckOS_UnmapUserLogical(
1801 IN gctPHYS_ADDR Physical,
1803 IN gctPOINTER Logical
1806 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1807 Os, Physical, Bytes, Logical);
1809 /* Verify the arguments. */
1810 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1811 gcmkVERIFY_ARGUMENT(Physical != 0);
1812 gcmkVERIFY_ARGUMENT(Bytes > 0);
1813 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1815 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1819 return gcvSTATUS_OK;
1823 /*******************************************************************************
1825 ** gckOS_AllocateNonPagedMemory
1827 ** Allocate a number of pages from non-paged memory.
1832 ** Pointer to an gckOS object.
1834 ** gctBOOL InUserSpace
1835 ** gcvTRUE if the pages need to be mapped into user space.
1837 ** gctSIZE_T * Bytes
1838 ** Pointer to a variable that holds the number of bytes to allocate.
1842 ** gctSIZE_T * Bytes
1843 ** Pointer to a variable that hold the number of bytes allocated.
1845 ** gctPHYS_ADDR * Physical
1846 ** Pointer to a variable that will hold the physical address of the
1849 ** gctPOINTER * Logical
1850 ** Pointer to a variable that will hold the logical address of the
1854 gckOS_AllocateNonPagedMemory(
1856 IN gctBOOL InUserSpace,
1857 IN OUT gctSIZE_T * Bytes,
1858 OUT gctPHYS_ADDR * Physical,
1859 OUT gctPOINTER * Logical
1864 PLINUX_MDL mdl = gcvNULL;
1865 PLINUX_MDL_MAP mdlMap = gcvNULL;
1867 #ifdef NO_DMA_COHERENT
1872 gctBOOL locked = gcvFALSE;
1875 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1876 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1878 /* Verify the arguments. */
1879 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1880 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1881 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1882 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1883 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1885 /* Align number of bytes to page size. */
1886 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1888 /* Get total number of pages.. */
1889 numPages = GetPageCount(bytes, 0);
1891 /* Allocate mdl+vector structure */
1892 mdl = _CreateMdl(_GetProcessID());
1895 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1899 mdl->numPages = numPages;
1904 #ifndef NO_DMA_COHERENT
1905 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1906 addr = _GetNonPagedMemoryCache(Os,
1907 mdl->numPages * PAGE_SIZE,
1910 if (addr == gcvNULL)
1913 addr = dma_alloc_coherent(gcvNULL,
1914 mdl->numPages * PAGE_SIZE,
1916 GFP_KERNEL | gcdNOWARN);
1919 size = mdl->numPages * PAGE_SIZE;
1920 order = get_order(size);
1921 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1922 page = _GetNonPagedMemoryCache(Os, order);
1924 if (page == gcvNULL)
1927 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
1930 if (page == gcvNULL)
1932 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1935 vaddr = (gctPOINTER)page_address(page);
1936 mdl->contiguous = gcvTRUE;
1937 mdl->u.contiguousPages = page;
1938 addr = _CreateKernelVirtualMapping(mdl);
1939 mdl->dmaHandle = virt_to_phys(vaddr);
1941 mdl->u.contiguousPages = page;
1943 #if !defined(CONFIG_PPC)
1944 /* Cache invalidate. */
1945 dma_sync_single_for_device(
1954 SetPageReserved(virt_to_page(vaddr));
1961 if (addr == gcvNULL)
1963 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1966 if ((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
1968 mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1969 | (Os->device->baseAddress & 0x80000000);
1974 /* Return allocated memory. */
1976 *Physical = (gctPHYS_ADDR) mdl;
1980 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1982 if (mdlMap == gcvNULL)
1984 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1987 /* Only after mmap this will be valid. */
1989 /* We need to map this to user space. */
1990 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1991 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
1993 mdl->numPages * PAGE_SIZE,
1994 PROT_READ | PROT_WRITE,
1998 down_write(¤t->mm->mmap_sem);
2000 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
2002 mdl->numPages * PAGE_SIZE,
2003 PROT_READ | PROT_WRITE,
2007 up_write(¤t->mm->mmap_sem);
2010 if (IS_ERR(mdlMap->vmaAddr))
2013 gcvLEVEL_WARNING, gcvZONE_OS,
2014 "%s(%d): do_mmap_pgoff error",
2015 __FUNCTION__, __LINE__
2018 mdlMap->vmaAddr = gcvNULL;
2020 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2023 down_write(¤t->mm->mmap_sem);
2025 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
2027 if (mdlMap->vma == gcvNULL)
2030 gcvLEVEL_WARNING, gcvZONE_OS,
2031 "%s(%d): find_vma error",
2032 __FUNCTION__, __LINE__
2035 up_write(¤t->mm->mmap_sem);
2037 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2040 #ifndef NO_DMA_COHERENT
2041 if (dma_mmap_coherent(gcvNULL,
2045 mdl->numPages * PAGE_SIZE) < 0)
2048 gcvLEVEL_WARNING, gcvZONE_OS,
2049 "%s(%d): dma_mmap_coherent error",
2050 __FUNCTION__, __LINE__
2053 up_write(¤t->mm->mmap_sem);
2055 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2058 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
2059 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
2060 mdlMap->vma->vm_pgoff = 0;
2062 if (remap_pfn_range(mdlMap->vma,
2063 mdlMap->vma->vm_start,
2064 mdl->dmaHandle >> PAGE_SHIFT,
2065 mdl->numPages * PAGE_SIZE,
2066 mdlMap->vma->vm_page_prot))
2069 gcvLEVEL_WARNING, gcvZONE_OS,
2070 "%s(%d): remap_pfn_range error",
2071 __FUNCTION__, __LINE__
2074 up_write(¤t->mm->mmap_sem);
2076 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2078 #endif /* NO_DMA_COHERENT */
2080 up_write(¤t->mm->mmap_sem);
2082 *Logical = mdlMap->vmaAddr;
2086 *Logical = (gctPOINTER)mdl->addr;
2090 * Add this to a global list.
2091 * Will be used by get physical address
2092 * and mapuser pointer functions.
2097 /* Initialize the queue. */
2098 Os->mdlHead = Os->mdlTail = mdl;
2102 /* Add to the tail. */
2103 mdl->prev = Os->mdlTail;
2104 Os->mdlTail->next = mdl;
2111 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
2112 *Bytes, *Physical, *Logical);
2113 return gcvSTATUS_OK;
2116 if (mdlMap != gcvNULL)
2118 /* Free LINUX_MDL_MAP. */
2119 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
2124 /* Free LINUX_MDL. */
2125 gcmkVERIFY_OK(_DestroyMdl(mdl));
2130 /* Unlock memory. */
2134 /* Return the status. */
2139 /*******************************************************************************
2141 ** gckOS_FreeNonPagedMemory
2143 ** Free previously allocated and mapped pages from non-paged memory.
2148 ** Pointer to an gckOS object.
2151 ** Number of bytes allocated.
2153 ** gctPHYS_ADDR Physical
2154 ** Physical address of the allocated memory.
2156 ** gctPOINTER Logical
2157 ** Logical address of the allocated memory.
2163 gceSTATUS gckOS_FreeNonPagedMemory(
2166 IN gctPHYS_ADDR Physical,
2167 IN gctPOINTER Logical
2171 PLINUX_MDL_MAP mdlMap;
2172 #ifdef NO_DMA_COHERENT
2175 #endif /* NO_DMA_COHERENT */
2177 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
2178 Os, Bytes, Physical, Logical);
2180 /* Verify the arguments. */
2181 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2182 gcmkVERIFY_ARGUMENT(Bytes > 0);
2183 gcmkVERIFY_ARGUMENT(Physical != 0);
2184 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2186 /* Convert physical address into a pointer to a MDL. */
2187 mdl = (PLINUX_MDL) Physical;
2191 #ifndef NO_DMA_COHERENT
2192 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2193 if (!_AddNonPagedMemoryCache(Os,
2194 mdl->numPages * PAGE_SIZE,
2199 dma_free_coherent(gcvNULL,
2200 mdl->numPages * PAGE_SIZE,
2205 size = mdl->numPages * PAGE_SIZE;
2210 ClearPageReserved(virt_to_page(vaddr));
2216 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2217 if (!_AddNonPagedMemoryCache(Os,
2218 get_order(mdl->numPages * PAGE_SIZE),
2219 virt_to_page(mdl->kaddr)))
2222 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
2225 _DestoryKernelVirtualMapping(mdl->addr);
2226 #endif /* NO_DMA_COHERENT */
2230 while (mdlMap != gcvNULL)
2232 if (mdlMap->vmaAddr != gcvNULL)
2234 /* No mapped memory exists when free nonpaged memory */
2238 mdlMap = mdlMap->next;
2241 /* Remove the node from global list.. */
2242 if (mdl == Os->mdlHead)
2244 if ((Os->mdlHead = mdl->next) == gcvNULL)
2246 Os->mdlTail = gcvNULL;
2251 mdl->prev->next = mdl->next;
2252 if (mdl == Os->mdlTail)
2254 Os->mdlTail = mdl->prev;
2258 mdl->next->prev = mdl->prev;
2264 gcmkVERIFY_OK(_DestroyMdl(mdl));
2268 return gcvSTATUS_OK;
2271 /*******************************************************************************
2273 ** gckOS_ReadRegister
2275 ** Read data from a register.
2280 ** Pointer to an gckOS object.
2282 ** gctUINT32 Address
2283 ** Address of register.
2288 ** Pointer to a variable that receives the data read from the register.
2293 IN gctUINT32 Address,
2294 OUT gctUINT32 * Data
2297 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2301 gckOS_ReadRegisterEx(
2304 IN gctUINT32 Address,
2305 OUT gctUINT32 * Data
2308 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
2310 /* Verify the arguments. */
2311 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2312 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2314 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
2317 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2318 return gcvSTATUS_OK;
2321 /*******************************************************************************
2323 ** gckOS_WriteRegister
2325 ** Write data to a register.
2330 ** Pointer to an gckOS object.
2332 ** gctUINT32 Address
2333 ** Address of register.
2336 ** Data for register.
2343 gckOS_WriteRegister(
2345 IN gctUINT32 Address,
2349 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2353 gckOS_WriteRegisterEx(
2356 IN gctUINT32 Address,
2360 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2362 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2366 return gcvSTATUS_OK;
2369 /*******************************************************************************
2371 ** gckOS_GetPageSize
2373 ** Get the system's page size.
2378 ** Pointer to an gckOS object.
2382 ** gctSIZE_T * PageSize
2383 ** Pointer to a variable that will receive the system's page size.
2385 gceSTATUS gckOS_GetPageSize(
2387 OUT gctSIZE_T * PageSize
2390 gcmkHEADER_ARG("Os=0x%X", Os);
2392 /* Verify the arguments. */
2393 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2394 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2396 /* Return the page size. */
2397 *PageSize = (gctSIZE_T) PAGE_SIZE;
2400 gcmkFOOTER_ARG("*PageSize", *PageSize);
2401 return gcvSTATUS_OK;
2404 /*******************************************************************************
2406 ** gckOS_GetPhysicalAddress
2408 ** Get the physical system address of a corresponding virtual address.
2413 ** Pointer to an gckOS object.
2415 ** gctPOINTER Logical
2420 ** gctUINT32 * Address
2421 ** Poinetr to a variable that receives the 32-bit physical adress.
2424 gckOS_GetPhysicalAddress(
2426 IN gctPOINTER Logical,
2427 OUT gctUINT32 * Address
2431 gctUINT32 processID;
2433 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2435 /* Verify the arguments. */
2436 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2437 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2439 /* Query page table of current process first. */
2440 status = _QueryProcessPageTable(Logical, Address);
2442 if (gcmIS_ERROR(status))
2444 /* Get current process ID. */
2445 processID = _GetProcessID();
2447 /* Route through other function. */
2449 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2453 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2454 return gcvSTATUS_OK;
2457 /* Return the status. */
2466 IN gctUINT32 Physical,
2467 IN gctPOINTER Logical,
2472 gcsUSER_MAPPING_PTR map;
2474 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2475 Os, Physical, Logical, Bytes);
2477 gcmkONERROR(gckOS_Allocate(Os,
2478 gcmSIZEOF(gcsUSER_MAPPING),
2479 (gctPOINTER *) &map));
2481 map->next = Os->userMap;
2482 map->physical = Physical - Os->device->baseAddress;
2483 map->logical = Logical;
2485 map->start = (gctINT8_PTR) Logical;
2486 map->end = map->start + Bytes;
2491 return gcvSTATUS_OK;
2499 gckOS_RemoveMapping(
2501 IN gctPOINTER Logical,
2506 gcsUSER_MAPPING_PTR map, prev;
2508 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2510 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2512 if ((map->logical == Logical)
2513 && (map->bytes == Bytes)
2524 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2527 if (prev == gcvNULL)
2529 Os->userMap = map->next;
2533 prev->next = map->next;
2536 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2539 return gcvSTATUS_OK;
2548 _ConvertLogical2Physical(
2550 IN gctPOINTER Logical,
2551 IN gctUINT32 ProcessID,
2553 OUT gctUINT32_PTR Physical
2556 gctINT8_PTR base, vBase;
2559 gcsUSER_MAPPING_PTR userMap;
2561 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2563 /* Check for the logical address match. */
2564 if ((base != gcvNULL)
2565 && ((gctINT8_PTR) Logical >= base)
2566 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2569 offset = (gctINT8_PTR) Logical - base;
2571 if (Mdl->dmaHandle != 0)
2573 /* The memory was from coherent area. */
2574 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2576 else if (Mdl->pagedMem && !Mdl->contiguous)
2578 /* paged memory is not mapped to kernel space. */
2579 return gcvSTATUS_INVALID_ADDRESS;
2583 *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
2586 return gcvSTATUS_OK;
2589 /* Walk user maps. */
2590 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2592 if (((gctINT8_PTR) Logical >= userMap->start)
2593 && ((gctINT8_PTR) Logical < userMap->end)
2596 *Physical = userMap->physical
2597 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2599 return gcvSTATUS_OK;
2603 if (ProcessID != Os->kernelProcessID)
2605 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2606 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2608 /* Is the given address within that range. */
2609 if ((vBase != gcvNULL)
2610 && ((gctINT8_PTR) Logical >= vBase)
2611 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2614 offset = (gctINT8_PTR) Logical - vBase;
2616 if (Mdl->dmaHandle != 0)
2618 /* The memory was from coherent area. */
2619 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2621 else if (Mdl->pagedMem && !Mdl->contiguous)
2623 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2627 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2630 return gcvSTATUS_OK;
2634 /* Address not yet found. */
2635 return gcvSTATUS_INVALID_ADDRESS;
2638 /*******************************************************************************
2640 ** gckOS_GetPhysicalAddressProcess
2642 ** Get the physical system address of a corresponding virtual address for a
2648 ** Pointer to gckOS object.
2650 ** gctPOINTER Logical
2653 ** gctUINT32 ProcessID
2658 ** gctUINT32 * Address
2659 ** Poinetr to a variable that receives the 32-bit physical adress.
2662 gckOS_GetPhysicalAddressProcess(
2664 IN gctPOINTER Logical,
2665 IN gctUINT32 ProcessID,
2666 OUT gctUINT32 * Address
2671 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2673 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2675 /* Verify the arguments. */
2676 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2677 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2681 /* First try the contiguous memory pool. */
2682 if (Os->device->contiguousMapped)
2684 base = (gctINT8_PTR) Os->device->contiguousBase;
2686 if (((gctINT8_PTR) Logical >= base)
2687 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2690 /* Convert logical address into physical. */
2691 *Address = Os->device->contiguousVidMem->baseAddress
2692 + (gctINT8_PTR) Logical - base;
2693 status = gcvSTATUS_OK;
2698 /* Try the contiguous memory pool. */
2699 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2700 status = _ConvertLogical2Physical(Os,
2707 if (gcmIS_ERROR(status))
2709 /* Walk all MDLs. */
2710 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2713 status = _ConvertLogical2Physical(Os,
2718 if (gcmIS_SUCCESS(status))
2727 gcmkONERROR(status);
2730 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2731 return gcvSTATUS_OK;
2734 /* Return the status. */
2739 /*******************************************************************************
2741 ** gckOS_MapPhysical
2743 ** Map a physical address into kernel space.
2748 ** Pointer to an gckOS object.
2750 ** gctUINT32 Physical
2751 ** Physical address of the memory to map.
2754 ** Number of bytes to map.
2758 ** gctPOINTER * Logical
2759 ** Pointer to a variable that receives the base address of the mapped
2765 IN gctUINT32 Physical,
2767 OUT gctPOINTER * Logical
2772 gctUINT32 physical = Physical;
2774 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2776 /* Verify the arguments. */
2777 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2778 gcmkVERIFY_ARGUMENT(Bytes > 0);
2779 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2783 /* Go through our mapping to see if we know this physical address already. */
2786 while (mdl != gcvNULL)
2788 if (mdl->dmaHandle != 0)
2790 if ((physical >= mdl->dmaHandle)
2791 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2794 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2804 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2805 struct contiguous_mem_pool *pool = Os->device->pool;
2807 if (Physical >= pool->phys && Physical < pool->phys + pool->size)
2808 logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
2812 /* Map memory as cached memory. */
2813 request_mem_region(physical, Bytes, "MapRegion");
2814 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2817 if (logical == gcvNULL)
2820 gcvLEVEL_INFO, gcvZONE_OS,
2821 "%s(%d): Failed to map physical address 0x%08x",
2822 __FUNCTION__, __LINE__, Physical
2827 /* Out of resources. */
2828 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2829 return gcvSTATUS_OUT_OF_RESOURCES;
2832 /* Return pointer to mapped memory. */
2839 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2840 return gcvSTATUS_OK;
2843 /*******************************************************************************
2845 ** gckOS_UnmapPhysical
2847 ** Unmap a previously mapped memory region from kernel memory.
2852 ** Pointer to an gckOS object.
2854 ** gctPOINTER Logical
2855 ** Pointer to the base address of the memory to unmap.
2858 ** Number of bytes to unmap.
2865 gckOS_UnmapPhysical(
2867 IN gctPOINTER Logical,
2873 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2875 /* Verify the arguments. */
2876 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2877 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2878 gcmkVERIFY_ARGUMENT(Bytes > 0);
2884 while (mdl != gcvNULL)
2886 if (mdl->addr != gcvNULL)
2888 if (Logical >= (gctPOINTER)mdl->addr
2889 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2900 /* Unmap the memory. */
2908 return gcvSTATUS_OK;
2911 /*******************************************************************************
2913 ** gckOS_CreateMutex
2915 ** Create a new mutex.
2920 ** Pointer to an gckOS object.
2924 ** gctPOINTER * Mutex
2925 ** Pointer to a variable that will hold a pointer to the mutex.
2930 OUT gctPOINTER * Mutex
2935 gcmkHEADER_ARG("Os=0x%X", Os);
2937 /* Validate the arguments. */
2938 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2939 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2941 /* Allocate the mutex structure. */
2942 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
2944 /* Initialize the mutex. */
2947 /* Return status. */
2948 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
2949 return gcvSTATUS_OK;
2952 /* Return status. */
2957 /*******************************************************************************
2959 ** gckOS_DeleteMutex
2966 ** Pointer to an gckOS object.
2969 ** Pointer to the mute to be deleted.
2983 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
2985 /* Validate the arguments. */
2986 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2987 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2989 /* Destroy the mutex. */
2990 mutex_destroy(Mutex);
2992 /* Free the mutex structure. */
2993 gcmkONERROR(gckOS_Free(Os, Mutex));
2996 return gcvSTATUS_OK;
2999 /* Return status. */
3004 /*******************************************************************************
3006 ** gckOS_AcquireMutex
3013 ** Pointer to an gckOS object.
3016 ** Pointer to the mutex to be acquired.
3018 ** gctUINT32 Timeout
3019 ** Timeout value specified in milliseconds.
3020 ** Specify the value of gcvINFINITE to keep the thread suspended
3021 ** until the mutex has been acquired.
3030 IN gctPOINTER Mutex,
3031 IN gctUINT32 Timeout
3034 #if gcdDETECT_TIMEOUT
3038 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
3040 /* Validate the arguments. */
3041 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3042 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3044 #if gcdDETECT_TIMEOUT
3049 /* Try to acquire the mutex. */
3050 if (mutex_trylock(Mutex))
3054 return gcvSTATUS_OK;
3057 /* Advance the timeout. */
3060 if (Timeout == gcvINFINITE)
3062 if (timeout == gcdINFINITE_TIMEOUT)
3064 gctUINT32 dmaAddress1, dmaAddress2;
3065 gctUINT32 dmaState1, dmaState2;
3067 dmaState1 = dmaState2 =
3068 dmaAddress1 = dmaAddress2 = 0;
3070 /* Verify whether DMA is running. */
3071 gcmkVERIFY_OK(_VerifyDMA(
3072 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
3075 #if gcdDETECT_DMA_ADDRESS
3076 /* Dump only if DMA appears stuck. */
3078 (dmaAddress1 == dmaAddress2)
3079 #if gcdDETECT_DMA_STATE
3080 && (dmaState1 == dmaState2)
3085 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
3088 "%s(%d): mutex 0x%X; forced message flush.",
3089 __FUNCTION__, __LINE__, Mutex
3092 /* Flush the debug cache. */
3093 gcmkDEBUGFLUSH(dmaAddress2);
3102 if (timeout >= Timeout)
3108 /* Wait for 1 millisecond. */
3109 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3112 if (Timeout == gcvINFINITE)
3114 /* Lock the mutex. */
3119 return gcvSTATUS_OK;
3124 /* Try to acquire the mutex. */
3125 if (mutex_trylock(Mutex))
3129 return gcvSTATUS_OK;
3137 /* Wait for 1 millisecond. */
3138 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3143 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
3144 return gcvSTATUS_TIMEOUT;
3147 /*******************************************************************************
3149 ** gckOS_ReleaseMutex
3151 ** Release an acquired mutex.
3156 ** Pointer to an gckOS object.
3159 ** Pointer to the mutex to be released.
3171 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
3173 /* Validate the arguments. */
3174 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3175 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3177 /* Release the mutex. */
3178 mutex_unlock(Mutex);
3182 return gcvSTATUS_OK;
3185 /*******************************************************************************
3187 ** gckOS_AtomicExchange
3189 ** Atomically exchange a pair of 32-bit values.
3194 ** Pointer to an gckOS object.
3196 ** IN OUT gctINT32_PTR Target
3197 ** Pointer to the 32-bit value to exchange.
3199 ** IN gctINT32 NewValue
3200 ** Specifies a new value for the 32-bit value pointed to by Target.
3202 ** OUT gctINT32_PTR OldValue
3203 ** The old value of the 32-bit value pointed to by Target.
3210 gckOS_AtomicExchange(
3212 IN OUT gctUINT32_PTR Target,
3213 IN gctUINT32 NewValue,
3214 OUT gctUINT32_PTR OldValue
3217 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
3219 /* Verify the arguments. */
3220 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3222 /* Exchange the pair of 32-bit values. */
3223 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
3226 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
3227 return gcvSTATUS_OK;
3230 /*******************************************************************************
3232 ** gckOS_AtomicExchangePtr
3234 ** Atomically exchange a pair of pointers.
3239 ** Pointer to an gckOS object.
3241 ** IN OUT gctPOINTER * Target
3242 ** Pointer to the 32-bit value to exchange.
3244 ** IN gctPOINTER NewValue
3245 ** Specifies a new value for the pointer pointed to by Target.
3247 ** OUT gctPOINTER * OldValue
3248 ** The old value of the pointer pointed to by Target.
3255 gckOS_AtomicExchangePtr(
3257 IN OUT gctPOINTER * Target,
3258 IN gctPOINTER NewValue,
3259 OUT gctPOINTER * OldValue
3262 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3264 /* Verify the arguments. */
3265 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3267 /* Exchange the pair of pointers. */
3268 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3271 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3272 return gcvSTATUS_OK;
3276 /*******************************************************************************
3278 ** gckOS_AtomicSetMask
3280 ** Atomically set mask to Atom
3283 ** IN OUT gctPOINTER Atom
3284 ** Pointer to the atom to set.
3286 ** IN gctUINT32 Mask
3299 gctUINT32 oval, nval;
3301 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3302 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3306 oval = atomic_read((atomic_t *) Atom);
3308 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3311 return gcvSTATUS_OK;
3314 /*******************************************************************************
3316 ** gckOS_AtomClearMask
3318 ** Atomically clear mask from Atom
3321 ** IN OUT gctPOINTER Atom
3322 ** Pointer to the atom to clear.
3324 ** IN gctUINT32 Mask
3332 gckOS_AtomClearMask(
3337 gctUINT32 oval, nval;
3339 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3340 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3344 oval = atomic_read((atomic_t *) Atom);
3345 nval = oval & ~Mask;
3346 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3349 return gcvSTATUS_OK;
3353 /*******************************************************************************
3355 ** gckOS_AtomConstruct
3362 ** Pointer to a gckOS object.
3366 ** gctPOINTER * Atom
3367 ** Pointer to a variable receiving the constructed atom.
3370 gckOS_AtomConstruct(
3372 OUT gctPOINTER * Atom
3377 gcmkHEADER_ARG("Os=0x%X", Os);
3379 /* Verify the arguments. */
3380 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3381 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3383 /* Allocate the atom. */
3384 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3386 /* Initialize the atom. */
3387 atomic_set((atomic_t *) *Atom, 0);
3390 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3391 return gcvSTATUS_OK;
3394 /* Return the status. */
3399 /*******************************************************************************
3401 ** gckOS_AtomDestroy
3408 ** Pointer to a gckOS object.
3411 ** Pointer to the atom to destroy.
3425 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3427 /* Verify the arguments. */
3428 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3429 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3431 /* Free the atom. */
3432 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3436 return gcvSTATUS_OK;
3439 /* Return the status. */
3444 /*******************************************************************************
3448 ** Get the 32-bit value protected by an atom.
3453 ** Pointer to a gckOS object.
3456 ** Pointer to the atom.
3460 ** gctINT32_PTR Value
3461 ** Pointer to a variable the receives the value of the atom.
3467 OUT gctINT32_PTR Value
3470 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3472 /* Verify the arguments. */
3473 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3474 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3476 /* Return the current value of atom. */
3477 *Value = atomic_read((atomic_t *) Atom);
3480 gcmkFOOTER_ARG("*Value=%d", *Value);
3481 return gcvSTATUS_OK;
3484 /*******************************************************************************
3488 ** Set the 32-bit value protected by an atom.
3493 ** Pointer to a gckOS object.
3496 ** Pointer to the atom.
3499 ** The value of the atom.
3512 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3514 /* Verify the arguments. */
3515 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3516 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3518 /* Set the current value of atom. */
3519 atomic_set((atomic_t *) Atom, Value);
3523 return gcvSTATUS_OK;
3526 /*******************************************************************************
3528 ** gckOS_AtomIncrement
3530 ** Atomically increment the 32-bit integer value inside an atom.
3535 ** Pointer to a gckOS object.
3538 ** Pointer to the atom.
3542 ** gctINT32_PTR Value
3543 ** Pointer to a variable that receives the original value of the atom.
3546 gckOS_AtomIncrement(
3549 OUT gctINT32_PTR Value
3552 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3554 /* Verify the arguments. */
3555 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3556 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3558 /* Increment the atom. */
3559 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3562 gcmkFOOTER_ARG("*Value=%d", *Value);
3563 return gcvSTATUS_OK;
3566 /*******************************************************************************
3568 ** gckOS_AtomDecrement
3570 ** Atomically decrement the 32-bit integer value inside an atom.
3575 ** Pointer to a gckOS object.
3578 ** Pointer to the atom.
3582 ** gctINT32_PTR Value
3583 ** Pointer to a variable that receives the original value of the atom.
3586 gckOS_AtomDecrement(
3589 OUT gctINT32_PTR Value
3592 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3594 /* Verify the arguments. */
3595 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3596 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3598 /* Decrement the atom. */
3599 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3602 gcmkFOOTER_ARG("*Value=%d", *Value);
3603 return gcvSTATUS_OK;
3606 /*******************************************************************************
3610 ** Delay execution of the current thread for a number of milliseconds.
3615 ** Pointer to an gckOS object.
3618 ** Delay to sleep, specified in milliseconds.
3630 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3634 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3635 ktime_t delay = ktime_set(0, Delay * NSEC_PER_MSEC);
3636 __set_current_state(TASK_UNINTERRUPTIBLE);
3637 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3646 return gcvSTATUS_OK;
3649 /*******************************************************************************
3653 ** Get the number of milliseconds since the system started.
3659 ** gctUINT32_PTR Time
3660 ** Pointer to a variable to get time.
3665 OUT gctUINT32_PTR Time
3670 *Time = jiffies_to_msecs(jiffies);
3673 return gcvSTATUS_OK;
3676 /*******************************************************************************
3680 ** Compare time values got from gckOS_GetTicks.
3684 ** First time value to be compared.
3687 ** Second time value to be compared.
3691 ** gctBOOL_PTR IsAfter
3692 ** Pointer to a variable to result.
3699 OUT gctBOOL_PTR IsAfter
3704 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3707 return gcvSTATUS_OK;
3710 /*******************************************************************************
3714 ** Get the number of microseconds since the system started.
3720 ** gctUINT64_PTR Time
3721 ** Pointer to a variable to get time.
3726 OUT gctUINT64_PTR Time
3734 return gcvSTATUS_OK;
3737 /*******************************************************************************
3739 ** gckOS_MemoryBarrier
3741 ** Make sure the CPU has executed everything up to this point and the data got
3742 ** written to the specified pointer.
3747 ** Pointer to an gckOS object.
3749 ** gctPOINTER Address
3750 ** Address of memory that needs to be barriered.
3757 gckOS_MemoryBarrier(
3759 IN gctPOINTER Address
3762 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3764 /* Verify the arguments. */
3765 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3767 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3768 && defined (CONFIG_ARM) \
3769 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3770 /* drain write buffer */
3773 /* drain outer cache's write buffer? */
3780 return gcvSTATUS_OK;
3783 /*******************************************************************************
3785 ** gckOS_AllocatePagedMemory
3787 ** Allocate memory from the paged pool.
3792 ** Pointer to an gckOS object.
3795 ** Number of bytes to allocate.
3799 ** gctPHYS_ADDR * Physical
3800 ** Pointer to a variable that receives the physical address of the
3801 ** memory allocation.
3804 gckOS_AllocatePagedMemory(
3807 OUT gctPHYS_ADDR * Physical
3812 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3814 /* Verify the arguments. */
3815 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3816 gcmkVERIFY_ARGUMENT(Bytes > 0);
3817 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3819 /* Allocate the memory. */
3820 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
3823 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3824 return gcvSTATUS_OK;
3827 /* Return the status. */
3832 /*******************************************************************************
3834 ** gckOS_AllocatePagedMemoryEx
3836 ** Allocate memory from the paged pool.
3841 ** Pointer to an gckOS object.
3843 ** gctBOOL Contiguous
3844 ** Need contiguous memory or not.
3847 ** Number of bytes to allocate.
3851 ** gctPHYS_ADDR * Physical
3852 ** Pointer to a variable that receives the physical address of the
3853 ** memory allocation.
3856 gckOS_AllocatePagedMemoryEx(
3858 IN gctBOOL Contiguous,
3860 OUT gctPHYS_ADDR * Physical
3865 PLINUX_MDL mdl = gcvNULL;
3867 gctBOOL locked = gcvFALSE;
3869 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3870 gctPOINTER addr = gcvNULL;
3873 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
3875 /* Verify the arguments. */
3876 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3877 gcmkVERIFY_ARGUMENT(Bytes > 0);
3878 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3880 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3882 numPages = GetPageCount(bytes, 0);
3887 mdl = _CreateMdl(_GetProcessID());
3890 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3895 /* Get contiguous pages, and suppress warning (stack dump) from kernel when
3896 we run out of memory. */
3897 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3899 alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
3901 mdl->u.contiguousPages = addr
3902 ? virt_to_page(addr)
3905 mdl->exact = gcvTRUE;
3907 mdl->u.contiguousPages =
3908 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, GetOrder(numPages));
3910 if (mdl->u.contiguousPages == gcvNULL)
3912 mdl->u.contiguousPages =
3913 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, GetOrder(numPages));
3915 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3916 mdl->exact = gcvFALSE;
3922 mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
3925 if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
3927 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3932 mdl->numPages = numPages;
3934 mdl->contiguous = Contiguous;
3936 for (i = 0; i < mdl->numPages; i++)
3940 if (mdl->contiguous)
3942 page = nth_page(mdl->u.contiguousPages, i);
3946 page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
3949 SetPageReserved(page);
3951 if (!PageHighMem(page) && page_to_phys(page))
3954 gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
3955 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
3961 /* Return physical address. */
3962 *Physical = (gctPHYS_ADDR) mdl;
3965 * Add this to a global list.
3966 * Will be used by get physical address
3967 * and mapuser pointer functions.
3971 /* Initialize the queue. */
3972 Os->mdlHead = Os->mdlTail = mdl;
3977 mdl->prev = Os->mdlTail;
3978 Os->mdlTail->next = mdl;
3985 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3986 return gcvSTATUS_OK;
3991 /* Free the memory. */
3997 /* Unlock the memory. */
4001 /* Return the status. */
4006 /*******************************************************************************
4008 ** gckOS_FreePagedMemory
4010 ** Free memory allocated from the paged pool.
4015 ** Pointer to an gckOS object.
4017 ** gctPHYS_ADDR Physical
4018 ** Physical address of the allocation.
4021 ** Number of bytes of the allocation.
4028 gckOS_FreePagedMemory(
4030 IN gctPHYS_ADDR Physical,
4034 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
4037 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
4039 /* Verify the arguments. */
4040 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4041 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4042 gcmkVERIFY_ARGUMENT(Bytes > 0);
4044 /*addr = mdl->addr;*/
4048 for (i = 0; i < mdl->numPages; i++)
4050 if (mdl->contiguous)
4052 ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
4056 ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
4060 if (mdl->contiguous)
4062 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4063 if (mdl->exact == gcvTRUE)
4065 free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
4070 __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
4075 _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
4078 /* Remove the node from global list. */
4079 if (mdl == Os->mdlHead)
4081 if ((Os->mdlHead = mdl->next) == gcvNULL)
4083 Os->mdlTail = gcvNULL;
4088 mdl->prev->next = mdl->next;
4090 if (mdl == Os->mdlTail)
4092 Os->mdlTail = mdl->prev;
4096 mdl->next->prev = mdl->prev;
4102 /* Free the structure... */
4103 gcmkVERIFY_OK(_DestroyMdl(mdl));
4107 return gcvSTATUS_OK;
4110 /*******************************************************************************
4114 ** Lock memory allocated from the paged pool.
4119 ** Pointer to an gckOS object.
4121 ** gctPHYS_ADDR Physical
4122 ** Physical address of the allocation.
4125 ** Number of bytes of the allocation.
4127 ** gctBOOL Cacheable
4128 ** Cache mode of mapping.
4132 ** gctPOINTER * Logical
4133 ** Pointer to a variable that receives the address of the mapped
4136 ** gctSIZE_T * PageCount
4137 ** Pointer to a variable that receives the number of pages required for
4138 ** the page table according to the GPU page size.
4143 IN gctPHYS_ADDR Physical,
4145 IN gctBOOL Cacheable,
4146 OUT gctPOINTER * Logical,
4147 OUT gctSIZE_T * PageCount
4151 PLINUX_MDL_MAP mdlMap;
4153 unsigned long start;
4157 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
4159 /* Verify the arguments. */
4160 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4161 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4162 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4163 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
4165 mdl = (PLINUX_MDL) Physical;
4169 mdlMap = FindMdlMap(mdl, _GetProcessID());
4171 if (mdlMap == gcvNULL)
4173 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
4175 if (mdlMap == gcvNULL)
4179 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4180 return gcvSTATUS_OUT_OF_MEMORY;
4184 if (mdlMap->vmaAddr == gcvNULL)
4186 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
4187 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
4189 mdl->numPages * PAGE_SIZE,
4190 PROT_READ | PROT_WRITE,
4194 down_write(¤t->mm->mmap_sem);
4196 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
4198 mdl->numPages * PAGE_SIZE,
4199 PROT_READ | PROT_WRITE,
4203 up_write(¤t->mm->mmap_sem);
4207 gcvLEVEL_INFO, gcvZONE_OS,
4208 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
4209 __FUNCTION__, __LINE__,
4210 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
4211 (gctUINT32)(gctUINTPTR_T)mdl
4214 if (IS_ERR(mdlMap->vmaAddr))
4217 gcvLEVEL_INFO, gcvZONE_OS,
4218 "%s(%d): do_mmap_pgoff error",
4219 __FUNCTION__, __LINE__
4222 mdlMap->vmaAddr = gcvNULL;
4226 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4227 return gcvSTATUS_OUT_OF_MEMORY;
4230 down_write(¤t->mm->mmap_sem);
4232 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
4234 if (mdlMap->vma == gcvNULL)
4236 up_write(¤t->mm->mmap_sem);
4239 gcvLEVEL_INFO, gcvZONE_OS,
4240 "%s(%d): find_vma error",
4241 __FUNCTION__, __LINE__
4244 mdlMap->vmaAddr = gcvNULL;
4248 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
4249 return gcvSTATUS_OUT_OF_RESOURCES;
4252 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
4253 #if !gcdPAGED_MEMORY_CACHEABLE
4254 if (Cacheable == gcvFALSE)
4256 /* Make this mapping non-cached. */
4257 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
4262 /* Now map all the vmalloc pages to this user address. */
4263 if (mdl->contiguous)
4265 /* map kernel memory to user space.. */
4266 if (remap_pfn_range(mdlMap->vma,
4267 mdlMap->vma->vm_start,
4268 page_to_pfn(mdl->u.contiguousPages),
4269 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
4270 mdlMap->vma->vm_page_prot) < 0)
4272 up_write(¤t->mm->mmap_sem);
4275 gcvLEVEL_INFO, gcvZONE_OS,
4276 "%s(%d): unable to mmap ret",
4277 __FUNCTION__, __LINE__
4280 mdlMap->vmaAddr = gcvNULL;
4284 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4285 return gcvSTATUS_OUT_OF_MEMORY;
4290 start = mdlMap->vma->vm_start;
4292 for (i = 0; i < mdl->numPages; i++)
4294 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
4296 if (remap_pfn_range(mdlMap->vma,
4300 mdlMap->vma->vm_page_prot) < 0)
4302 up_write(¤t->mm->mmap_sem);
4305 gcvLEVEL_INFO, gcvZONE_OS,
4306 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
4307 __FUNCTION__, __LINE__,
4308 (gctUINT32)(gctUINTPTR_T)Physical,
4309 (gctUINT32)(gctUINTPTR_T)*Logical,
4310 (gctUINT32)(gctUINTPTR_T)addr,
4311 (gctUINT32)(gctUINTPTR_T)start
4314 mdlMap->vmaAddr = gcvNULL;
4318 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4319 return gcvSTATUS_OUT_OF_MEMORY;
4327 up_write(¤t->mm->mmap_sem);
4331 /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */
4334 gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED, mdlMap->vmaAddr);
4335 return gcvSTATUS_MEMORY_LOCKED;
4338 /* Convert pointer to MDL. */
4339 *Logical = mdlMap->vmaAddr;
4341 /* Return the page number according to the GPU page size. */
4342 gcmkASSERT((PAGE_SIZE % 4096) == 0);
4343 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
4345 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
4349 gcmkVERIFY_OK(gckOS_CacheFlush(
4354 (gctPOINTER)mdlMap->vmaAddr,
4355 mdl->numPages * PAGE_SIZE
4359 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
4360 return gcvSTATUS_OK;
4363 /*******************************************************************************
4367 ** Map paged memory into a page table.
4372 ** Pointer to an gckOS object.
4374 ** gctPHYS_ADDR Physical
4375 ** Physical address of the allocation.
4377 ** gctSIZE_T PageCount
4378 ** Number of pages required for the physical address.
4380 ** gctPOINTER PageTable
4381 ** Pointer to the page table to fill in.
4390 IN gctPHYS_ADDR Physical,
4391 IN gctSIZE_T PageCount,
4392 IN gctPOINTER PageTable
4395 return gckOS_MapPagesEx(Os,
4406 IN gctPHYS_ADDR Physical,
4407 IN gctSIZE_T PageCount,
4408 IN gctPOINTER PageTable
4411 gceSTATUS status = gcvSTATUS_OK;
4415 #if gcdNONPAGED_MEMORY_CACHEABLE
4419 gctPHYS_ADDR pageTablePhysical;
4422 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
4423 Os, Core, Physical, PageCount, PageTable);
4425 /* Verify the arguments. */
4426 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4427 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4428 gcmkVERIFY_ARGUMENT(PageCount > 0);
4429 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
4431 /* Convert pointer to MDL. */
4432 mdl = (PLINUX_MDL)Physical;
4435 gcvLEVEL_INFO, gcvZONE_OS,
4436 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4437 __FUNCTION__, __LINE__,
4438 (gctUINT32)(gctUINTPTR_T)Physical,
4439 (gctUINT32)(gctUINTPTR_T)PageCount,
4445 table = (gctUINT32 *)PageTable;
4446 #if gcdNONPAGED_MEMORY_CACHEABLE
4447 mmu = Os->device->kernels[Core]->mmu;
4448 bytes = PageCount * sizeof(*table);
4449 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4452 /* Get all the physical addresses and store them in the page table. */
4458 /* Try to get the user pages so DMA can happen. */
4459 while (PageCount-- > 0)
4462 if (Core == gcvCORE_VG)
4464 if (mdl->contiguous)
4467 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4468 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4474 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4475 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4482 if (mdl->contiguous)
4485 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4486 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4492 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4493 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4505 gcvLEVEL_INFO, gcvZONE_OS,
4506 "%s(%d): we should not get this call for Non Paged Memory!",
4507 __FUNCTION__, __LINE__
4510 while (PageCount-- > 0)
4513 if (Core == gcvCORE_VG)
4516 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4517 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4524 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4525 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4533 #if gcdNONPAGED_MEMORY_CACHEABLE
4534 /* Get physical address of pageTable */
4535 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4536 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4538 /* Flush the mmu page table cache. */
4539 gcmkONERROR(gckOS_CacheClean(
4553 /* Return the status. */
4558 /*******************************************************************************
4560 ** gckOS_UnlockPages
4562 ** Unlock memory allocated from the paged pool.
4567 ** Pointer to an gckOS object.
4569 ** gctPHYS_ADDR Physical
4570 ** Physical address of the allocation.
4573 ** Number of bytes of the allocation.
4575 ** gctPOINTER Logical
4576 ** Address of the mapped memory.
4585 IN gctPHYS_ADDR Physical,
4587 IN gctPOINTER Logical
4590 PLINUX_MDL_MAP mdlMap;
4591 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4593 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4594 Os, Physical, Bytes, Logical);
4596 /* Verify the arguments. */
4597 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4598 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4599 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4601 /* Make sure there is already a mapping...*/
4602 gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
4603 || mdl->u.contiguousPages != gcvNULL);
4609 while (mdlMap != gcvNULL)
4611 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4613 _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
4614 mdlMap->vmaAddr = gcvNULL;
4617 mdlMap = mdlMap->next;
4624 return gcvSTATUS_OK;
4628 /*******************************************************************************
4630 ** gckOS_AllocateContiguous
4632 ** Allocate memory from the contiguous pool.
4637 ** Pointer to an gckOS object.
4639 ** gctBOOL InUserSpace
4640 ** gcvTRUE if the pages need to be mapped into user space.
4642 ** gctSIZE_T * Bytes
4643 ** Pointer to the number of bytes to allocate.
4647 ** gctSIZE_T * Bytes
4648 ** Pointer to a variable that receives the number of bytes allocated.
4650 ** gctPHYS_ADDR * Physical
4651 ** Pointer to a variable that receives the physical address of the
4652 ** memory allocation.
4654 ** gctPOINTER * Logical
4655 ** Pointer to a variable that receives the logical address of the
4656 ** memory allocation.
4659 gckOS_AllocateContiguous(
4661 IN gctBOOL InUserSpace,
4662 IN OUT gctSIZE_T * Bytes,
4663 OUT gctPHYS_ADDR * Physical,
4664 OUT gctPOINTER * Logical
4669 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4670 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4672 /* Verify the arguments. */
4673 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4674 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4675 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4676 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4677 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4679 /* Same as non-paged memory for now. */
4680 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4687 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4688 *Bytes, *Physical, *Logical);
4689 return gcvSTATUS_OK;
4692 /* Return the status. */
4697 /*******************************************************************************
4699 ** gckOS_FreeContiguous
4701 ** Free memory allocated from the contiguous pool.
4706 ** Pointer to an gckOS object.
4708 ** gctPHYS_ADDR Physical
4709 ** Physical address of the allocation.
4711 ** gctPOINTER Logical
4712 ** Logicval address of the allocation.
4715 ** Number of bytes of the allocation.
4722 gckOS_FreeContiguous(
4724 IN gctPHYS_ADDR Physical,
4725 IN gctPOINTER Logical,
4731 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4732 Os, Physical, Logical, Bytes);
4734 /* Verify the arguments. */
4735 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4736 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4737 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4738 gcmkVERIFY_ARGUMENT(Bytes > 0);
4740 /* Same of non-paged memory for now. */
4741 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4745 return gcvSTATUS_OK;
4748 /* Return the status. */
4754 /******************************************************************************
4756 ** gckOS_GetKernelLogical
4758 ** Return the kernel logical pointer that corresponods to the specified
4759 ** hardware address.
4764 ** Pointer to an gckOS object.
4766 ** gctUINT32 Address
4767 ** Hardware physical address.
4771 ** gctPOINTER * KernelPointer
4772 ** Pointer to a variable receiving the pointer in kernel address space.
4775 gckOS_GetKernelLogical(
4777 IN gctUINT32 Address,
4778 OUT gctPOINTER * KernelPointer
4781 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4785 gckOS_GetKernelLogicalEx(
4788 IN gctUINT32 Address,
4789 OUT gctPOINTER * KernelPointer
4794 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4798 gckGALDEVICE device;
4804 /* Extract the pointer to the gckGALDEVICE class. */
4805 device = (gckGALDEVICE) Os->device;
4807 /* Kernel shortcut. */
4808 kernel = device->kernels[Core];
4810 if (Core == gcvCORE_VG)
4812 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4813 kernel->vg->hardware, Address, &pool, &offset
4819 /* Split the memory address into a pool type and offset. */
4820 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4821 kernel->hardware, Address, &pool, &offset
4825 /* Dispatch on pool. */
4828 case gcvPOOL_LOCAL_INTERNAL:
4829 /* Internal memory. */
4830 logical = device->internalLogical;
4833 case gcvPOOL_LOCAL_EXTERNAL:
4834 /* External memory. */
4835 logical = device->externalLogical;
4838 case gcvPOOL_SYSTEM:
4839 /* System memory. */
4840 logical = device->contiguousBase;
4844 /* Invalid memory pool. */
4846 return gcvSTATUS_INVALID_ARGUMENT;
4849 /* Build logical address of specified address. */
4850 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4853 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4854 return gcvSTATUS_OK;
4858 /* Return status. */
4864 /*******************************************************************************
4866 ** gckOS_MapUserPointer
4868 ** Map a pointer from the user process into the kernel address space.
4873 ** Pointer to an gckOS object.
4875 ** gctPOINTER Pointer
4876 ** Pointer in user process space that needs to be mapped.
4879 ** Number of bytes that need to be mapped.
4883 ** gctPOINTER * KernelPointer
4884 ** Pointer to a variable receiving the mapped pointer in kernel address
4888 gckOS_MapUserPointer(
4890 IN gctPOINTER Pointer,
4892 OUT gctPOINTER * KernelPointer
4895 gctPOINTER buf = gcvNULL;
4898 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
4900 /* Verify the arguments. */
4901 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4902 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4903 gcmkVERIFY_ARGUMENT(Size > 0);
4904 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4906 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
4911 "%s(%d): Failed to allocate memory.",
4912 __FUNCTION__, __LINE__
4915 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4916 return gcvSTATUS_OUT_OF_MEMORY;
4919 len = copy_from_user(buf, Pointer, Size);
4924 "%s(%d): Failed to copy data from user.",
4925 __FUNCTION__, __LINE__
4933 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
4934 return gcvSTATUS_GENERIC_IO;
4937 *KernelPointer = buf;
4939 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4940 return gcvSTATUS_OK;
4943 /*******************************************************************************
4945 ** gckOS_UnmapUserPointer
4947 ** Unmap a user process pointer from the kernel address space.
4952 ** Pointer to an gckOS object.
4954 ** gctPOINTER Pointer
4955 ** Pointer in user process space that needs to be unmapped.
4958 ** Number of bytes that need to be unmapped.
4960 ** gctPOINTER KernelPointer
4961 ** Pointer in kernel address space that needs to be unmapped.
4968 gckOS_UnmapUserPointer(
4970 IN gctPOINTER Pointer,
4972 IN gctPOINTER KernelPointer
4977 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
4978 Os, Pointer, Size, KernelPointer);
4981 /* Verify the arguments. */
4982 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4983 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4984 gcmkVERIFY_ARGUMENT(Size > 0);
4985 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4987 len = copy_to_user(Pointer, KernelPointer, Size);
4989 kfree(KernelPointer);
4995 "%s(%d): Failed to copy data to user.",
4996 __FUNCTION__, __LINE__
4999 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
5000 return gcvSTATUS_GENERIC_IO;
5004 return gcvSTATUS_OK;
5007 /*******************************************************************************
5009 ** gckOS_QueryNeedCopy
5011 ** Query whether the memory can be accessed or mapped directly or it has to be
5017 ** Pointer to an gckOS object.
5019 ** gctUINT32 ProcessID
5020 ** Process ID of the current process.
5024 ** gctBOOL_PTR NeedCopy
5025 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
5026 ** gcvFALSE if the memory can be accessed or mapped dircetly.
5029 gckOS_QueryNeedCopy(
5031 IN gctUINT32 ProcessID,
5032 OUT gctBOOL_PTR NeedCopy
5035 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
5037 /* Verify the arguments. */
5038 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5039 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
5041 /* We need to copy data. */
5042 *NeedCopy = gcvTRUE;
5045 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
5046 return gcvSTATUS_OK;
5049 /*******************************************************************************
5051 ** gckOS_CopyFromUserData
5053 ** Copy data from user to kernel memory.
5058 ** Pointer to an gckOS object.
5060 ** gctPOINTER KernelPointer
5061 ** Pointer to kernel memory.
5063 ** gctPOINTER Pointer
5064 ** Pointer to user memory.
5067 ** Number of bytes to copy.
5074 gckOS_CopyFromUserData(
5076 IN gctPOINTER KernelPointer,
5077 IN gctPOINTER Pointer,
5083 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5084 Os, KernelPointer, Pointer, Size);
5086 /* Verify the arguments. */
5087 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5088 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5089 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5090 gcmkVERIFY_ARGUMENT(Size > 0);
5092 /* Copy data from user. */
5093 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
5095 /* Could not copy all the bytes. */
5096 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5101 return gcvSTATUS_OK;
5104 /* Return the status. */
5109 /*******************************************************************************
5111 ** gckOS_CopyToUserData
5113 ** Copy data from kernel to user memory.
5118 ** Pointer to an gckOS object.
5120 ** gctPOINTER KernelPointer
5121 ** Pointer to kernel memory.
5123 ** gctPOINTER Pointer
5124 ** Pointer to user memory.
5127 ** Number of bytes to copy.
5134 gckOS_CopyToUserData(
5136 IN gctPOINTER KernelPointer,
5137 IN gctPOINTER Pointer,
5143 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5144 Os, KernelPointer, Pointer, Size);
5146 /* Verify the arguments. */
5147 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5148 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5149 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5150 gcmkVERIFY_ARGUMENT(Size > 0);
5152 /* Copy data to user. */
5153 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
5155 /* Could not copy all the bytes. */
5156 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5161 return gcvSTATUS_OK;
5164 /* Return the status. */
5169 /*******************************************************************************
5171 ** gckOS_WriteMemory
5173 ** Write data to a memory.
5178 ** Pointer to an gckOS object.
5180 ** gctPOINTER Address
5181 ** Address of the memory to write to.
5184 ** Data for register.
5193 IN gctPOINTER Address,
5198 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
5200 /* Verify the arguments. */
5201 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5204 if (access_ok(VERIFY_WRITE, Address, 4))
5207 if(put_user(Data, (gctUINT32*)Address))
5209 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
5214 /* Kernel address. */
5215 *(gctUINT32 *)Address = Data;
5220 return gcvSTATUS_OK;
5227 /*******************************************************************************
5229 ** gckOS_MapUserMemory
5231 ** Lock down a user buffer and return an DMA'able address to be used by the
5232 ** hardware to access it.
5236 ** gctPOINTER Memory
5237 ** Pointer to memory to lock down.
5240 ** Size in bytes of the memory to lock down.
5244 ** gctPOINTER * Info
5245 ** Pointer to variable receiving the information record required by
5246 ** gckOS_UnmapUserMemory.
5248 ** gctUINT32_PTR Address
5249 ** Pointer to a variable that will receive the address DMA'able by the
5253 gckOS_MapUserMemory(
5256 IN gctPOINTER Memory,
5257 IN gctUINT32 Physical,
5259 OUT gctPOINTER * Info,
5260 OUT gctUINT32_PTR Address
5265 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
5268 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
5271 return gcvSTATUS_OK;
5278 gctSIZE_T pageCount, i, j;
5279 gctUINT32_PTR pageTable;
5280 gctUINT32 address = 0, physical = ~0U;
5281 gctUINTPTR_T start, end, memory;
5285 gcsPageInfo_PTR info = gcvNULL;
5286 struct page **pages = gcvNULL;
5288 /* Verify the arguments. */
5289 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5290 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
5291 gcmkVERIFY_ARGUMENT(Size > 0);
5292 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5293 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5297 memory = (gctUINTPTR_T) Memory;
5299 /* Get the number of required pages. */
5300 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5301 start = memory >> PAGE_SHIFT;
5302 pageCount = end - start;
5305 gcvLEVEL_INFO, gcvZONE_OS,
5306 "%s(%d): pageCount: %d.",
5307 __FUNCTION__, __LINE__,
5312 if ((memory + Size) < memory)
5314 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5315 return gcvSTATUS_INVALID_ARGUMENT;
5318 MEMORY_MAP_LOCK(Os);
5320 /* Allocate the Info struct. */
5321 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
5323 if (info == gcvNULL)
5325 status = gcvSTATUS_OUT_OF_MEMORY;
5329 /* Allocate the array of page addresses. */
5330 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
5332 if (pages == gcvNULL)
5334 status = gcvSTATUS_OUT_OF_MEMORY;
5338 if (Physical != ~0U)
5340 for (i = 0; i < pageCount; i++)
5342 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
5348 /* Get the user pages. */
5349 down_read(¤t->mm->mmap_sem);
5350 result = get_user_pages(current,
5359 up_read(¤t->mm->mmap_sem);
5361 if (result <=0 || result < pageCount)
5363 struct vm_area_struct *vma;
5365 /* Free the page table. */
5366 if (pages != gcvNULL)
5368 /* Release the pages if any. */
5371 for (i = 0; i < result; i++)
5373 if (pages[i] == gcvNULL)
5378 page_cache_release(pages[i]);
5386 vma = find_vma(current->mm, memory);
5388 if (vma && (vma->vm_flags & VM_PFNMAP) )
5394 pgd_t * pgd = pgd_offset(current->mm, memory);
5395 pud_t * pud = pud_offset(pgd, memory);
5398 pmd_t * pmd = pmd_offset(pud, memory);
5399 pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
5402 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5407 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5410 pfn = pte_pfn(*pte);
5412 physical = (pfn << PAGE_SHIFT) | (memory & ~PAGE_MASK);
5414 pte_unmap_unlock(pte, ptl);
5416 if ((Os->device->kernels[Core]->hardware->mmuVersion == 0)
5417 && !((physical - Os->device->baseAddress) & 0x80000000))
5419 info->pages = gcvNULL;
5420 info->pageTable = gcvNULL;
5422 MEMORY_MAP_UNLOCK(Os);
5424 *Address = physical - Os->device->baseAddress;
5427 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5430 return gcvSTATUS_OK;
5435 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5442 for (i = 0; i < pageCount; i++)
5444 /* Flush(clean) the data cache. */
5445 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5446 (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
5447 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5453 /* Flush(clean) the data cache. */
5454 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5455 (gctPOINTER)(gctUINTPTR_T)(physical & PAGE_MASK),
5456 (gctPOINTER)(memory & PAGE_MASK),
5457 PAGE_SIZE * pageCount));
5461 if (Core == gcvCORE_VG)
5463 /* Allocate pages inside the page table. */
5464 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5465 pageCount * (PAGE_SIZE/4096),
5466 (gctPOINTER *) &pageTable,
5472 /* Allocate pages inside the page table. */
5473 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5474 pageCount * (PAGE_SIZE/4096),
5475 (gctPOINTER *) &pageTable,
5478 /* Fill the page table. */
5479 for (i = 0; i < pageCount; i++)
5482 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5486 phys = page_to_phys(pages[i]);
5490 phys = (physical & PAGE_MASK) + i * PAGE_SIZE;
5494 if (Core == gcvCORE_VG)
5496 /* Get the physical address from page struct. */
5498 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5505 /* Get the physical address from page struct. */
5507 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5512 for (j = 1; j < (PAGE_SIZE/4096); j++)
5514 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5518 gcvLEVEL_INFO, gcvZONE_OS,
5519 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5520 __FUNCTION__, __LINE__,
5521 i, phys, pageTable[i]);
5525 if (Core == gcvCORE_VG)
5527 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5532 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
5535 /* Save pointer to page table. */
5536 info->pageTable = pageTable;
5537 info->pages = pages;
5539 *Info = (gctPOINTER) info;
5542 gcvLEVEL_INFO, gcvZONE_OS,
5543 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5544 __FUNCTION__, __LINE__,
5550 offset = (Physical != ~0U)
5551 ? (Physical & ~PAGE_MASK)
5552 : (memory & ~PAGE_MASK);
5554 /* Return address. */
5555 *Address = address + offset;
5558 gcvLEVEL_INFO, gcvZONE_OS,
5559 "%s(%d): Address: 0x%X.",
5560 __FUNCTION__, __LINE__,
5565 status = gcvSTATUS_OK;
5571 if (gcmIS_ERROR(status))
5575 "%s(%d): error occured: %d.",
5576 __FUNCTION__, __LINE__,
5580 /* Release page array. */
5581 if (result > 0 && pages != gcvNULL)
5585 "%s(%d): error: page table is freed.",
5586 __FUNCTION__, __LINE__
5589 for (i = 0; i < result; i++)
5591 if (pages[i] == gcvNULL)
5595 page_cache_release(pages[i]);
5599 if (info!= gcvNULL && pages != gcvNULL)
5603 "%s(%d): error: pages is freed.",
5604 __FUNCTION__, __LINE__
5607 /* Free the page table. */
5609 info->pages = gcvNULL;
5612 /* Release page info struct. */
5613 if (info != gcvNULL)
5617 "%s(%d): error: info is freed.",
5618 __FUNCTION__, __LINE__
5621 /* Free the page info struct. */
5627 MEMORY_MAP_UNLOCK(Os);
5629 /* Return the status. */
5630 if (gcmIS_SUCCESS(status))
5632 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5644 /*******************************************************************************
5646 ** gckOS_UnmapUserMemory
5648 ** Unlock a user buffer and that was previously locked down by
5649 ** gckOS_MapUserMemory.
5653 ** gctPOINTER Memory
5654 ** Pointer to memory to unlock.
5657 ** Size in bytes of the memory to unlock.
5660 ** Information record returned by gckOS_MapUserMemory.
5662 ** gctUINT32_PTR Address
5663 ** The address returned by gckOS_MapUserMemory.
5670 gckOS_UnmapUserMemory(
5673 IN gctPOINTER Memory,
5676 IN gctUINT32 Address
5681 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5682 Os, Core, Memory, Size, Info, Address);
5685 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5688 return gcvSTATUS_OK;
5695 gctUINTPTR_T memory, start, end;
5696 gcsPageInfo_PTR info;
5697 gctSIZE_T pageCount, i;
5698 struct page **pages;
5700 /* Verify the arguments. */
5701 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5702 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5703 gcmkVERIFY_ARGUMENT(Size > 0);
5704 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5708 info = (gcsPageInfo_PTR) Info;
5710 pages = info->pages;
5713 gcvLEVEL_INFO, gcvZONE_OS,
5714 "%s(%d): info=0x%X, pages=0x%X.",
5715 __FUNCTION__, __LINE__,
5719 /* Invalid page array. */
5720 if (pages == gcvNULL && info->pageTable == gcvNULL)
5725 return gcvSTATUS_OK;
5728 memory = (gctUINTPTR_T)Memory;
5729 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5730 start = memory >> PAGE_SHIFT;
5731 pageCount = end - start;
5734 if ((memory + Size) < memory)
5736 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5737 return gcvSTATUS_INVALID_ARGUMENT;
5741 gcvLEVEL_INFO, gcvZONE_OS,
5742 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5743 __FUNCTION__, __LINE__,
5744 memory, pageCount, info->pageTable
5747 MEMORY_MAP_LOCK(Os);
5749 gcmkASSERT(info->pageTable != gcvNULL);
5752 if (Core == gcvCORE_VG)
5754 /* Free the pages from the MMU. */
5755 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5757 pageCount * (PAGE_SIZE/4096)
5763 /* Free the pages from the MMU. */
5764 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5766 pageCount * (PAGE_SIZE/4096)
5770 /* Release the page cache. */
5773 for (i = 0; i < pageCount; i++)
5776 gcvLEVEL_INFO, gcvZONE_OS,
5777 "%s(%d): pages[%d]: 0x%X.",
5778 __FUNCTION__, __LINE__,
5782 if (!PageReserved(pages[i]))
5784 SetPageDirty(pages[i]);
5787 page_cache_release(pages[i]);
5792 status = gcvSTATUS_OK;
5796 if (info != gcvNULL)
5798 /* Free the page array. */
5799 if (info->pages != gcvNULL)
5807 MEMORY_MAP_UNLOCK(Os);
5809 /* Return the status. */
5816 /*******************************************************************************
5818 ** gckOS_GetBaseAddress
5820 ** Get the base address for the physical memory.
5825 ** Pointer to the gckOS object.
5829 ** gctUINT32_PTR BaseAddress
5830 ** Pointer to a variable that will receive the base address.
5833 gckOS_GetBaseAddress(
5835 OUT gctUINT32_PTR BaseAddress
5838 gcmkHEADER_ARG("Os=0x%X", Os);
5840 /* Verify the arguments. */
5841 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5842 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5844 /* Return base address. */
5845 *BaseAddress = Os->device->baseAddress;
5848 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5849 return gcvSTATUS_OK;
5853 gckOS_SuspendInterrupt(
5857 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5861 gckOS_SuspendInterruptEx(
5866 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5868 /* Verify the arguments. */
5869 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5871 disable_irq(Os->device->irqLines[Core]);
5874 return gcvSTATUS_OK;
5878 gckOS_ResumeInterrupt(
5882 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
5886 gckOS_ResumeInterruptEx(
5891 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5893 /* Verify the arguments. */
5894 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5896 enable_irq(Os->device->irqLines[Core]);
5899 return gcvSTATUS_OK;
5904 IN gctPOINTER Destination,
5905 IN gctCONST_POINTER Source,
5909 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
5910 Destination, Source, Bytes);
5912 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
5913 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
5914 gcmkVERIFY_ARGUMENT(Bytes > 0);
5916 memcpy(Destination, Source, Bytes);
5919 return gcvSTATUS_OK;
5924 IN gctPOINTER Memory,
5928 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
5930 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5931 gcmkVERIFY_ARGUMENT(Bytes > 0);
5933 memset(Memory, 0, Bytes);
5936 return gcvSTATUS_OK;
5939 /*******************************************************************************
5940 ********************************* Cache Control ********************************
5941 *******************************************************************************/
5943 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
5944 static inline gceSTATUS
5946 gceCACHEOPERATION Type,
5947 unsigned long Start,
5953 case gcvCACHE_CLEAN:
5954 outer_clean_range(Start, End);
5956 case gcvCACHE_INVALIDATE:
5957 outer_inv_range(Start, End);
5959 case gcvCACHE_FLUSH:
5960 outer_flush_range(Start, End);
5963 return gcvSTATUS_INVALID_ARGUMENT;
5966 return gcvSTATUS_OK;
5969 #if gcdENABLE_OUTER_CACHE_PATCH
5970 /*******************************************************************************
5971 ** _HandleOuterCache
5973 ** Handle the outer cache for the specified addresses.
5978 ** Pointer to gckOS object.
5980 ** gctUINT32 ProcessID
5981 ** Process ID Logical belongs.
5983 ** gctPHYS_ADDR Handle
5984 ** Physical address handle. If gcvNULL it is video memory.
5986 ** gctPOINTER Physical
5987 ** Physical address to flush.
5989 ** gctPOINTER Logical
5990 ** Logical address to flush.
5993 ** Size of the address range in bytes to flush.
5995 ** gceOUTERCACHE_OPERATION Type
5996 ** Operation need to be execute.
6001 IN gctUINT32 ProcessID,
6002 IN gctPHYS_ADDR Handle,
6003 IN gctPOINTER Physical,
6004 IN gctPOINTER Logical,
6006 IN gceCACHEOPERATION Type
6010 gctUINT32 i, pageNum;
6011 unsigned long paddr;
6014 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6015 Os, ProcessID, Handle, Logical, Bytes);
6017 if (Physical != gcvNULL)
6019 /* Non paged memory or gcvPOOL_USER surface */
6020 paddr = (unsigned long) Physical;
6021 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6023 else if ((Handle == gcvNULL)
6024 || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
6027 /* Video Memory or contiguous virtual memory */
6028 gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
6029 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6033 /* Non contiguous virtual memory */
6034 vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
6035 pageNum = GetPageCount(Bytes, 0);
6037 for (i = 0; i < pageNum; i += 1)
6039 gcmkONERROR(_ConvertLogical2Physical(
6041 vaddr + PAGE_SIZE * i,
6047 gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
6055 return gcvSTATUS_OK;
6058 /* Return the status. */
6065 /*******************************************************************************
6068 ** Clean the cache for the specified addresses. The GPU is going to need the
6069 ** data. If the system is allocating memory as non-cachable, this function can
6075 ** Pointer to gckOS object.
6077 ** gctUINT32 ProcessID
6078 ** Process ID Logical belongs.
6080 ** gctPHYS_ADDR Handle
6081 ** Physical address handle. If gcvNULL it is video memory.
6083 ** gctPOINTER Physical
6084 ** Physical address to flush.
6086 ** gctPOINTER Logical
6087 ** Logical address to flush.
6090 ** Size of the address range in bytes to flush.
6095 IN gctUINT32 ProcessID,
6096 IN gctPHYS_ADDR Handle,
6097 IN gctPOINTER Physical,
6098 IN gctPOINTER Logical,
6102 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6103 Os, ProcessID, Handle, Logical, Bytes);
6105 /* Verify the arguments. */
6106 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6107 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6108 gcmkVERIFY_ARGUMENT(Bytes > 0);
6110 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6114 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6115 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
6117 dmac_clean_range(Logical, Logical + Bytes);
6120 #if defined(CONFIG_OUTER_CACHE)
6122 #if gcdENABLE_OUTER_CACHE_PATCH
6123 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
6125 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6129 #elif defined(CONFIG_MIPS)
6131 dma_cache_wback((unsigned long) Logical, Bytes);
6133 #elif defined(CONFIG_PPC)
6138 dma_sync_single_for_device(
6148 return gcvSTATUS_OK;
6151 /*******************************************************************************
6152 ** gckOS_CacheInvalidate
6154 ** Invalidate the cache for the specified addresses. The GPU is going to need
6155 ** data. If the system is allocating memory as non-cachable, this function can
6161 ** Pointer to gckOS object.
6163 ** gctUINT32 ProcessID
6164 ** Process ID Logical belongs.
6166 ** gctPHYS_ADDR Handle
6167 ** Physical address handle. If gcvNULL it is video memory.
6169 ** gctPOINTER Logical
6170 ** Logical address to flush.
6173 ** Size of the address range in bytes to flush.
6176 gckOS_CacheInvalidate(
6178 IN gctUINT32 ProcessID,
6179 IN gctPHYS_ADDR Handle,
6180 IN gctPOINTER Physical,
6181 IN gctPOINTER Logical,
6185 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6186 Os, ProcessID, Handle, Logical, Bytes);
6188 /* Verify the arguments. */
6189 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6190 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6191 gcmkVERIFY_ARGUMENT(Bytes > 0);
6193 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6197 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6198 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
6200 dmac_inv_range(Logical, Logical + Bytes);
6203 #if defined(CONFIG_OUTER_CACHE)
6205 #if gcdENABLE_OUTER_CACHE_PATCH
6206 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
6208 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6212 #elif defined(CONFIG_MIPS)
6213 dma_cache_inv((unsigned long) Logical, Bytes);
6214 #elif defined(CONFIG_PPC)
6217 dma_sync_single_for_device(
6227 return gcvSTATUS_OK;
6230 /*******************************************************************************
6233 ** Clean the cache for the specified addresses and invalidate the lines as
6234 ** well. The GPU is going to need and modify the data. If the system is
6235 ** allocating memory as non-cachable, this function can be ignored.
6240 ** Pointer to gckOS object.
6242 ** gctUINT32 ProcessID
6243 ** Process ID Logical belongs.
6245 ** gctPHYS_ADDR Handle
6246 ** Physical address handle. If gcvNULL it is video memory.
6248 ** gctPOINTER Logical
6249 ** Logical address to flush.
6252 ** Size of the address range in bytes to flush.
6257 IN gctUINT32 ProcessID,
6258 IN gctPHYS_ADDR Handle,
6259 IN gctPOINTER Physical,
6260 IN gctPOINTER Logical,
6264 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6265 Os, ProcessID, Handle, Logical, Bytes);
6267 /* Verify the arguments. */
6268 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6269 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6270 gcmkVERIFY_ARGUMENT(Bytes > 0);
6272 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6275 dmac_flush_range(Logical, Logical + Bytes);
6277 #if defined(CONFIG_OUTER_CACHE)
6279 #if gcdENABLE_OUTER_CACHE_PATCH
6280 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6282 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6286 #elif defined(CONFIG_MIPS)
6287 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6288 #elif defined(CONFIG_PPC)
6291 dma_sync_single_for_device(
6301 return gcvSTATUS_OK;
6304 /*******************************************************************************
6305 ********************************* Broadcasting *********************************
6306 *******************************************************************************/
6308 /*******************************************************************************
6312 ** System hook for broadcast events from the kernel driver.
6317 ** Pointer to the gckOS object.
6319 ** gckHARDWARE Hardware
6320 ** Pointer to the gckHARDWARE object.
6322 ** gceBROADCAST Reason
6323 ** Reason for the broadcast. Can be one of the following values:
6325 ** gcvBROADCAST_GPU_IDLE
6326 ** Broadcasted when the kernel driver thinks the GPU might be
6327 ** idle. This can be used to handle power management.
6329 ** gcvBROADCAST_GPU_COMMIT
6330 ** Broadcasted when any client process commits a command
6331 ** buffer. This can be used to handle power management.
6333 ** gcvBROADCAST_GPU_STUCK
6334 ** Broadcasted when the kernel driver hits the timeout waiting
6337 ** gcvBROADCAST_FIRST_PROCESS
6338 ** First process is trying to connect to the kernel.
6340 ** gcvBROADCAST_LAST_PROCESS
6341 ** Last process has detached from the kernel.
6350 IN gckHARDWARE Hardware,
6351 IN gceBROADCAST Reason
6356 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6358 /* Verify the arguments. */
6359 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6360 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6364 case gcvBROADCAST_FIRST_PROCESS:
6365 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6368 case gcvBROADCAST_LAST_PROCESS:
6369 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6373 gckHARDWARE_SetPowerManagementState(Hardware,
6374 gcvPOWER_OFF_BROADCAST));
6377 case gcvBROADCAST_GPU_IDLE:
6378 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6382 gckHARDWARE_SetPowerManagementState(Hardware,
6383 #if gcdPOWER_SUSNPEND_WHEN_IDLE
6384 gcvPOWER_SUSPEND_BROADCAST));
6386 gcvPOWER_IDLE_BROADCAST));
6389 /* Add idle process DB. */
6390 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6393 gcvNULL, gcvNULL, 0));
6396 case gcvBROADCAST_GPU_COMMIT:
6397 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6399 /* Add busy process DB. */
6400 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6403 gcvNULL, gcvNULL, 0));
6407 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6410 case gcvBROADCAST_GPU_STUCK:
6411 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6412 #if !gcdENABLE_RECOVERY
6413 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6415 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6418 case gcvBROADCAST_AXI_BUS_ERROR:
6419 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6420 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6421 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6427 return gcvSTATUS_OK;
6430 /* Return the status. */
6435 /*******************************************************************************
6437 ** gckOS_BroadcastHurry
6439 ** The GPU is running too slow.
6444 ** Pointer to the gckOS object.
6446 ** gckHARDWARE Hardware
6447 ** Pointer to the gckHARDWARE object.
6450 ** The higher the number, the higher the urgency to speed up the GPU.
6451 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6458 gckOS_BroadcastHurry(
6460 IN gckHARDWARE Hardware,
6464 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6466 /* Do whatever you need to do to speed up the GPU now. */
6470 return gcvSTATUS_OK;
6473 /*******************************************************************************
6475 ** gckOS_BroadcastCalibrateSpeed
6477 ** Calibrate the speed of the GPU.
6482 ** Pointer to the gckOS object.
6484 ** gckHARDWARE Hardware
6485 ** Pointer to the gckHARDWARE object.
6487 ** gctUINT Idle, Time
6488 ** Idle/Time will give the percentage the GPU is idle, so you can use
6489 ** this to calibrate the working point of the GPU.
6496 gckOS_BroadcastCalibrateSpeed(
6498 IN gckHARDWARE Hardware,
6503 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6504 Os, Hardware, Idle, Time);
6506 /* Do whatever you need to do to callibrate the GPU speed. */
6510 return gcvSTATUS_OK;
6513 /*******************************************************************************
6514 ********************************** Semaphores **********************************
6515 *******************************************************************************/
6517 /*******************************************************************************
6519 ** gckOS_CreateSemaphore
6521 ** Create a semaphore.
6526 ** Pointer to the gckOS object.
6530 ** gctPOINTER * Semaphore
6531 ** Pointer to the variable that will receive the created semaphore.
6534 gckOS_CreateSemaphore(
6536 OUT gctPOINTER * Semaphore
6540 struct semaphore *sem = gcvNULL;
6542 gcmkHEADER_ARG("Os=0x%X", Os);
6544 /* Verify the arguments. */
6545 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6546 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6548 /* Allocate the semaphore structure. */
6549 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6552 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6555 /* Initialize the semaphore. */
6558 /* Return to caller. */
6559 *Semaphore = (gctPOINTER) sem;
6563 return gcvSTATUS_OK;
6566 /* Return the status. */
6571 /*******************************************************************************
6573 ** gckOS_AcquireSemaphore
6575 ** Acquire a semaphore.
6580 ** Pointer to the gckOS object.
6582 ** gctPOINTER Semaphore
6583 ** Pointer to the semaphore thet needs to be acquired.
6590 gckOS_AcquireSemaphore(
6592 IN gctPOINTER Semaphore
6597 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6599 /* Verify the arguments. */
6600 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6601 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6603 /* Acquire the semaphore. */
6604 if (down_interruptible((struct semaphore *) Semaphore))
6606 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6611 return gcvSTATUS_OK;
6614 /* Return the status. */
6619 /*******************************************************************************
6621 ** gckOS_TryAcquireSemaphore
6623 ** Try to acquire a semaphore.
6628 ** Pointer to the gckOS object.
6630 ** gctPOINTER Semaphore
6631 ** Pointer to the semaphore thet needs to be acquired.
6638 gckOS_TryAcquireSemaphore(
6640 IN gctPOINTER Semaphore
6645 gcmkHEADER_ARG("Os=0x%x", Os);
6647 /* Verify the arguments. */
6648 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6649 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6651 /* Acquire the semaphore. */
6652 if (down_trylock((struct semaphore *) Semaphore))
6655 status = gcvSTATUS_TIMEOUT;
6662 return gcvSTATUS_OK;
6665 /*******************************************************************************
6667 ** gckOS_ReleaseSemaphore
6669 ** Release a previously acquired semaphore.
6674 ** Pointer to the gckOS object.
6676 ** gctPOINTER Semaphore
6677 ** Pointer to the semaphore thet needs to be released.
6684 gckOS_ReleaseSemaphore(
6686 IN gctPOINTER Semaphore
6689 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6691 /* Verify the arguments. */
6692 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6693 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6695 /* Release the semaphore. */
6696 up((struct semaphore *) Semaphore);
6700 return gcvSTATUS_OK;
6703 /*******************************************************************************
6705 ** gckOS_DestroySemaphore
6707 ** Destroy a semaphore.
6712 ** Pointer to the gckOS object.
6714 ** gctPOINTER Semaphore
6715 ** Pointer to the semaphore thet needs to be destroyed.
6722 gckOS_DestroySemaphore(
6724 IN gctPOINTER Semaphore
6727 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6729 /* Verify the arguments. */
6730 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6731 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6733 /* Free the sempahore structure. */
6738 return gcvSTATUS_OK;
6741 /*******************************************************************************
6743 ** gckOS_GetProcessID
6745 ** Get current process ID.
6753 ** gctUINT32_PTR ProcessID
6754 ** Pointer to the variable that receives the process ID.
6758 OUT gctUINT32_PTR ProcessID
6761 /* Get process ID. */
6762 if (ProcessID != gcvNULL)
6764 *ProcessID = _GetProcessID();
6768 return gcvSTATUS_OK;
6771 /*******************************************************************************
6773 ** gckOS_GetThreadID
6775 ** Get current thread ID.
6783 ** gctUINT32_PTR ThreadID
6784 ** Pointer to the variable that receives the thread ID.
6788 OUT gctUINT32_PTR ThreadID
6791 /* Get thread ID. */
6792 if (ThreadID != gcvNULL)
6794 *ThreadID = _GetThreadID();
6798 return gcvSTATUS_OK;
6801 /*******************************************************************************
6803 ** gckOS_SetGPUPower
6805 ** Set the power of the GPU on or off.
6810 ** Pointer to a gckOS object.
6813 ** GPU whose power is set.
6816 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6819 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6833 struct clk *clk_3dcore = Os->device->clk_3d_core;
6834 struct clk *clk_3dshader = Os->device->clk_3d_shader;
6835 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
6836 struct clk *clk_3d_axi = Os->device->clk_3d_axi;
6838 struct clk *clk_2dcore = Os->device->clk_2d_core;
6839 struct clk *clk_2d_axi = Os->device->clk_2d_axi;
6840 struct clk *clk_vg_axi = Os->device->clk_vg_axi;
6842 gctBOOL oldClockState = gcvFALSE;
6843 gctBOOL oldPowerState = gcvFALSE;
6845 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6847 if (Os->device->kernels[Core] != NULL)
6850 if (Core == gcvCORE_VG)
6852 oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
6853 oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
6858 oldClockState = Os->device->kernels[Core]->hardware->clockState;
6859 oldPowerState = Os->device->kernels[Core]->hardware->powerState;
6864 if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
6866 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6867 if(!IS_ERR(Os->device->gpu_regulator))
6868 regulator_enable(Os->device->gpu_regulator);
6870 imx_gpc_power_up_pu(true);
6874 pm_runtime_get_sync(Os->device->pmdev);
6878 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6879 if (Clock == gcvTRUE) {
6880 if (oldClockState == gcvFALSE) {
6883 clk_enable(clk_3dcore);
6885 clk_enable(clk_3dshader);
6888 clk_enable(clk_2dcore);
6889 clk_enable(clk_2d_axi);
6892 clk_enable(clk_2dcore);
6893 clk_enable(clk_vg_axi);
6900 if (oldClockState == gcvTRUE) {
6904 clk_disable(clk_3dshader);
6905 clk_disable(clk_3dcore);
6908 clk_disable(clk_2dcore);
6909 clk_disable(clk_2d_axi);
6912 clk_disable(clk_2dcore);
6913 clk_disable(clk_vg_axi);
6921 if (Clock == gcvTRUE) {
6922 if (oldClockState == gcvFALSE) {
6925 clk_prepare(clk_3dcore);
6926 clk_enable(clk_3dcore);
6927 clk_prepare(clk_3dshader);
6928 clk_enable(clk_3dshader);
6929 clk_prepare(clk_3d_axi);
6930 clk_enable(clk_3d_axi);
6933 clk_prepare(clk_2dcore);
6934 clk_enable(clk_2dcore);
6935 clk_prepare(clk_2d_axi);
6936 clk_enable(clk_2d_axi);
6939 clk_prepare(clk_2dcore);
6940 clk_enable(clk_2dcore);
6941 clk_prepare(clk_vg_axi);
6942 clk_enable(clk_vg_axi);
6949 if (oldClockState == gcvTRUE) {
6952 clk_disable(clk_3dshader);
6953 clk_unprepare(clk_3dshader);
6954 clk_disable(clk_3dcore);
6955 clk_unprepare(clk_3dcore);
6956 clk_disable(clk_3d_axi);
6957 clk_unprepare(clk_3d_axi);
6960 clk_disable(clk_2dcore);
6961 clk_unprepare(clk_2dcore);
6962 clk_disable(clk_2d_axi);
6963 clk_unprepare(clk_2d_axi);
6966 clk_disable(clk_2dcore);
6967 clk_unprepare(clk_2dcore);
6968 clk_disable(clk_vg_axi);
6969 clk_unprepare(clk_vg_axi);
6977 if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
6980 pm_runtime_put_sync(Os->device->pmdev);
6983 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6984 if(!IS_ERR(Os->device->gpu_regulator))
6985 regulator_disable(Os->device->gpu_regulator);
6987 imx_gpc_power_up_pu(false);
6991 /* TODO: Put your code here. */
6993 return gcvSTATUS_OK;
6996 /*******************************************************************************
7005 ** Pointer to a gckOS object.
7008 ** GPU whose power is set.
7020 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7021 #define SRC_SCR_OFFSET 0
7022 #define BP_SRC_SCR_GPU3D_RST 1
7023 #define BP_SRC_SCR_GPU2D_RST 4
7024 void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
7025 gctUINT32 bit_offset,val;
7027 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
7029 if(Core == gcvCORE_MAJOR) {
7030 bit_offset = BP_SRC_SCR_GPU3D_RST;
7031 } else if((Core == gcvCORE_VG)
7032 ||(Core == gcvCORE_2D)) {
7033 bit_offset = BP_SRC_SCR_GPU2D_RST;
7035 return gcvSTATUS_INVALID_CONFIG;
7037 val = __raw_readl(src_base + SRC_SCR_OFFSET);
7038 val &= ~(1 << (bit_offset));
7039 val |= (1 << (bit_offset));
7040 __raw_writel(val, src_base + SRC_SCR_OFFSET);
7042 while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
7043 (1 << (bit_offset))) != 0) {
7048 imx_src_reset_gpu((int)Core);
7050 return gcvSTATUS_OK;
7053 /*******************************************************************************
7055 ** gckOS_PrepareGPUFrequency
7057 ** Prepare to set GPU frequency and voltage.
7062 ** Pointer to a gckOS object.
7065 ** GPU whose frequency and voltage will be set.
7072 gckOS_PrepareGPUFrequency(
7077 return gcvSTATUS_OK;
7080 /*******************************************************************************
7082 ** gckOS_FinishGPUFrequency
7084 ** Finish GPU frequency setting.
7089 ** Pointer to a gckOS object.
7092 ** GPU whose frequency and voltage is set.
7099 gckOS_FinishGPUFrequency(
7104 return gcvSTATUS_OK;
7107 /*******************************************************************************
7109 ** gckOS_QueryGPUFrequency
7111 ** Query the current frequency of the GPU.
7116 ** Pointer to a gckOS object.
7119 ** GPU whose power is set.
7121 ** gctUINT32 * Frequency
7122 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
7125 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
7132 gckOS_QueryGPUFrequency(
7135 OUT gctUINT32 * Frequency,
7136 OUT gctUINT8 * Scale
7139 return gcvSTATUS_OK;
7142 /*******************************************************************************
7144 ** gckOS_SetGPUFrequency
7146 ** Set frequency and voltage of the GPU.
7148 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
7149 ** a real frequency according to this scale and board's configure.
7151 ** 2. BSP should find a suitable voltage for this frequency.
7153 ** 3. BSP must make sure setting take effect before this function returns.
7158 ** Pointer to a gckOS object.
7161 ** GPU whose power is set.
7164 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
7165 ** full frequency and 64 means 64/64 of full frequency.
7172 gckOS_SetGPUFrequency(
7178 return gcvSTATUS_OK;
7181 /*----------------------------------------------------------------------------*/
7182 /*----- Profile --------------------------------------------------------------*/
7185 gckOS_GetProfileTick(
7186 OUT gctUINT64_PTR Tick
7189 struct timespec time;
7191 ktime_get_ts(&time);
7193 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
7195 return gcvSTATUS_OK;
7199 gckOS_QueryProfileTickRate(
7200 OUT gctUINT64_PTR TickRate
7203 struct timespec res;
7205 hrtimer_get_res(CLOCK_MONOTONIC, &res);
7207 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
7209 return gcvSTATUS_OK;
7217 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
7218 return div_u64(Ticks, 1000000);
7220 gctUINT64 rem = Ticks;
7221 gctUINT64 b = 1000000;
7222 gctUINT64 res, d = 1;
7223 gctUINT32 high = rem >> 32;
7225 /* Reduce the thing a bit first */
7227 if (high >= 1000000)
7230 res = (gctUINT64) high << 32;
7231 rem -= (gctUINT64) (high * 1000000) << 32;
7234 while (((gctINT64) b > 0) && (b < rem))
7253 return (gctUINT32) res;
7257 /******************************************************************************\
7258 ******************************* Signal Management ******************************
7259 \******************************************************************************/
7262 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
7264 /*******************************************************************************
7266 ** gckOS_CreateSignal
7268 ** Create a new signal.
7273 ** Pointer to an gckOS object.
7275 ** gctBOOL ManualReset
7276 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7277 ** order to set the signal to nonsignaled state.
7278 ** If set to gcvFALSE, the signal will automatically be set to
7279 ** nonsignaled state by gckOS_WaitSignal function.
7283 ** gctSIGNAL * Signal
7284 ** Pointer to a variable receiving the created gctSIGNAL.
7289 IN gctBOOL ManualReset,
7290 OUT gctSIGNAL * Signal
7294 gcsSIGNAL_PTR signal;
7296 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
7298 /* Verify the arguments. */
7299 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7300 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7302 /* Create an event structure. */
7303 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
7305 if (signal == gcvNULL)
7307 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7310 /* Save the process ID. */
7311 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
7312 signal->manualReset = ManualReset;
7313 signal->hardware = gcvNULL;
7314 init_completion(&signal->obj);
7315 atomic_set(&signal->ref, 1);
7317 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
7319 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
7321 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
7322 return gcvSTATUS_OK;
7325 if (signal != gcvNULL)
7335 gckOS_SignalQueryHardware(
7337 IN gctSIGNAL Signal,
7338 OUT gckHARDWARE * Hardware
7342 gcsSIGNAL_PTR signal;
7344 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7346 /* Verify the arguments. */
7347 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7348 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7349 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7351 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7353 *Hardware = signal->hardware;
7356 return gcvSTATUS_OK;
7363 gckOS_SignalSetHardware(
7365 IN gctSIGNAL Signal,
7366 IN gckHARDWARE Hardware
7370 gcsSIGNAL_PTR signal;
7372 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7374 /* Verify the arguments. */
7375 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7376 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7378 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7380 signal->hardware = Hardware;
7383 return gcvSTATUS_OK;
7389 /*******************************************************************************
7391 ** gckOS_DestroySignal
7393 ** Destroy a signal.
7398 ** Pointer to an gckOS object.
7401 ** Pointer to the gctSIGNAL.
7408 gckOS_DestroySignal(
7414 gcsSIGNAL_PTR signal;
7415 gctBOOL acquired = gcvFALSE;
7417 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7419 /* Verify the arguments. */
7420 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7421 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7423 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7426 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7428 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7430 if (atomic_dec_and_test(&signal->ref))
7432 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7434 /* Free the sgianl. */
7438 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7439 acquired = gcvFALSE;
7443 return gcvSTATUS_OK;
7448 /* Release the mutex. */
7449 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7456 /*******************************************************************************
7460 ** Set a state of the specified signal.
7465 ** Pointer to an gckOS object.
7468 ** Pointer to the gctSIGNAL.
7471 ** If gcvTRUE, the signal will be set to signaled state.
7472 ** If gcvFALSE, the signal will be set to nonsignaled state.
7481 IN gctSIGNAL Signal,
7486 gcsSIGNAL_PTR signal;
7487 gctBOOL acquired = gcvFALSE;
7489 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7491 /* Verify the arguments. */
7492 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7493 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7495 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7498 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7500 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7504 /* unbind the signal from hardware. */
7505 signal->hardware = gcvNULL;
7507 /* Set the event to a signaled state. */
7508 complete(&signal->obj);
7512 /* Set the event to an unsignaled state. */
7513 INIT_COMPLETION(signal->obj);
7516 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7517 acquired = gcvFALSE;
7521 return gcvSTATUS_OK;
7526 /* Release the mutex. */
7527 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7538 IN gctHANDLE Process,
7544 struct task_struct * userTask;
7545 struct siginfo info;
7547 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7549 if (userTask != gcvNULL)
7552 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7555 info.si_ptr = (gctPOINTER) Signal;
7557 /* Signals with numbers between 32 and 63 are real-time,
7558 send a real-time signal to the user process. */
7559 result = send_sig_info(48, &info, userTask);
7561 printk("gckOS_SetSignalVG:0x%x\n", result);
7565 status = gcvSTATUS_GENERIC_IO;
7569 "%s(%d): an error has occurred.\n",
7570 __FUNCTION__, __LINE__
7575 status = gcvSTATUS_OK;
7580 status = gcvSTATUS_GENERIC_IO;
7584 "%s(%d): an error has occurred.\n",
7585 __FUNCTION__, __LINE__
7589 /* Return status. */
7594 /*******************************************************************************
7598 ** Set the specified signal which is owned by a process to signaled state.
7603 ** Pointer to an gckOS object.
7606 ** Pointer to the gctSIGNAL.
7608 ** gctHANDLE Process
7609 ** Handle of process owning the signal.
7618 IN gctSIGNAL Signal,
7619 IN gctHANDLE Process
7625 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7626 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7628 /* Map the signal into kernel space. */
7629 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7632 status = gckOS_Signal(Os, signal, gcvTRUE);
7634 /* Unmap the signal */
7635 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7641 /* Return the status. */
7646 /*******************************************************************************
7650 ** Wait for a signal to become signaled.
7655 ** Pointer to an gckOS object.
7658 ** Pointer to the gctSIGNAL.
7661 ** Number of milliseconds to wait.
7662 ** Pass the value of gcvINFINITE for an infinite wait.
7671 IN gctSIGNAL Signal,
7675 gceSTATUS status = gcvSTATUS_OK;
7676 gcsSIGNAL_PTR signal;
7678 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7680 /* Verify the arguments. */
7681 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7682 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7684 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7686 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7690 spin_lock_irq(&signal->obj.wait.lock);
7692 if (signal->obj.done)
7694 if (!signal->manualReset)
7696 signal->obj.done = 0;
7699 status = gcvSTATUS_OK;
7703 status = gcvSTATUS_TIMEOUT;
7707 /* Convert wait to milliseconds. */
7708 #if gcdDETECT_TIMEOUT
7709 gctINT timeout = (Wait == gcvINFINITE)
7710 ? gcdINFINITE_TIMEOUT * HZ / 1000
7713 gctUINT complained = 0;
7715 gctINT timeout = (Wait == gcvINFINITE)
7716 ? MAX_SCHEDULE_TIMEOUT
7720 DECLARE_WAITQUEUE(wait, current);
7721 wait.flags |= WQ_FLAG_EXCLUSIVE;
7722 __add_wait_queue_tail(&signal->obj.wait, &wait);
7726 if (signal_pending(current))
7728 /* Interrupt received. */
7729 status = gcvSTATUS_INTERRUPTED;
7733 __set_current_state(TASK_INTERRUPTIBLE);
7734 spin_unlock_irq(&signal->obj.wait.lock);
7735 timeout = schedule_timeout(timeout);
7736 spin_lock_irq(&signal->obj.wait.lock);
7738 if (signal->obj.done)
7740 if (!signal->manualReset)
7742 signal->obj.done = 0;
7745 status = gcvSTATUS_OK;
7749 #if gcdDETECT_TIMEOUT
7750 if ((Wait == gcvINFINITE) && (timeout == 0))
7752 gctUINT32 dmaAddress1, dmaAddress2;
7753 gctUINT32 dmaState1, dmaState2;
7755 dmaState1 = dmaState2 =
7756 dmaAddress1 = dmaAddress2 = 0;
7758 /* Verify whether DMA is running. */
7759 gcmkVERIFY_OK(_VerifyDMA(
7760 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7763 #if gcdDETECT_DMA_ADDRESS
7764 /* Dump only if DMA appears stuck. */
7766 (dmaAddress1 == dmaAddress2)
7767 #if gcdDETECT_DMA_STATE
7768 && (dmaState1 == dmaState2)
7773 /* Increment complain count. */
7776 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
7779 "%s(%d): signal 0x%X; forced message flush (%d).",
7780 __FUNCTION__, __LINE__, Signal, complained
7783 /* Flush the debug cache. */
7784 gcmkDEBUGFLUSH(dmaAddress2);
7787 /* Reset timeout. */
7788 timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
7795 status = gcvSTATUS_TIMEOUT;
7800 __remove_wait_queue(&signal->obj.wait, &wait);
7802 #if gcdDETECT_TIMEOUT
7806 "%s(%d): signal=0x%X; waiting done; status=%d",
7807 __FUNCTION__, __LINE__, Signal, status
7813 spin_unlock_irq(&signal->obj.wait.lock);
7816 /* Return status. */
7817 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7821 /*******************************************************************************
7825 ** Map a signal in to the current process space.
7830 ** Pointer to an gckOS object.
7833 ** Pointer to tha gctSIGNAL to map.
7835 ** gctHANDLE Process
7836 ** Handle of process owning the signal.
7840 ** gctSIGNAL * MappedSignal
7841 ** Pointer to a variable receiving the mapped gctSIGNAL.
7846 IN gctSIGNAL Signal,
7847 IN gctHANDLE Process,
7848 OUT gctSIGNAL * MappedSignal
7852 gcsSIGNAL_PTR signal;
7853 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7855 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7856 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7858 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7860 if(atomic_inc_return(&signal->ref) <= 1)
7862 /* The previous value is 0, it has been deleted. */
7863 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7866 *MappedSignal = (gctSIGNAL) Signal;
7869 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
7870 return gcvSTATUS_OK;
7877 /*******************************************************************************
7879 ** gckOS_UnmapSignal
7886 ** Pointer to an gckOS object.
7889 ** Pointer to that gctSIGNAL mapped.
7897 return gckOS_DestroySignal(Os, Signal);
7900 /*******************************************************************************
7902 ** gckOS_CreateUserSignal
7904 ** Create a new signal to be used in the user space.
7909 ** Pointer to an gckOS object.
7911 ** gctBOOL ManualReset
7912 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7913 ** order to set the signal to nonsignaled state.
7914 ** If set to gcvFALSE, the signal will automatically be set to
7915 ** nonsignaled state by gckOS_WaitSignal function.
7919 ** gctINT * SignalID
7920 ** Pointer to a variable receiving the created signal's ID.
7923 gckOS_CreateUserSignal(
7925 IN gctBOOL ManualReset,
7926 OUT gctINT * SignalID
7932 /* Create a new signal. */
7933 status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
7934 *SignalID = (gctINT) signal;
7939 /*******************************************************************************
7941 ** gckOS_DestroyUserSignal
7943 ** Destroy a signal to be used in the user space.
7948 ** Pointer to an gckOS object.
7958 gckOS_DestroyUserSignal(
7963 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
7966 /*******************************************************************************
7968 ** gckOS_WaitUserSignal
7970 ** Wait for a signal used in the user mode to become signaled.
7975 ** Pointer to an gckOS object.
7981 ** Number of milliseconds to wait.
7982 ** Pass the value of gcvINFINITE for an infinite wait.
7989 gckOS_WaitUserSignal(
7995 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
7998 /*******************************************************************************
8000 ** gckOS_SignalUserSignal
8002 ** Set a state of the specified signal to be used in the user space.
8007 ** Pointer to an gckOS object.
8013 ** If gcvTRUE, the signal will be set to signaled state.
8014 ** If gcvFALSE, the signal will be set to nonsignaled state.
8021 gckOS_SignalUserSignal(
8027 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
8032 gckOS_CreateSemaphoreVG(
8034 OUT gctSEMAPHORE * Semaphore
8038 struct semaphore * newSemaphore;
8040 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8041 /* Verify the arguments. */
8042 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8043 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8047 /* Allocate the semaphore structure. */
8048 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
8049 if (newSemaphore == gcvNULL)
8051 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
8054 /* Initialize the semaphore. */
8055 sema_init(newSemaphore, 0);
8057 /* Set the handle. */
8058 * Semaphore = (gctSEMAPHORE) newSemaphore;
8061 status = gcvSTATUS_OK;
8066 /* Return the status. */
8072 gckOS_IncrementSemaphore(
8074 IN gctSEMAPHORE Semaphore
8077 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8078 /* Verify the arguments. */
8079 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8080 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8082 /* Increment the semaphore's count. */
8083 up((struct semaphore *) Semaphore);
8087 return gcvSTATUS_OK;
8091 gckOS_DecrementSemaphore(
8093 IN gctSEMAPHORE Semaphore
8099 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8100 /* Verify the arguments. */
8101 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8102 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8106 /* Decrement the semaphore's count. If the count is zero, wait
8107 until it gets incremented. */
8108 result = down_interruptible((struct semaphore *) Semaphore);
8110 /* Signal received? */
8113 status = gcvSTATUS_TERMINATE;
8118 status = gcvSTATUS_OK;
8123 /* Return the status. */
8127 /*******************************************************************************
8131 ** Set the specified signal to signaled state.
8136 ** Pointer to the gckOS object.
8138 ** gctHANDLE Process
8139 ** Handle of process owning the signal.
8142 ** Pointer to the gctSIGNAL.
8151 IN gctHANDLE Process,
8157 struct task_struct * userTask;
8158 struct siginfo info;
8160 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
8162 if (userTask != gcvNULL)
8165 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
8168 info.si_ptr = (gctPOINTER) Signal;
8170 /* Signals with numbers between 32 and 63 are real-time,
8171 send a real-time signal to the user process. */
8172 result = send_sig_info(48, &info, userTask);
8177 status = gcvSTATUS_GENERIC_IO;
8181 "%s(%d): an error has occurred.\n",
8182 __FUNCTION__, __LINE__
8187 status = gcvSTATUS_OK;
8192 status = gcvSTATUS_GENERIC_IO;
8196 "%s(%d): an error has occurred.\n",
8197 __FUNCTION__, __LINE__
8201 /* Return status. */
8205 /******************************************************************************\
8206 ******************************** Thread Object *********************************
8207 \******************************************************************************/
8212 IN gctTHREADFUNC ThreadFunction,
8213 IN gctPOINTER ThreadParameter,
8214 OUT gctTHREAD * Thread
8218 struct task_struct * thread;
8220 gcmkHEADER_ARG("Os=0x%X ", Os);
8221 /* Verify the arguments. */
8222 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8223 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
8224 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8228 /* Create the thread. */
8229 thread = kthread_create(
8232 "Vivante Kernel Thread"
8238 status = gcvSTATUS_GENERIC_IO;
8242 /* Start the thread. */
8243 wake_up_process(thread);
8245 /* Set the thread handle. */
8246 * Thread = (gctTHREAD) thread;
8249 status = gcvSTATUS_OK;
8254 /* Return the status. */
8264 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8265 /* Verify the arguments. */
8266 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8267 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8269 /* Thread should have already been enabled to terminate. */
8270 kthread_stop((struct task_struct *) Thread);
8274 return gcvSTATUS_OK;
8283 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8284 /* Verify the arguments. */
8285 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8286 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8290 return gcvSTATUS_OK;
8294 /******************************************************************************\
8295 ******************************** Software Timer ********************************
8296 \******************************************************************************/
8300 struct work_struct * work
8303 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
8305 gctTIMERFUNCTION function = timer->function;
8307 function(timer->data);
8310 /*******************************************************************************
8312 ** gckOS_CreateTimer
8314 ** Create a software timer.
8319 ** Pointer to the gckOS object.
8321 ** gctTIMERFUNCTION Function.
8322 ** Pointer to a call back function which will be called when timer is
8326 ** Private data which will be passed to call back function.
8330 ** gctPOINTER * Timer
8331 ** Pointer to a variable receiving the created timer.
8336 IN gctTIMERFUNCTION Function,
8338 OUT gctPOINTER * Timer
8342 gcsOSTIMER_PTR pointer;
8343 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
8345 /* Verify the arguments. */
8346 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8347 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8349 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
8351 pointer->function = Function;
8352 pointer->data = Data;
8354 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
8359 return gcvSTATUS_OK;
8366 /*******************************************************************************
8368 ** gckOS_DestroyTimer
8370 ** Destory a software timer.
8375 ** Pointer to the gckOS object.
8378 ** Pointer to the timer to be destoryed.
8390 gcsOSTIMER_PTR timer;
8391 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8393 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8394 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8396 timer = (gcsOSTIMER_PTR)Timer;
8398 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8399 cancel_delayed_work_sync(&timer->work);
8401 cancel_delayed_work(&timer->work);
8402 flush_workqueue(Os->workqueue);
8405 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8408 return gcvSTATUS_OK;
8411 /*******************************************************************************
8415 ** Schedule a software timer.
8420 ** Pointer to the gckOS object.
8423 ** Pointer to the timer to be scheduled.
8426 ** Delay in milliseconds.
8435 IN gctPOINTER Timer,
8439 gcsOSTIMER_PTR timer;
8441 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8443 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8444 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8445 gcmkVERIFY_ARGUMENT(Delay != 0);
8447 timer = (gcsOSTIMER_PTR)Timer;
8449 if (unlikely(delayed_work_pending(&timer->work)))
8451 cancel_delayed_work(&timer->work);
8454 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8457 return gcvSTATUS_OK;
8460 /*******************************************************************************
8464 ** Cancel a unscheduled timer.
8469 ** Pointer to the gckOS object.
8472 ** Pointer to the timer to be cancel.
8484 gcsOSTIMER_PTR timer;
8485 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8487 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8488 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8490 timer = (gcsOSTIMER_PTR)Timer;
8492 cancel_delayed_work(&timer->work);
8495 return gcvSTATUS_OK;
8500 gckOS_DumpCallStack(
8504 gcmkHEADER_ARG("Os=0x%X", Os);
8506 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8511 return gcvSTATUS_OK;
8516 gckOS_GetProcessNameByPid(
8518 IN gctSIZE_T Length,
8519 OUT gctUINT8_PTR String
8522 struct task_struct *task;
8524 /* Get the task_struct of the task with pid. */
8527 task = FIND_TASK_BY_PID(Pid);
8529 if (task == gcvNULL)
8532 return gcvSTATUS_NOT_FOUND;
8535 /* Get name of process. */
8536 strncpy(String, task->comm, Length);
8540 return gcvSTATUS_OK;