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,10,0)
42 #include <linux/reset.h>
43 static inline void imx_gpc_power_up_pu(bool flag) {}
44 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
45 #include <mach/common.h>
47 #include <linux/delay.h>
48 #include <linux/pm_runtime.h>
51 #define _GC_OBJ_ZONE gcvZONE_OS
53 /*******************************************************************************
54 ***** Version Signature *******************************************************/
57 const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
59 const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
62 #define USER_SIGNAL_TABLE_LEN_INIT 64
63 #define gcdSUPPRESS_OOM_MESSAGE 1
65 #define MEMORY_LOCK(os) \
66 gcmkVERIFY_OK(gckOS_AcquireMutex( \
71 #define MEMORY_UNLOCK(os) \
72 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
74 #define MEMORY_MAP_LOCK(os) \
75 gcmkVERIFY_OK(gckOS_AcquireMutex( \
77 (os)->memoryMapLock, \
80 #define MEMORY_MAP_UNLOCK(os) \
81 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
83 /* Protection bit when mapping memroy to user sapce */
84 #define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
86 #if gcdNONPAGED_MEMORY_BUFFERABLE
87 #define gcmkIOREMAP ioremap_wc
88 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
89 #elif !gcdNONPAGED_MEMORY_CACHEABLE
90 #define gcmkIOREMAP ioremap_nocache
91 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
94 #if gcdSUPPRESS_OOM_MESSAGE
95 #define gcdNOWARN __GFP_NOWARN
100 #define gcdINFINITE_TIMEOUT (60 * 1000)
101 #define gcdDETECT_TIMEOUT 0
102 #define gcdDETECT_DMA_ADDRESS 1
103 #define gcdDETECT_DMA_STATE 1
105 #define gcdUSE_NON_PAGED_MEMORY_CACHE 10
107 /******************************************************************************\
108 ********************************** Structures **********************************
109 \******************************************************************************/
110 #if gcdUSE_NON_PAGED_MEMORY_CACHE
111 typedef struct _gcsNonPagedMemoryCache
113 #ifndef NO_DMA_COHERENT
116 dma_addr_t dmaHandle;
122 struct _gcsNonPagedMemoryCache * prev;
123 struct _gcsNonPagedMemoryCache * next;
125 gcsNonPagedMemoryCache;
126 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
128 typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
129 typedef struct _gcsUSER_MAPPING
131 /* Pointer to next mapping structure. */
132 gcsUSER_MAPPING_PTR next;
134 /* Physical address of this mapping. */
137 /* Logical address of this mapping. */
140 /* Number of bytes of this mapping. */
143 /* Starting address of this mapping. */
146 /* Ending address of this mapping. */
151 typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
152 typedef struct _gcsINTEGER_DB
167 /* Pointer to device */
170 /* Memory management */
171 gctPOINTER memoryLock;
172 gctPOINTER memoryMapLock;
174 struct _LINUX_MDL *mdlHead;
175 struct _LINUX_MDL *mdlTail;
177 /* Kernel process ID. */
178 gctUINT32 kernelProcessID;
180 /* Signal management. */
183 gctPOINTER signalMutex;
185 /* signal id database. */
186 gcsINTEGER_DB signalDB;
188 gcsUSER_MAPPING_PTR userMap;
189 gctPOINTER debugLock;
191 #if gcdUSE_NON_PAGED_MEMORY_CACHE
193 gcsNonPagedMemoryCache * cacheHead;
194 gcsNonPagedMemoryCache * cacheTail;
197 /* workqueue for os timer. */
198 struct workqueue_struct * workqueue;
201 typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
202 typedef struct _gcsSIGNAL
204 /* Kernel sync primitive. */
205 struct completion obj;
207 /* Manual reset flag. */
210 /* The reference counter. */
213 /* The owner of the signal. */
216 gckHARDWARE hardware;
223 typedef struct _gcsPageInfo * gcsPageInfo_PTR;
224 typedef struct _gcsPageInfo
227 gctUINT32_PTR pageTable;
231 typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
232 typedef struct _gcsOSTIMER
234 struct delayed_work work;
235 gctTIMERFUNCTION function;
239 /******************************************************************************\
240 ******************************* Private Functions ******************************
241 \******************************************************************************/
248 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
249 return task_tgid_vnr(current);
251 return current->tgid;
260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
261 return task_pid_vnr(current);
274 gcmkHEADER_ARG("ProcessID=%d", ProcessID);
276 mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
283 mdl->pid = ProcessID;
288 gcmkFOOTER_ARG("0x%X", mdl);
295 IN PLINUX_MDL_MAP MdlMap
303 PLINUX_MDL_MAP mdlMap, next;
305 gcmkHEADER_ARG("Mdl=0x%X", Mdl);
307 /* Verify the arguments. */
308 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
312 while (mdlMap != gcvNULL)
316 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
327 static PLINUX_MDL_MAP
333 PLINUX_MDL_MAP mdlMap;
335 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
337 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
338 if (mdlMap == gcvNULL)
344 mdlMap->pid = ProcessID;
345 mdlMap->vmaAddr = gcvNULL;
346 mdlMap->vma = gcvNULL;
348 mdlMap->next = Mdl->maps;
351 gcmkFOOTER_ARG("0x%X", mdlMap);
358 IN PLINUX_MDL_MAP MdlMap
361 PLINUX_MDL_MAP prevMdlMap;
363 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
365 /* Verify the arguments. */
366 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
367 gcmkASSERT(Mdl->maps != gcvNULL);
369 if (Mdl->maps == MdlMap)
371 Mdl->maps = MdlMap->next;
375 prevMdlMap = Mdl->maps;
377 while (prevMdlMap->next != MdlMap)
379 prevMdlMap = prevMdlMap->next;
381 gcmkASSERT(prevMdlMap != gcvNULL);
384 prevMdlMap->next = MdlMap->next;
393 extern PLINUX_MDL_MAP
399 PLINUX_MDL_MAP mdlMap;
401 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
409 while (mdlMap != gcvNULL)
411 if (mdlMap->pid == ProcessID)
413 gcmkFOOTER_ARG("0x%X", mdlMap);
417 mdlMap = mdlMap->next;
432 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
438 unsigned long addr = (unsigned long)Addr;
440 return addr >= VMALLOC_START && addr < VMALLOC_END;
446 IN struct page ** Pages,
447 IN gctUINT32 NumPages
452 gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
454 gcmkASSERT(Pages != gcvNULL);
456 for (i = 0; i < NumPages; i++)
458 __free_page(Pages[i]);
461 if (is_vmalloc_addr(Pages))
473 static struct page **
475 IN gctUINT32 NumPages
478 struct page ** pages;
482 gcmkHEADER_ARG("NumPages=%lu", NumPages);
484 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
485 if (NumPages > totalram_pages)
487 if (NumPages > num_physpages)
494 size = NumPages * sizeof(struct page *);
496 pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
500 pages = vmalloc(size);
509 for (i = 0; i < NumPages; i++)
511 p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
515 _NonContiguousFree(pages, i);
523 gcmkFOOTER_ARG("pages=0x%X", pages);
527 static inline struct page *
528 _NonContiguousToPage(
529 IN struct page ** Pages,
533 gcmkASSERT(Pages != gcvNULL);
537 static inline unsigned long
539 IN struct page ** Pages,
543 gcmkASSERT(Pages != gcvNULL);
544 return page_to_pfn(_NonContiguousToPage(Pages, Index));
547 static inline unsigned long
548 _NonContiguousToPhys(
549 IN struct page ** Pages,
553 gcmkASSERT(Pages != gcvNULL);
554 return page_to_phys(_NonContiguousToPage(Pages, Index));
558 #if gcdUSE_NON_PAGED_MEMORY_CACHE
561 _AddNonPagedMemoryCache(
563 #ifndef NO_DMA_COHERENT
573 gcsNonPagedMemoryCache *cache;
575 if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
580 /* Allocate the cache record */
581 cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
583 if (cache == gcvNULL) return gcvFALSE;
585 #ifndef NO_DMA_COHERENT
588 cache->dmaHandle = DmaHandle;
590 cache->order = Order;
595 if (Os->cacheHead == gcvNULL)
597 cache->prev = gcvNULL;
598 cache->next = gcvNULL;
600 Os->cacheTail = cache;
604 /* Add to the tail. */
605 cache->prev = Os->cacheTail;
606 cache->next = gcvNULL;
607 Os->cacheTail->next = cache;
608 Os->cacheTail = cache;
616 #ifndef NO_DMA_COHERENT
618 _GetNonPagedMemoryCache(
621 dma_addr_t * DmaHandle
625 _GetNonPagedMemoryCache(
631 gcsNonPagedMemoryCache *cache;
632 #ifndef NO_DMA_COHERENT
638 if (Os->cacheHead == gcvNULL) return gcvNULL;
640 /* Find the right cache */
641 cache = Os->cacheHead;
643 while (cache != gcvNULL)
645 #ifndef NO_DMA_COHERENT
646 if (cache->size == Size) break;
648 if (cache->order == Order) break;
654 if (cache == gcvNULL) return gcvNULL;
656 /* Remove the cache from list */
657 if (cache == Os->cacheHead)
659 Os->cacheHead = cache->next;
661 if (Os->cacheHead == gcvNULL)
663 Os->cacheTail = gcvNULL;
668 cache->prev->next = cache->next;
670 if (cache == Os->cacheTail)
672 Os->cacheTail = cache->prev;
676 cache->next->prev = cache->prev;
681 #ifndef NO_DMA_COHERENT
683 *DmaHandle = cache->dmaHandle;
692 #ifndef NO_DMA_COHERENT
700 _FreeAllNonPagedMemoryCache(
704 gcsNonPagedMemoryCache *cache, *nextCache;
708 cache = Os->cacheHead;
710 while (cache != gcvNULL)
712 if (cache != Os->cacheTail)
714 nextCache = cache->next;
721 /* Remove the cache from list */
722 if (cache == Os->cacheHead)
724 Os->cacheHead = cache->next;
726 if (Os->cacheHead == gcvNULL)
728 Os->cacheTail = gcvNULL;
733 cache->prev->next = cache->next;
735 if (cache == Os->cacheTail)
737 Os->cacheTail = cache->prev;
741 cache->next->prev = cache->prev;
745 #ifndef NO_DMA_COHERENT
746 dma_free_coherent(gcvNULL,
751 free_pages((unsigned long)page_address(cache->page), cache->order);
762 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
764 /*******************************************************************************
765 ** Integer Id Management.
769 IN gcsINTEGER_DB_PTR Database,
770 IN gctPOINTER KernelPointer,
776 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
777 spin_lock(&Database->lock);
778 /* Try to get a id greater than 0. */
779 result = idr_alloc(&Database->idr, KernelPointer, 1, 0,
780 GFP_KERNEL | gcdNOWARN);
781 spin_unlock(&Database->lock);
784 return gcvSTATUS_OUT_OF_RESOURCES;
789 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
791 return gcvSTATUS_OUT_OF_MEMORY;
794 spin_lock(&Database->lock);
796 /* Try to get a id greater than 0. */
797 result = idr_get_new_above(&Database->idr, KernelPointer, 1, Id);
799 spin_unlock(&Database->lock);
801 if (result == -EAGAIN)
808 return gcvSTATUS_OUT_OF_RESOURCES;
817 IN gcsINTEGER_DB_PTR Database,
819 OUT gctPOINTER * KernelPointer
824 spin_lock(&Database->lock);
826 pointer = idr_find(&Database->idr, Id);
828 spin_unlock(&Database->lock);
832 *KernelPointer = pointer;
838 gcvLEVEL_ERROR, gcvZONE_OS,
839 "%s(%d) Id = %d is not found",
840 __FUNCTION__, __LINE__, Id);
842 return gcvSTATUS_NOT_FOUND;
848 IN gcsINTEGER_DB_PTR Database,
852 spin_lock(&Database->lock);
854 idr_remove(&Database->idr, Id);
856 spin_unlock(&Database->lock);
864 IN gctPOINTER Logical,
868 if (unlikely(current->mm == gcvNULL))
870 /* Do nothing if process is exiting. */
874 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
875 if (vm_munmap((unsigned long)Logical, Size) < 0)
878 gcvLEVEL_WARNING, gcvZONE_OS,
879 "%s(%d): vm_munmap failed",
880 __FUNCTION__, __LINE__
884 down_write(¤t->mm->mmap_sem);
885 if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
888 gcvLEVEL_WARNING, gcvZONE_OS,
889 "%s(%d): do_munmap failed",
890 __FUNCTION__, __LINE__
893 up_write(¤t->mm->mmap_sem);
898 _QueryProcessPageTable(
899 IN gctPOINTER Logical,
900 OUT gctUINT32 * Address
904 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
912 return gcvSTATUS_NOT_FOUND;
915 pgd = pgd_offset(current->mm, logical);
916 if (pgd_none(*pgd) || pgd_bad(*pgd))
918 return gcvSTATUS_NOT_FOUND;
921 pud = pud_offset(pgd, logical);
922 if (pud_none(*pud) || pud_bad(*pud))
924 return gcvSTATUS_NOT_FOUND;
927 pmd = pmd_offset(pud, logical);
928 if (pmd_none(*pmd) || pmd_bad(*pmd))
930 return gcvSTATUS_NOT_FOUND;
933 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
936 return gcvSTATUS_NOT_FOUND;
939 if (!pte_present(*pte))
941 pte_unmap_unlock(pte, lock);
942 return gcvSTATUS_NOT_FOUND;
945 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
946 pte_unmap_unlock(pte, lock);
951 /*******************************************************************************
955 ** Construct a new gckOS object.
959 ** gctPOINTER Context
960 ** Pointer to the gckGALDEVICE class.
965 ** Pointer to a variable that will hold the pointer to the gckOS object.
969 IN gctPOINTER Context,
976 gcmkHEADER_ARG("Context=0x%X", Context);
978 /* Verify the arguments. */
979 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
981 /* Allocate the gckOS object. */
982 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
987 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
988 return gcvSTATUS_OUT_OF_MEMORY;
991 /* Zero the memory. */
992 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
994 /* Initialize the gckOS object. */
995 os->object.type = gcvOBJ_OS;
997 /* Set device device. */
998 os->device = Context;
1000 /* IMPORTANT! No heap yet. */
1003 /* Initialize the memory lock. */
1004 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
1005 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
1007 /* Create debug lock mutex. */
1008 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
1011 os->mdlHead = os->mdlTail = gcvNULL;
1013 /* Get the kernel process ID. */
1014 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
1017 * Initialize the signal manager.
1020 /* Initialize mutex. */
1021 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
1023 /* Initialize signal id database lock. */
1024 spin_lock_init(&os->signalDB.lock);
1026 /* Initialize signal id database. */
1027 idr_init(&os->signalDB.idr);
1029 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1031 os->cacheHead = gcvNULL;
1032 os->cacheTail = gcvNULL;
1035 /* Create a workqueue for os timer. */
1036 os->workqueue = create_singlethread_workqueue("galcore workqueue");
1038 if (os->workqueue == gcvNULL)
1040 /* Out of memory. */
1041 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1044 /* Return pointer to the gckOS object. */
1048 gcmkFOOTER_ARG("*Os=0x%X", *Os);
1049 return gcvSTATUS_OK;
1052 if (os->signalMutex != gcvNULL)
1055 gckOS_DeleteMutex(os, os->signalMutex));
1058 if (os->heap != gcvNULL)
1061 gckHEAP_Destroy(os->heap));
1064 if (os->memoryMapLock != gcvNULL)
1067 gckOS_DeleteMutex(os, os->memoryMapLock));
1070 if (os->memoryLock != gcvNULL)
1073 gckOS_DeleteMutex(os, os->memoryLock));
1076 if (os->debugLock != gcvNULL)
1079 gckOS_DeleteMutex(os, os->debugLock));
1082 if (os->workqueue != gcvNULL)
1084 destroy_workqueue(os->workqueue);
1089 /* Return the error. */
1094 /*******************************************************************************
1098 ** Destroy an gckOS object.
1103 ** Pointer to an gckOS object that needs to be destroyed.
1116 gcmkHEADER_ARG("Os=0x%X", Os);
1118 /* Verify the arguments. */
1119 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1121 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1122 _FreeAllNonPagedMemoryCache(Os);
1126 * Destroy the signal manager.
1129 /* Destroy the mutex. */
1130 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
1132 if (Os->heap != gcvNULL)
1134 /* Mark gckHEAP as gone. */
1138 /* Destroy the gckHEAP object. */
1139 gcmkVERIFY_OK(gckHEAP_Destroy(heap));
1142 /* Destroy the memory lock. */
1143 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
1144 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
1146 /* Destroy debug lock mutex. */
1147 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
1149 /* Wait for all works done. */
1150 flush_workqueue(Os->workqueue);
1152 /* Destory work queue. */
1153 destroy_workqueue(Os->workqueue);
1155 /* Flush the debug cache. */
1156 gcmkDEBUGFLUSH(~0U);
1158 /* Mark the gckOS object as unknown. */
1159 Os->object.type = gcvOBJ_UNKNOWN;
1161 /* Free the gckOS object. */
1166 return gcvSTATUS_OK;
1170 _CreateKernelVirtualMapping(
1175 gctINT numPages = Mdl->numPages;
1177 #if gcdNONPAGED_MEMORY_CACHEABLE
1178 if (Mdl->contiguous)
1180 addr = page_address(Mdl->u.contiguousPages);
1184 addr = vmap(Mdl->u.nonContiguousPages,
1189 /* Trigger a page fault. */
1190 memset(addr, 0, numPages * PAGE_SIZE);
1193 struct page ** pages;
1194 gctBOOL free = gcvFALSE;
1197 if (Mdl->contiguous)
1199 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
1206 for (i = 0; i < numPages; i++)
1208 pages[i] = nth_page(Mdl->u.contiguousPages, i);
1215 pages = Mdl->u.nonContiguousPages;
1218 /* ioremap() can't work on system memory since 2.6.38. */
1219 addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
1221 /* Trigger a page fault. */
1222 memset(addr, 0, numPages * PAGE_SIZE);
1235 _DestoryKernelVirtualMapping(
1239 #if !gcdNONPAGED_MEMORY_CACHEABLE
1245 gckOS_CreateKernelVirtualMapping(
1246 IN gctPHYS_ADDR Physical,
1247 OUT gctSIZE_T * PageCount,
1248 OUT gctPOINTER * Logical
1251 *PageCount = ((PLINUX_MDL)Physical)->numPages;
1252 *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
1254 return gcvSTATUS_OK;
1258 gckOS_DestroyKernelVirtualMapping(
1259 IN gctPOINTER Logical
1262 _DestoryKernelVirtualMapping((gctSTRING)Logical);
1263 return gcvSTATUS_OK;
1266 /*******************************************************************************
1275 ** Pointer to an gckOS object.
1278 ** Number of bytes to allocate.
1282 ** gctPOINTER * Memory
1283 ** Pointer to a variable that will hold the allocated memory location.
1289 OUT gctPOINTER * Memory
1294 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1296 /* Verify the arguments. */
1297 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1298 gcmkVERIFY_ARGUMENT(Bytes > 0);
1299 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1301 /* Do we have a heap? */
1302 if (Os->heap != gcvNULL)
1304 /* Allocate from the heap. */
1305 gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
1309 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
1313 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1314 return gcvSTATUS_OK;
1317 /* Return the status. */
1322 /*******************************************************************************
1326 ** Free allocated memory.
1331 ** Pointer to an gckOS object.
1333 ** gctPOINTER Memory
1334 ** Pointer to memory allocation to free.
1343 IN gctPOINTER Memory
1348 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
1350 /* Verify the arguments. */
1351 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1352 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1354 /* Do we have a heap? */
1355 if (Os->heap != gcvNULL)
1357 /* Free from the heap. */
1358 gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
1362 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1367 return gcvSTATUS_OK;
1370 /* Return the status. */
1375 /*******************************************************************************
1377 ** gckOS_AllocateMemory
1379 ** Allocate memory wrapper.
1384 ** Number of bytes to allocate.
1388 ** gctPOINTER * Memory
1389 ** Pointer to a variable that will hold the allocated memory location.
1392 gckOS_AllocateMemory(
1395 OUT gctPOINTER * Memory
1401 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1403 /* Verify the arguments. */
1404 gcmkVERIFY_ARGUMENT(Bytes > 0);
1405 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1407 if (Bytes > PAGE_SIZE)
1409 memory = (gctPOINTER) vmalloc(Bytes);
1413 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1416 if (memory == gcvNULL)
1418 /* Out of memory. */
1419 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1422 /* Return pointer to the memory allocation. */
1426 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1427 return gcvSTATUS_OK;
1430 /* Return the status. */
1435 /*******************************************************************************
1439 ** Free allocated memory wrapper.
1443 ** gctPOINTER Memory
1444 ** Pointer to memory allocation to free.
1453 IN gctPOINTER Memory
1456 gcmkHEADER_ARG("Memory=0x%X", Memory);
1458 /* Verify the arguments. */
1459 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1461 /* Free the memory from the OS pool. */
1462 if (is_vmalloc_addr(Memory))
1473 return gcvSTATUS_OK;
1476 /*******************************************************************************
1480 ** Map physical memory into the current process.
1485 ** Pointer to an gckOS object.
1487 ** gctPHYS_ADDR Physical
1488 ** Start of physical address memory.
1491 ** Number of bytes to map.
1495 ** gctPOINTER * Memory
1496 ** Pointer to a variable that will hold the logical address of the
1502 IN gctPHYS_ADDR Physical,
1504 OUT gctPOINTER * Logical
1507 PLINUX_MDL_MAP mdlMap;
1508 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1510 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1512 /* Verify the arguments. */
1513 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1514 gcmkVERIFY_ARGUMENT(Physical != 0);
1515 gcmkVERIFY_ARGUMENT(Bytes > 0);
1516 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1520 mdlMap = FindMdlMap(mdl, _GetProcessID());
1522 if (mdlMap == gcvNULL)
1524 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1526 if (mdlMap == gcvNULL)
1530 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1531 return gcvSTATUS_OUT_OF_MEMORY;
1535 if (mdlMap->vmaAddr == gcvNULL)
1537 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1538 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1540 mdl->numPages * PAGE_SIZE,
1541 PROT_READ | PROT_WRITE,
1545 down_write(¤t->mm->mmap_sem);
1547 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1549 mdl->numPages * PAGE_SIZE,
1550 PROT_READ | PROT_WRITE,
1554 up_write(¤t->mm->mmap_sem);
1557 if (IS_ERR(mdlMap->vmaAddr))
1561 "%s(%d): do_mmap_pgoff error",
1562 __FUNCTION__, __LINE__
1567 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1568 __FUNCTION__, __LINE__,
1573 mdlMap->vmaAddr = gcvNULL;
1577 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1578 return gcvSTATUS_OUT_OF_MEMORY;
1581 down_write(¤t->mm->mmap_sem);
1583 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1589 "%s(%d): find_vma error.",
1590 __FUNCTION__, __LINE__
1593 mdlMap->vmaAddr = gcvNULL;
1595 up_write(¤t->mm->mmap_sem);
1599 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1600 return gcvSTATUS_OUT_OF_RESOURCES;
1603 #ifndef NO_DMA_COHERENT
1604 if (dma_mmap_coherent(gcvNULL,
1608 mdl->numPages * PAGE_SIZE) < 0)
1610 up_write(¤t->mm->mmap_sem);
1614 "%s(%d): dma_mmap_coherent error.",
1615 __FUNCTION__, __LINE__
1618 mdlMap->vmaAddr = gcvNULL;
1622 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1623 return gcvSTATUS_OUT_OF_RESOURCES;
1626 #if !gcdPAGED_MEMORY_CACHEABLE
1627 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1628 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1630 mdlMap->vma->vm_pgoff = 0;
1632 if (remap_pfn_range(mdlMap->vma,
1633 mdlMap->vma->vm_start,
1634 mdl->dmaHandle >> PAGE_SHIFT,
1635 mdl->numPages*PAGE_SIZE,
1636 mdlMap->vma->vm_page_prot) < 0)
1638 up_write(¤t->mm->mmap_sem);
1642 "%s(%d): remap_pfn_range error.",
1643 __FUNCTION__, __LINE__
1646 mdlMap->vmaAddr = gcvNULL;
1650 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1651 return gcvSTATUS_OUT_OF_RESOURCES;
1655 up_write(¤t->mm->mmap_sem);
1660 *Logical = mdlMap->vmaAddr;
1662 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1663 return gcvSTATUS_OK;
1666 /*******************************************************************************
1668 ** gckOS_UnmapMemory
1670 ** Unmap physical memory out of the current process.
1675 ** Pointer to an gckOS object.
1677 ** gctPHYS_ADDR Physical
1678 ** Start of physical address memory.
1681 ** Number of bytes to unmap.
1683 ** gctPOINTER Memory
1684 ** Pointer to a previously mapped memory region.
1693 IN gctPHYS_ADDR Physical,
1695 IN gctPOINTER Logical
1698 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1699 Os, Physical, Bytes, Logical);
1701 /* Verify the arguments. */
1702 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1703 gcmkVERIFY_ARGUMENT(Physical != 0);
1704 gcmkVERIFY_ARGUMENT(Bytes > 0);
1705 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1707 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1711 return gcvSTATUS_OK;
1715 /*******************************************************************************
1717 ** gckOS_UnmapMemoryEx
1719 ** Unmap physical memory in the specified process.
1724 ** Pointer to an gckOS object.
1726 ** gctPHYS_ADDR Physical
1727 ** Start of physical address memory.
1730 ** Number of bytes to unmap.
1732 ** gctPOINTER Memory
1733 ** Pointer to a previously mapped memory region.
1736 ** Pid of the process that opened the device and mapped this memory.
1743 gckOS_UnmapMemoryEx(
1745 IN gctPHYS_ADDR Physical,
1747 IN gctPOINTER Logical,
1751 PLINUX_MDL_MAP mdlMap;
1752 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1754 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1755 Os, Physical, Bytes, Logical, PID);
1757 /* Verify the arguments. */
1758 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1759 gcmkVERIFY_ARGUMENT(Physical != 0);
1760 gcmkVERIFY_ARGUMENT(Bytes > 0);
1761 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1762 gcmkVERIFY_ARGUMENT(PID != 0);
1768 mdlMap = FindMdlMap(mdl, PID);
1770 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1774 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1775 return gcvSTATUS_INVALID_ARGUMENT;
1778 _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1780 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1787 return gcvSTATUS_OK;
1790 /*******************************************************************************
1792 ** gckOS_UnmapUserLogical
1794 ** Unmap user logical memory out of physical memory.
1799 ** Pointer to an gckOS object.
1801 ** gctPHYS_ADDR Physical
1802 ** Start of physical address memory.
1805 ** Number of bytes to unmap.
1807 ** gctPOINTER Memory
1808 ** Pointer to a previously mapped memory region.
1815 gckOS_UnmapUserLogical(
1817 IN gctPHYS_ADDR Physical,
1819 IN gctPOINTER Logical
1822 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1823 Os, Physical, Bytes, Logical);
1825 /* Verify the arguments. */
1826 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1827 gcmkVERIFY_ARGUMENT(Physical != 0);
1828 gcmkVERIFY_ARGUMENT(Bytes > 0);
1829 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1831 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1835 return gcvSTATUS_OK;
1839 /*******************************************************************************
1841 ** gckOS_AllocateNonPagedMemory
1843 ** Allocate a number of pages from non-paged memory.
1848 ** Pointer to an gckOS object.
1850 ** gctBOOL InUserSpace
1851 ** gcvTRUE if the pages need to be mapped into user space.
1853 ** gctSIZE_T * Bytes
1854 ** Pointer to a variable that holds the number of bytes to allocate.
1858 ** gctSIZE_T * Bytes
1859 ** Pointer to a variable that hold the number of bytes allocated.
1861 ** gctPHYS_ADDR * Physical
1862 ** Pointer to a variable that will hold the physical address of the
1865 ** gctPOINTER * Logical
1866 ** Pointer to a variable that will hold the logical address of the
1870 gckOS_AllocateNonPagedMemory(
1872 IN gctBOOL InUserSpace,
1873 IN OUT gctSIZE_T * Bytes,
1874 OUT gctPHYS_ADDR * Physical,
1875 OUT gctPOINTER * Logical
1880 PLINUX_MDL mdl = gcvNULL;
1881 PLINUX_MDL_MAP mdlMap = gcvNULL;
1883 #ifdef NO_DMA_COHERENT
1888 gctBOOL locked = gcvFALSE;
1891 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1892 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1894 /* Verify the arguments. */
1895 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1896 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1897 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1898 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1899 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1901 /* Align number of bytes to page size. */
1902 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1904 /* Get total number of pages.. */
1905 numPages = GetPageCount(bytes, 0);
1907 /* Allocate mdl+vector structure */
1908 mdl = _CreateMdl(_GetProcessID());
1911 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1915 mdl->numPages = numPages;
1920 #ifndef NO_DMA_COHERENT
1921 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1922 addr = _GetNonPagedMemoryCache(Os,
1923 mdl->numPages * PAGE_SIZE,
1926 if (addr == gcvNULL)
1929 addr = dma_alloc_coherent(gcvNULL,
1930 mdl->numPages * PAGE_SIZE,
1932 GFP_KERNEL | gcdNOWARN);
1935 size = mdl->numPages * PAGE_SIZE;
1936 order = get_order(size);
1937 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1938 page = _GetNonPagedMemoryCache(Os, order);
1940 if (page == gcvNULL)
1943 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
1946 if (page == gcvNULL)
1948 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1951 vaddr = (gctPOINTER)page_address(page);
1952 mdl->contiguous = gcvTRUE;
1953 mdl->u.contiguousPages = page;
1954 addr = _CreateKernelVirtualMapping(mdl);
1955 mdl->dmaHandle = virt_to_phys(vaddr);
1957 mdl->u.contiguousPages = page;
1959 #if !defined(CONFIG_PPC)
1960 /* Cache invalidate. */
1961 dma_sync_single_for_device(
1970 SetPageReserved(virt_to_page(vaddr));
1977 if (addr == gcvNULL)
1979 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1982 if ((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
1984 mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1985 | (Os->device->baseAddress & 0x80000000);
1990 /* Return allocated memory. */
1992 *Physical = (gctPHYS_ADDR) mdl;
1996 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1998 if (mdlMap == gcvNULL)
2000 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2003 /* Only after mmap this will be valid. */
2005 /* We need to map this to user space. */
2006 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2007 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
2009 mdl->numPages * PAGE_SIZE,
2010 PROT_READ | PROT_WRITE,
2014 down_write(¤t->mm->mmap_sem);
2016 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
2018 mdl->numPages * PAGE_SIZE,
2019 PROT_READ | PROT_WRITE,
2023 up_write(¤t->mm->mmap_sem);
2026 if (IS_ERR(mdlMap->vmaAddr))
2029 gcvLEVEL_WARNING, gcvZONE_OS,
2030 "%s(%d): do_mmap_pgoff error",
2031 __FUNCTION__, __LINE__
2034 mdlMap->vmaAddr = gcvNULL;
2036 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2039 down_write(¤t->mm->mmap_sem);
2041 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
2043 if (mdlMap->vma == gcvNULL)
2046 gcvLEVEL_WARNING, gcvZONE_OS,
2047 "%s(%d): find_vma error",
2048 __FUNCTION__, __LINE__
2051 up_write(¤t->mm->mmap_sem);
2053 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2056 #ifndef NO_DMA_COHERENT
2057 if (dma_mmap_coherent(gcvNULL,
2061 mdl->numPages * PAGE_SIZE) < 0)
2064 gcvLEVEL_WARNING, gcvZONE_OS,
2065 "%s(%d): dma_mmap_coherent error",
2066 __FUNCTION__, __LINE__
2069 up_write(¤t->mm->mmap_sem);
2071 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2074 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
2075 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
2076 mdlMap->vma->vm_pgoff = 0;
2078 if (remap_pfn_range(mdlMap->vma,
2079 mdlMap->vma->vm_start,
2080 mdl->dmaHandle >> PAGE_SHIFT,
2081 mdl->numPages * PAGE_SIZE,
2082 mdlMap->vma->vm_page_prot))
2085 gcvLEVEL_WARNING, gcvZONE_OS,
2086 "%s(%d): remap_pfn_range error",
2087 __FUNCTION__, __LINE__
2090 up_write(¤t->mm->mmap_sem);
2092 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2094 #endif /* NO_DMA_COHERENT */
2096 up_write(¤t->mm->mmap_sem);
2098 *Logical = mdlMap->vmaAddr;
2102 *Logical = (gctPOINTER)mdl->addr;
2106 * Add this to a global list.
2107 * Will be used by get physical address
2108 * and mapuser pointer functions.
2113 /* Initialize the queue. */
2114 Os->mdlHead = Os->mdlTail = mdl;
2118 /* Add to the tail. */
2119 mdl->prev = Os->mdlTail;
2120 Os->mdlTail->next = mdl;
2127 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
2128 *Bytes, *Physical, *Logical);
2129 return gcvSTATUS_OK;
2132 if (mdlMap != gcvNULL)
2134 /* Free LINUX_MDL_MAP. */
2135 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
2140 /* Free LINUX_MDL. */
2141 gcmkVERIFY_OK(_DestroyMdl(mdl));
2146 /* Unlock memory. */
2150 /* Return the status. */
2155 /*******************************************************************************
2157 ** gckOS_FreeNonPagedMemory
2159 ** Free previously allocated and mapped pages from non-paged memory.
2164 ** Pointer to an gckOS object.
2167 ** Number of bytes allocated.
2169 ** gctPHYS_ADDR Physical
2170 ** Physical address of the allocated memory.
2172 ** gctPOINTER Logical
2173 ** Logical address of the allocated memory.
2179 gceSTATUS gckOS_FreeNonPagedMemory(
2182 IN gctPHYS_ADDR Physical,
2183 IN gctPOINTER Logical
2187 PLINUX_MDL_MAP mdlMap;
2188 #ifdef NO_DMA_COHERENT
2191 #endif /* NO_DMA_COHERENT */
2193 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
2194 Os, Bytes, Physical, Logical);
2196 /* Verify the arguments. */
2197 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2198 gcmkVERIFY_ARGUMENT(Bytes > 0);
2199 gcmkVERIFY_ARGUMENT(Physical != 0);
2200 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2202 /* Convert physical address into a pointer to a MDL. */
2203 mdl = (PLINUX_MDL) Physical;
2207 #ifndef NO_DMA_COHERENT
2208 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2209 if (!_AddNonPagedMemoryCache(Os,
2210 mdl->numPages * PAGE_SIZE,
2215 dma_free_coherent(gcvNULL,
2216 mdl->numPages * PAGE_SIZE,
2221 size = mdl->numPages * PAGE_SIZE;
2226 ClearPageReserved(virt_to_page(vaddr));
2232 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2233 if (!_AddNonPagedMemoryCache(Os,
2234 get_order(mdl->numPages * PAGE_SIZE),
2235 virt_to_page(mdl->kaddr)))
2238 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
2241 _DestoryKernelVirtualMapping(mdl->addr);
2242 #endif /* NO_DMA_COHERENT */
2246 while (mdlMap != gcvNULL)
2248 if (mdlMap->vmaAddr != gcvNULL)
2250 /* No mapped memory exists when free nonpaged memory */
2254 mdlMap = mdlMap->next;
2257 /* Remove the node from global list.. */
2258 if (mdl == Os->mdlHead)
2260 if ((Os->mdlHead = mdl->next) == gcvNULL)
2262 Os->mdlTail = gcvNULL;
2267 mdl->prev->next = mdl->next;
2268 if (mdl == Os->mdlTail)
2270 Os->mdlTail = mdl->prev;
2274 mdl->next->prev = mdl->prev;
2280 gcmkVERIFY_OK(_DestroyMdl(mdl));
2284 return gcvSTATUS_OK;
2287 /*******************************************************************************
2289 ** gckOS_ReadRegister
2291 ** Read data from a register.
2296 ** Pointer to an gckOS object.
2298 ** gctUINT32 Address
2299 ** Address of register.
2304 ** Pointer to a variable that receives the data read from the register.
2309 IN gctUINT32 Address,
2310 OUT gctUINT32 * Data
2313 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2317 gckOS_ReadRegisterEx(
2320 IN gctUINT32 Address,
2321 OUT gctUINT32 * Data
2324 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
2326 /* Verify the arguments. */
2327 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2328 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2330 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
2333 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2334 return gcvSTATUS_OK;
2337 /*******************************************************************************
2339 ** gckOS_WriteRegister
2341 ** Write data to a register.
2346 ** Pointer to an gckOS object.
2348 ** gctUINT32 Address
2349 ** Address of register.
2352 ** Data for register.
2359 gckOS_WriteRegister(
2361 IN gctUINT32 Address,
2365 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2369 gckOS_WriteRegisterEx(
2372 IN gctUINT32 Address,
2376 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2378 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2382 return gcvSTATUS_OK;
2385 /*******************************************************************************
2387 ** gckOS_GetPageSize
2389 ** Get the system's page size.
2394 ** Pointer to an gckOS object.
2398 ** gctSIZE_T * PageSize
2399 ** Pointer to a variable that will receive the system's page size.
2401 gceSTATUS gckOS_GetPageSize(
2403 OUT gctSIZE_T * PageSize
2406 gcmkHEADER_ARG("Os=0x%X", Os);
2408 /* Verify the arguments. */
2409 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2410 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2412 /* Return the page size. */
2413 *PageSize = (gctSIZE_T) PAGE_SIZE;
2416 gcmkFOOTER_ARG("*PageSize", *PageSize);
2417 return gcvSTATUS_OK;
2420 /*******************************************************************************
2422 ** gckOS_GetPhysicalAddress
2424 ** Get the physical system address of a corresponding virtual address.
2429 ** Pointer to an gckOS object.
2431 ** gctPOINTER Logical
2436 ** gctUINT32 * Address
2437 ** Poinetr to a variable that receives the 32-bit physical adress.
2440 gckOS_GetPhysicalAddress(
2442 IN gctPOINTER Logical,
2443 OUT gctUINT32 * Address
2447 gctUINT32 processID;
2449 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2451 /* Verify the arguments. */
2452 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2453 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2455 /* Query page table of current process first. */
2456 status = _QueryProcessPageTable(Logical, Address);
2458 if (gcmIS_ERROR(status))
2460 /* Get current process ID. */
2461 processID = _GetProcessID();
2463 /* Route through other function. */
2465 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2469 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2470 return gcvSTATUS_OK;
2473 /* Return the status. */
2482 IN gctUINT32 Physical,
2483 IN gctPOINTER Logical,
2488 gcsUSER_MAPPING_PTR map;
2490 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2491 Os, Physical, Logical, Bytes);
2493 gcmkONERROR(gckOS_Allocate(Os,
2494 gcmSIZEOF(gcsUSER_MAPPING),
2495 (gctPOINTER *) &map));
2497 map->next = Os->userMap;
2498 map->physical = Physical - Os->device->baseAddress;
2499 map->logical = Logical;
2501 map->start = (gctINT8_PTR) Logical;
2502 map->end = map->start + Bytes;
2507 return gcvSTATUS_OK;
2515 gckOS_RemoveMapping(
2517 IN gctPOINTER Logical,
2522 gcsUSER_MAPPING_PTR map, prev;
2524 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2526 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2528 if ((map->logical == Logical)
2529 && (map->bytes == Bytes)
2540 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2543 if (prev == gcvNULL)
2545 Os->userMap = map->next;
2549 prev->next = map->next;
2552 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2555 return gcvSTATUS_OK;
2564 _ConvertLogical2Physical(
2566 IN gctPOINTER Logical,
2567 IN gctUINT32 ProcessID,
2569 OUT gctUINT32_PTR Physical
2572 gctINT8_PTR base, vBase;
2575 gcsUSER_MAPPING_PTR userMap;
2577 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2579 /* Check for the logical address match. */
2580 if ((base != gcvNULL)
2581 && ((gctINT8_PTR) Logical >= base)
2582 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2585 offset = (gctINT8_PTR) Logical - base;
2587 if (Mdl->dmaHandle != 0)
2589 /* The memory was from coherent area. */
2590 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2592 else if (Mdl->pagedMem && !Mdl->contiguous)
2594 /* paged memory is not mapped to kernel space. */
2595 return gcvSTATUS_INVALID_ADDRESS;
2599 *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
2602 return gcvSTATUS_OK;
2605 /* Walk user maps. */
2606 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2608 if (((gctINT8_PTR) Logical >= userMap->start)
2609 && ((gctINT8_PTR) Logical < userMap->end)
2612 *Physical = userMap->physical
2613 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2615 return gcvSTATUS_OK;
2619 if (ProcessID != Os->kernelProcessID)
2621 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2622 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2624 /* Is the given address within that range. */
2625 if ((vBase != gcvNULL)
2626 && ((gctINT8_PTR) Logical >= vBase)
2627 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2630 offset = (gctINT8_PTR) Logical - vBase;
2632 if (Mdl->dmaHandle != 0)
2634 /* The memory was from coherent area. */
2635 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2637 else if (Mdl->pagedMem && !Mdl->contiguous)
2639 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2643 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2646 return gcvSTATUS_OK;
2650 /* Address not yet found. */
2651 return gcvSTATUS_INVALID_ADDRESS;
2654 /*******************************************************************************
2656 ** gckOS_GetPhysicalAddressProcess
2658 ** Get the physical system address of a corresponding virtual address for a
2664 ** Pointer to gckOS object.
2666 ** gctPOINTER Logical
2669 ** gctUINT32 ProcessID
2674 ** gctUINT32 * Address
2675 ** Poinetr to a variable that receives the 32-bit physical adress.
2678 gckOS_GetPhysicalAddressProcess(
2680 IN gctPOINTER Logical,
2681 IN gctUINT32 ProcessID,
2682 OUT gctUINT32 * Address
2687 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2689 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2691 /* Verify the arguments. */
2692 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2693 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2697 /* First try the contiguous memory pool. */
2698 if (Os->device->contiguousMapped)
2700 base = (gctINT8_PTR) Os->device->contiguousBase;
2702 if (((gctINT8_PTR) Logical >= base)
2703 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2706 /* Convert logical address into physical. */
2707 *Address = Os->device->contiguousVidMem->baseAddress
2708 + (gctINT8_PTR) Logical - base;
2709 status = gcvSTATUS_OK;
2714 /* Try the contiguous memory pool. */
2715 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2716 status = _ConvertLogical2Physical(Os,
2723 if (gcmIS_ERROR(status))
2725 /* Walk all MDLs. */
2726 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2729 status = _ConvertLogical2Physical(Os,
2734 if (gcmIS_SUCCESS(status))
2743 gcmkONERROR(status);
2746 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2747 return gcvSTATUS_OK;
2750 /* Return the status. */
2755 /*******************************************************************************
2757 ** gckOS_MapPhysical
2759 ** Map a physical address into kernel space.
2764 ** Pointer to an gckOS object.
2766 ** gctUINT32 Physical
2767 ** Physical address of the memory to map.
2770 ** Number of bytes to map.
2774 ** gctPOINTER * Logical
2775 ** Pointer to a variable that receives the base address of the mapped
2781 IN gctUINT32 Physical,
2783 OUT gctPOINTER * Logical
2788 gctUINT32 physical = Physical;
2790 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2792 /* Verify the arguments. */
2793 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2794 gcmkVERIFY_ARGUMENT(Bytes > 0);
2795 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2799 /* Go through our mapping to see if we know this physical address already. */
2802 while (mdl != gcvNULL)
2804 if (mdl->dmaHandle != 0)
2806 if ((physical >= mdl->dmaHandle)
2807 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2810 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2820 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2821 struct contiguous_mem_pool *pool = Os->device->pool;
2823 if (Physical >= pool->phys && Physical < pool->phys + pool->size)
2824 logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
2828 /* Map memory as cached memory. */
2829 request_mem_region(physical, Bytes, "MapRegion");
2830 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2833 if (logical == gcvNULL)
2836 gcvLEVEL_INFO, gcvZONE_OS,
2837 "%s(%d): Failed to map physical address 0x%08x",
2838 __FUNCTION__, __LINE__, Physical
2843 /* Out of resources. */
2844 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2845 return gcvSTATUS_OUT_OF_RESOURCES;
2848 /* Return pointer to mapped memory. */
2855 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2856 return gcvSTATUS_OK;
2859 /*******************************************************************************
2861 ** gckOS_UnmapPhysical
2863 ** Unmap a previously mapped memory region from kernel memory.
2868 ** Pointer to an gckOS object.
2870 ** gctPOINTER Logical
2871 ** Pointer to the base address of the memory to unmap.
2874 ** Number of bytes to unmap.
2881 gckOS_UnmapPhysical(
2883 IN gctPOINTER Logical,
2889 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2891 /* Verify the arguments. */
2892 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2893 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2894 gcmkVERIFY_ARGUMENT(Bytes > 0);
2900 while (mdl != gcvNULL)
2902 if (mdl->addr != gcvNULL)
2904 if (Logical >= (gctPOINTER)mdl->addr
2905 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2916 /* Unmap the memory. */
2924 return gcvSTATUS_OK;
2927 /*******************************************************************************
2929 ** gckOS_CreateMutex
2931 ** Create a new mutex.
2936 ** Pointer to an gckOS object.
2940 ** gctPOINTER * Mutex
2941 ** Pointer to a variable that will hold a pointer to the mutex.
2946 OUT gctPOINTER * Mutex
2951 gcmkHEADER_ARG("Os=0x%X", Os);
2953 /* Validate the arguments. */
2954 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2955 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2957 /* Allocate the mutex structure. */
2958 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
2960 /* Initialize the mutex. */
2963 /* Return status. */
2964 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
2965 return gcvSTATUS_OK;
2968 /* Return status. */
2973 /*******************************************************************************
2975 ** gckOS_DeleteMutex
2982 ** Pointer to an gckOS object.
2985 ** Pointer to the mute to be deleted.
2999 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
3001 /* Validate the arguments. */
3002 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3003 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3005 /* Destroy the mutex. */
3006 mutex_destroy(Mutex);
3008 /* Free the mutex structure. */
3009 gcmkONERROR(gckOS_Free(Os, Mutex));
3012 return gcvSTATUS_OK;
3015 /* Return status. */
3020 /*******************************************************************************
3022 ** gckOS_AcquireMutex
3029 ** Pointer to an gckOS object.
3032 ** Pointer to the mutex to be acquired.
3034 ** gctUINT32 Timeout
3035 ** Timeout value specified in milliseconds.
3036 ** Specify the value of gcvINFINITE to keep the thread suspended
3037 ** until the mutex has been acquired.
3046 IN gctPOINTER Mutex,
3047 IN gctUINT32 Timeout
3050 #if gcdDETECT_TIMEOUT
3054 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
3056 /* Validate the arguments. */
3057 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3058 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3060 #if gcdDETECT_TIMEOUT
3065 /* Try to acquire the mutex. */
3066 if (mutex_trylock(Mutex))
3070 return gcvSTATUS_OK;
3073 /* Advance the timeout. */
3076 if (Timeout == gcvINFINITE)
3078 if (timeout == gcdINFINITE_TIMEOUT)
3080 gctUINT32 dmaAddress1, dmaAddress2;
3081 gctUINT32 dmaState1, dmaState2;
3083 dmaState1 = dmaState2 =
3084 dmaAddress1 = dmaAddress2 = 0;
3086 /* Verify whether DMA is running. */
3087 gcmkVERIFY_OK(_VerifyDMA(
3088 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
3091 #if gcdDETECT_DMA_ADDRESS
3092 /* Dump only if DMA appears stuck. */
3094 (dmaAddress1 == dmaAddress2)
3095 #if gcdDETECT_DMA_STATE
3096 && (dmaState1 == dmaState2)
3101 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
3104 "%s(%d): mutex 0x%X; forced message flush.",
3105 __FUNCTION__, __LINE__, Mutex
3108 /* Flush the debug cache. */
3109 gcmkDEBUGFLUSH(dmaAddress2);
3118 if (timeout >= Timeout)
3124 /* Wait for 1 millisecond. */
3125 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3128 if (Timeout == gcvINFINITE)
3130 /* Lock the mutex. */
3135 return gcvSTATUS_OK;
3140 /* Try to acquire the mutex. */
3141 if (mutex_trylock(Mutex))
3145 return gcvSTATUS_OK;
3153 /* Wait for 1 millisecond. */
3154 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3159 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
3160 return gcvSTATUS_TIMEOUT;
3163 /*******************************************************************************
3165 ** gckOS_ReleaseMutex
3167 ** Release an acquired mutex.
3172 ** Pointer to an gckOS object.
3175 ** Pointer to the mutex to be released.
3187 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
3189 /* Validate the arguments. */
3190 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3191 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3193 /* Release the mutex. */
3194 mutex_unlock(Mutex);
3198 return gcvSTATUS_OK;
3201 /*******************************************************************************
3203 ** gckOS_AtomicExchange
3205 ** Atomically exchange a pair of 32-bit values.
3210 ** Pointer to an gckOS object.
3212 ** IN OUT gctINT32_PTR Target
3213 ** Pointer to the 32-bit value to exchange.
3215 ** IN gctINT32 NewValue
3216 ** Specifies a new value for the 32-bit value pointed to by Target.
3218 ** OUT gctINT32_PTR OldValue
3219 ** The old value of the 32-bit value pointed to by Target.
3226 gckOS_AtomicExchange(
3228 IN OUT gctUINT32_PTR Target,
3229 IN gctUINT32 NewValue,
3230 OUT gctUINT32_PTR OldValue
3233 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
3235 /* Verify the arguments. */
3236 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3238 /* Exchange the pair of 32-bit values. */
3239 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
3242 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
3243 return gcvSTATUS_OK;
3246 /*******************************************************************************
3248 ** gckOS_AtomicExchangePtr
3250 ** Atomically exchange a pair of pointers.
3255 ** Pointer to an gckOS object.
3257 ** IN OUT gctPOINTER * Target
3258 ** Pointer to the 32-bit value to exchange.
3260 ** IN gctPOINTER NewValue
3261 ** Specifies a new value for the pointer pointed to by Target.
3263 ** OUT gctPOINTER * OldValue
3264 ** The old value of the pointer pointed to by Target.
3271 gckOS_AtomicExchangePtr(
3273 IN OUT gctPOINTER * Target,
3274 IN gctPOINTER NewValue,
3275 OUT gctPOINTER * OldValue
3278 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3280 /* Verify the arguments. */
3281 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3283 /* Exchange the pair of pointers. */
3284 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3287 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3288 return gcvSTATUS_OK;
3292 /*******************************************************************************
3294 ** gckOS_AtomicSetMask
3296 ** Atomically set mask to Atom
3299 ** IN OUT gctPOINTER Atom
3300 ** Pointer to the atom to set.
3302 ** IN gctUINT32 Mask
3315 gctUINT32 oval, nval;
3317 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3318 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3322 oval = atomic_read((atomic_t *) Atom);
3324 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3327 return gcvSTATUS_OK;
3330 /*******************************************************************************
3332 ** gckOS_AtomClearMask
3334 ** Atomically clear mask from Atom
3337 ** IN OUT gctPOINTER Atom
3338 ** Pointer to the atom to clear.
3340 ** IN gctUINT32 Mask
3348 gckOS_AtomClearMask(
3353 gctUINT32 oval, nval;
3355 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3356 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3360 oval = atomic_read((atomic_t *) Atom);
3361 nval = oval & ~Mask;
3362 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3365 return gcvSTATUS_OK;
3369 /*******************************************************************************
3371 ** gckOS_AtomConstruct
3378 ** Pointer to a gckOS object.
3382 ** gctPOINTER * Atom
3383 ** Pointer to a variable receiving the constructed atom.
3386 gckOS_AtomConstruct(
3388 OUT gctPOINTER * Atom
3393 gcmkHEADER_ARG("Os=0x%X", Os);
3395 /* Verify the arguments. */
3396 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3397 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3399 /* Allocate the atom. */
3400 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3402 /* Initialize the atom. */
3403 atomic_set((atomic_t *) *Atom, 0);
3406 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3407 return gcvSTATUS_OK;
3410 /* Return the status. */
3415 /*******************************************************************************
3417 ** gckOS_AtomDestroy
3424 ** Pointer to a gckOS object.
3427 ** Pointer to the atom to destroy.
3441 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3443 /* Verify the arguments. */
3444 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3445 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3447 /* Free the atom. */
3448 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3452 return gcvSTATUS_OK;
3455 /* Return the status. */
3460 /*******************************************************************************
3464 ** Get the 32-bit value protected by an atom.
3469 ** Pointer to a gckOS object.
3472 ** Pointer to the atom.
3476 ** gctINT32_PTR Value
3477 ** Pointer to a variable the receives the value of the atom.
3483 OUT gctINT32_PTR Value
3486 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3488 /* Verify the arguments. */
3489 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3490 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3492 /* Return the current value of atom. */
3493 *Value = atomic_read((atomic_t *) Atom);
3496 gcmkFOOTER_ARG("*Value=%d", *Value);
3497 return gcvSTATUS_OK;
3500 /*******************************************************************************
3504 ** Set the 32-bit value protected by an atom.
3509 ** Pointer to a gckOS object.
3512 ** Pointer to the atom.
3515 ** The value of the atom.
3528 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3530 /* Verify the arguments. */
3531 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3532 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3534 /* Set the current value of atom. */
3535 atomic_set((atomic_t *) Atom, Value);
3539 return gcvSTATUS_OK;
3542 /*******************************************************************************
3544 ** gckOS_AtomIncrement
3546 ** Atomically increment the 32-bit integer value inside an atom.
3551 ** Pointer to a gckOS object.
3554 ** Pointer to the atom.
3558 ** gctINT32_PTR Value
3559 ** Pointer to a variable that receives the original value of the atom.
3562 gckOS_AtomIncrement(
3565 OUT gctINT32_PTR Value
3568 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3570 /* Verify the arguments. */
3571 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3572 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3574 /* Increment the atom. */
3575 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3578 gcmkFOOTER_ARG("*Value=%d", *Value);
3579 return gcvSTATUS_OK;
3582 /*******************************************************************************
3584 ** gckOS_AtomDecrement
3586 ** Atomically decrement the 32-bit integer value inside an atom.
3591 ** Pointer to a gckOS object.
3594 ** Pointer to the atom.
3598 ** gctINT32_PTR Value
3599 ** Pointer to a variable that receives the original value of the atom.
3602 gckOS_AtomDecrement(
3605 OUT gctINT32_PTR Value
3608 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3610 /* Verify the arguments. */
3611 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3612 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3614 /* Decrement the atom. */
3615 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3618 gcmkFOOTER_ARG("*Value=%d", *Value);
3619 return gcvSTATUS_OK;
3622 /*******************************************************************************
3626 ** Delay execution of the current thread for a number of milliseconds.
3631 ** Pointer to an gckOS object.
3634 ** Delay to sleep, specified in milliseconds.
3646 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3650 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3651 ktime_t delay = ktime_set(0, Delay * NSEC_PER_MSEC);
3652 __set_current_state(TASK_UNINTERRUPTIBLE);
3653 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3662 return gcvSTATUS_OK;
3665 /*******************************************************************************
3669 ** Get the number of milliseconds since the system started.
3675 ** gctUINT32_PTR Time
3676 ** Pointer to a variable to get time.
3681 OUT gctUINT32_PTR Time
3686 *Time = jiffies_to_msecs(jiffies);
3689 return gcvSTATUS_OK;
3692 /*******************************************************************************
3696 ** Compare time values got from gckOS_GetTicks.
3700 ** First time value to be compared.
3703 ** Second time value to be compared.
3707 ** gctBOOL_PTR IsAfter
3708 ** Pointer to a variable to result.
3715 OUT gctBOOL_PTR IsAfter
3720 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3723 return gcvSTATUS_OK;
3726 /*******************************************************************************
3730 ** Get the number of microseconds since the system started.
3736 ** gctUINT64_PTR Time
3737 ** Pointer to a variable to get time.
3742 OUT gctUINT64_PTR Time
3750 return gcvSTATUS_OK;
3753 /*******************************************************************************
3755 ** gckOS_MemoryBarrier
3757 ** Make sure the CPU has executed everything up to this point and the data got
3758 ** written to the specified pointer.
3763 ** Pointer to an gckOS object.
3765 ** gctPOINTER Address
3766 ** Address of memory that needs to be barriered.
3773 gckOS_MemoryBarrier(
3775 IN gctPOINTER Address
3778 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3780 /* Verify the arguments. */
3781 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3783 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3784 && defined (CONFIG_ARM) \
3785 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3786 /* drain write buffer */
3789 /* drain outer cache's write buffer? */
3796 return gcvSTATUS_OK;
3799 /*******************************************************************************
3801 ** gckOS_AllocatePagedMemory
3803 ** Allocate memory from the paged pool.
3808 ** Pointer to an gckOS object.
3811 ** Number of bytes to allocate.
3815 ** gctPHYS_ADDR * Physical
3816 ** Pointer to a variable that receives the physical address of the
3817 ** memory allocation.
3820 gckOS_AllocatePagedMemory(
3823 OUT gctPHYS_ADDR * Physical
3828 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3830 /* Verify the arguments. */
3831 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3832 gcmkVERIFY_ARGUMENT(Bytes > 0);
3833 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3835 /* Allocate the memory. */
3836 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
3839 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3840 return gcvSTATUS_OK;
3843 /* Return the status. */
3848 /*******************************************************************************
3850 ** gckOS_AllocatePagedMemoryEx
3852 ** Allocate memory from the paged pool.
3857 ** Pointer to an gckOS object.
3859 ** gctBOOL Contiguous
3860 ** Need contiguous memory or not.
3863 ** Number of bytes to allocate.
3867 ** gctPHYS_ADDR * Physical
3868 ** Pointer to a variable that receives the physical address of the
3869 ** memory allocation.
3872 gckOS_AllocatePagedMemoryEx(
3874 IN gctBOOL Contiguous,
3876 OUT gctPHYS_ADDR * Physical
3881 PLINUX_MDL mdl = gcvNULL;
3883 gctBOOL locked = gcvFALSE;
3885 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3886 gctPOINTER addr = gcvNULL;
3889 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
3891 /* Verify the arguments. */
3892 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3893 gcmkVERIFY_ARGUMENT(Bytes > 0);
3894 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3896 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3898 numPages = GetPageCount(bytes, 0);
3903 mdl = _CreateMdl(_GetProcessID());
3906 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3911 /* Get contiguous pages, and suppress warning (stack dump) from kernel when
3912 we run out of memory. */
3913 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3915 alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
3917 mdl->u.contiguousPages = addr
3918 ? virt_to_page(addr)
3921 mdl->exact = gcvTRUE;
3923 mdl->u.contiguousPages =
3924 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, GetOrder(numPages));
3926 if (mdl->u.contiguousPages == gcvNULL)
3928 mdl->u.contiguousPages =
3929 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, GetOrder(numPages));
3931 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3932 mdl->exact = gcvFALSE;
3938 mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
3941 if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
3943 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3948 mdl->numPages = numPages;
3950 mdl->contiguous = Contiguous;
3952 for (i = 0; i < mdl->numPages; i++)
3956 if (mdl->contiguous)
3958 page = nth_page(mdl->u.contiguousPages, i);
3962 page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
3965 SetPageReserved(page);
3967 if (!PageHighMem(page) && page_to_phys(page))
3970 gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
3971 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
3977 /* Return physical address. */
3978 *Physical = (gctPHYS_ADDR) mdl;
3981 * Add this to a global list.
3982 * Will be used by get physical address
3983 * and mapuser pointer functions.
3987 /* Initialize the queue. */
3988 Os->mdlHead = Os->mdlTail = mdl;
3993 mdl->prev = Os->mdlTail;
3994 Os->mdlTail->next = mdl;
4001 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
4002 return gcvSTATUS_OK;
4007 /* Free the memory. */
4013 /* Unlock the memory. */
4017 /* Return the status. */
4022 /*******************************************************************************
4024 ** gckOS_FreePagedMemory
4026 ** Free memory allocated from the paged pool.
4031 ** Pointer to an gckOS object.
4033 ** gctPHYS_ADDR Physical
4034 ** Physical address of the allocation.
4037 ** Number of bytes of the allocation.
4044 gckOS_FreePagedMemory(
4046 IN gctPHYS_ADDR Physical,
4050 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
4053 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
4055 /* Verify the arguments. */
4056 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4057 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4058 gcmkVERIFY_ARGUMENT(Bytes > 0);
4060 /*addr = mdl->addr;*/
4064 for (i = 0; i < mdl->numPages; i++)
4066 if (mdl->contiguous)
4068 ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
4072 ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
4076 if (mdl->contiguous)
4078 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4079 if (mdl->exact == gcvTRUE)
4081 free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
4086 __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
4091 _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
4094 /* Remove the node from global list. */
4095 if (mdl == Os->mdlHead)
4097 if ((Os->mdlHead = mdl->next) == gcvNULL)
4099 Os->mdlTail = gcvNULL;
4104 mdl->prev->next = mdl->next;
4106 if (mdl == Os->mdlTail)
4108 Os->mdlTail = mdl->prev;
4112 mdl->next->prev = mdl->prev;
4118 /* Free the structure... */
4119 gcmkVERIFY_OK(_DestroyMdl(mdl));
4123 return gcvSTATUS_OK;
4126 /*******************************************************************************
4130 ** Lock memory allocated from the paged pool.
4135 ** Pointer to an gckOS object.
4137 ** gctPHYS_ADDR Physical
4138 ** Physical address of the allocation.
4141 ** Number of bytes of the allocation.
4143 ** gctBOOL Cacheable
4144 ** Cache mode of mapping.
4148 ** gctPOINTER * Logical
4149 ** Pointer to a variable that receives the address of the mapped
4152 ** gctSIZE_T * PageCount
4153 ** Pointer to a variable that receives the number of pages required for
4154 ** the page table according to the GPU page size.
4159 IN gctPHYS_ADDR Physical,
4161 IN gctBOOL Cacheable,
4162 OUT gctPOINTER * Logical,
4163 OUT gctSIZE_T * PageCount
4167 PLINUX_MDL_MAP mdlMap;
4169 unsigned long start;
4173 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
4175 /* Verify the arguments. */
4176 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4177 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4178 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4179 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
4181 mdl = (PLINUX_MDL) Physical;
4185 mdlMap = FindMdlMap(mdl, _GetProcessID());
4187 if (mdlMap == gcvNULL)
4189 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
4191 if (mdlMap == gcvNULL)
4195 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4196 return gcvSTATUS_OUT_OF_MEMORY;
4200 if (mdlMap->vmaAddr == gcvNULL)
4202 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
4203 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
4205 mdl->numPages * PAGE_SIZE,
4206 PROT_READ | PROT_WRITE,
4210 down_write(¤t->mm->mmap_sem);
4212 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
4214 mdl->numPages * PAGE_SIZE,
4215 PROT_READ | PROT_WRITE,
4219 up_write(¤t->mm->mmap_sem);
4223 gcvLEVEL_INFO, gcvZONE_OS,
4224 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
4225 __FUNCTION__, __LINE__,
4226 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
4227 (gctUINT32)(gctUINTPTR_T)mdl
4230 if (IS_ERR(mdlMap->vmaAddr))
4233 gcvLEVEL_INFO, gcvZONE_OS,
4234 "%s(%d): do_mmap_pgoff error",
4235 __FUNCTION__, __LINE__
4238 mdlMap->vmaAddr = gcvNULL;
4242 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4243 return gcvSTATUS_OUT_OF_MEMORY;
4246 down_write(¤t->mm->mmap_sem);
4248 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
4250 if (mdlMap->vma == gcvNULL)
4252 up_write(¤t->mm->mmap_sem);
4255 gcvLEVEL_INFO, gcvZONE_OS,
4256 "%s(%d): find_vma error",
4257 __FUNCTION__, __LINE__
4260 mdlMap->vmaAddr = gcvNULL;
4264 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
4265 return gcvSTATUS_OUT_OF_RESOURCES;
4268 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
4269 #if !gcdPAGED_MEMORY_CACHEABLE
4270 if (Cacheable == gcvFALSE)
4272 /* Make this mapping non-cached. */
4273 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
4278 /* Now map all the vmalloc pages to this user address. */
4279 if (mdl->contiguous)
4281 /* map kernel memory to user space.. */
4282 if (remap_pfn_range(mdlMap->vma,
4283 mdlMap->vma->vm_start,
4284 page_to_pfn(mdl->u.contiguousPages),
4285 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
4286 mdlMap->vma->vm_page_prot) < 0)
4288 up_write(¤t->mm->mmap_sem);
4291 gcvLEVEL_INFO, gcvZONE_OS,
4292 "%s(%d): unable to mmap ret",
4293 __FUNCTION__, __LINE__
4296 mdlMap->vmaAddr = gcvNULL;
4300 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4301 return gcvSTATUS_OUT_OF_MEMORY;
4306 start = mdlMap->vma->vm_start;
4308 for (i = 0; i < mdl->numPages; i++)
4310 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
4312 if (remap_pfn_range(mdlMap->vma,
4316 mdlMap->vma->vm_page_prot) < 0)
4318 up_write(¤t->mm->mmap_sem);
4321 gcvLEVEL_INFO, gcvZONE_OS,
4322 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
4323 __FUNCTION__, __LINE__,
4324 (gctUINT32)(gctUINTPTR_T)Physical,
4325 (gctUINT32)(gctUINTPTR_T)*Logical,
4326 (gctUINT32)(gctUINTPTR_T)addr,
4327 (gctUINT32)(gctUINTPTR_T)start
4330 mdlMap->vmaAddr = gcvNULL;
4334 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4335 return gcvSTATUS_OUT_OF_MEMORY;
4343 up_write(¤t->mm->mmap_sem);
4347 /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */
4350 gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED, mdlMap->vmaAddr);
4351 return gcvSTATUS_MEMORY_LOCKED;
4354 /* Convert pointer to MDL. */
4355 *Logical = mdlMap->vmaAddr;
4357 /* Return the page number according to the GPU page size. */
4358 gcmkASSERT((PAGE_SIZE % 4096) == 0);
4359 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
4361 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
4365 gcmkVERIFY_OK(gckOS_CacheFlush(
4370 (gctPOINTER)mdlMap->vmaAddr,
4371 mdl->numPages * PAGE_SIZE
4375 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
4376 return gcvSTATUS_OK;
4379 /*******************************************************************************
4383 ** Map paged memory into a page table.
4388 ** Pointer to an gckOS object.
4390 ** gctPHYS_ADDR Physical
4391 ** Physical address of the allocation.
4393 ** gctSIZE_T PageCount
4394 ** Number of pages required for the physical address.
4396 ** gctPOINTER PageTable
4397 ** Pointer to the page table to fill in.
4406 IN gctPHYS_ADDR Physical,
4407 IN gctSIZE_T PageCount,
4408 IN gctPOINTER PageTable
4411 return gckOS_MapPagesEx(Os,
4422 IN gctPHYS_ADDR Physical,
4423 IN gctSIZE_T PageCount,
4424 IN gctPOINTER PageTable
4427 gceSTATUS status = gcvSTATUS_OK;
4431 #if gcdNONPAGED_MEMORY_CACHEABLE
4435 gctPHYS_ADDR pageTablePhysical;
4438 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
4439 Os, Core, Physical, PageCount, PageTable);
4441 /* Verify the arguments. */
4442 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4443 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4444 gcmkVERIFY_ARGUMENT(PageCount > 0);
4445 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
4447 /* Convert pointer to MDL. */
4448 mdl = (PLINUX_MDL)Physical;
4451 gcvLEVEL_INFO, gcvZONE_OS,
4452 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4453 __FUNCTION__, __LINE__,
4454 (gctUINT32)(gctUINTPTR_T)Physical,
4455 (gctUINT32)(gctUINTPTR_T)PageCount,
4461 table = (gctUINT32 *)PageTable;
4462 #if gcdNONPAGED_MEMORY_CACHEABLE
4463 mmu = Os->device->kernels[Core]->mmu;
4464 bytes = PageCount * sizeof(*table);
4465 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4468 /* Get all the physical addresses and store them in the page table. */
4474 /* Try to get the user pages so DMA can happen. */
4475 while (PageCount-- > 0)
4478 if (Core == gcvCORE_VG)
4480 if (mdl->contiguous)
4483 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4484 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4490 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4491 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4498 if (mdl->contiguous)
4501 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4502 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4508 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4509 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4521 gcvLEVEL_INFO, gcvZONE_OS,
4522 "%s(%d): we should not get this call for Non Paged Memory!",
4523 __FUNCTION__, __LINE__
4526 while (PageCount-- > 0)
4529 if (Core == gcvCORE_VG)
4532 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4533 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4540 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4541 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4549 #if gcdNONPAGED_MEMORY_CACHEABLE
4550 /* Get physical address of pageTable */
4551 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4552 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4554 /* Flush the mmu page table cache. */
4555 gcmkONERROR(gckOS_CacheClean(
4569 /* Return the status. */
4574 /*******************************************************************************
4576 ** gckOS_UnlockPages
4578 ** Unlock memory allocated from the paged pool.
4583 ** Pointer to an gckOS object.
4585 ** gctPHYS_ADDR Physical
4586 ** Physical address of the allocation.
4589 ** Number of bytes of the allocation.
4591 ** gctPOINTER Logical
4592 ** Address of the mapped memory.
4601 IN gctPHYS_ADDR Physical,
4603 IN gctPOINTER Logical
4606 PLINUX_MDL_MAP mdlMap;
4607 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4609 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4610 Os, Physical, Bytes, Logical);
4612 /* Verify the arguments. */
4613 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4614 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4615 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4617 /* Make sure there is already a mapping...*/
4618 gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
4619 || mdl->u.contiguousPages != gcvNULL);
4625 while (mdlMap != gcvNULL)
4627 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4629 _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
4630 mdlMap->vmaAddr = gcvNULL;
4633 mdlMap = mdlMap->next;
4640 return gcvSTATUS_OK;
4644 /*******************************************************************************
4646 ** gckOS_AllocateContiguous
4648 ** Allocate memory from the contiguous pool.
4653 ** Pointer to an gckOS object.
4655 ** gctBOOL InUserSpace
4656 ** gcvTRUE if the pages need to be mapped into user space.
4658 ** gctSIZE_T * Bytes
4659 ** Pointer to the number of bytes to allocate.
4663 ** gctSIZE_T * Bytes
4664 ** Pointer to a variable that receives the number of bytes allocated.
4666 ** gctPHYS_ADDR * Physical
4667 ** Pointer to a variable that receives the physical address of the
4668 ** memory allocation.
4670 ** gctPOINTER * Logical
4671 ** Pointer to a variable that receives the logical address of the
4672 ** memory allocation.
4675 gckOS_AllocateContiguous(
4677 IN gctBOOL InUserSpace,
4678 IN OUT gctSIZE_T * Bytes,
4679 OUT gctPHYS_ADDR * Physical,
4680 OUT gctPOINTER * Logical
4685 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4686 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4688 /* Verify the arguments. */
4689 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4690 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4691 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4692 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4693 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4695 /* Same as non-paged memory for now. */
4696 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4703 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4704 *Bytes, *Physical, *Logical);
4705 return gcvSTATUS_OK;
4708 /* Return the status. */
4713 /*******************************************************************************
4715 ** gckOS_FreeContiguous
4717 ** Free memory allocated from the contiguous pool.
4722 ** Pointer to an gckOS object.
4724 ** gctPHYS_ADDR Physical
4725 ** Physical address of the allocation.
4727 ** gctPOINTER Logical
4728 ** Logicval address of the allocation.
4731 ** Number of bytes of the allocation.
4738 gckOS_FreeContiguous(
4740 IN gctPHYS_ADDR Physical,
4741 IN gctPOINTER Logical,
4747 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4748 Os, Physical, Logical, Bytes);
4750 /* Verify the arguments. */
4751 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4752 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4753 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4754 gcmkVERIFY_ARGUMENT(Bytes > 0);
4756 /* Same of non-paged memory for now. */
4757 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4761 return gcvSTATUS_OK;
4764 /* Return the status. */
4770 /******************************************************************************
4772 ** gckOS_GetKernelLogical
4774 ** Return the kernel logical pointer that corresponods to the specified
4775 ** hardware address.
4780 ** Pointer to an gckOS object.
4782 ** gctUINT32 Address
4783 ** Hardware physical address.
4787 ** gctPOINTER * KernelPointer
4788 ** Pointer to a variable receiving the pointer in kernel address space.
4791 gckOS_GetKernelLogical(
4793 IN gctUINT32 Address,
4794 OUT gctPOINTER * KernelPointer
4797 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4801 gckOS_GetKernelLogicalEx(
4804 IN gctUINT32 Address,
4805 OUT gctPOINTER * KernelPointer
4810 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4814 gckGALDEVICE device;
4820 /* Extract the pointer to the gckGALDEVICE class. */
4821 device = (gckGALDEVICE) Os->device;
4823 /* Kernel shortcut. */
4824 kernel = device->kernels[Core];
4826 if (Core == gcvCORE_VG)
4828 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4829 kernel->vg->hardware, Address, &pool, &offset
4835 /* Split the memory address into a pool type and offset. */
4836 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4837 kernel->hardware, Address, &pool, &offset
4841 /* Dispatch on pool. */
4844 case gcvPOOL_LOCAL_INTERNAL:
4845 /* Internal memory. */
4846 logical = device->internalLogical;
4849 case gcvPOOL_LOCAL_EXTERNAL:
4850 /* External memory. */
4851 logical = device->externalLogical;
4854 case gcvPOOL_SYSTEM:
4855 /* System memory. */
4856 logical = device->contiguousBase;
4860 /* Invalid memory pool. */
4862 return gcvSTATUS_INVALID_ARGUMENT;
4865 /* Build logical address of specified address. */
4866 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4869 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4870 return gcvSTATUS_OK;
4874 /* Return status. */
4880 /*******************************************************************************
4882 ** gckOS_MapUserPointer
4884 ** Map a pointer from the user process into the kernel address space.
4889 ** Pointer to an gckOS object.
4891 ** gctPOINTER Pointer
4892 ** Pointer in user process space that needs to be mapped.
4895 ** Number of bytes that need to be mapped.
4899 ** gctPOINTER * KernelPointer
4900 ** Pointer to a variable receiving the mapped pointer in kernel address
4904 gckOS_MapUserPointer(
4906 IN gctPOINTER Pointer,
4908 OUT gctPOINTER * KernelPointer
4911 gctPOINTER buf = gcvNULL;
4914 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
4916 /* Verify the arguments. */
4917 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4918 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4919 gcmkVERIFY_ARGUMENT(Size > 0);
4920 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4922 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
4927 "%s(%d): Failed to allocate memory.",
4928 __FUNCTION__, __LINE__
4931 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4932 return gcvSTATUS_OUT_OF_MEMORY;
4935 len = copy_from_user(buf, Pointer, Size);
4940 "%s(%d): Failed to copy data from user.",
4941 __FUNCTION__, __LINE__
4949 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
4950 return gcvSTATUS_GENERIC_IO;
4953 *KernelPointer = buf;
4955 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4956 return gcvSTATUS_OK;
4959 /*******************************************************************************
4961 ** gckOS_UnmapUserPointer
4963 ** Unmap a user process pointer from the kernel address space.
4968 ** Pointer to an gckOS object.
4970 ** gctPOINTER Pointer
4971 ** Pointer in user process space that needs to be unmapped.
4974 ** Number of bytes that need to be unmapped.
4976 ** gctPOINTER KernelPointer
4977 ** Pointer in kernel address space that needs to be unmapped.
4984 gckOS_UnmapUserPointer(
4986 IN gctPOINTER Pointer,
4988 IN gctPOINTER KernelPointer
4993 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
4994 Os, Pointer, Size, KernelPointer);
4997 /* Verify the arguments. */
4998 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4999 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5000 gcmkVERIFY_ARGUMENT(Size > 0);
5001 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5003 len = copy_to_user(Pointer, KernelPointer, Size);
5005 kfree(KernelPointer);
5011 "%s(%d): Failed to copy data to user.",
5012 __FUNCTION__, __LINE__
5015 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
5016 return gcvSTATUS_GENERIC_IO;
5020 return gcvSTATUS_OK;
5023 /*******************************************************************************
5025 ** gckOS_QueryNeedCopy
5027 ** Query whether the memory can be accessed or mapped directly or it has to be
5033 ** Pointer to an gckOS object.
5035 ** gctUINT32 ProcessID
5036 ** Process ID of the current process.
5040 ** gctBOOL_PTR NeedCopy
5041 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
5042 ** gcvFALSE if the memory can be accessed or mapped dircetly.
5045 gckOS_QueryNeedCopy(
5047 IN gctUINT32 ProcessID,
5048 OUT gctBOOL_PTR NeedCopy
5051 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
5053 /* Verify the arguments. */
5054 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5055 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
5057 /* We need to copy data. */
5058 *NeedCopy = gcvTRUE;
5061 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
5062 return gcvSTATUS_OK;
5065 /*******************************************************************************
5067 ** gckOS_CopyFromUserData
5069 ** Copy data from user to kernel memory.
5074 ** Pointer to an gckOS object.
5076 ** gctPOINTER KernelPointer
5077 ** Pointer to kernel memory.
5079 ** gctPOINTER Pointer
5080 ** Pointer to user memory.
5083 ** Number of bytes to copy.
5090 gckOS_CopyFromUserData(
5092 IN gctPOINTER KernelPointer,
5093 IN gctPOINTER Pointer,
5099 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5100 Os, KernelPointer, Pointer, Size);
5102 /* Verify the arguments. */
5103 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5104 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5105 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5106 gcmkVERIFY_ARGUMENT(Size > 0);
5108 /* Copy data from user. */
5109 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
5111 /* Could not copy all the bytes. */
5112 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5117 return gcvSTATUS_OK;
5120 /* Return the status. */
5125 /*******************************************************************************
5127 ** gckOS_CopyToUserData
5129 ** Copy data from kernel to user memory.
5134 ** Pointer to an gckOS object.
5136 ** gctPOINTER KernelPointer
5137 ** Pointer to kernel memory.
5139 ** gctPOINTER Pointer
5140 ** Pointer to user memory.
5143 ** Number of bytes to copy.
5150 gckOS_CopyToUserData(
5152 IN gctPOINTER KernelPointer,
5153 IN gctPOINTER Pointer,
5159 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5160 Os, KernelPointer, Pointer, Size);
5162 /* Verify the arguments. */
5163 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5164 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5165 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5166 gcmkVERIFY_ARGUMENT(Size > 0);
5168 /* Copy data to user. */
5169 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
5171 /* Could not copy all the bytes. */
5172 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5177 return gcvSTATUS_OK;
5180 /* Return the status. */
5185 /*******************************************************************************
5187 ** gckOS_WriteMemory
5189 ** Write data to a memory.
5194 ** Pointer to an gckOS object.
5196 ** gctPOINTER Address
5197 ** Address of the memory to write to.
5200 ** Data for register.
5209 IN gctPOINTER Address,
5214 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
5216 /* Verify the arguments. */
5217 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5220 if (access_ok(VERIFY_WRITE, Address, 4))
5223 if(put_user(Data, (gctUINT32*)Address))
5225 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
5230 /* Kernel address. */
5231 *(gctUINT32 *)Address = Data;
5236 return gcvSTATUS_OK;
5243 /*******************************************************************************
5245 ** gckOS_MapUserMemory
5247 ** Lock down a user buffer and return an DMA'able address to be used by the
5248 ** hardware to access it.
5252 ** gctPOINTER Memory
5253 ** Pointer to memory to lock down.
5256 ** Size in bytes of the memory to lock down.
5260 ** gctPOINTER * Info
5261 ** Pointer to variable receiving the information record required by
5262 ** gckOS_UnmapUserMemory.
5264 ** gctUINT32_PTR Address
5265 ** Pointer to a variable that will receive the address DMA'able by the
5269 gckOS_MapUserMemory(
5272 IN gctPOINTER Memory,
5273 IN gctUINT32 Physical,
5275 OUT gctPOINTER * Info,
5276 OUT gctUINT32_PTR Address
5281 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
5284 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
5287 return gcvSTATUS_OK;
5294 gctSIZE_T pageCount, i, j;
5295 gctUINT32_PTR pageTable;
5296 gctUINT32 address = 0, physical = ~0U;
5297 gctUINTPTR_T start, end, memory;
5301 gcsPageInfo_PTR info = gcvNULL;
5302 struct page **pages = gcvNULL;
5304 /* Verify the arguments. */
5305 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5306 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
5307 gcmkVERIFY_ARGUMENT(Size > 0);
5308 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5309 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5313 memory = (gctUINTPTR_T) Memory;
5315 /* Get the number of required pages. */
5316 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5317 start = memory >> PAGE_SHIFT;
5318 pageCount = end - start;
5321 gcvLEVEL_INFO, gcvZONE_OS,
5322 "%s(%d): pageCount: %d.",
5323 __FUNCTION__, __LINE__,
5328 if ((memory + Size) < memory)
5330 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5331 return gcvSTATUS_INVALID_ARGUMENT;
5334 MEMORY_MAP_LOCK(Os);
5336 /* Allocate the Info struct. */
5337 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
5339 if (info == gcvNULL)
5341 status = gcvSTATUS_OUT_OF_MEMORY;
5345 /* Allocate the array of page addresses. */
5346 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
5348 if (pages == gcvNULL)
5350 status = gcvSTATUS_OUT_OF_MEMORY;
5354 if (Physical != ~0U)
5356 for (i = 0; i < pageCount; i++)
5358 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
5364 /* Get the user pages. */
5365 down_read(¤t->mm->mmap_sem);
5366 result = get_user_pages(current,
5375 up_read(¤t->mm->mmap_sem);
5377 if (result <=0 || result < pageCount)
5379 struct vm_area_struct *vma;
5381 /* Free the page table. */
5382 if (pages != gcvNULL)
5384 /* Release the pages if any. */
5387 for (i = 0; i < result; i++)
5389 if (pages[i] == gcvNULL)
5394 page_cache_release(pages[i]);
5402 vma = find_vma(current->mm, memory);
5404 if (vma && (vma->vm_flags & VM_PFNMAP) )
5410 pgd_t * pgd = pgd_offset(current->mm, memory);
5411 pud_t * pud = pud_offset(pgd, memory);
5414 pmd_t * pmd = pmd_offset(pud, memory);
5415 pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
5418 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5423 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5426 pfn = pte_pfn(*pte);
5428 physical = (pfn << PAGE_SHIFT) | (memory & ~PAGE_MASK);
5430 pte_unmap_unlock(pte, ptl);
5432 if ((Os->device->kernels[Core]->hardware->mmuVersion == 0)
5433 && !((physical - Os->device->baseAddress) & 0x80000000))
5435 info->pages = gcvNULL;
5436 info->pageTable = gcvNULL;
5438 MEMORY_MAP_UNLOCK(Os);
5440 *Address = physical - Os->device->baseAddress;
5443 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5446 return gcvSTATUS_OK;
5451 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5458 for (i = 0; i < pageCount; i++)
5460 /* Flush(clean) the data cache. */
5461 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5462 (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
5463 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5469 /* Flush(clean) the data cache. */
5470 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5471 (gctPOINTER)(gctUINTPTR_T)(physical & PAGE_MASK),
5472 (gctPOINTER)(memory & PAGE_MASK),
5473 PAGE_SIZE * pageCount));
5477 if (Core == gcvCORE_VG)
5479 /* Allocate pages inside the page table. */
5480 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5481 pageCount * (PAGE_SIZE/4096),
5482 (gctPOINTER *) &pageTable,
5488 /* Allocate pages inside the page table. */
5489 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5490 pageCount * (PAGE_SIZE/4096),
5491 (gctPOINTER *) &pageTable,
5494 /* Fill the page table. */
5495 for (i = 0; i < pageCount; i++)
5498 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5502 phys = page_to_phys(pages[i]);
5506 phys = (physical & PAGE_MASK) + i * PAGE_SIZE;
5510 if (Core == gcvCORE_VG)
5512 /* Get the physical address from page struct. */
5514 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5521 /* Get the physical address from page struct. */
5523 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5528 for (j = 1; j < (PAGE_SIZE/4096); j++)
5530 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5534 gcvLEVEL_INFO, gcvZONE_OS,
5535 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5536 __FUNCTION__, __LINE__,
5537 i, phys, pageTable[i]);
5541 if (Core == gcvCORE_VG)
5543 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5548 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
5551 /* Save pointer to page table. */
5552 info->pageTable = pageTable;
5553 info->pages = pages;
5555 *Info = (gctPOINTER) info;
5558 gcvLEVEL_INFO, gcvZONE_OS,
5559 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5560 __FUNCTION__, __LINE__,
5566 offset = (Physical != ~0U)
5567 ? (Physical & ~PAGE_MASK)
5568 : (memory & ~PAGE_MASK);
5570 /* Return address. */
5571 *Address = address + offset;
5574 gcvLEVEL_INFO, gcvZONE_OS,
5575 "%s(%d): Address: 0x%X.",
5576 __FUNCTION__, __LINE__,
5581 status = gcvSTATUS_OK;
5587 if (gcmIS_ERROR(status))
5591 "%s(%d): error occured: %d.",
5592 __FUNCTION__, __LINE__,
5596 /* Release page array. */
5597 if (result > 0 && pages != gcvNULL)
5601 "%s(%d): error: page table is freed.",
5602 __FUNCTION__, __LINE__
5605 for (i = 0; i < result; i++)
5607 if (pages[i] == gcvNULL)
5611 page_cache_release(pages[i]);
5615 if (info!= gcvNULL && pages != gcvNULL)
5619 "%s(%d): error: pages is freed.",
5620 __FUNCTION__, __LINE__
5623 /* Free the page table. */
5625 info->pages = gcvNULL;
5628 /* Release page info struct. */
5629 if (info != gcvNULL)
5633 "%s(%d): error: info is freed.",
5634 __FUNCTION__, __LINE__
5637 /* Free the page info struct. */
5643 MEMORY_MAP_UNLOCK(Os);
5645 /* Return the status. */
5646 if (gcmIS_SUCCESS(status))
5648 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5660 /*******************************************************************************
5662 ** gckOS_UnmapUserMemory
5664 ** Unlock a user buffer and that was previously locked down by
5665 ** gckOS_MapUserMemory.
5669 ** gctPOINTER Memory
5670 ** Pointer to memory to unlock.
5673 ** Size in bytes of the memory to unlock.
5676 ** Information record returned by gckOS_MapUserMemory.
5678 ** gctUINT32_PTR Address
5679 ** The address returned by gckOS_MapUserMemory.
5686 gckOS_UnmapUserMemory(
5689 IN gctPOINTER Memory,
5692 IN gctUINT32 Address
5697 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5698 Os, Core, Memory, Size, Info, Address);
5701 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5704 return gcvSTATUS_OK;
5711 gctUINTPTR_T memory, start, end;
5712 gcsPageInfo_PTR info;
5713 gctSIZE_T pageCount, i;
5714 struct page **pages;
5716 /* Verify the arguments. */
5717 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5718 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5719 gcmkVERIFY_ARGUMENT(Size > 0);
5720 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5724 info = (gcsPageInfo_PTR) Info;
5726 pages = info->pages;
5729 gcvLEVEL_INFO, gcvZONE_OS,
5730 "%s(%d): info=0x%X, pages=0x%X.",
5731 __FUNCTION__, __LINE__,
5735 /* Invalid page array. */
5736 if (pages == gcvNULL && info->pageTable == gcvNULL)
5741 return gcvSTATUS_OK;
5744 memory = (gctUINTPTR_T)Memory;
5745 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5746 start = memory >> PAGE_SHIFT;
5747 pageCount = end - start;
5750 if ((memory + Size) < memory)
5752 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5753 return gcvSTATUS_INVALID_ARGUMENT;
5757 gcvLEVEL_INFO, gcvZONE_OS,
5758 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5759 __FUNCTION__, __LINE__,
5760 memory, pageCount, info->pageTable
5763 MEMORY_MAP_LOCK(Os);
5765 gcmkASSERT(info->pageTable != gcvNULL);
5768 if (Core == gcvCORE_VG)
5770 /* Free the pages from the MMU. */
5771 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5773 pageCount * (PAGE_SIZE/4096)
5779 /* Free the pages from the MMU. */
5780 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5782 pageCount * (PAGE_SIZE/4096)
5786 /* Release the page cache. */
5789 for (i = 0; i < pageCount; i++)
5792 gcvLEVEL_INFO, gcvZONE_OS,
5793 "%s(%d): pages[%d]: 0x%X.",
5794 __FUNCTION__, __LINE__,
5798 if (!PageReserved(pages[i]))
5800 SetPageDirty(pages[i]);
5803 page_cache_release(pages[i]);
5808 status = gcvSTATUS_OK;
5812 if (info != gcvNULL)
5814 /* Free the page array. */
5815 if (info->pages != gcvNULL)
5823 MEMORY_MAP_UNLOCK(Os);
5825 /* Return the status. */
5832 /*******************************************************************************
5834 ** gckOS_GetBaseAddress
5836 ** Get the base address for the physical memory.
5841 ** Pointer to the gckOS object.
5845 ** gctUINT32_PTR BaseAddress
5846 ** Pointer to a variable that will receive the base address.
5849 gckOS_GetBaseAddress(
5851 OUT gctUINT32_PTR BaseAddress
5854 gcmkHEADER_ARG("Os=0x%X", Os);
5856 /* Verify the arguments. */
5857 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5858 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5860 /* Return base address. */
5861 *BaseAddress = Os->device->baseAddress;
5864 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5865 return gcvSTATUS_OK;
5869 gckOS_SuspendInterrupt(
5873 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5877 gckOS_SuspendInterruptEx(
5882 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5884 /* Verify the arguments. */
5885 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5887 disable_irq(Os->device->irqLines[Core]);
5890 return gcvSTATUS_OK;
5894 gckOS_ResumeInterrupt(
5898 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
5902 gckOS_ResumeInterruptEx(
5907 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5909 /* Verify the arguments. */
5910 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5912 enable_irq(Os->device->irqLines[Core]);
5915 return gcvSTATUS_OK;
5920 IN gctPOINTER Destination,
5921 IN gctCONST_POINTER Source,
5925 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
5926 Destination, Source, Bytes);
5928 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
5929 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
5930 gcmkVERIFY_ARGUMENT(Bytes > 0);
5932 memcpy(Destination, Source, Bytes);
5935 return gcvSTATUS_OK;
5940 IN gctPOINTER Memory,
5944 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
5946 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5947 gcmkVERIFY_ARGUMENT(Bytes > 0);
5949 memset(Memory, 0, Bytes);
5952 return gcvSTATUS_OK;
5955 /*******************************************************************************
5956 ********************************* Cache Control ********************************
5957 *******************************************************************************/
5959 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
5960 static inline gceSTATUS
5962 gceCACHEOPERATION Type,
5963 unsigned long Start,
5969 case gcvCACHE_CLEAN:
5970 outer_clean_range(Start, End);
5972 case gcvCACHE_INVALIDATE:
5973 outer_inv_range(Start, End);
5975 case gcvCACHE_FLUSH:
5976 outer_flush_range(Start, End);
5979 return gcvSTATUS_INVALID_ARGUMENT;
5982 return gcvSTATUS_OK;
5985 #if gcdENABLE_OUTER_CACHE_PATCH
5986 /*******************************************************************************
5987 ** _HandleOuterCache
5989 ** Handle the outer cache for the specified addresses.
5994 ** Pointer to gckOS object.
5996 ** gctUINT32 ProcessID
5997 ** Process ID Logical belongs.
5999 ** gctPHYS_ADDR Handle
6000 ** Physical address handle. If gcvNULL it is video memory.
6002 ** gctPOINTER Physical
6003 ** Physical address to flush.
6005 ** gctPOINTER Logical
6006 ** Logical address to flush.
6009 ** Size of the address range in bytes to flush.
6011 ** gceOUTERCACHE_OPERATION Type
6012 ** Operation need to be execute.
6017 IN gctUINT32 ProcessID,
6018 IN gctPHYS_ADDR Handle,
6019 IN gctPOINTER Physical,
6020 IN gctPOINTER Logical,
6022 IN gceCACHEOPERATION Type
6026 gctUINT32 i, pageNum;
6027 unsigned long paddr;
6030 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6031 Os, ProcessID, Handle, Logical, Bytes);
6033 if (Physical != gcvNULL)
6035 /* Non paged memory or gcvPOOL_USER surface */
6036 paddr = (unsigned long) Physical;
6037 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6039 else if ((Handle == gcvNULL)
6040 || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
6043 /* Video Memory or contiguous virtual memory */
6044 gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
6045 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6049 /* Non contiguous virtual memory */
6050 vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
6051 pageNum = GetPageCount(Bytes, 0);
6053 for (i = 0; i < pageNum; i += 1)
6055 gcmkONERROR(_ConvertLogical2Physical(
6057 vaddr + PAGE_SIZE * i,
6063 gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
6071 return gcvSTATUS_OK;
6074 /* Return the status. */
6081 /*******************************************************************************
6084 ** Clean the cache for the specified addresses. The GPU is going to need the
6085 ** data. If the system is allocating memory as non-cachable, this function can
6091 ** Pointer to gckOS object.
6093 ** gctUINT32 ProcessID
6094 ** Process ID Logical belongs.
6096 ** gctPHYS_ADDR Handle
6097 ** Physical address handle. If gcvNULL it is video memory.
6099 ** gctPOINTER Physical
6100 ** Physical address to flush.
6102 ** gctPOINTER Logical
6103 ** Logical address to flush.
6106 ** Size of the address range in bytes to flush.
6111 IN gctUINT32 ProcessID,
6112 IN gctPHYS_ADDR Handle,
6113 IN gctPOINTER Physical,
6114 IN gctPOINTER Logical,
6118 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6119 Os, ProcessID, Handle, Logical, Bytes);
6121 /* Verify the arguments. */
6122 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6123 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6124 gcmkVERIFY_ARGUMENT(Bytes > 0);
6126 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6130 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6131 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
6133 dmac_clean_range(Logical, Logical + Bytes);
6136 #if defined(CONFIG_OUTER_CACHE)
6138 #if gcdENABLE_OUTER_CACHE_PATCH
6139 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
6141 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6145 #elif defined(CONFIG_MIPS)
6147 dma_cache_wback((unsigned long) Logical, Bytes);
6149 #elif defined(CONFIG_PPC)
6154 dma_sync_single_for_device(
6164 return gcvSTATUS_OK;
6167 /*******************************************************************************
6168 ** gckOS_CacheInvalidate
6170 ** Invalidate the cache for the specified addresses. The GPU is going to need
6171 ** data. If the system is allocating memory as non-cachable, this function can
6177 ** Pointer to gckOS object.
6179 ** gctUINT32 ProcessID
6180 ** Process ID Logical belongs.
6182 ** gctPHYS_ADDR Handle
6183 ** Physical address handle. If gcvNULL it is video memory.
6185 ** gctPOINTER Logical
6186 ** Logical address to flush.
6189 ** Size of the address range in bytes to flush.
6192 gckOS_CacheInvalidate(
6194 IN gctUINT32 ProcessID,
6195 IN gctPHYS_ADDR Handle,
6196 IN gctPOINTER Physical,
6197 IN gctPOINTER Logical,
6201 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6202 Os, ProcessID, Handle, Logical, Bytes);
6204 /* Verify the arguments. */
6205 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6206 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6207 gcmkVERIFY_ARGUMENT(Bytes > 0);
6209 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6213 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6214 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
6216 dmac_inv_range(Logical, Logical + Bytes);
6219 #if defined(CONFIG_OUTER_CACHE)
6221 #if gcdENABLE_OUTER_CACHE_PATCH
6222 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
6224 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6228 #elif defined(CONFIG_MIPS)
6229 dma_cache_inv((unsigned long) Logical, Bytes);
6230 #elif defined(CONFIG_PPC)
6233 dma_sync_single_for_device(
6243 return gcvSTATUS_OK;
6246 /*******************************************************************************
6249 ** Clean the cache for the specified addresses and invalidate the lines as
6250 ** well. The GPU is going to need and modify the data. If the system is
6251 ** allocating memory as non-cachable, this function can be ignored.
6256 ** Pointer to gckOS object.
6258 ** gctUINT32 ProcessID
6259 ** Process ID Logical belongs.
6261 ** gctPHYS_ADDR Handle
6262 ** Physical address handle. If gcvNULL it is video memory.
6264 ** gctPOINTER Logical
6265 ** Logical address to flush.
6268 ** Size of the address range in bytes to flush.
6273 IN gctUINT32 ProcessID,
6274 IN gctPHYS_ADDR Handle,
6275 IN gctPOINTER Physical,
6276 IN gctPOINTER Logical,
6280 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6281 Os, ProcessID, Handle, Logical, Bytes);
6283 /* Verify the arguments. */
6284 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6285 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6286 gcmkVERIFY_ARGUMENT(Bytes > 0);
6288 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6291 dmac_flush_range(Logical, Logical + Bytes);
6293 #if defined(CONFIG_OUTER_CACHE)
6295 #if gcdENABLE_OUTER_CACHE_PATCH
6296 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6298 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6302 #elif defined(CONFIG_MIPS)
6303 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6304 #elif defined(CONFIG_PPC)
6307 dma_sync_single_for_device(
6317 return gcvSTATUS_OK;
6320 /*******************************************************************************
6321 ********************************* Broadcasting *********************************
6322 *******************************************************************************/
6324 /*******************************************************************************
6328 ** System hook for broadcast events from the kernel driver.
6333 ** Pointer to the gckOS object.
6335 ** gckHARDWARE Hardware
6336 ** Pointer to the gckHARDWARE object.
6338 ** gceBROADCAST Reason
6339 ** Reason for the broadcast. Can be one of the following values:
6341 ** gcvBROADCAST_GPU_IDLE
6342 ** Broadcasted when the kernel driver thinks the GPU might be
6343 ** idle. This can be used to handle power management.
6345 ** gcvBROADCAST_GPU_COMMIT
6346 ** Broadcasted when any client process commits a command
6347 ** buffer. This can be used to handle power management.
6349 ** gcvBROADCAST_GPU_STUCK
6350 ** Broadcasted when the kernel driver hits the timeout waiting
6353 ** gcvBROADCAST_FIRST_PROCESS
6354 ** First process is trying to connect to the kernel.
6356 ** gcvBROADCAST_LAST_PROCESS
6357 ** Last process has detached from the kernel.
6366 IN gckHARDWARE Hardware,
6367 IN gceBROADCAST Reason
6372 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6374 /* Verify the arguments. */
6375 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6376 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6380 case gcvBROADCAST_FIRST_PROCESS:
6381 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6384 case gcvBROADCAST_LAST_PROCESS:
6385 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6389 gckHARDWARE_SetPowerManagementState(Hardware,
6390 gcvPOWER_OFF_BROADCAST));
6393 case gcvBROADCAST_GPU_IDLE:
6394 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6398 gckHARDWARE_SetPowerManagementState(Hardware,
6399 #if gcdPOWER_SUSNPEND_WHEN_IDLE
6400 gcvPOWER_SUSPEND_BROADCAST));
6402 gcvPOWER_IDLE_BROADCAST));
6405 /* Add idle process DB. */
6406 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6409 gcvNULL, gcvNULL, 0));
6412 case gcvBROADCAST_GPU_COMMIT:
6413 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6415 /* Add busy process DB. */
6416 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6419 gcvNULL, gcvNULL, 0));
6423 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6426 case gcvBROADCAST_GPU_STUCK:
6427 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6428 #if !gcdENABLE_RECOVERY
6429 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6431 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6434 case gcvBROADCAST_AXI_BUS_ERROR:
6435 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6436 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6437 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6443 return gcvSTATUS_OK;
6446 /* Return the status. */
6451 /*******************************************************************************
6453 ** gckOS_BroadcastHurry
6455 ** The GPU is running too slow.
6460 ** Pointer to the gckOS object.
6462 ** gckHARDWARE Hardware
6463 ** Pointer to the gckHARDWARE object.
6466 ** The higher the number, the higher the urgency to speed up the GPU.
6467 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6474 gckOS_BroadcastHurry(
6476 IN gckHARDWARE Hardware,
6480 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6482 /* Do whatever you need to do to speed up the GPU now. */
6486 return gcvSTATUS_OK;
6489 /*******************************************************************************
6491 ** gckOS_BroadcastCalibrateSpeed
6493 ** Calibrate the speed of the GPU.
6498 ** Pointer to the gckOS object.
6500 ** gckHARDWARE Hardware
6501 ** Pointer to the gckHARDWARE object.
6503 ** gctUINT Idle, Time
6504 ** Idle/Time will give the percentage the GPU is idle, so you can use
6505 ** this to calibrate the working point of the GPU.
6512 gckOS_BroadcastCalibrateSpeed(
6514 IN gckHARDWARE Hardware,
6519 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6520 Os, Hardware, Idle, Time);
6522 /* Do whatever you need to do to callibrate the GPU speed. */
6526 return gcvSTATUS_OK;
6529 /*******************************************************************************
6530 ********************************** Semaphores **********************************
6531 *******************************************************************************/
6533 /*******************************************************************************
6535 ** gckOS_CreateSemaphore
6537 ** Create a semaphore.
6542 ** Pointer to the gckOS object.
6546 ** gctPOINTER * Semaphore
6547 ** Pointer to the variable that will receive the created semaphore.
6550 gckOS_CreateSemaphore(
6552 OUT gctPOINTER * Semaphore
6556 struct semaphore *sem = gcvNULL;
6558 gcmkHEADER_ARG("Os=0x%X", Os);
6560 /* Verify the arguments. */
6561 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6562 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6564 /* Allocate the semaphore structure. */
6565 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6568 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6571 /* Initialize the semaphore. */
6574 /* Return to caller. */
6575 *Semaphore = (gctPOINTER) sem;
6579 return gcvSTATUS_OK;
6582 /* Return the status. */
6587 /*******************************************************************************
6589 ** gckOS_AcquireSemaphore
6591 ** Acquire a semaphore.
6596 ** Pointer to the gckOS object.
6598 ** gctPOINTER Semaphore
6599 ** Pointer to the semaphore thet needs to be acquired.
6606 gckOS_AcquireSemaphore(
6608 IN gctPOINTER Semaphore
6613 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6615 /* Verify the arguments. */
6616 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6617 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6619 /* Acquire the semaphore. */
6620 if (down_interruptible((struct semaphore *) Semaphore))
6622 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6627 return gcvSTATUS_OK;
6630 /* Return the status. */
6635 /*******************************************************************************
6637 ** gckOS_TryAcquireSemaphore
6639 ** Try to acquire a semaphore.
6644 ** Pointer to the gckOS object.
6646 ** gctPOINTER Semaphore
6647 ** Pointer to the semaphore thet needs to be acquired.
6654 gckOS_TryAcquireSemaphore(
6656 IN gctPOINTER Semaphore
6661 gcmkHEADER_ARG("Os=0x%x", Os);
6663 /* Verify the arguments. */
6664 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6665 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6667 /* Acquire the semaphore. */
6668 if (down_trylock((struct semaphore *) Semaphore))
6671 status = gcvSTATUS_TIMEOUT;
6678 return gcvSTATUS_OK;
6681 /*******************************************************************************
6683 ** gckOS_ReleaseSemaphore
6685 ** Release a previously acquired semaphore.
6690 ** Pointer to the gckOS object.
6692 ** gctPOINTER Semaphore
6693 ** Pointer to the semaphore thet needs to be released.
6700 gckOS_ReleaseSemaphore(
6702 IN gctPOINTER Semaphore
6705 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6707 /* Verify the arguments. */
6708 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6709 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6711 /* Release the semaphore. */
6712 up((struct semaphore *) Semaphore);
6716 return gcvSTATUS_OK;
6719 /*******************************************************************************
6721 ** gckOS_DestroySemaphore
6723 ** Destroy a semaphore.
6728 ** Pointer to the gckOS object.
6730 ** gctPOINTER Semaphore
6731 ** Pointer to the semaphore thet needs to be destroyed.
6738 gckOS_DestroySemaphore(
6740 IN gctPOINTER Semaphore
6743 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6745 /* Verify the arguments. */
6746 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6747 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6749 /* Free the sempahore structure. */
6754 return gcvSTATUS_OK;
6757 /*******************************************************************************
6759 ** gckOS_GetProcessID
6761 ** Get current process ID.
6769 ** gctUINT32_PTR ProcessID
6770 ** Pointer to the variable that receives the process ID.
6774 OUT gctUINT32_PTR ProcessID
6777 /* Get process ID. */
6778 if (ProcessID != gcvNULL)
6780 *ProcessID = _GetProcessID();
6784 return gcvSTATUS_OK;
6787 /*******************************************************************************
6789 ** gckOS_GetThreadID
6791 ** Get current thread ID.
6799 ** gctUINT32_PTR ThreadID
6800 ** Pointer to the variable that receives the thread ID.
6804 OUT gctUINT32_PTR ThreadID
6807 /* Get thread ID. */
6808 if (ThreadID != gcvNULL)
6810 *ThreadID = _GetThreadID();
6814 return gcvSTATUS_OK;
6817 /*******************************************************************************
6819 ** gckOS_SetGPUPower
6821 ** Set the power of the GPU on or off.
6826 ** Pointer to a gckOS object.
6829 ** GPU whose power is set.
6832 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6835 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6849 struct clk *clk_3dcore = Os->device->clk_3d_core;
6850 struct clk *clk_3dshader = Os->device->clk_3d_shader;
6851 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
6852 struct clk *clk_3d_axi = Os->device->clk_3d_axi;
6854 struct clk *clk_2dcore = Os->device->clk_2d_core;
6855 struct clk *clk_2d_axi = Os->device->clk_2d_axi;
6856 struct clk *clk_vg_axi = Os->device->clk_vg_axi;
6857 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6861 gctBOOL oldClockState = gcvFALSE;
6862 gctBOOL oldPowerState = gcvFALSE;
6864 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6866 if (Os->device->kernels[Core] != NULL)
6869 if (Core == gcvCORE_VG)
6871 oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
6872 oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
6877 oldClockState = Os->device->kernels[Core]->hardware->clockState;
6878 oldPowerState = Os->device->kernels[Core]->hardware->powerState;
6883 if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
6885 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6886 if(!IS_ERR(Os->device->gpu_regulator)) {
6887 ret = regulator_enable(Os->device->gpu_regulator);
6889 gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
6890 __FUNCTION__, __LINE__, ret);
6893 imx_gpc_power_up_pu(true);
6897 pm_runtime_get_sync(Os->device->pmdev);
6901 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6902 if (Clock == gcvTRUE) {
6903 if (oldClockState == gcvFALSE) {
6906 clk_enable(clk_3dcore);
6908 clk_enable(clk_3dshader);
6911 clk_enable(clk_2dcore);
6912 clk_enable(clk_2d_axi);
6915 clk_enable(clk_2dcore);
6916 clk_enable(clk_vg_axi);
6923 if (oldClockState == gcvTRUE) {
6927 clk_disable(clk_3dshader);
6928 clk_disable(clk_3dcore);
6931 clk_disable(clk_2dcore);
6932 clk_disable(clk_2d_axi);
6935 clk_disable(clk_2dcore);
6936 clk_disable(clk_vg_axi);
6944 if (Clock == gcvTRUE) {
6945 if (oldClockState == gcvFALSE) {
6948 clk_prepare(clk_3dcore);
6949 clk_enable(clk_3dcore);
6950 clk_prepare(clk_3dshader);
6951 clk_enable(clk_3dshader);
6952 clk_prepare(clk_3d_axi);
6953 clk_enable(clk_3d_axi);
6956 clk_prepare(clk_2dcore);
6957 clk_enable(clk_2dcore);
6958 clk_prepare(clk_2d_axi);
6959 clk_enable(clk_2d_axi);
6962 clk_prepare(clk_2dcore);
6963 clk_enable(clk_2dcore);
6964 clk_prepare(clk_vg_axi);
6965 clk_enable(clk_vg_axi);
6972 if (oldClockState == gcvTRUE) {
6975 clk_disable(clk_3dshader);
6976 clk_unprepare(clk_3dshader);
6977 clk_disable(clk_3dcore);
6978 clk_unprepare(clk_3dcore);
6979 clk_disable(clk_3d_axi);
6980 clk_unprepare(clk_3d_axi);
6983 clk_disable(clk_2dcore);
6984 clk_unprepare(clk_2dcore);
6985 clk_disable(clk_2d_axi);
6986 clk_unprepare(clk_2d_axi);
6989 clk_disable(clk_2dcore);
6990 clk_unprepare(clk_2dcore);
6991 clk_disable(clk_vg_axi);
6992 clk_unprepare(clk_vg_axi);
7000 if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
7003 pm_runtime_put_sync(Os->device->pmdev);
7006 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7007 if(!IS_ERR(Os->device->gpu_regulator))
7008 regulator_disable(Os->device->gpu_regulator);
7010 imx_gpc_power_up_pu(false);
7014 /* TODO: Put your code here. */
7016 return gcvSTATUS_OK;
7019 /*******************************************************************************
7028 ** Pointer to a gckOS object.
7031 ** GPU whose power is set.
7043 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7044 #define SRC_SCR_OFFSET 0
7045 #define BP_SRC_SCR_GPU3D_RST 1
7046 #define BP_SRC_SCR_GPU2D_RST 4
7047 void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
7048 gctUINT32 bit_offset,val;
7050 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
7052 if(Core == gcvCORE_MAJOR) {
7053 bit_offset = BP_SRC_SCR_GPU3D_RST;
7054 } else if((Core == gcvCORE_VG)
7055 ||(Core == gcvCORE_2D)) {
7056 bit_offset = BP_SRC_SCR_GPU2D_RST;
7058 return gcvSTATUS_INVALID_CONFIG;
7060 val = __raw_readl(src_base + SRC_SCR_OFFSET);
7061 val &= ~(1 << (bit_offset));
7062 val |= (1 << (bit_offset));
7063 __raw_writel(val, src_base + SRC_SCR_OFFSET);
7065 while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
7066 (1 << (bit_offset))) != 0) {
7070 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7071 struct reset_control *rstc = Os->device->rstc[Core];
7073 reset_control_reset(rstc);
7075 imx_src_reset_gpu((int)Core);
7077 return gcvSTATUS_OK;
7080 /*******************************************************************************
7082 ** gckOS_PrepareGPUFrequency
7084 ** Prepare to set GPU frequency and voltage.
7089 ** Pointer to a gckOS object.
7092 ** GPU whose frequency and voltage will be set.
7099 gckOS_PrepareGPUFrequency(
7104 return gcvSTATUS_OK;
7107 /*******************************************************************************
7109 ** gckOS_FinishGPUFrequency
7111 ** Finish GPU frequency setting.
7116 ** Pointer to a gckOS object.
7119 ** GPU whose frequency and voltage is set.
7126 gckOS_FinishGPUFrequency(
7131 return gcvSTATUS_OK;
7134 /*******************************************************************************
7136 ** gckOS_QueryGPUFrequency
7138 ** Query the current frequency of the GPU.
7143 ** Pointer to a gckOS object.
7146 ** GPU whose power is set.
7148 ** gctUINT32 * Frequency
7149 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
7152 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
7159 gckOS_QueryGPUFrequency(
7162 OUT gctUINT32 * Frequency,
7163 OUT gctUINT8 * Scale
7166 return gcvSTATUS_OK;
7169 /*******************************************************************************
7171 ** gckOS_SetGPUFrequency
7173 ** Set frequency and voltage of the GPU.
7175 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
7176 ** a real frequency according to this scale and board's configure.
7178 ** 2. BSP should find a suitable voltage for this frequency.
7180 ** 3. BSP must make sure setting take effect before this function returns.
7185 ** Pointer to a gckOS object.
7188 ** GPU whose power is set.
7191 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
7192 ** full frequency and 64 means 64/64 of full frequency.
7199 gckOS_SetGPUFrequency(
7205 return gcvSTATUS_OK;
7208 /*----------------------------------------------------------------------------*/
7209 /*----- Profile --------------------------------------------------------------*/
7212 gckOS_GetProfileTick(
7213 OUT gctUINT64_PTR Tick
7216 struct timespec time;
7218 ktime_get_ts(&time);
7220 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
7222 return gcvSTATUS_OK;
7226 gckOS_QueryProfileTickRate(
7227 OUT gctUINT64_PTR TickRate
7230 struct timespec res;
7232 hrtimer_get_res(CLOCK_MONOTONIC, &res);
7234 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
7236 return gcvSTATUS_OK;
7244 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
7245 return div_u64(Ticks, 1000000);
7247 gctUINT64 rem = Ticks;
7248 gctUINT64 b = 1000000;
7249 gctUINT64 res, d = 1;
7250 gctUINT32 high = rem >> 32;
7252 /* Reduce the thing a bit first */
7254 if (high >= 1000000)
7257 res = (gctUINT64) high << 32;
7258 rem -= (gctUINT64) (high * 1000000) << 32;
7261 while (((gctINT64) b > 0) && (b < rem))
7280 return (gctUINT32) res;
7284 /******************************************************************************\
7285 ******************************* Signal Management ******************************
7286 \******************************************************************************/
7289 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
7291 /*******************************************************************************
7293 ** gckOS_CreateSignal
7295 ** Create a new signal.
7300 ** Pointer to an gckOS object.
7302 ** gctBOOL ManualReset
7303 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7304 ** order to set the signal to nonsignaled state.
7305 ** If set to gcvFALSE, the signal will automatically be set to
7306 ** nonsignaled state by gckOS_WaitSignal function.
7310 ** gctSIGNAL * Signal
7311 ** Pointer to a variable receiving the created gctSIGNAL.
7316 IN gctBOOL ManualReset,
7317 OUT gctSIGNAL * Signal
7321 gcsSIGNAL_PTR signal;
7323 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
7325 /* Verify the arguments. */
7326 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7327 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7329 /* Create an event structure. */
7330 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
7332 if (signal == gcvNULL)
7334 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7337 /* Save the process ID. */
7338 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
7339 signal->manualReset = ManualReset;
7340 signal->hardware = gcvNULL;
7341 init_completion(&signal->obj);
7342 atomic_set(&signal->ref, 1);
7344 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
7346 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
7348 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
7349 return gcvSTATUS_OK;
7352 if (signal != gcvNULL)
7362 gckOS_SignalQueryHardware(
7364 IN gctSIGNAL Signal,
7365 OUT gckHARDWARE * Hardware
7369 gcsSIGNAL_PTR signal;
7371 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7373 /* Verify the arguments. */
7374 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7375 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7376 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7378 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7380 *Hardware = signal->hardware;
7383 return gcvSTATUS_OK;
7390 gckOS_SignalSetHardware(
7392 IN gctSIGNAL Signal,
7393 IN gckHARDWARE Hardware
7397 gcsSIGNAL_PTR signal;
7399 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7401 /* Verify the arguments. */
7402 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7403 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7405 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7407 signal->hardware = Hardware;
7410 return gcvSTATUS_OK;
7416 /*******************************************************************************
7418 ** gckOS_DestroySignal
7420 ** Destroy a signal.
7425 ** Pointer to an gckOS object.
7428 ** Pointer to the gctSIGNAL.
7435 gckOS_DestroySignal(
7441 gcsSIGNAL_PTR signal;
7442 gctBOOL acquired = gcvFALSE;
7444 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7446 /* Verify the arguments. */
7447 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7448 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7450 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7453 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7455 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7457 if (atomic_dec_and_test(&signal->ref))
7459 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7461 /* Free the sgianl. */
7465 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7466 acquired = gcvFALSE;
7470 return gcvSTATUS_OK;
7475 /* Release the mutex. */
7476 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7483 /*******************************************************************************
7487 ** Set a state of the specified signal.
7492 ** Pointer to an gckOS object.
7495 ** Pointer to the gctSIGNAL.
7498 ** If gcvTRUE, the signal will be set to signaled state.
7499 ** If gcvFALSE, the signal will be set to nonsignaled state.
7508 IN gctSIGNAL Signal,
7513 gcsSIGNAL_PTR signal;
7514 gctBOOL acquired = gcvFALSE;
7516 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7518 /* Verify the arguments. */
7519 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7520 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7522 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7525 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7527 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7531 /* unbind the signal from hardware. */
7532 signal->hardware = gcvNULL;
7534 /* Set the event to a signaled state. */
7535 complete(&signal->obj);
7539 /* Set the event to an unsignaled state. */
7540 INIT_COMPLETION(signal->obj);
7543 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7544 acquired = gcvFALSE;
7548 return gcvSTATUS_OK;
7553 /* Release the mutex. */
7554 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7565 IN gctHANDLE Process,
7571 struct task_struct * userTask;
7572 struct siginfo info;
7574 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7576 if (userTask != gcvNULL)
7579 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7582 info.si_ptr = (gctPOINTER) Signal;
7584 /* Signals with numbers between 32 and 63 are real-time,
7585 send a real-time signal to the user process. */
7586 result = send_sig_info(48, &info, userTask);
7588 printk("gckOS_SetSignalVG:0x%x\n", result);
7592 status = gcvSTATUS_GENERIC_IO;
7596 "%s(%d): an error has occurred.\n",
7597 __FUNCTION__, __LINE__
7602 status = gcvSTATUS_OK;
7607 status = gcvSTATUS_GENERIC_IO;
7611 "%s(%d): an error has occurred.\n",
7612 __FUNCTION__, __LINE__
7616 /* Return status. */
7621 /*******************************************************************************
7625 ** Set the specified signal which is owned by a process to signaled state.
7630 ** Pointer to an gckOS object.
7633 ** Pointer to the gctSIGNAL.
7635 ** gctHANDLE Process
7636 ** Handle of process owning the signal.
7645 IN gctSIGNAL Signal,
7646 IN gctHANDLE Process
7652 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7653 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7655 /* Map the signal into kernel space. */
7656 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7659 status = gckOS_Signal(Os, signal, gcvTRUE);
7661 /* Unmap the signal */
7662 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7668 /* Return the status. */
7673 /*******************************************************************************
7677 ** Wait for a signal to become signaled.
7682 ** Pointer to an gckOS object.
7685 ** Pointer to the gctSIGNAL.
7688 ** Number of milliseconds to wait.
7689 ** Pass the value of gcvINFINITE for an infinite wait.
7698 IN gctSIGNAL Signal,
7702 gceSTATUS status = gcvSTATUS_OK;
7703 gcsSIGNAL_PTR signal;
7705 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7707 /* Verify the arguments. */
7708 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7709 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7711 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7713 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7717 spin_lock_irq(&signal->obj.wait.lock);
7719 if (signal->obj.done)
7721 if (!signal->manualReset)
7723 signal->obj.done = 0;
7726 status = gcvSTATUS_OK;
7730 status = gcvSTATUS_TIMEOUT;
7734 /* Convert wait to milliseconds. */
7735 #if gcdDETECT_TIMEOUT
7736 gctINT timeout = (Wait == gcvINFINITE)
7737 ? gcdINFINITE_TIMEOUT * HZ / 1000
7740 gctUINT complained = 0;
7742 gctINT timeout = (Wait == gcvINFINITE)
7743 ? MAX_SCHEDULE_TIMEOUT
7747 DECLARE_WAITQUEUE(wait, current);
7748 wait.flags |= WQ_FLAG_EXCLUSIVE;
7749 __add_wait_queue_tail(&signal->obj.wait, &wait);
7753 if (signal_pending(current))
7755 /* Interrupt received. */
7756 status = gcvSTATUS_INTERRUPTED;
7760 __set_current_state(TASK_INTERRUPTIBLE);
7761 spin_unlock_irq(&signal->obj.wait.lock);
7762 timeout = schedule_timeout(timeout);
7763 spin_lock_irq(&signal->obj.wait.lock);
7765 if (signal->obj.done)
7767 if (!signal->manualReset)
7769 signal->obj.done = 0;
7772 status = gcvSTATUS_OK;
7776 #if gcdDETECT_TIMEOUT
7777 if ((Wait == gcvINFINITE) && (timeout == 0))
7779 gctUINT32 dmaAddress1, dmaAddress2;
7780 gctUINT32 dmaState1, dmaState2;
7782 dmaState1 = dmaState2 =
7783 dmaAddress1 = dmaAddress2 = 0;
7785 /* Verify whether DMA is running. */
7786 gcmkVERIFY_OK(_VerifyDMA(
7787 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7790 #if gcdDETECT_DMA_ADDRESS
7791 /* Dump only if DMA appears stuck. */
7793 (dmaAddress1 == dmaAddress2)
7794 #if gcdDETECT_DMA_STATE
7795 && (dmaState1 == dmaState2)
7800 /* Increment complain count. */
7803 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
7806 "%s(%d): signal 0x%X; forced message flush (%d).",
7807 __FUNCTION__, __LINE__, Signal, complained
7810 /* Flush the debug cache. */
7811 gcmkDEBUGFLUSH(dmaAddress2);
7814 /* Reset timeout. */
7815 timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
7822 status = gcvSTATUS_TIMEOUT;
7827 __remove_wait_queue(&signal->obj.wait, &wait);
7829 #if gcdDETECT_TIMEOUT
7833 "%s(%d): signal=0x%X; waiting done; status=%d",
7834 __FUNCTION__, __LINE__, Signal, status
7840 spin_unlock_irq(&signal->obj.wait.lock);
7843 /* Return status. */
7844 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7848 /*******************************************************************************
7852 ** Map a signal in to the current process space.
7857 ** Pointer to an gckOS object.
7860 ** Pointer to tha gctSIGNAL to map.
7862 ** gctHANDLE Process
7863 ** Handle of process owning the signal.
7867 ** gctSIGNAL * MappedSignal
7868 ** Pointer to a variable receiving the mapped gctSIGNAL.
7873 IN gctSIGNAL Signal,
7874 IN gctHANDLE Process,
7875 OUT gctSIGNAL * MappedSignal
7879 gcsSIGNAL_PTR signal;
7880 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7882 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7883 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7885 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7887 if(atomic_inc_return(&signal->ref) <= 1)
7889 /* The previous value is 0, it has been deleted. */
7890 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7893 *MappedSignal = (gctSIGNAL) Signal;
7896 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
7897 return gcvSTATUS_OK;
7904 /*******************************************************************************
7906 ** gckOS_UnmapSignal
7913 ** Pointer to an gckOS object.
7916 ** Pointer to that gctSIGNAL mapped.
7924 return gckOS_DestroySignal(Os, Signal);
7927 /*******************************************************************************
7929 ** gckOS_CreateUserSignal
7931 ** Create a new signal to be used in the user space.
7936 ** Pointer to an gckOS object.
7938 ** gctBOOL ManualReset
7939 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7940 ** order to set the signal to nonsignaled state.
7941 ** If set to gcvFALSE, the signal will automatically be set to
7942 ** nonsignaled state by gckOS_WaitSignal function.
7946 ** gctINT * SignalID
7947 ** Pointer to a variable receiving the created signal's ID.
7950 gckOS_CreateUserSignal(
7952 IN gctBOOL ManualReset,
7953 OUT gctINT * SignalID
7959 /* Create a new signal. */
7960 status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
7961 *SignalID = (gctINT) signal;
7966 /*******************************************************************************
7968 ** gckOS_DestroyUserSignal
7970 ** Destroy a signal to be used in the user space.
7975 ** Pointer to an gckOS object.
7985 gckOS_DestroyUserSignal(
7990 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
7993 /*******************************************************************************
7995 ** gckOS_WaitUserSignal
7997 ** Wait for a signal used in the user mode to become signaled.
8002 ** Pointer to an gckOS object.
8008 ** Number of milliseconds to wait.
8009 ** Pass the value of gcvINFINITE for an infinite wait.
8016 gckOS_WaitUserSignal(
8022 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
8025 /*******************************************************************************
8027 ** gckOS_SignalUserSignal
8029 ** Set a state of the specified signal to be used in the user space.
8034 ** Pointer to an gckOS object.
8040 ** If gcvTRUE, the signal will be set to signaled state.
8041 ** If gcvFALSE, the signal will be set to nonsignaled state.
8048 gckOS_SignalUserSignal(
8054 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
8059 gckOS_CreateSemaphoreVG(
8061 OUT gctSEMAPHORE * Semaphore
8065 struct semaphore * newSemaphore;
8067 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8068 /* Verify the arguments. */
8069 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8070 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8074 /* Allocate the semaphore structure. */
8075 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
8076 if (newSemaphore == gcvNULL)
8078 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
8081 /* Initialize the semaphore. */
8082 sema_init(newSemaphore, 0);
8084 /* Set the handle. */
8085 * Semaphore = (gctSEMAPHORE) newSemaphore;
8088 status = gcvSTATUS_OK;
8093 /* Return the status. */
8099 gckOS_IncrementSemaphore(
8101 IN gctSEMAPHORE Semaphore
8104 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8105 /* Verify the arguments. */
8106 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8107 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8109 /* Increment the semaphore's count. */
8110 up((struct semaphore *) Semaphore);
8114 return gcvSTATUS_OK;
8118 gckOS_DecrementSemaphore(
8120 IN gctSEMAPHORE Semaphore
8126 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8127 /* Verify the arguments. */
8128 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8129 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8133 /* Decrement the semaphore's count. If the count is zero, wait
8134 until it gets incremented. */
8135 result = down_interruptible((struct semaphore *) Semaphore);
8137 /* Signal received? */
8140 status = gcvSTATUS_TERMINATE;
8145 status = gcvSTATUS_OK;
8150 /* Return the status. */
8154 /*******************************************************************************
8158 ** Set the specified signal to signaled state.
8163 ** Pointer to the gckOS object.
8165 ** gctHANDLE Process
8166 ** Handle of process owning the signal.
8169 ** Pointer to the gctSIGNAL.
8178 IN gctHANDLE Process,
8184 struct task_struct * userTask;
8185 struct siginfo info;
8187 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
8189 if (userTask != gcvNULL)
8192 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
8195 info.si_ptr = (gctPOINTER) Signal;
8197 /* Signals with numbers between 32 and 63 are real-time,
8198 send a real-time signal to the user process. */
8199 result = send_sig_info(48, &info, userTask);
8204 status = gcvSTATUS_GENERIC_IO;
8208 "%s(%d): an error has occurred.\n",
8209 __FUNCTION__, __LINE__
8214 status = gcvSTATUS_OK;
8219 status = gcvSTATUS_GENERIC_IO;
8223 "%s(%d): an error has occurred.\n",
8224 __FUNCTION__, __LINE__
8228 /* Return status. */
8232 /******************************************************************************\
8233 ******************************** Thread Object *********************************
8234 \******************************************************************************/
8239 IN gctTHREADFUNC ThreadFunction,
8240 IN gctPOINTER ThreadParameter,
8241 OUT gctTHREAD * Thread
8245 struct task_struct * thread;
8247 gcmkHEADER_ARG("Os=0x%X ", Os);
8248 /* Verify the arguments. */
8249 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8250 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
8251 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8255 /* Create the thread. */
8256 thread = kthread_create(
8259 "Vivante Kernel Thread"
8265 status = gcvSTATUS_GENERIC_IO;
8269 /* Start the thread. */
8270 wake_up_process(thread);
8272 /* Set the thread handle. */
8273 * Thread = (gctTHREAD) thread;
8276 status = gcvSTATUS_OK;
8281 /* Return the status. */
8291 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8292 /* Verify the arguments. */
8293 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8294 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8296 /* Thread should have already been enabled to terminate. */
8297 kthread_stop((struct task_struct *) Thread);
8301 return gcvSTATUS_OK;
8310 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8311 /* Verify the arguments. */
8312 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8313 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8317 return gcvSTATUS_OK;
8321 /******************************************************************************\
8322 ******************************** Software Timer ********************************
8323 \******************************************************************************/
8327 struct work_struct * work
8330 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
8332 gctTIMERFUNCTION function = timer->function;
8334 function(timer->data);
8337 /*******************************************************************************
8339 ** gckOS_CreateTimer
8341 ** Create a software timer.
8346 ** Pointer to the gckOS object.
8348 ** gctTIMERFUNCTION Function.
8349 ** Pointer to a call back function which will be called when timer is
8353 ** Private data which will be passed to call back function.
8357 ** gctPOINTER * Timer
8358 ** Pointer to a variable receiving the created timer.
8363 IN gctTIMERFUNCTION Function,
8365 OUT gctPOINTER * Timer
8369 gcsOSTIMER_PTR pointer;
8370 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
8372 /* Verify the arguments. */
8373 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8374 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8376 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
8378 pointer->function = Function;
8379 pointer->data = Data;
8381 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
8386 return gcvSTATUS_OK;
8393 /*******************************************************************************
8395 ** gckOS_DestroyTimer
8397 ** Destory a software timer.
8402 ** Pointer to the gckOS object.
8405 ** Pointer to the timer to be destoryed.
8417 gcsOSTIMER_PTR timer;
8418 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8420 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8421 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8423 timer = (gcsOSTIMER_PTR)Timer;
8425 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8426 cancel_delayed_work_sync(&timer->work);
8428 cancel_delayed_work(&timer->work);
8429 flush_workqueue(Os->workqueue);
8432 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8435 return gcvSTATUS_OK;
8438 /*******************************************************************************
8442 ** Schedule a software timer.
8447 ** Pointer to the gckOS object.
8450 ** Pointer to the timer to be scheduled.
8453 ** Delay in milliseconds.
8462 IN gctPOINTER Timer,
8466 gcsOSTIMER_PTR timer;
8468 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8470 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8471 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8472 gcmkVERIFY_ARGUMENT(Delay != 0);
8474 timer = (gcsOSTIMER_PTR)Timer;
8476 if (unlikely(delayed_work_pending(&timer->work)))
8478 cancel_delayed_work(&timer->work);
8481 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8484 return gcvSTATUS_OK;
8487 /*******************************************************************************
8491 ** Cancel a unscheduled timer.
8496 ** Pointer to the gckOS object.
8499 ** Pointer to the timer to be cancel.
8511 gcsOSTIMER_PTR timer;
8512 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8514 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8515 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8517 timer = (gcsOSTIMER_PTR)Timer;
8519 cancel_delayed_work(&timer->work);
8522 return gcvSTATUS_OK;
8527 gckOS_DumpCallStack(
8531 gcmkHEADER_ARG("Os=0x%X", Os);
8533 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8538 return gcvSTATUS_OK;
8543 gckOS_GetProcessNameByPid(
8545 IN gctSIZE_T Length,
8546 OUT gctUINT8_PTR String
8549 struct task_struct *task;
8551 /* Get the task_struct of the task with pid. */
8554 task = FIND_TASK_BY_PID(Pid);
8556 if (task == gcvNULL)
8559 return gcvSTATUS_NOT_FOUND;
8562 /* Get name of process. */
8563 strncpy(String, task->comm, Length);
8567 return gcvSTATUS_OK;