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 static inline void imx_gpc_power_up_pu(bool flag) {}
43 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
44 #include <mach/common.h>
46 #include <linux/delay.h>
47 #include <linux/pm_runtime.h>
50 #define _GC_OBJ_ZONE gcvZONE_OS
52 /*******************************************************************************
53 ***** Version Signature *******************************************************/
56 const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
58 const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
61 #define USER_SIGNAL_TABLE_LEN_INIT 64
62 #define gcdSUPPRESS_OOM_MESSAGE 1
64 #define MEMORY_LOCK(os) \
65 gcmkVERIFY_OK(gckOS_AcquireMutex( \
70 #define MEMORY_UNLOCK(os) \
71 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
73 #define MEMORY_MAP_LOCK(os) \
74 gcmkVERIFY_OK(gckOS_AcquireMutex( \
76 (os)->memoryMapLock, \
79 #define MEMORY_MAP_UNLOCK(os) \
80 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
82 /* Protection bit when mapping memroy to user sapce */
83 #define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
85 #if gcdNONPAGED_MEMORY_BUFFERABLE
86 #define gcmkIOREMAP ioremap_wc
87 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
88 #elif !gcdNONPAGED_MEMORY_CACHEABLE
89 #define gcmkIOREMAP ioremap_nocache
90 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
93 #if gcdSUPPRESS_OOM_MESSAGE
94 #define gcdNOWARN __GFP_NOWARN
99 #define gcdINFINITE_TIMEOUT (60 * 1000)
100 #define gcdDETECT_TIMEOUT 0
101 #define gcdDETECT_DMA_ADDRESS 1
102 #define gcdDETECT_DMA_STATE 1
104 #define gcdUSE_NON_PAGED_MEMORY_CACHE 10
106 /******************************************************************************\
107 ********************************** Structures **********************************
108 \******************************************************************************/
109 #if gcdUSE_NON_PAGED_MEMORY_CACHE
110 typedef struct _gcsNonPagedMemoryCache
112 #ifndef NO_DMA_COHERENT
115 dma_addr_t dmaHandle;
121 struct _gcsNonPagedMemoryCache * prev;
122 struct _gcsNonPagedMemoryCache * next;
124 gcsNonPagedMemoryCache;
125 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
127 typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
128 typedef struct _gcsUSER_MAPPING
130 /* Pointer to next mapping structure. */
131 gcsUSER_MAPPING_PTR next;
133 /* Physical address of this mapping. */
136 /* Logical address of this mapping. */
139 /* Number of bytes of this mapping. */
142 /* Starting address of this mapping. */
145 /* Ending address of this mapping. */
150 typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
151 typedef struct _gcsINTEGER_DB
166 /* Pointer to device */
169 /* Memory management */
170 gctPOINTER memoryLock;
171 gctPOINTER memoryMapLock;
173 struct _LINUX_MDL *mdlHead;
174 struct _LINUX_MDL *mdlTail;
176 /* Kernel process ID. */
177 gctUINT32 kernelProcessID;
179 /* Signal management. */
182 gctPOINTER signalMutex;
184 /* signal id database. */
185 gcsINTEGER_DB signalDB;
187 gcsUSER_MAPPING_PTR userMap;
188 gctPOINTER debugLock;
190 #if gcdUSE_NON_PAGED_MEMORY_CACHE
192 gcsNonPagedMemoryCache * cacheHead;
193 gcsNonPagedMemoryCache * cacheTail;
196 /* workqueue for os timer. */
197 struct workqueue_struct * workqueue;
200 typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
201 typedef struct _gcsSIGNAL
203 /* Kernel sync primitive. */
204 struct completion obj;
206 /* Manual reset flag. */
209 /* The reference counter. */
212 /* The owner of the signal. */
215 gckHARDWARE hardware;
222 typedef struct _gcsPageInfo * gcsPageInfo_PTR;
223 typedef struct _gcsPageInfo
226 gctUINT32_PTR pageTable;
230 typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
231 typedef struct _gcsOSTIMER
233 struct delayed_work work;
234 gctTIMERFUNCTION function;
238 /******************************************************************************\
239 ******************************* Private Functions ******************************
240 \******************************************************************************/
247 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
248 return task_tgid_vnr(current);
250 return current->tgid;
259 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
260 return task_pid_vnr(current);
273 gcmkHEADER_ARG("ProcessID=%d", ProcessID);
275 mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
282 mdl->pid = ProcessID;
287 gcmkFOOTER_ARG("0x%X", mdl);
294 IN PLINUX_MDL_MAP MdlMap
302 PLINUX_MDL_MAP mdlMap, next;
304 gcmkHEADER_ARG("Mdl=0x%X", Mdl);
306 /* Verify the arguments. */
307 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
311 while (mdlMap != gcvNULL)
315 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
326 static PLINUX_MDL_MAP
332 PLINUX_MDL_MAP mdlMap;
334 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
336 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
337 if (mdlMap == gcvNULL)
343 mdlMap->pid = ProcessID;
344 mdlMap->vmaAddr = gcvNULL;
345 mdlMap->vma = gcvNULL;
347 mdlMap->next = Mdl->maps;
350 gcmkFOOTER_ARG("0x%X", mdlMap);
357 IN PLINUX_MDL_MAP MdlMap
360 PLINUX_MDL_MAP prevMdlMap;
362 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
364 /* Verify the arguments. */
365 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
366 gcmkASSERT(Mdl->maps != gcvNULL);
368 if (Mdl->maps == MdlMap)
370 Mdl->maps = MdlMap->next;
374 prevMdlMap = Mdl->maps;
376 while (prevMdlMap->next != MdlMap)
378 prevMdlMap = prevMdlMap->next;
380 gcmkASSERT(prevMdlMap != gcvNULL);
383 prevMdlMap->next = MdlMap->next;
392 extern PLINUX_MDL_MAP
398 PLINUX_MDL_MAP mdlMap;
400 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
408 while (mdlMap != gcvNULL)
410 if (mdlMap->pid == ProcessID)
412 gcmkFOOTER_ARG("0x%X", mdlMap);
416 mdlMap = mdlMap->next;
431 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
437 unsigned long addr = (unsigned long)Addr;
439 return addr >= VMALLOC_START && addr < VMALLOC_END;
445 IN struct page ** Pages,
446 IN gctUINT32 NumPages
451 gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
453 gcmkASSERT(Pages != gcvNULL);
455 for (i = 0; i < NumPages; i++)
457 __free_page(Pages[i]);
460 if (is_vmalloc_addr(Pages))
472 static struct page **
474 IN gctUINT32 NumPages
477 struct page ** pages;
481 gcmkHEADER_ARG("NumPages=%lu", NumPages);
483 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
484 if (NumPages > totalram_pages)
486 if (NumPages > num_physpages)
493 size = NumPages * sizeof(struct page *);
495 pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
499 pages = vmalloc(size);
508 for (i = 0; i < NumPages; i++)
510 p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
514 _NonContiguousFree(pages, i);
522 gcmkFOOTER_ARG("pages=0x%X", pages);
526 static inline struct page *
527 _NonContiguousToPage(
528 IN struct page ** Pages,
532 gcmkASSERT(Pages != gcvNULL);
536 static inline unsigned long
538 IN struct page ** Pages,
542 gcmkASSERT(Pages != gcvNULL);
543 return page_to_pfn(_NonContiguousToPage(Pages, Index));
546 static inline unsigned long
547 _NonContiguousToPhys(
548 IN struct page ** Pages,
552 gcmkASSERT(Pages != gcvNULL);
553 return page_to_phys(_NonContiguousToPage(Pages, Index));
557 #if gcdUSE_NON_PAGED_MEMORY_CACHE
560 _AddNonPagedMemoryCache(
562 #ifndef NO_DMA_COHERENT
572 gcsNonPagedMemoryCache *cache;
574 if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
579 /* Allocate the cache record */
580 cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
582 if (cache == gcvNULL) return gcvFALSE;
584 #ifndef NO_DMA_COHERENT
587 cache->dmaHandle = DmaHandle;
589 cache->order = Order;
594 if (Os->cacheHead == gcvNULL)
596 cache->prev = gcvNULL;
597 cache->next = gcvNULL;
599 Os->cacheTail = cache;
603 /* Add to the tail. */
604 cache->prev = Os->cacheTail;
605 cache->next = gcvNULL;
606 Os->cacheTail->next = cache;
607 Os->cacheTail = cache;
615 #ifndef NO_DMA_COHERENT
617 _GetNonPagedMemoryCache(
620 dma_addr_t * DmaHandle
624 _GetNonPagedMemoryCache(
630 gcsNonPagedMemoryCache *cache;
631 #ifndef NO_DMA_COHERENT
637 if (Os->cacheHead == gcvNULL) return gcvNULL;
639 /* Find the right cache */
640 cache = Os->cacheHead;
642 while (cache != gcvNULL)
644 #ifndef NO_DMA_COHERENT
645 if (cache->size == Size) break;
647 if (cache->order == Order) break;
653 if (cache == gcvNULL) return gcvNULL;
655 /* Remove the cache from list */
656 if (cache == Os->cacheHead)
658 Os->cacheHead = cache->next;
660 if (Os->cacheHead == gcvNULL)
662 Os->cacheTail = gcvNULL;
667 cache->prev->next = cache->next;
669 if (cache == Os->cacheTail)
671 Os->cacheTail = cache->prev;
675 cache->next->prev = cache->prev;
680 #ifndef NO_DMA_COHERENT
682 *DmaHandle = cache->dmaHandle;
691 #ifndef NO_DMA_COHERENT
699 _FreeAllNonPagedMemoryCache(
703 gcsNonPagedMemoryCache *cache, *nextCache;
707 cache = Os->cacheHead;
709 while (cache != gcvNULL)
711 if (cache != Os->cacheTail)
713 nextCache = cache->next;
720 /* Remove the cache from list */
721 if (cache == Os->cacheHead)
723 Os->cacheHead = cache->next;
725 if (Os->cacheHead == gcvNULL)
727 Os->cacheTail = gcvNULL;
732 cache->prev->next = cache->next;
734 if (cache == Os->cacheTail)
736 Os->cacheTail = cache->prev;
740 cache->next->prev = cache->prev;
744 #ifndef NO_DMA_COHERENT
745 dma_free_coherent(gcvNULL,
750 free_pages((unsigned long)page_address(cache->page), cache->order);
761 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
763 /*******************************************************************************
764 ** Integer Id Management.
768 IN gcsINTEGER_DB_PTR Database,
769 IN gctPOINTER KernelPointer,
775 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
776 spin_lock(&Database->lock);
777 /* Try to get a id greater than 0. */
778 result = idr_alloc(&Database->idr, KernelPointer, 1, 0,
779 GFP_KERNEL | gcdNOWARN);
780 spin_unlock(&Database->lock);
783 return gcvSTATUS_OUT_OF_RESOURCES;
788 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
790 return gcvSTATUS_OUT_OF_MEMORY;
793 spin_lock(&Database->lock);
795 /* Try to get a id greater than 0. */
796 result = idr_get_new_above(&Database->idr, KernelPointer, 1, Id);
798 spin_unlock(&Database->lock);
800 if (result == -EAGAIN)
807 return gcvSTATUS_OUT_OF_RESOURCES;
816 IN gcsINTEGER_DB_PTR Database,
818 OUT gctPOINTER * KernelPointer
823 spin_lock(&Database->lock);
825 pointer = idr_find(&Database->idr, Id);
827 spin_unlock(&Database->lock);
831 *KernelPointer = pointer;
837 gcvLEVEL_ERROR, gcvZONE_OS,
838 "%s(%d) Id = %d is not found",
839 __FUNCTION__, __LINE__, Id);
841 return gcvSTATUS_NOT_FOUND;
847 IN gcsINTEGER_DB_PTR Database,
851 spin_lock(&Database->lock);
853 idr_remove(&Database->idr, Id);
855 spin_unlock(&Database->lock);
863 IN gctPOINTER Logical,
867 if (unlikely(current->mm == gcvNULL))
869 /* Do nothing if process is exiting. */
873 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
874 if (vm_munmap((unsigned long)Logical, Size) < 0)
877 gcvLEVEL_WARNING, gcvZONE_OS,
878 "%s(%d): vm_munmap failed",
879 __FUNCTION__, __LINE__
883 down_write(¤t->mm->mmap_sem);
884 if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
887 gcvLEVEL_WARNING, gcvZONE_OS,
888 "%s(%d): do_munmap failed",
889 __FUNCTION__, __LINE__
892 up_write(¤t->mm->mmap_sem);
897 _QueryProcessPageTable(
898 IN gctPOINTER Logical,
899 OUT gctUINT32 * Address
903 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
911 return gcvSTATUS_NOT_FOUND;
914 pgd = pgd_offset(current->mm, logical);
915 if (pgd_none(*pgd) || pgd_bad(*pgd))
917 return gcvSTATUS_NOT_FOUND;
920 pud = pud_offset(pgd, logical);
921 if (pud_none(*pud) || pud_bad(*pud))
923 return gcvSTATUS_NOT_FOUND;
926 pmd = pmd_offset(pud, logical);
927 if (pmd_none(*pmd) || pmd_bad(*pmd))
929 return gcvSTATUS_NOT_FOUND;
932 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
935 return gcvSTATUS_NOT_FOUND;
938 if (!pte_present(*pte))
940 pte_unmap_unlock(pte, lock);
941 return gcvSTATUS_NOT_FOUND;
944 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
945 pte_unmap_unlock(pte, lock);
950 /*******************************************************************************
954 ** Construct a new gckOS object.
958 ** gctPOINTER Context
959 ** Pointer to the gckGALDEVICE class.
964 ** Pointer to a variable that will hold the pointer to the gckOS object.
968 IN gctPOINTER Context,
975 gcmkHEADER_ARG("Context=0x%X", Context);
977 /* Verify the arguments. */
978 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
980 /* Allocate the gckOS object. */
981 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
986 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
987 return gcvSTATUS_OUT_OF_MEMORY;
990 /* Zero the memory. */
991 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
993 /* Initialize the gckOS object. */
994 os->object.type = gcvOBJ_OS;
996 /* Set device device. */
997 os->device = Context;
999 /* IMPORTANT! No heap yet. */
1002 /* Initialize the memory lock. */
1003 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
1004 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
1006 /* Create debug lock mutex. */
1007 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
1010 os->mdlHead = os->mdlTail = gcvNULL;
1012 /* Get the kernel process ID. */
1013 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
1016 * Initialize the signal manager.
1019 /* Initialize mutex. */
1020 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
1022 /* Initialize signal id database lock. */
1023 spin_lock_init(&os->signalDB.lock);
1025 /* Initialize signal id database. */
1026 idr_init(&os->signalDB.idr);
1028 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1030 os->cacheHead = gcvNULL;
1031 os->cacheTail = gcvNULL;
1034 /* Create a workqueue for os timer. */
1035 os->workqueue = create_singlethread_workqueue("galcore workqueue");
1037 if (os->workqueue == gcvNULL)
1039 /* Out of memory. */
1040 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1043 /* Return pointer to the gckOS object. */
1047 gcmkFOOTER_ARG("*Os=0x%X", *Os);
1048 return gcvSTATUS_OK;
1051 if (os->signalMutex != gcvNULL)
1054 gckOS_DeleteMutex(os, os->signalMutex));
1057 if (os->heap != gcvNULL)
1060 gckHEAP_Destroy(os->heap));
1063 if (os->memoryMapLock != gcvNULL)
1066 gckOS_DeleteMutex(os, os->memoryMapLock));
1069 if (os->memoryLock != gcvNULL)
1072 gckOS_DeleteMutex(os, os->memoryLock));
1075 if (os->debugLock != gcvNULL)
1078 gckOS_DeleteMutex(os, os->debugLock));
1081 if (os->workqueue != gcvNULL)
1083 destroy_workqueue(os->workqueue);
1088 /* Return the error. */
1093 /*******************************************************************************
1097 ** Destroy an gckOS object.
1102 ** Pointer to an gckOS object that needs to be destroyed.
1115 gcmkHEADER_ARG("Os=0x%X", Os);
1117 /* Verify the arguments. */
1118 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1120 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1121 _FreeAllNonPagedMemoryCache(Os);
1125 * Destroy the signal manager.
1128 /* Destroy the mutex. */
1129 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
1131 if (Os->heap != gcvNULL)
1133 /* Mark gckHEAP as gone. */
1137 /* Destroy the gckHEAP object. */
1138 gcmkVERIFY_OK(gckHEAP_Destroy(heap));
1141 /* Destroy the memory lock. */
1142 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
1143 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
1145 /* Destroy debug lock mutex. */
1146 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
1148 /* Wait for all works done. */
1149 flush_workqueue(Os->workqueue);
1151 /* Destory work queue. */
1152 destroy_workqueue(Os->workqueue);
1154 /* Flush the debug cache. */
1155 gcmkDEBUGFLUSH(~0U);
1157 /* Mark the gckOS object as unknown. */
1158 Os->object.type = gcvOBJ_UNKNOWN;
1160 /* Free the gckOS object. */
1165 return gcvSTATUS_OK;
1169 _CreateKernelVirtualMapping(
1174 gctINT numPages = Mdl->numPages;
1176 #if gcdNONPAGED_MEMORY_CACHEABLE
1177 if (Mdl->contiguous)
1179 addr = page_address(Mdl->u.contiguousPages);
1183 addr = vmap(Mdl->u.nonContiguousPages,
1188 /* Trigger a page fault. */
1189 memset(addr, 0, numPages * PAGE_SIZE);
1192 struct page ** pages;
1193 gctBOOL free = gcvFALSE;
1196 if (Mdl->contiguous)
1198 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
1205 for (i = 0; i < numPages; i++)
1207 pages[i] = nth_page(Mdl->u.contiguousPages, i);
1214 pages = Mdl->u.nonContiguousPages;
1217 /* ioremap() can't work on system memory since 2.6.38. */
1218 addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
1220 /* Trigger a page fault. */
1221 memset(addr, 0, numPages * PAGE_SIZE);
1234 _DestoryKernelVirtualMapping(
1238 #if !gcdNONPAGED_MEMORY_CACHEABLE
1244 gckOS_CreateKernelVirtualMapping(
1245 IN gctPHYS_ADDR Physical,
1246 OUT gctSIZE_T * PageCount,
1247 OUT gctPOINTER * Logical
1250 *PageCount = ((PLINUX_MDL)Physical)->numPages;
1251 *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
1253 return gcvSTATUS_OK;
1257 gckOS_DestroyKernelVirtualMapping(
1258 IN gctPOINTER Logical
1261 _DestoryKernelVirtualMapping((gctSTRING)Logical);
1262 return gcvSTATUS_OK;
1265 /*******************************************************************************
1274 ** Pointer to an gckOS object.
1277 ** Number of bytes to allocate.
1281 ** gctPOINTER * Memory
1282 ** Pointer to a variable that will hold the allocated memory location.
1288 OUT gctPOINTER * Memory
1293 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1295 /* Verify the arguments. */
1296 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1297 gcmkVERIFY_ARGUMENT(Bytes > 0);
1298 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1300 /* Do we have a heap? */
1301 if (Os->heap != gcvNULL)
1303 /* Allocate from the heap. */
1304 gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
1308 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
1312 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1313 return gcvSTATUS_OK;
1316 /* Return the status. */
1321 /*******************************************************************************
1325 ** Free allocated memory.
1330 ** Pointer to an gckOS object.
1332 ** gctPOINTER Memory
1333 ** Pointer to memory allocation to free.
1342 IN gctPOINTER Memory
1347 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
1349 /* Verify the arguments. */
1350 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1351 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1353 /* Do we have a heap? */
1354 if (Os->heap != gcvNULL)
1356 /* Free from the heap. */
1357 gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
1361 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1366 return gcvSTATUS_OK;
1369 /* Return the status. */
1374 /*******************************************************************************
1376 ** gckOS_AllocateMemory
1378 ** Allocate memory wrapper.
1383 ** Number of bytes to allocate.
1387 ** gctPOINTER * Memory
1388 ** Pointer to a variable that will hold the allocated memory location.
1391 gckOS_AllocateMemory(
1394 OUT gctPOINTER * Memory
1400 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1402 /* Verify the arguments. */
1403 gcmkVERIFY_ARGUMENT(Bytes > 0);
1404 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1406 if (Bytes > PAGE_SIZE)
1408 memory = (gctPOINTER) vmalloc(Bytes);
1412 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1415 if (memory == gcvNULL)
1417 /* Out of memory. */
1418 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1421 /* Return pointer to the memory allocation. */
1425 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1426 return gcvSTATUS_OK;
1429 /* Return the status. */
1434 /*******************************************************************************
1438 ** Free allocated memory wrapper.
1442 ** gctPOINTER Memory
1443 ** Pointer to memory allocation to free.
1452 IN gctPOINTER Memory
1455 gcmkHEADER_ARG("Memory=0x%X", Memory);
1457 /* Verify the arguments. */
1458 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1460 /* Free the memory from the OS pool. */
1461 if (is_vmalloc_addr(Memory))
1472 return gcvSTATUS_OK;
1475 /*******************************************************************************
1479 ** Map physical memory into the current process.
1484 ** Pointer to an gckOS object.
1486 ** gctPHYS_ADDR Physical
1487 ** Start of physical address memory.
1490 ** Number of bytes to map.
1494 ** gctPOINTER * Memory
1495 ** Pointer to a variable that will hold the logical address of the
1501 IN gctPHYS_ADDR Physical,
1503 OUT gctPOINTER * Logical
1506 PLINUX_MDL_MAP mdlMap;
1507 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1509 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1511 /* Verify the arguments. */
1512 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1513 gcmkVERIFY_ARGUMENT(Physical != 0);
1514 gcmkVERIFY_ARGUMENT(Bytes > 0);
1515 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1519 mdlMap = FindMdlMap(mdl, _GetProcessID());
1521 if (mdlMap == gcvNULL)
1523 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1525 if (mdlMap == gcvNULL)
1529 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1530 return gcvSTATUS_OUT_OF_MEMORY;
1534 if (mdlMap->vmaAddr == gcvNULL)
1536 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1537 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1539 mdl->numPages * PAGE_SIZE,
1540 PROT_READ | PROT_WRITE,
1544 down_write(¤t->mm->mmap_sem);
1546 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1548 mdl->numPages * PAGE_SIZE,
1549 PROT_READ | PROT_WRITE,
1553 up_write(¤t->mm->mmap_sem);
1556 if (IS_ERR(mdlMap->vmaAddr))
1560 "%s(%d): do_mmap_pgoff error",
1561 __FUNCTION__, __LINE__
1566 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1567 __FUNCTION__, __LINE__,
1572 mdlMap->vmaAddr = gcvNULL;
1576 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1577 return gcvSTATUS_OUT_OF_MEMORY;
1580 down_write(¤t->mm->mmap_sem);
1582 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1588 "%s(%d): find_vma error.",
1589 __FUNCTION__, __LINE__
1592 mdlMap->vmaAddr = gcvNULL;
1594 up_write(¤t->mm->mmap_sem);
1598 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1599 return gcvSTATUS_OUT_OF_RESOURCES;
1602 #ifndef NO_DMA_COHERENT
1603 if (dma_mmap_coherent(gcvNULL,
1607 mdl->numPages * PAGE_SIZE) < 0)
1609 up_write(¤t->mm->mmap_sem);
1613 "%s(%d): dma_mmap_coherent error.",
1614 __FUNCTION__, __LINE__
1617 mdlMap->vmaAddr = gcvNULL;
1621 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1622 return gcvSTATUS_OUT_OF_RESOURCES;
1625 #if !gcdPAGED_MEMORY_CACHEABLE
1626 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1627 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1629 mdlMap->vma->vm_pgoff = 0;
1631 if (remap_pfn_range(mdlMap->vma,
1632 mdlMap->vma->vm_start,
1633 mdl->dmaHandle >> PAGE_SHIFT,
1634 mdl->numPages*PAGE_SIZE,
1635 mdlMap->vma->vm_page_prot) < 0)
1637 up_write(¤t->mm->mmap_sem);
1641 "%s(%d): remap_pfn_range error.",
1642 __FUNCTION__, __LINE__
1645 mdlMap->vmaAddr = gcvNULL;
1649 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1650 return gcvSTATUS_OUT_OF_RESOURCES;
1654 up_write(¤t->mm->mmap_sem);
1659 *Logical = mdlMap->vmaAddr;
1661 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1662 return gcvSTATUS_OK;
1665 /*******************************************************************************
1667 ** gckOS_UnmapMemory
1669 ** Unmap physical memory out of the current process.
1674 ** Pointer to an gckOS object.
1676 ** gctPHYS_ADDR Physical
1677 ** Start of physical address memory.
1680 ** Number of bytes to unmap.
1682 ** gctPOINTER Memory
1683 ** Pointer to a previously mapped memory region.
1692 IN gctPHYS_ADDR Physical,
1694 IN gctPOINTER Logical
1697 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1698 Os, Physical, Bytes, Logical);
1700 /* Verify the arguments. */
1701 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1702 gcmkVERIFY_ARGUMENT(Physical != 0);
1703 gcmkVERIFY_ARGUMENT(Bytes > 0);
1704 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1706 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1710 return gcvSTATUS_OK;
1714 /*******************************************************************************
1716 ** gckOS_UnmapMemoryEx
1718 ** Unmap physical memory in the specified process.
1723 ** Pointer to an gckOS object.
1725 ** gctPHYS_ADDR Physical
1726 ** Start of physical address memory.
1729 ** Number of bytes to unmap.
1731 ** gctPOINTER Memory
1732 ** Pointer to a previously mapped memory region.
1735 ** Pid of the process that opened the device and mapped this memory.
1742 gckOS_UnmapMemoryEx(
1744 IN gctPHYS_ADDR Physical,
1746 IN gctPOINTER Logical,
1750 PLINUX_MDL_MAP mdlMap;
1751 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1753 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1754 Os, Physical, Bytes, Logical, PID);
1756 /* Verify the arguments. */
1757 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1758 gcmkVERIFY_ARGUMENT(Physical != 0);
1759 gcmkVERIFY_ARGUMENT(Bytes > 0);
1760 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1761 gcmkVERIFY_ARGUMENT(PID != 0);
1767 mdlMap = FindMdlMap(mdl, PID);
1769 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1773 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1774 return gcvSTATUS_INVALID_ARGUMENT;
1777 _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1779 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1786 return gcvSTATUS_OK;
1789 /*******************************************************************************
1791 ** gckOS_UnmapUserLogical
1793 ** Unmap user logical memory out of physical memory.
1798 ** Pointer to an gckOS object.
1800 ** gctPHYS_ADDR Physical
1801 ** Start of physical address memory.
1804 ** Number of bytes to unmap.
1806 ** gctPOINTER Memory
1807 ** Pointer to a previously mapped memory region.
1814 gckOS_UnmapUserLogical(
1816 IN gctPHYS_ADDR Physical,
1818 IN gctPOINTER Logical
1821 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1822 Os, Physical, Bytes, Logical);
1824 /* Verify the arguments. */
1825 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1826 gcmkVERIFY_ARGUMENT(Physical != 0);
1827 gcmkVERIFY_ARGUMENT(Bytes > 0);
1828 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1830 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1834 return gcvSTATUS_OK;
1838 /*******************************************************************************
1840 ** gckOS_AllocateNonPagedMemory
1842 ** Allocate a number of pages from non-paged memory.
1847 ** Pointer to an gckOS object.
1849 ** gctBOOL InUserSpace
1850 ** gcvTRUE if the pages need to be mapped into user space.
1852 ** gctSIZE_T * Bytes
1853 ** Pointer to a variable that holds the number of bytes to allocate.
1857 ** gctSIZE_T * Bytes
1858 ** Pointer to a variable that hold the number of bytes allocated.
1860 ** gctPHYS_ADDR * Physical
1861 ** Pointer to a variable that will hold the physical address of the
1864 ** gctPOINTER * Logical
1865 ** Pointer to a variable that will hold the logical address of the
1869 gckOS_AllocateNonPagedMemory(
1871 IN gctBOOL InUserSpace,
1872 IN OUT gctSIZE_T * Bytes,
1873 OUT gctPHYS_ADDR * Physical,
1874 OUT gctPOINTER * Logical
1879 PLINUX_MDL mdl = gcvNULL;
1880 PLINUX_MDL_MAP mdlMap = gcvNULL;
1882 #ifdef NO_DMA_COHERENT
1887 gctBOOL locked = gcvFALSE;
1890 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1891 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1893 /* Verify the arguments. */
1894 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1895 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1896 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1897 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1898 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1900 /* Align number of bytes to page size. */
1901 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1903 /* Get total number of pages.. */
1904 numPages = GetPageCount(bytes, 0);
1906 /* Allocate mdl+vector structure */
1907 mdl = _CreateMdl(_GetProcessID());
1910 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1914 mdl->numPages = numPages;
1919 #ifndef NO_DMA_COHERENT
1920 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1921 addr = _GetNonPagedMemoryCache(Os,
1922 mdl->numPages * PAGE_SIZE,
1925 if (addr == gcvNULL)
1928 addr = dma_alloc_coherent(gcvNULL,
1929 mdl->numPages * PAGE_SIZE,
1931 GFP_KERNEL | gcdNOWARN);
1934 size = mdl->numPages * PAGE_SIZE;
1935 order = get_order(size);
1936 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1937 page = _GetNonPagedMemoryCache(Os, order);
1939 if (page == gcvNULL)
1942 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
1945 if (page == gcvNULL)
1947 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1950 vaddr = (gctPOINTER)page_address(page);
1951 mdl->contiguous = gcvTRUE;
1952 mdl->u.contiguousPages = page;
1953 addr = _CreateKernelVirtualMapping(mdl);
1954 mdl->dmaHandle = virt_to_phys(vaddr);
1956 mdl->u.contiguousPages = page;
1958 #if !defined(CONFIG_PPC)
1959 /* Cache invalidate. */
1960 dma_sync_single_for_device(
1969 SetPageReserved(virt_to_page(vaddr));
1976 if (addr == gcvNULL)
1978 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1981 if ((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
1983 mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1984 | (Os->device->baseAddress & 0x80000000);
1989 /* Return allocated memory. */
1991 *Physical = (gctPHYS_ADDR) mdl;
1995 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1997 if (mdlMap == gcvNULL)
1999 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2002 /* Only after mmap this will be valid. */
2004 /* We need to map this to user space. */
2005 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2006 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
2008 mdl->numPages * PAGE_SIZE,
2009 PROT_READ | PROT_WRITE,
2013 down_write(¤t->mm->mmap_sem);
2015 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
2017 mdl->numPages * PAGE_SIZE,
2018 PROT_READ | PROT_WRITE,
2022 up_write(¤t->mm->mmap_sem);
2025 if (IS_ERR(mdlMap->vmaAddr))
2028 gcvLEVEL_WARNING, gcvZONE_OS,
2029 "%s(%d): do_mmap_pgoff error",
2030 __FUNCTION__, __LINE__
2033 mdlMap->vmaAddr = gcvNULL;
2035 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2038 down_write(¤t->mm->mmap_sem);
2040 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
2042 if (mdlMap->vma == gcvNULL)
2045 gcvLEVEL_WARNING, gcvZONE_OS,
2046 "%s(%d): find_vma error",
2047 __FUNCTION__, __LINE__
2050 up_write(¤t->mm->mmap_sem);
2052 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2055 #ifndef NO_DMA_COHERENT
2056 if (dma_mmap_coherent(gcvNULL,
2060 mdl->numPages * PAGE_SIZE) < 0)
2063 gcvLEVEL_WARNING, gcvZONE_OS,
2064 "%s(%d): dma_mmap_coherent error",
2065 __FUNCTION__, __LINE__
2068 up_write(¤t->mm->mmap_sem);
2070 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2073 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
2074 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
2075 mdlMap->vma->vm_pgoff = 0;
2077 if (remap_pfn_range(mdlMap->vma,
2078 mdlMap->vma->vm_start,
2079 mdl->dmaHandle >> PAGE_SHIFT,
2080 mdl->numPages * PAGE_SIZE,
2081 mdlMap->vma->vm_page_prot))
2084 gcvLEVEL_WARNING, gcvZONE_OS,
2085 "%s(%d): remap_pfn_range error",
2086 __FUNCTION__, __LINE__
2089 up_write(¤t->mm->mmap_sem);
2091 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2093 #endif /* NO_DMA_COHERENT */
2095 up_write(¤t->mm->mmap_sem);
2097 *Logical = mdlMap->vmaAddr;
2101 *Logical = (gctPOINTER)mdl->addr;
2105 * Add this to a global list.
2106 * Will be used by get physical address
2107 * and mapuser pointer functions.
2112 /* Initialize the queue. */
2113 Os->mdlHead = Os->mdlTail = mdl;
2117 /* Add to the tail. */
2118 mdl->prev = Os->mdlTail;
2119 Os->mdlTail->next = mdl;
2126 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
2127 *Bytes, *Physical, *Logical);
2128 return gcvSTATUS_OK;
2131 if (mdlMap != gcvNULL)
2133 /* Free LINUX_MDL_MAP. */
2134 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
2139 /* Free LINUX_MDL. */
2140 gcmkVERIFY_OK(_DestroyMdl(mdl));
2145 /* Unlock memory. */
2149 /* Return the status. */
2154 /*******************************************************************************
2156 ** gckOS_FreeNonPagedMemory
2158 ** Free previously allocated and mapped pages from non-paged memory.
2163 ** Pointer to an gckOS object.
2166 ** Number of bytes allocated.
2168 ** gctPHYS_ADDR Physical
2169 ** Physical address of the allocated memory.
2171 ** gctPOINTER Logical
2172 ** Logical address of the allocated memory.
2178 gceSTATUS gckOS_FreeNonPagedMemory(
2181 IN gctPHYS_ADDR Physical,
2182 IN gctPOINTER Logical
2186 PLINUX_MDL_MAP mdlMap;
2187 #ifdef NO_DMA_COHERENT
2190 #endif /* NO_DMA_COHERENT */
2192 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
2193 Os, Bytes, Physical, Logical);
2195 /* Verify the arguments. */
2196 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2197 gcmkVERIFY_ARGUMENT(Bytes > 0);
2198 gcmkVERIFY_ARGUMENT(Physical != 0);
2199 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2201 /* Convert physical address into a pointer to a MDL. */
2202 mdl = (PLINUX_MDL) Physical;
2206 #ifndef NO_DMA_COHERENT
2207 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2208 if (!_AddNonPagedMemoryCache(Os,
2209 mdl->numPages * PAGE_SIZE,
2214 dma_free_coherent(gcvNULL,
2215 mdl->numPages * PAGE_SIZE,
2220 size = mdl->numPages * PAGE_SIZE;
2225 ClearPageReserved(virt_to_page(vaddr));
2231 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2232 if (!_AddNonPagedMemoryCache(Os,
2233 get_order(mdl->numPages * PAGE_SIZE),
2234 virt_to_page(mdl->kaddr)))
2237 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
2240 _DestoryKernelVirtualMapping(mdl->addr);
2241 #endif /* NO_DMA_COHERENT */
2245 while (mdlMap != gcvNULL)
2247 if (mdlMap->vmaAddr != gcvNULL)
2249 /* No mapped memory exists when free nonpaged memory */
2253 mdlMap = mdlMap->next;
2256 /* Remove the node from global list.. */
2257 if (mdl == Os->mdlHead)
2259 if ((Os->mdlHead = mdl->next) == gcvNULL)
2261 Os->mdlTail = gcvNULL;
2266 mdl->prev->next = mdl->next;
2267 if (mdl == Os->mdlTail)
2269 Os->mdlTail = mdl->prev;
2273 mdl->next->prev = mdl->prev;
2279 gcmkVERIFY_OK(_DestroyMdl(mdl));
2283 return gcvSTATUS_OK;
2286 /*******************************************************************************
2288 ** gckOS_ReadRegister
2290 ** Read data from a register.
2295 ** Pointer to an gckOS object.
2297 ** gctUINT32 Address
2298 ** Address of register.
2303 ** Pointer to a variable that receives the data read from the register.
2308 IN gctUINT32 Address,
2309 OUT gctUINT32 * Data
2312 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2316 gckOS_ReadRegisterEx(
2319 IN gctUINT32 Address,
2320 OUT gctUINT32 * Data
2323 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
2325 /* Verify the arguments. */
2326 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2327 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2329 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
2332 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2333 return gcvSTATUS_OK;
2336 /*******************************************************************************
2338 ** gckOS_WriteRegister
2340 ** Write data to a register.
2345 ** Pointer to an gckOS object.
2347 ** gctUINT32 Address
2348 ** Address of register.
2351 ** Data for register.
2358 gckOS_WriteRegister(
2360 IN gctUINT32 Address,
2364 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2368 gckOS_WriteRegisterEx(
2371 IN gctUINT32 Address,
2375 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2377 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2381 return gcvSTATUS_OK;
2384 /*******************************************************************************
2386 ** gckOS_GetPageSize
2388 ** Get the system's page size.
2393 ** Pointer to an gckOS object.
2397 ** gctSIZE_T * PageSize
2398 ** Pointer to a variable that will receive the system's page size.
2400 gceSTATUS gckOS_GetPageSize(
2402 OUT gctSIZE_T * PageSize
2405 gcmkHEADER_ARG("Os=0x%X", Os);
2407 /* Verify the arguments. */
2408 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2409 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2411 /* Return the page size. */
2412 *PageSize = (gctSIZE_T) PAGE_SIZE;
2415 gcmkFOOTER_ARG("*PageSize", *PageSize);
2416 return gcvSTATUS_OK;
2419 /*******************************************************************************
2421 ** gckOS_GetPhysicalAddress
2423 ** Get the physical system address of a corresponding virtual address.
2428 ** Pointer to an gckOS object.
2430 ** gctPOINTER Logical
2435 ** gctUINT32 * Address
2436 ** Poinetr to a variable that receives the 32-bit physical adress.
2439 gckOS_GetPhysicalAddress(
2441 IN gctPOINTER Logical,
2442 OUT gctUINT32 * Address
2446 gctUINT32 processID;
2448 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2450 /* Verify the arguments. */
2451 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2452 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2454 /* Query page table of current process first. */
2455 status = _QueryProcessPageTable(Logical, Address);
2457 if (gcmIS_ERROR(status))
2459 /* Get current process ID. */
2460 processID = _GetProcessID();
2462 /* Route through other function. */
2464 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2468 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2469 return gcvSTATUS_OK;
2472 /* Return the status. */
2481 IN gctUINT32 Physical,
2482 IN gctPOINTER Logical,
2487 gcsUSER_MAPPING_PTR map;
2489 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2490 Os, Physical, Logical, Bytes);
2492 gcmkONERROR(gckOS_Allocate(Os,
2493 gcmSIZEOF(gcsUSER_MAPPING),
2494 (gctPOINTER *) &map));
2496 map->next = Os->userMap;
2497 map->physical = Physical - Os->device->baseAddress;
2498 map->logical = Logical;
2500 map->start = (gctINT8_PTR) Logical;
2501 map->end = map->start + Bytes;
2506 return gcvSTATUS_OK;
2514 gckOS_RemoveMapping(
2516 IN gctPOINTER Logical,
2521 gcsUSER_MAPPING_PTR map, prev;
2523 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2525 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2527 if ((map->logical == Logical)
2528 && (map->bytes == Bytes)
2539 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2542 if (prev == gcvNULL)
2544 Os->userMap = map->next;
2548 prev->next = map->next;
2551 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2554 return gcvSTATUS_OK;
2563 _ConvertLogical2Physical(
2565 IN gctPOINTER Logical,
2566 IN gctUINT32 ProcessID,
2568 OUT gctUINT32_PTR Physical
2571 gctINT8_PTR base, vBase;
2574 gcsUSER_MAPPING_PTR userMap;
2576 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2578 /* Check for the logical address match. */
2579 if ((base != gcvNULL)
2580 && ((gctINT8_PTR) Logical >= base)
2581 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2584 offset = (gctINT8_PTR) Logical - base;
2586 if (Mdl->dmaHandle != 0)
2588 /* The memory was from coherent area. */
2589 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2591 else if (Mdl->pagedMem && !Mdl->contiguous)
2593 /* paged memory is not mapped to kernel space. */
2594 return gcvSTATUS_INVALID_ADDRESS;
2598 *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
2601 return gcvSTATUS_OK;
2604 /* Walk user maps. */
2605 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2607 if (((gctINT8_PTR) Logical >= userMap->start)
2608 && ((gctINT8_PTR) Logical < userMap->end)
2611 *Physical = userMap->physical
2612 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2614 return gcvSTATUS_OK;
2618 if (ProcessID != Os->kernelProcessID)
2620 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2621 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2623 /* Is the given address within that range. */
2624 if ((vBase != gcvNULL)
2625 && ((gctINT8_PTR) Logical >= vBase)
2626 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2629 offset = (gctINT8_PTR) Logical - vBase;
2631 if (Mdl->dmaHandle != 0)
2633 /* The memory was from coherent area. */
2634 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2636 else if (Mdl->pagedMem && !Mdl->contiguous)
2638 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2642 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2645 return gcvSTATUS_OK;
2649 /* Address not yet found. */
2650 return gcvSTATUS_INVALID_ADDRESS;
2653 /*******************************************************************************
2655 ** gckOS_GetPhysicalAddressProcess
2657 ** Get the physical system address of a corresponding virtual address for a
2663 ** Pointer to gckOS object.
2665 ** gctPOINTER Logical
2668 ** gctUINT32 ProcessID
2673 ** gctUINT32 * Address
2674 ** Poinetr to a variable that receives the 32-bit physical adress.
2677 gckOS_GetPhysicalAddressProcess(
2679 IN gctPOINTER Logical,
2680 IN gctUINT32 ProcessID,
2681 OUT gctUINT32 * Address
2686 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2688 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2690 /* Verify the arguments. */
2691 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2692 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2696 /* First try the contiguous memory pool. */
2697 if (Os->device->contiguousMapped)
2699 base = (gctINT8_PTR) Os->device->contiguousBase;
2701 if (((gctINT8_PTR) Logical >= base)
2702 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2705 /* Convert logical address into physical. */
2706 *Address = Os->device->contiguousVidMem->baseAddress
2707 + (gctINT8_PTR) Logical - base;
2708 status = gcvSTATUS_OK;
2713 /* Try the contiguous memory pool. */
2714 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2715 status = _ConvertLogical2Physical(Os,
2722 if (gcmIS_ERROR(status))
2724 /* Walk all MDLs. */
2725 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2728 status = _ConvertLogical2Physical(Os,
2733 if (gcmIS_SUCCESS(status))
2742 gcmkONERROR(status);
2745 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2746 return gcvSTATUS_OK;
2749 /* Return the status. */
2754 /*******************************************************************************
2756 ** gckOS_MapPhysical
2758 ** Map a physical address into kernel space.
2763 ** Pointer to an gckOS object.
2765 ** gctUINT32 Physical
2766 ** Physical address of the memory to map.
2769 ** Number of bytes to map.
2773 ** gctPOINTER * Logical
2774 ** Pointer to a variable that receives the base address of the mapped
2780 IN gctUINT32 Physical,
2782 OUT gctPOINTER * Logical
2787 gctUINT32 physical = Physical;
2789 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2791 /* Verify the arguments. */
2792 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2793 gcmkVERIFY_ARGUMENT(Bytes > 0);
2794 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2798 /* Go through our mapping to see if we know this physical address already. */
2801 while (mdl != gcvNULL)
2803 if (mdl->dmaHandle != 0)
2805 if ((physical >= mdl->dmaHandle)
2806 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2809 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2819 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2820 struct contiguous_mem_pool *pool = Os->device->pool;
2822 if (Physical >= pool->phys && Physical < pool->phys + pool->size)
2823 logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
2827 /* Map memory as cached memory. */
2828 request_mem_region(physical, Bytes, "MapRegion");
2829 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2832 if (logical == gcvNULL)
2835 gcvLEVEL_INFO, gcvZONE_OS,
2836 "%s(%d): Failed to map physical address 0x%08x",
2837 __FUNCTION__, __LINE__, Physical
2842 /* Out of resources. */
2843 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2844 return gcvSTATUS_OUT_OF_RESOURCES;
2847 /* Return pointer to mapped memory. */
2854 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2855 return gcvSTATUS_OK;
2858 /*******************************************************************************
2860 ** gckOS_UnmapPhysical
2862 ** Unmap a previously mapped memory region from kernel memory.
2867 ** Pointer to an gckOS object.
2869 ** gctPOINTER Logical
2870 ** Pointer to the base address of the memory to unmap.
2873 ** Number of bytes to unmap.
2880 gckOS_UnmapPhysical(
2882 IN gctPOINTER Logical,
2888 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2890 /* Verify the arguments. */
2891 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2892 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2893 gcmkVERIFY_ARGUMENT(Bytes > 0);
2899 while (mdl != gcvNULL)
2901 if (mdl->addr != gcvNULL)
2903 if (Logical >= (gctPOINTER)mdl->addr
2904 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2915 /* Unmap the memory. */
2923 return gcvSTATUS_OK;
2926 /*******************************************************************************
2928 ** gckOS_CreateMutex
2930 ** Create a new mutex.
2935 ** Pointer to an gckOS object.
2939 ** gctPOINTER * Mutex
2940 ** Pointer to a variable that will hold a pointer to the mutex.
2945 OUT gctPOINTER * Mutex
2950 gcmkHEADER_ARG("Os=0x%X", Os);
2952 /* Validate the arguments. */
2953 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2954 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2956 /* Allocate the mutex structure. */
2957 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
2959 /* Initialize the mutex. */
2962 /* Return status. */
2963 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
2964 return gcvSTATUS_OK;
2967 /* Return status. */
2972 /*******************************************************************************
2974 ** gckOS_DeleteMutex
2981 ** Pointer to an gckOS object.
2984 ** Pointer to the mute to be deleted.
2998 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
3000 /* Validate the arguments. */
3001 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3002 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3004 /* Destroy the mutex. */
3005 mutex_destroy(Mutex);
3007 /* Free the mutex structure. */
3008 gcmkONERROR(gckOS_Free(Os, Mutex));
3011 return gcvSTATUS_OK;
3014 /* Return status. */
3019 /*******************************************************************************
3021 ** gckOS_AcquireMutex
3028 ** Pointer to an gckOS object.
3031 ** Pointer to the mutex to be acquired.
3033 ** gctUINT32 Timeout
3034 ** Timeout value specified in milliseconds.
3035 ** Specify the value of gcvINFINITE to keep the thread suspended
3036 ** until the mutex has been acquired.
3045 IN gctPOINTER Mutex,
3046 IN gctUINT32 Timeout
3049 #if gcdDETECT_TIMEOUT
3053 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
3055 /* Validate the arguments. */
3056 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3057 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3059 #if gcdDETECT_TIMEOUT
3064 /* Try to acquire the mutex. */
3065 if (mutex_trylock(Mutex))
3069 return gcvSTATUS_OK;
3072 /* Advance the timeout. */
3075 if (Timeout == gcvINFINITE)
3077 if (timeout == gcdINFINITE_TIMEOUT)
3079 gctUINT32 dmaAddress1, dmaAddress2;
3080 gctUINT32 dmaState1, dmaState2;
3082 dmaState1 = dmaState2 =
3083 dmaAddress1 = dmaAddress2 = 0;
3085 /* Verify whether DMA is running. */
3086 gcmkVERIFY_OK(_VerifyDMA(
3087 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
3090 #if gcdDETECT_DMA_ADDRESS
3091 /* Dump only if DMA appears stuck. */
3093 (dmaAddress1 == dmaAddress2)
3094 #if gcdDETECT_DMA_STATE
3095 && (dmaState1 == dmaState2)
3100 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
3103 "%s(%d): mutex 0x%X; forced message flush.",
3104 __FUNCTION__, __LINE__, Mutex
3107 /* Flush the debug cache. */
3108 gcmkDEBUGFLUSH(dmaAddress2);
3117 if (timeout >= Timeout)
3123 /* Wait for 1 millisecond. */
3124 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3127 if (Timeout == gcvINFINITE)
3129 /* Lock the mutex. */
3134 return gcvSTATUS_OK;
3139 /* Try to acquire the mutex. */
3140 if (mutex_trylock(Mutex))
3144 return gcvSTATUS_OK;
3152 /* Wait for 1 millisecond. */
3153 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3158 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
3159 return gcvSTATUS_TIMEOUT;
3162 /*******************************************************************************
3164 ** gckOS_ReleaseMutex
3166 ** Release an acquired mutex.
3171 ** Pointer to an gckOS object.
3174 ** Pointer to the mutex to be released.
3186 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
3188 /* Validate the arguments. */
3189 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3190 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3192 /* Release the mutex. */
3193 mutex_unlock(Mutex);
3197 return gcvSTATUS_OK;
3200 /*******************************************************************************
3202 ** gckOS_AtomicExchange
3204 ** Atomically exchange a pair of 32-bit values.
3209 ** Pointer to an gckOS object.
3211 ** IN OUT gctINT32_PTR Target
3212 ** Pointer to the 32-bit value to exchange.
3214 ** IN gctINT32 NewValue
3215 ** Specifies a new value for the 32-bit value pointed to by Target.
3217 ** OUT gctINT32_PTR OldValue
3218 ** The old value of the 32-bit value pointed to by Target.
3225 gckOS_AtomicExchange(
3227 IN OUT gctUINT32_PTR Target,
3228 IN gctUINT32 NewValue,
3229 OUT gctUINT32_PTR OldValue
3232 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
3234 /* Verify the arguments. */
3235 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3237 /* Exchange the pair of 32-bit values. */
3238 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
3241 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
3242 return gcvSTATUS_OK;
3245 /*******************************************************************************
3247 ** gckOS_AtomicExchangePtr
3249 ** Atomically exchange a pair of pointers.
3254 ** Pointer to an gckOS object.
3256 ** IN OUT gctPOINTER * Target
3257 ** Pointer to the 32-bit value to exchange.
3259 ** IN gctPOINTER NewValue
3260 ** Specifies a new value for the pointer pointed to by Target.
3262 ** OUT gctPOINTER * OldValue
3263 ** The old value of the pointer pointed to by Target.
3270 gckOS_AtomicExchangePtr(
3272 IN OUT gctPOINTER * Target,
3273 IN gctPOINTER NewValue,
3274 OUT gctPOINTER * OldValue
3277 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3279 /* Verify the arguments. */
3280 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3282 /* Exchange the pair of pointers. */
3283 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3286 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3287 return gcvSTATUS_OK;
3291 /*******************************************************************************
3293 ** gckOS_AtomicSetMask
3295 ** Atomically set mask to Atom
3298 ** IN OUT gctPOINTER Atom
3299 ** Pointer to the atom to set.
3301 ** IN gctUINT32 Mask
3314 gctUINT32 oval, nval;
3316 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3317 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3321 oval = atomic_read((atomic_t *) Atom);
3323 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3326 return gcvSTATUS_OK;
3329 /*******************************************************************************
3331 ** gckOS_AtomClearMask
3333 ** Atomically clear mask from Atom
3336 ** IN OUT gctPOINTER Atom
3337 ** Pointer to the atom to clear.
3339 ** IN gctUINT32 Mask
3347 gckOS_AtomClearMask(
3352 gctUINT32 oval, nval;
3354 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3355 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3359 oval = atomic_read((atomic_t *) Atom);
3360 nval = oval & ~Mask;
3361 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3364 return gcvSTATUS_OK;
3368 /*******************************************************************************
3370 ** gckOS_AtomConstruct
3377 ** Pointer to a gckOS object.
3381 ** gctPOINTER * Atom
3382 ** Pointer to a variable receiving the constructed atom.
3385 gckOS_AtomConstruct(
3387 OUT gctPOINTER * Atom
3392 gcmkHEADER_ARG("Os=0x%X", Os);
3394 /* Verify the arguments. */
3395 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3396 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3398 /* Allocate the atom. */
3399 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3401 /* Initialize the atom. */
3402 atomic_set((atomic_t *) *Atom, 0);
3405 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3406 return gcvSTATUS_OK;
3409 /* Return the status. */
3414 /*******************************************************************************
3416 ** gckOS_AtomDestroy
3423 ** Pointer to a gckOS object.
3426 ** Pointer to the atom to destroy.
3440 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3442 /* Verify the arguments. */
3443 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3444 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3446 /* Free the atom. */
3447 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3451 return gcvSTATUS_OK;
3454 /* Return the status. */
3459 /*******************************************************************************
3463 ** Get the 32-bit value protected by an atom.
3468 ** Pointer to a gckOS object.
3471 ** Pointer to the atom.
3475 ** gctINT32_PTR Value
3476 ** Pointer to a variable the receives the value of the atom.
3482 OUT gctINT32_PTR Value
3485 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3487 /* Verify the arguments. */
3488 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3489 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3491 /* Return the current value of atom. */
3492 *Value = atomic_read((atomic_t *) Atom);
3495 gcmkFOOTER_ARG("*Value=%d", *Value);
3496 return gcvSTATUS_OK;
3499 /*******************************************************************************
3503 ** Set the 32-bit value protected by an atom.
3508 ** Pointer to a gckOS object.
3511 ** Pointer to the atom.
3514 ** The value of the atom.
3527 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3529 /* Verify the arguments. */
3530 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3531 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3533 /* Set the current value of atom. */
3534 atomic_set((atomic_t *) Atom, Value);
3538 return gcvSTATUS_OK;
3541 /*******************************************************************************
3543 ** gckOS_AtomIncrement
3545 ** Atomically increment the 32-bit integer value inside an atom.
3550 ** Pointer to a gckOS object.
3553 ** Pointer to the atom.
3557 ** gctINT32_PTR Value
3558 ** Pointer to a variable that receives the original value of the atom.
3561 gckOS_AtomIncrement(
3564 OUT gctINT32_PTR Value
3567 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3569 /* Verify the arguments. */
3570 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3571 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3573 /* Increment the atom. */
3574 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3577 gcmkFOOTER_ARG("*Value=%d", *Value);
3578 return gcvSTATUS_OK;
3581 /*******************************************************************************
3583 ** gckOS_AtomDecrement
3585 ** Atomically decrement the 32-bit integer value inside an atom.
3590 ** Pointer to a gckOS object.
3593 ** Pointer to the atom.
3597 ** gctINT32_PTR Value
3598 ** Pointer to a variable that receives the original value of the atom.
3601 gckOS_AtomDecrement(
3604 OUT gctINT32_PTR Value
3607 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3609 /* Verify the arguments. */
3610 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3611 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3613 /* Decrement the atom. */
3614 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3617 gcmkFOOTER_ARG("*Value=%d", *Value);
3618 return gcvSTATUS_OK;
3621 /*******************************************************************************
3625 ** Delay execution of the current thread for a number of milliseconds.
3630 ** Pointer to an gckOS object.
3633 ** Delay to sleep, specified in milliseconds.
3645 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3649 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3650 ktime_t delay = ktime_set(0, Delay * NSEC_PER_MSEC);
3651 __set_current_state(TASK_UNINTERRUPTIBLE);
3652 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3661 return gcvSTATUS_OK;
3664 /*******************************************************************************
3668 ** Get the number of milliseconds since the system started.
3674 ** gctUINT32_PTR Time
3675 ** Pointer to a variable to get time.
3680 OUT gctUINT32_PTR Time
3685 *Time = jiffies_to_msecs(jiffies);
3688 return gcvSTATUS_OK;
3691 /*******************************************************************************
3695 ** Compare time values got from gckOS_GetTicks.
3699 ** First time value to be compared.
3702 ** Second time value to be compared.
3706 ** gctBOOL_PTR IsAfter
3707 ** Pointer to a variable to result.
3714 OUT gctBOOL_PTR IsAfter
3719 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3722 return gcvSTATUS_OK;
3725 /*******************************************************************************
3729 ** Get the number of microseconds since the system started.
3735 ** gctUINT64_PTR Time
3736 ** Pointer to a variable to get time.
3741 OUT gctUINT64_PTR Time
3749 return gcvSTATUS_OK;
3752 /*******************************************************************************
3754 ** gckOS_MemoryBarrier
3756 ** Make sure the CPU has executed everything up to this point and the data got
3757 ** written to the specified pointer.
3762 ** Pointer to an gckOS object.
3764 ** gctPOINTER Address
3765 ** Address of memory that needs to be barriered.
3772 gckOS_MemoryBarrier(
3774 IN gctPOINTER Address
3777 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3779 /* Verify the arguments. */
3780 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3782 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3783 && defined (CONFIG_ARM) \
3784 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3785 /* drain write buffer */
3788 /* drain outer cache's write buffer? */
3795 return gcvSTATUS_OK;
3798 /*******************************************************************************
3800 ** gckOS_AllocatePagedMemory
3802 ** Allocate memory from the paged pool.
3807 ** Pointer to an gckOS object.
3810 ** Number of bytes to allocate.
3814 ** gctPHYS_ADDR * Physical
3815 ** Pointer to a variable that receives the physical address of the
3816 ** memory allocation.
3819 gckOS_AllocatePagedMemory(
3822 OUT gctPHYS_ADDR * Physical
3827 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3829 /* Verify the arguments. */
3830 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3831 gcmkVERIFY_ARGUMENT(Bytes > 0);
3832 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3834 /* Allocate the memory. */
3835 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
3838 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3839 return gcvSTATUS_OK;
3842 /* Return the status. */
3847 /*******************************************************************************
3849 ** gckOS_AllocatePagedMemoryEx
3851 ** Allocate memory from the paged pool.
3856 ** Pointer to an gckOS object.
3858 ** gctBOOL Contiguous
3859 ** Need contiguous memory or not.
3862 ** Number of bytes to allocate.
3866 ** gctPHYS_ADDR * Physical
3867 ** Pointer to a variable that receives the physical address of the
3868 ** memory allocation.
3871 gckOS_AllocatePagedMemoryEx(
3873 IN gctBOOL Contiguous,
3875 OUT gctPHYS_ADDR * Physical
3880 PLINUX_MDL mdl = gcvNULL;
3882 gctBOOL locked = gcvFALSE;
3884 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3885 gctPOINTER addr = gcvNULL;
3888 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
3890 /* Verify the arguments. */
3891 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3892 gcmkVERIFY_ARGUMENT(Bytes > 0);
3893 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3895 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3897 numPages = GetPageCount(bytes, 0);
3902 mdl = _CreateMdl(_GetProcessID());
3905 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3910 /* Get contiguous pages, and suppress warning (stack dump) from kernel when
3911 we run out of memory. */
3912 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3914 alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
3916 mdl->u.contiguousPages = addr
3917 ? virt_to_page(addr)
3920 mdl->exact = gcvTRUE;
3922 mdl->u.contiguousPages =
3923 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, GetOrder(numPages));
3925 if (mdl->u.contiguousPages == gcvNULL)
3927 mdl->u.contiguousPages =
3928 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, GetOrder(numPages));
3930 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3931 mdl->exact = gcvFALSE;
3937 mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
3940 if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
3942 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3947 mdl->numPages = numPages;
3949 mdl->contiguous = Contiguous;
3951 for (i = 0; i < mdl->numPages; i++)
3955 if (mdl->contiguous)
3957 page = nth_page(mdl->u.contiguousPages, i);
3961 page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
3964 SetPageReserved(page);
3966 if (!PageHighMem(page) && page_to_phys(page))
3969 gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
3970 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
3976 /* Return physical address. */
3977 *Physical = (gctPHYS_ADDR) mdl;
3980 * Add this to a global list.
3981 * Will be used by get physical address
3982 * and mapuser pointer functions.
3986 /* Initialize the queue. */
3987 Os->mdlHead = Os->mdlTail = mdl;
3992 mdl->prev = Os->mdlTail;
3993 Os->mdlTail->next = mdl;
4000 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
4001 return gcvSTATUS_OK;
4006 /* Free the memory. */
4012 /* Unlock the memory. */
4016 /* Return the status. */
4021 /*******************************************************************************
4023 ** gckOS_FreePagedMemory
4025 ** Free memory allocated from the paged pool.
4030 ** Pointer to an gckOS object.
4032 ** gctPHYS_ADDR Physical
4033 ** Physical address of the allocation.
4036 ** Number of bytes of the allocation.
4043 gckOS_FreePagedMemory(
4045 IN gctPHYS_ADDR Physical,
4049 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
4052 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
4054 /* Verify the arguments. */
4055 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4056 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4057 gcmkVERIFY_ARGUMENT(Bytes > 0);
4059 /*addr = mdl->addr;*/
4063 for (i = 0; i < mdl->numPages; i++)
4065 if (mdl->contiguous)
4067 ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
4071 ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
4075 if (mdl->contiguous)
4077 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4078 if (mdl->exact == gcvTRUE)
4080 free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
4085 __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
4090 _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
4093 /* Remove the node from global list. */
4094 if (mdl == Os->mdlHead)
4096 if ((Os->mdlHead = mdl->next) == gcvNULL)
4098 Os->mdlTail = gcvNULL;
4103 mdl->prev->next = mdl->next;
4105 if (mdl == Os->mdlTail)
4107 Os->mdlTail = mdl->prev;
4111 mdl->next->prev = mdl->prev;
4117 /* Free the structure... */
4118 gcmkVERIFY_OK(_DestroyMdl(mdl));
4122 return gcvSTATUS_OK;
4125 /*******************************************************************************
4129 ** Lock memory allocated from the paged pool.
4134 ** Pointer to an gckOS object.
4136 ** gctPHYS_ADDR Physical
4137 ** Physical address of the allocation.
4140 ** Number of bytes of the allocation.
4142 ** gctBOOL Cacheable
4143 ** Cache mode of mapping.
4147 ** gctPOINTER * Logical
4148 ** Pointer to a variable that receives the address of the mapped
4151 ** gctSIZE_T * PageCount
4152 ** Pointer to a variable that receives the number of pages required for
4153 ** the page table according to the GPU page size.
4158 IN gctPHYS_ADDR Physical,
4160 IN gctBOOL Cacheable,
4161 OUT gctPOINTER * Logical,
4162 OUT gctSIZE_T * PageCount
4166 PLINUX_MDL_MAP mdlMap;
4168 unsigned long start;
4172 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
4174 /* Verify the arguments. */
4175 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4176 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4177 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4178 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
4180 mdl = (PLINUX_MDL) Physical;
4184 mdlMap = FindMdlMap(mdl, _GetProcessID());
4186 if (mdlMap == gcvNULL)
4188 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
4190 if (mdlMap == gcvNULL)
4194 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4195 return gcvSTATUS_OUT_OF_MEMORY;
4199 if (mdlMap->vmaAddr == gcvNULL)
4201 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
4202 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
4204 mdl->numPages * PAGE_SIZE,
4205 PROT_READ | PROT_WRITE,
4209 down_write(¤t->mm->mmap_sem);
4211 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
4213 mdl->numPages * PAGE_SIZE,
4214 PROT_READ | PROT_WRITE,
4218 up_write(¤t->mm->mmap_sem);
4222 gcvLEVEL_INFO, gcvZONE_OS,
4223 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
4224 __FUNCTION__, __LINE__,
4225 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
4226 (gctUINT32)(gctUINTPTR_T)mdl
4229 if (IS_ERR(mdlMap->vmaAddr))
4232 gcvLEVEL_INFO, gcvZONE_OS,
4233 "%s(%d): do_mmap_pgoff error",
4234 __FUNCTION__, __LINE__
4237 mdlMap->vmaAddr = gcvNULL;
4241 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4242 return gcvSTATUS_OUT_OF_MEMORY;
4245 down_write(¤t->mm->mmap_sem);
4247 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
4249 if (mdlMap->vma == gcvNULL)
4251 up_write(¤t->mm->mmap_sem);
4254 gcvLEVEL_INFO, gcvZONE_OS,
4255 "%s(%d): find_vma error",
4256 __FUNCTION__, __LINE__
4259 mdlMap->vmaAddr = gcvNULL;
4263 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
4264 return gcvSTATUS_OUT_OF_RESOURCES;
4267 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
4268 #if !gcdPAGED_MEMORY_CACHEABLE
4269 if (Cacheable == gcvFALSE)
4271 /* Make this mapping non-cached. */
4272 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
4277 /* Now map all the vmalloc pages to this user address. */
4278 if (mdl->contiguous)
4280 /* map kernel memory to user space.. */
4281 if (remap_pfn_range(mdlMap->vma,
4282 mdlMap->vma->vm_start,
4283 page_to_pfn(mdl->u.contiguousPages),
4284 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
4285 mdlMap->vma->vm_page_prot) < 0)
4287 up_write(¤t->mm->mmap_sem);
4290 gcvLEVEL_INFO, gcvZONE_OS,
4291 "%s(%d): unable to mmap ret",
4292 __FUNCTION__, __LINE__
4295 mdlMap->vmaAddr = gcvNULL;
4299 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4300 return gcvSTATUS_OUT_OF_MEMORY;
4305 start = mdlMap->vma->vm_start;
4307 for (i = 0; i < mdl->numPages; i++)
4309 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
4311 if (remap_pfn_range(mdlMap->vma,
4315 mdlMap->vma->vm_page_prot) < 0)
4317 up_write(¤t->mm->mmap_sem);
4320 gcvLEVEL_INFO, gcvZONE_OS,
4321 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
4322 __FUNCTION__, __LINE__,
4323 (gctUINT32)(gctUINTPTR_T)Physical,
4324 (gctUINT32)(gctUINTPTR_T)*Logical,
4325 (gctUINT32)(gctUINTPTR_T)addr,
4326 (gctUINT32)(gctUINTPTR_T)start
4329 mdlMap->vmaAddr = gcvNULL;
4333 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4334 return gcvSTATUS_OUT_OF_MEMORY;
4342 up_write(¤t->mm->mmap_sem);
4346 /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */
4349 gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED, mdlMap->vmaAddr);
4350 return gcvSTATUS_MEMORY_LOCKED;
4353 /* Convert pointer to MDL. */
4354 *Logical = mdlMap->vmaAddr;
4356 /* Return the page number according to the GPU page size. */
4357 gcmkASSERT((PAGE_SIZE % 4096) == 0);
4358 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
4360 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
4364 gcmkVERIFY_OK(gckOS_CacheFlush(
4369 (gctPOINTER)mdlMap->vmaAddr,
4370 mdl->numPages * PAGE_SIZE
4374 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
4375 return gcvSTATUS_OK;
4378 /*******************************************************************************
4382 ** Map paged memory into a page table.
4387 ** Pointer to an gckOS object.
4389 ** gctPHYS_ADDR Physical
4390 ** Physical address of the allocation.
4392 ** gctSIZE_T PageCount
4393 ** Number of pages required for the physical address.
4395 ** gctPOINTER PageTable
4396 ** Pointer to the page table to fill in.
4405 IN gctPHYS_ADDR Physical,
4406 IN gctSIZE_T PageCount,
4407 IN gctPOINTER PageTable
4410 return gckOS_MapPagesEx(Os,
4421 IN gctPHYS_ADDR Physical,
4422 IN gctSIZE_T PageCount,
4423 IN gctPOINTER PageTable
4426 gceSTATUS status = gcvSTATUS_OK;
4430 #if gcdNONPAGED_MEMORY_CACHEABLE
4434 gctPHYS_ADDR pageTablePhysical;
4437 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
4438 Os, Core, Physical, PageCount, PageTable);
4440 /* Verify the arguments. */
4441 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4442 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4443 gcmkVERIFY_ARGUMENT(PageCount > 0);
4444 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
4446 /* Convert pointer to MDL. */
4447 mdl = (PLINUX_MDL)Physical;
4450 gcvLEVEL_INFO, gcvZONE_OS,
4451 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4452 __FUNCTION__, __LINE__,
4453 (gctUINT32)(gctUINTPTR_T)Physical,
4454 (gctUINT32)(gctUINTPTR_T)PageCount,
4460 table = (gctUINT32 *)PageTable;
4461 #if gcdNONPAGED_MEMORY_CACHEABLE
4462 mmu = Os->device->kernels[Core]->mmu;
4463 bytes = PageCount * sizeof(*table);
4464 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4467 /* Get all the physical addresses and store them in the page table. */
4473 /* Try to get the user pages so DMA can happen. */
4474 while (PageCount-- > 0)
4477 if (Core == gcvCORE_VG)
4479 if (mdl->contiguous)
4482 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4483 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4489 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4490 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4497 if (mdl->contiguous)
4500 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4501 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4507 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4508 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4520 gcvLEVEL_INFO, gcvZONE_OS,
4521 "%s(%d): we should not get this call for Non Paged Memory!",
4522 __FUNCTION__, __LINE__
4525 while (PageCount-- > 0)
4528 if (Core == gcvCORE_VG)
4531 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4532 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4539 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4540 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4548 #if gcdNONPAGED_MEMORY_CACHEABLE
4549 /* Get physical address of pageTable */
4550 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4551 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4553 /* Flush the mmu page table cache. */
4554 gcmkONERROR(gckOS_CacheClean(
4568 /* Return the status. */
4573 /*******************************************************************************
4575 ** gckOS_UnlockPages
4577 ** Unlock memory allocated from the paged pool.
4582 ** Pointer to an gckOS object.
4584 ** gctPHYS_ADDR Physical
4585 ** Physical address of the allocation.
4588 ** Number of bytes of the allocation.
4590 ** gctPOINTER Logical
4591 ** Address of the mapped memory.
4600 IN gctPHYS_ADDR Physical,
4602 IN gctPOINTER Logical
4605 PLINUX_MDL_MAP mdlMap;
4606 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4608 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4609 Os, Physical, Bytes, Logical);
4611 /* Verify the arguments. */
4612 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4613 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4614 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4616 /* Make sure there is already a mapping...*/
4617 gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
4618 || mdl->u.contiguousPages != gcvNULL);
4624 while (mdlMap != gcvNULL)
4626 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4628 _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
4629 mdlMap->vmaAddr = gcvNULL;
4632 mdlMap = mdlMap->next;
4639 return gcvSTATUS_OK;
4643 /*******************************************************************************
4645 ** gckOS_AllocateContiguous
4647 ** Allocate memory from the contiguous pool.
4652 ** Pointer to an gckOS object.
4654 ** gctBOOL InUserSpace
4655 ** gcvTRUE if the pages need to be mapped into user space.
4657 ** gctSIZE_T * Bytes
4658 ** Pointer to the number of bytes to allocate.
4662 ** gctSIZE_T * Bytes
4663 ** Pointer to a variable that receives the number of bytes allocated.
4665 ** gctPHYS_ADDR * Physical
4666 ** Pointer to a variable that receives the physical address of the
4667 ** memory allocation.
4669 ** gctPOINTER * Logical
4670 ** Pointer to a variable that receives the logical address of the
4671 ** memory allocation.
4674 gckOS_AllocateContiguous(
4676 IN gctBOOL InUserSpace,
4677 IN OUT gctSIZE_T * Bytes,
4678 OUT gctPHYS_ADDR * Physical,
4679 OUT gctPOINTER * Logical
4684 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4685 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4687 /* Verify the arguments. */
4688 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4689 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4690 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4691 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4692 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4694 /* Same as non-paged memory for now. */
4695 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4702 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4703 *Bytes, *Physical, *Logical);
4704 return gcvSTATUS_OK;
4707 /* Return the status. */
4712 /*******************************************************************************
4714 ** gckOS_FreeContiguous
4716 ** Free memory allocated from the contiguous pool.
4721 ** Pointer to an gckOS object.
4723 ** gctPHYS_ADDR Physical
4724 ** Physical address of the allocation.
4726 ** gctPOINTER Logical
4727 ** Logicval address of the allocation.
4730 ** Number of bytes of the allocation.
4737 gckOS_FreeContiguous(
4739 IN gctPHYS_ADDR Physical,
4740 IN gctPOINTER Logical,
4746 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4747 Os, Physical, Logical, Bytes);
4749 /* Verify the arguments. */
4750 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4751 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4752 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4753 gcmkVERIFY_ARGUMENT(Bytes > 0);
4755 /* Same of non-paged memory for now. */
4756 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4760 return gcvSTATUS_OK;
4763 /* Return the status. */
4769 /******************************************************************************
4771 ** gckOS_GetKernelLogical
4773 ** Return the kernel logical pointer that corresponods to the specified
4774 ** hardware address.
4779 ** Pointer to an gckOS object.
4781 ** gctUINT32 Address
4782 ** Hardware physical address.
4786 ** gctPOINTER * KernelPointer
4787 ** Pointer to a variable receiving the pointer in kernel address space.
4790 gckOS_GetKernelLogical(
4792 IN gctUINT32 Address,
4793 OUT gctPOINTER * KernelPointer
4796 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4800 gckOS_GetKernelLogicalEx(
4803 IN gctUINT32 Address,
4804 OUT gctPOINTER * KernelPointer
4809 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4813 gckGALDEVICE device;
4819 /* Extract the pointer to the gckGALDEVICE class. */
4820 device = (gckGALDEVICE) Os->device;
4822 /* Kernel shortcut. */
4823 kernel = device->kernels[Core];
4825 if (Core == gcvCORE_VG)
4827 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4828 kernel->vg->hardware, Address, &pool, &offset
4834 /* Split the memory address into a pool type and offset. */
4835 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4836 kernel->hardware, Address, &pool, &offset
4840 /* Dispatch on pool. */
4843 case gcvPOOL_LOCAL_INTERNAL:
4844 /* Internal memory. */
4845 logical = device->internalLogical;
4848 case gcvPOOL_LOCAL_EXTERNAL:
4849 /* External memory. */
4850 logical = device->externalLogical;
4853 case gcvPOOL_SYSTEM:
4854 /* System memory. */
4855 logical = device->contiguousBase;
4859 /* Invalid memory pool. */
4861 return gcvSTATUS_INVALID_ARGUMENT;
4864 /* Build logical address of specified address. */
4865 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4868 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4869 return gcvSTATUS_OK;
4873 /* Return status. */
4879 /*******************************************************************************
4881 ** gckOS_MapUserPointer
4883 ** Map a pointer from the user process into the kernel address space.
4888 ** Pointer to an gckOS object.
4890 ** gctPOINTER Pointer
4891 ** Pointer in user process space that needs to be mapped.
4894 ** Number of bytes that need to be mapped.
4898 ** gctPOINTER * KernelPointer
4899 ** Pointer to a variable receiving the mapped pointer in kernel address
4903 gckOS_MapUserPointer(
4905 IN gctPOINTER Pointer,
4907 OUT gctPOINTER * KernelPointer
4910 gctPOINTER buf = gcvNULL;
4913 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
4915 /* Verify the arguments. */
4916 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4917 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4918 gcmkVERIFY_ARGUMENT(Size > 0);
4919 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4921 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
4926 "%s(%d): Failed to allocate memory.",
4927 __FUNCTION__, __LINE__
4930 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4931 return gcvSTATUS_OUT_OF_MEMORY;
4934 len = copy_from_user(buf, Pointer, Size);
4939 "%s(%d): Failed to copy data from user.",
4940 __FUNCTION__, __LINE__
4948 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
4949 return gcvSTATUS_GENERIC_IO;
4952 *KernelPointer = buf;
4954 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4955 return gcvSTATUS_OK;
4958 /*******************************************************************************
4960 ** gckOS_UnmapUserPointer
4962 ** Unmap a user process pointer from the kernel address space.
4967 ** Pointer to an gckOS object.
4969 ** gctPOINTER Pointer
4970 ** Pointer in user process space that needs to be unmapped.
4973 ** Number of bytes that need to be unmapped.
4975 ** gctPOINTER KernelPointer
4976 ** Pointer in kernel address space that needs to be unmapped.
4983 gckOS_UnmapUserPointer(
4985 IN gctPOINTER Pointer,
4987 IN gctPOINTER KernelPointer
4992 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
4993 Os, Pointer, Size, KernelPointer);
4996 /* Verify the arguments. */
4997 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4998 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4999 gcmkVERIFY_ARGUMENT(Size > 0);
5000 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5002 len = copy_to_user(Pointer, KernelPointer, Size);
5004 kfree(KernelPointer);
5010 "%s(%d): Failed to copy data to user.",
5011 __FUNCTION__, __LINE__
5014 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
5015 return gcvSTATUS_GENERIC_IO;
5019 return gcvSTATUS_OK;
5022 /*******************************************************************************
5024 ** gckOS_QueryNeedCopy
5026 ** Query whether the memory can be accessed or mapped directly or it has to be
5032 ** Pointer to an gckOS object.
5034 ** gctUINT32 ProcessID
5035 ** Process ID of the current process.
5039 ** gctBOOL_PTR NeedCopy
5040 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
5041 ** gcvFALSE if the memory can be accessed or mapped dircetly.
5044 gckOS_QueryNeedCopy(
5046 IN gctUINT32 ProcessID,
5047 OUT gctBOOL_PTR NeedCopy
5050 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
5052 /* Verify the arguments. */
5053 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5054 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
5056 /* We need to copy data. */
5057 *NeedCopy = gcvTRUE;
5060 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
5061 return gcvSTATUS_OK;
5064 /*******************************************************************************
5066 ** gckOS_CopyFromUserData
5068 ** Copy data from user to kernel memory.
5073 ** Pointer to an gckOS object.
5075 ** gctPOINTER KernelPointer
5076 ** Pointer to kernel memory.
5078 ** gctPOINTER Pointer
5079 ** Pointer to user memory.
5082 ** Number of bytes to copy.
5089 gckOS_CopyFromUserData(
5091 IN gctPOINTER KernelPointer,
5092 IN gctPOINTER Pointer,
5098 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5099 Os, KernelPointer, Pointer, Size);
5101 /* Verify the arguments. */
5102 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5103 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5104 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5105 gcmkVERIFY_ARGUMENT(Size > 0);
5107 /* Copy data from user. */
5108 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
5110 /* Could not copy all the bytes. */
5111 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5116 return gcvSTATUS_OK;
5119 /* Return the status. */
5124 /*******************************************************************************
5126 ** gckOS_CopyToUserData
5128 ** Copy data from kernel to user memory.
5133 ** Pointer to an gckOS object.
5135 ** gctPOINTER KernelPointer
5136 ** Pointer to kernel memory.
5138 ** gctPOINTER Pointer
5139 ** Pointer to user memory.
5142 ** Number of bytes to copy.
5149 gckOS_CopyToUserData(
5151 IN gctPOINTER KernelPointer,
5152 IN gctPOINTER Pointer,
5158 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5159 Os, KernelPointer, Pointer, Size);
5161 /* Verify the arguments. */
5162 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5163 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5164 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5165 gcmkVERIFY_ARGUMENT(Size > 0);
5167 /* Copy data to user. */
5168 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
5170 /* Could not copy all the bytes. */
5171 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5176 return gcvSTATUS_OK;
5179 /* Return the status. */
5184 /*******************************************************************************
5186 ** gckOS_WriteMemory
5188 ** Write data to a memory.
5193 ** Pointer to an gckOS object.
5195 ** gctPOINTER Address
5196 ** Address of the memory to write to.
5199 ** Data for register.
5208 IN gctPOINTER Address,
5213 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
5215 /* Verify the arguments. */
5216 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5219 if (access_ok(VERIFY_WRITE, Address, 4))
5222 if(put_user(Data, (gctUINT32*)Address))
5224 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
5229 /* Kernel address. */
5230 *(gctUINT32 *)Address = Data;
5235 return gcvSTATUS_OK;
5242 /*******************************************************************************
5244 ** gckOS_MapUserMemory
5246 ** Lock down a user buffer and return an DMA'able address to be used by the
5247 ** hardware to access it.
5251 ** gctPOINTER Memory
5252 ** Pointer to memory to lock down.
5255 ** Size in bytes of the memory to lock down.
5259 ** gctPOINTER * Info
5260 ** Pointer to variable receiving the information record required by
5261 ** gckOS_UnmapUserMemory.
5263 ** gctUINT32_PTR Address
5264 ** Pointer to a variable that will receive the address DMA'able by the
5268 gckOS_MapUserMemory(
5271 IN gctPOINTER Memory,
5272 IN gctUINT32 Physical,
5274 OUT gctPOINTER * Info,
5275 OUT gctUINT32_PTR Address
5280 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
5283 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
5286 return gcvSTATUS_OK;
5293 gctSIZE_T pageCount, i, j;
5294 gctUINT32_PTR pageTable;
5295 gctUINT32 address = 0, physical = ~0U;
5296 gctUINTPTR_T start, end, memory;
5300 gcsPageInfo_PTR info = gcvNULL;
5301 struct page **pages = gcvNULL;
5303 /* Verify the arguments. */
5304 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5305 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
5306 gcmkVERIFY_ARGUMENT(Size > 0);
5307 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5308 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5312 memory = (gctUINTPTR_T) Memory;
5314 /* Get the number of required pages. */
5315 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5316 start = memory >> PAGE_SHIFT;
5317 pageCount = end - start;
5320 gcvLEVEL_INFO, gcvZONE_OS,
5321 "%s(%d): pageCount: %d.",
5322 __FUNCTION__, __LINE__,
5327 if ((memory + Size) < memory)
5329 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5330 return gcvSTATUS_INVALID_ARGUMENT;
5333 MEMORY_MAP_LOCK(Os);
5335 /* Allocate the Info struct. */
5336 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
5338 if (info == gcvNULL)
5340 status = gcvSTATUS_OUT_OF_MEMORY;
5344 /* Allocate the array of page addresses. */
5345 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
5347 if (pages == gcvNULL)
5349 status = gcvSTATUS_OUT_OF_MEMORY;
5353 if (Physical != ~0U)
5355 for (i = 0; i < pageCount; i++)
5357 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
5363 /* Get the user pages. */
5364 down_read(¤t->mm->mmap_sem);
5365 result = get_user_pages(current,
5374 up_read(¤t->mm->mmap_sem);
5376 if (result <=0 || result < pageCount)
5378 struct vm_area_struct *vma;
5380 /* Free the page table. */
5381 if (pages != gcvNULL)
5383 /* Release the pages if any. */
5386 for (i = 0; i < result; i++)
5388 if (pages[i] == gcvNULL)
5393 page_cache_release(pages[i]);
5401 vma = find_vma(current->mm, memory);
5403 if (vma && (vma->vm_flags & VM_PFNMAP) )
5409 pgd_t * pgd = pgd_offset(current->mm, memory);
5410 pud_t * pud = pud_offset(pgd, memory);
5413 pmd_t * pmd = pmd_offset(pud, memory);
5414 pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
5417 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5422 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5425 pfn = pte_pfn(*pte);
5427 physical = (pfn << PAGE_SHIFT) | (memory & ~PAGE_MASK);
5429 pte_unmap_unlock(pte, ptl);
5431 if ((Os->device->kernels[Core]->hardware->mmuVersion == 0)
5432 && !((physical - Os->device->baseAddress) & 0x80000000))
5434 info->pages = gcvNULL;
5435 info->pageTable = gcvNULL;
5437 MEMORY_MAP_UNLOCK(Os);
5439 *Address = physical - Os->device->baseAddress;
5442 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5445 return gcvSTATUS_OK;
5450 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5457 for (i = 0; i < pageCount; i++)
5459 /* Flush(clean) the data cache. */
5460 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5461 (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
5462 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5468 /* Flush(clean) the data cache. */
5469 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5470 (gctPOINTER)(gctUINTPTR_T)(physical & PAGE_MASK),
5471 (gctPOINTER)(memory & PAGE_MASK),
5472 PAGE_SIZE * pageCount));
5476 if (Core == gcvCORE_VG)
5478 /* Allocate pages inside the page table. */
5479 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5480 pageCount * (PAGE_SIZE/4096),
5481 (gctPOINTER *) &pageTable,
5487 /* Allocate pages inside the page table. */
5488 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5489 pageCount * (PAGE_SIZE/4096),
5490 (gctPOINTER *) &pageTable,
5493 /* Fill the page table. */
5494 for (i = 0; i < pageCount; i++)
5497 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5501 phys = page_to_phys(pages[i]);
5505 phys = (physical & PAGE_MASK) + i * PAGE_SIZE;
5509 if (Core == gcvCORE_VG)
5511 /* Get the physical address from page struct. */
5513 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5520 /* Get the physical address from page struct. */
5522 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5527 for (j = 1; j < (PAGE_SIZE/4096); j++)
5529 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5533 gcvLEVEL_INFO, gcvZONE_OS,
5534 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5535 __FUNCTION__, __LINE__,
5536 i, phys, pageTable[i]);
5540 if (Core == gcvCORE_VG)
5542 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5547 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
5550 /* Save pointer to page table. */
5551 info->pageTable = pageTable;
5552 info->pages = pages;
5554 *Info = (gctPOINTER) info;
5557 gcvLEVEL_INFO, gcvZONE_OS,
5558 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5559 __FUNCTION__, __LINE__,
5565 offset = (Physical != ~0U)
5566 ? (Physical & ~PAGE_MASK)
5567 : (memory & ~PAGE_MASK);
5569 /* Return address. */
5570 *Address = address + offset;
5573 gcvLEVEL_INFO, gcvZONE_OS,
5574 "%s(%d): Address: 0x%X.",
5575 __FUNCTION__, __LINE__,
5580 status = gcvSTATUS_OK;
5586 if (gcmIS_ERROR(status))
5590 "%s(%d): error occured: %d.",
5591 __FUNCTION__, __LINE__,
5595 /* Release page array. */
5596 if (result > 0 && pages != gcvNULL)
5600 "%s(%d): error: page table is freed.",
5601 __FUNCTION__, __LINE__
5604 for (i = 0; i < result; i++)
5606 if (pages[i] == gcvNULL)
5610 page_cache_release(pages[i]);
5614 if (info!= gcvNULL && pages != gcvNULL)
5618 "%s(%d): error: pages is freed.",
5619 __FUNCTION__, __LINE__
5622 /* Free the page table. */
5624 info->pages = gcvNULL;
5627 /* Release page info struct. */
5628 if (info != gcvNULL)
5632 "%s(%d): error: info is freed.",
5633 __FUNCTION__, __LINE__
5636 /* Free the page info struct. */
5642 MEMORY_MAP_UNLOCK(Os);
5644 /* Return the status. */
5645 if (gcmIS_SUCCESS(status))
5647 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5659 /*******************************************************************************
5661 ** gckOS_UnmapUserMemory
5663 ** Unlock a user buffer and that was previously locked down by
5664 ** gckOS_MapUserMemory.
5668 ** gctPOINTER Memory
5669 ** Pointer to memory to unlock.
5672 ** Size in bytes of the memory to unlock.
5675 ** Information record returned by gckOS_MapUserMemory.
5677 ** gctUINT32_PTR Address
5678 ** The address returned by gckOS_MapUserMemory.
5685 gckOS_UnmapUserMemory(
5688 IN gctPOINTER Memory,
5691 IN gctUINT32 Address
5696 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5697 Os, Core, Memory, Size, Info, Address);
5700 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5703 return gcvSTATUS_OK;
5710 gctUINTPTR_T memory, start, end;
5711 gcsPageInfo_PTR info;
5712 gctSIZE_T pageCount, i;
5713 struct page **pages;
5715 /* Verify the arguments. */
5716 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5717 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5718 gcmkVERIFY_ARGUMENT(Size > 0);
5719 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5723 info = (gcsPageInfo_PTR) Info;
5725 pages = info->pages;
5728 gcvLEVEL_INFO, gcvZONE_OS,
5729 "%s(%d): info=0x%X, pages=0x%X.",
5730 __FUNCTION__, __LINE__,
5734 /* Invalid page array. */
5735 if (pages == gcvNULL && info->pageTable == gcvNULL)
5740 return gcvSTATUS_OK;
5743 memory = (gctUINTPTR_T)Memory;
5744 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5745 start = memory >> PAGE_SHIFT;
5746 pageCount = end - start;
5749 if ((memory + Size) < memory)
5751 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5752 return gcvSTATUS_INVALID_ARGUMENT;
5756 gcvLEVEL_INFO, gcvZONE_OS,
5757 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5758 __FUNCTION__, __LINE__,
5759 memory, pageCount, info->pageTable
5762 MEMORY_MAP_LOCK(Os);
5764 gcmkASSERT(info->pageTable != gcvNULL);
5767 if (Core == gcvCORE_VG)
5769 /* Free the pages from the MMU. */
5770 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5772 pageCount * (PAGE_SIZE/4096)
5778 /* Free the pages from the MMU. */
5779 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5781 pageCount * (PAGE_SIZE/4096)
5785 /* Release the page cache. */
5788 for (i = 0; i < pageCount; i++)
5791 gcvLEVEL_INFO, gcvZONE_OS,
5792 "%s(%d): pages[%d]: 0x%X.",
5793 __FUNCTION__, __LINE__,
5797 if (!PageReserved(pages[i]))
5799 SetPageDirty(pages[i]);
5802 page_cache_release(pages[i]);
5807 status = gcvSTATUS_OK;
5811 if (info != gcvNULL)
5813 /* Free the page array. */
5814 if (info->pages != gcvNULL)
5822 MEMORY_MAP_UNLOCK(Os);
5824 /* Return the status. */
5831 /*******************************************************************************
5833 ** gckOS_GetBaseAddress
5835 ** Get the base address for the physical memory.
5840 ** Pointer to the gckOS object.
5844 ** gctUINT32_PTR BaseAddress
5845 ** Pointer to a variable that will receive the base address.
5848 gckOS_GetBaseAddress(
5850 OUT gctUINT32_PTR BaseAddress
5853 gcmkHEADER_ARG("Os=0x%X", Os);
5855 /* Verify the arguments. */
5856 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5857 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5859 /* Return base address. */
5860 *BaseAddress = Os->device->baseAddress;
5863 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5864 return gcvSTATUS_OK;
5868 gckOS_SuspendInterrupt(
5872 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5876 gckOS_SuspendInterruptEx(
5881 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5883 /* Verify the arguments. */
5884 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5886 disable_irq(Os->device->irqLines[Core]);
5889 return gcvSTATUS_OK;
5893 gckOS_ResumeInterrupt(
5897 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
5901 gckOS_ResumeInterruptEx(
5906 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5908 /* Verify the arguments. */
5909 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5911 enable_irq(Os->device->irqLines[Core]);
5914 return gcvSTATUS_OK;
5919 IN gctPOINTER Destination,
5920 IN gctCONST_POINTER Source,
5924 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
5925 Destination, Source, Bytes);
5927 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
5928 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
5929 gcmkVERIFY_ARGUMENT(Bytes > 0);
5931 memcpy(Destination, Source, Bytes);
5934 return gcvSTATUS_OK;
5939 IN gctPOINTER Memory,
5943 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
5945 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5946 gcmkVERIFY_ARGUMENT(Bytes > 0);
5948 memset(Memory, 0, Bytes);
5951 return gcvSTATUS_OK;
5954 /*******************************************************************************
5955 ********************************* Cache Control ********************************
5956 *******************************************************************************/
5958 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
5959 static inline gceSTATUS
5961 gceCACHEOPERATION Type,
5962 unsigned long Start,
5968 case gcvCACHE_CLEAN:
5969 outer_clean_range(Start, End);
5971 case gcvCACHE_INVALIDATE:
5972 outer_inv_range(Start, End);
5974 case gcvCACHE_FLUSH:
5975 outer_flush_range(Start, End);
5978 return gcvSTATUS_INVALID_ARGUMENT;
5981 return gcvSTATUS_OK;
5984 #if gcdENABLE_OUTER_CACHE_PATCH
5985 /*******************************************************************************
5986 ** _HandleOuterCache
5988 ** Handle the outer cache for the specified addresses.
5993 ** Pointer to gckOS object.
5995 ** gctUINT32 ProcessID
5996 ** Process ID Logical belongs.
5998 ** gctPHYS_ADDR Handle
5999 ** Physical address handle. If gcvNULL it is video memory.
6001 ** gctPOINTER Physical
6002 ** Physical address to flush.
6004 ** gctPOINTER Logical
6005 ** Logical address to flush.
6008 ** Size of the address range in bytes to flush.
6010 ** gceOUTERCACHE_OPERATION Type
6011 ** Operation need to be execute.
6016 IN gctUINT32 ProcessID,
6017 IN gctPHYS_ADDR Handle,
6018 IN gctPOINTER Physical,
6019 IN gctPOINTER Logical,
6021 IN gceCACHEOPERATION Type
6025 gctUINT32 i, pageNum;
6026 unsigned long paddr;
6029 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6030 Os, ProcessID, Handle, Logical, Bytes);
6032 if (Physical != gcvNULL)
6034 /* Non paged memory or gcvPOOL_USER surface */
6035 paddr = (unsigned long) Physical;
6036 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6038 else if ((Handle == gcvNULL)
6039 || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
6042 /* Video Memory or contiguous virtual memory */
6043 gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
6044 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6048 /* Non contiguous virtual memory */
6049 vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
6050 pageNum = GetPageCount(Bytes, 0);
6052 for (i = 0; i < pageNum; i += 1)
6054 gcmkONERROR(_ConvertLogical2Physical(
6056 vaddr + PAGE_SIZE * i,
6062 gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
6070 return gcvSTATUS_OK;
6073 /* Return the status. */
6080 /*******************************************************************************
6083 ** Clean the cache for the specified addresses. The GPU is going to need the
6084 ** data. If the system is allocating memory as non-cachable, this function can
6090 ** Pointer to gckOS object.
6092 ** gctUINT32 ProcessID
6093 ** Process ID Logical belongs.
6095 ** gctPHYS_ADDR Handle
6096 ** Physical address handle. If gcvNULL it is video memory.
6098 ** gctPOINTER Physical
6099 ** Physical address to flush.
6101 ** gctPOINTER Logical
6102 ** Logical address to flush.
6105 ** Size of the address range in bytes to flush.
6110 IN gctUINT32 ProcessID,
6111 IN gctPHYS_ADDR Handle,
6112 IN gctPOINTER Physical,
6113 IN gctPOINTER Logical,
6117 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6118 Os, ProcessID, Handle, Logical, Bytes);
6120 /* Verify the arguments. */
6121 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6122 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6123 gcmkVERIFY_ARGUMENT(Bytes > 0);
6125 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6129 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6130 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
6132 dmac_clean_range(Logical, Logical + Bytes);
6135 #if defined(CONFIG_OUTER_CACHE)
6137 #if gcdENABLE_OUTER_CACHE_PATCH
6138 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
6140 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6144 #elif defined(CONFIG_MIPS)
6146 dma_cache_wback((unsigned long) Logical, Bytes);
6148 #elif defined(CONFIG_PPC)
6153 dma_sync_single_for_device(
6163 return gcvSTATUS_OK;
6166 /*******************************************************************************
6167 ** gckOS_CacheInvalidate
6169 ** Invalidate the cache for the specified addresses. The GPU is going to need
6170 ** data. If the system is allocating memory as non-cachable, this function can
6176 ** Pointer to gckOS object.
6178 ** gctUINT32 ProcessID
6179 ** Process ID Logical belongs.
6181 ** gctPHYS_ADDR Handle
6182 ** Physical address handle. If gcvNULL it is video memory.
6184 ** gctPOINTER Logical
6185 ** Logical address to flush.
6188 ** Size of the address range in bytes to flush.
6191 gckOS_CacheInvalidate(
6193 IN gctUINT32 ProcessID,
6194 IN gctPHYS_ADDR Handle,
6195 IN gctPOINTER Physical,
6196 IN gctPOINTER Logical,
6200 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6201 Os, ProcessID, Handle, Logical, Bytes);
6203 /* Verify the arguments. */
6204 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6205 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6206 gcmkVERIFY_ARGUMENT(Bytes > 0);
6208 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6212 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6213 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
6215 dmac_inv_range(Logical, Logical + Bytes);
6218 #if defined(CONFIG_OUTER_CACHE)
6220 #if gcdENABLE_OUTER_CACHE_PATCH
6221 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
6223 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6227 #elif defined(CONFIG_MIPS)
6228 dma_cache_inv((unsigned long) Logical, Bytes);
6229 #elif defined(CONFIG_PPC)
6232 dma_sync_single_for_device(
6242 return gcvSTATUS_OK;
6245 /*******************************************************************************
6248 ** Clean the cache for the specified addresses and invalidate the lines as
6249 ** well. The GPU is going to need and modify the data. If the system is
6250 ** allocating memory as non-cachable, this function can be ignored.
6255 ** Pointer to gckOS object.
6257 ** gctUINT32 ProcessID
6258 ** Process ID Logical belongs.
6260 ** gctPHYS_ADDR Handle
6261 ** Physical address handle. If gcvNULL it is video memory.
6263 ** gctPOINTER Logical
6264 ** Logical address to flush.
6267 ** Size of the address range in bytes to flush.
6272 IN gctUINT32 ProcessID,
6273 IN gctPHYS_ADDR Handle,
6274 IN gctPOINTER Physical,
6275 IN gctPOINTER Logical,
6279 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6280 Os, ProcessID, Handle, Logical, Bytes);
6282 /* Verify the arguments. */
6283 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6284 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6285 gcmkVERIFY_ARGUMENT(Bytes > 0);
6287 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6290 dmac_flush_range(Logical, Logical + Bytes);
6292 #if defined(CONFIG_OUTER_CACHE)
6294 #if gcdENABLE_OUTER_CACHE_PATCH
6295 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6297 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6301 #elif defined(CONFIG_MIPS)
6302 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6303 #elif defined(CONFIG_PPC)
6306 dma_sync_single_for_device(
6316 return gcvSTATUS_OK;
6319 /*******************************************************************************
6320 ********************************* Broadcasting *********************************
6321 *******************************************************************************/
6323 /*******************************************************************************
6327 ** System hook for broadcast events from the kernel driver.
6332 ** Pointer to the gckOS object.
6334 ** gckHARDWARE Hardware
6335 ** Pointer to the gckHARDWARE object.
6337 ** gceBROADCAST Reason
6338 ** Reason for the broadcast. Can be one of the following values:
6340 ** gcvBROADCAST_GPU_IDLE
6341 ** Broadcasted when the kernel driver thinks the GPU might be
6342 ** idle. This can be used to handle power management.
6344 ** gcvBROADCAST_GPU_COMMIT
6345 ** Broadcasted when any client process commits a command
6346 ** buffer. This can be used to handle power management.
6348 ** gcvBROADCAST_GPU_STUCK
6349 ** Broadcasted when the kernel driver hits the timeout waiting
6352 ** gcvBROADCAST_FIRST_PROCESS
6353 ** First process is trying to connect to the kernel.
6355 ** gcvBROADCAST_LAST_PROCESS
6356 ** Last process has detached from the kernel.
6365 IN gckHARDWARE Hardware,
6366 IN gceBROADCAST Reason
6371 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6373 /* Verify the arguments. */
6374 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6375 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6379 case gcvBROADCAST_FIRST_PROCESS:
6380 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6383 case gcvBROADCAST_LAST_PROCESS:
6384 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6388 gckHARDWARE_SetPowerManagementState(Hardware,
6389 gcvPOWER_OFF_BROADCAST));
6392 case gcvBROADCAST_GPU_IDLE:
6393 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6397 gckHARDWARE_SetPowerManagementState(Hardware,
6398 #if gcdPOWER_SUSNPEND_WHEN_IDLE
6399 gcvPOWER_SUSPEND_BROADCAST));
6401 gcvPOWER_IDLE_BROADCAST));
6404 /* Add idle process DB. */
6405 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6408 gcvNULL, gcvNULL, 0));
6411 case gcvBROADCAST_GPU_COMMIT:
6412 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6414 /* Add busy process DB. */
6415 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6418 gcvNULL, gcvNULL, 0));
6422 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6425 case gcvBROADCAST_GPU_STUCK:
6426 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6427 #if !gcdENABLE_RECOVERY
6428 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6430 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6433 case gcvBROADCAST_AXI_BUS_ERROR:
6434 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6435 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6436 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6442 return gcvSTATUS_OK;
6445 /* Return the status. */
6450 /*******************************************************************************
6452 ** gckOS_BroadcastHurry
6454 ** The GPU is running too slow.
6459 ** Pointer to the gckOS object.
6461 ** gckHARDWARE Hardware
6462 ** Pointer to the gckHARDWARE object.
6465 ** The higher the number, the higher the urgency to speed up the GPU.
6466 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6473 gckOS_BroadcastHurry(
6475 IN gckHARDWARE Hardware,
6479 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6481 /* Do whatever you need to do to speed up the GPU now. */
6485 return gcvSTATUS_OK;
6488 /*******************************************************************************
6490 ** gckOS_BroadcastCalibrateSpeed
6492 ** Calibrate the speed of the GPU.
6497 ** Pointer to the gckOS object.
6499 ** gckHARDWARE Hardware
6500 ** Pointer to the gckHARDWARE object.
6502 ** gctUINT Idle, Time
6503 ** Idle/Time will give the percentage the GPU is idle, so you can use
6504 ** this to calibrate the working point of the GPU.
6511 gckOS_BroadcastCalibrateSpeed(
6513 IN gckHARDWARE Hardware,
6518 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6519 Os, Hardware, Idle, Time);
6521 /* Do whatever you need to do to callibrate the GPU speed. */
6525 return gcvSTATUS_OK;
6528 /*******************************************************************************
6529 ********************************** Semaphores **********************************
6530 *******************************************************************************/
6532 /*******************************************************************************
6534 ** gckOS_CreateSemaphore
6536 ** Create a semaphore.
6541 ** Pointer to the gckOS object.
6545 ** gctPOINTER * Semaphore
6546 ** Pointer to the variable that will receive the created semaphore.
6549 gckOS_CreateSemaphore(
6551 OUT gctPOINTER * Semaphore
6555 struct semaphore *sem = gcvNULL;
6557 gcmkHEADER_ARG("Os=0x%X", Os);
6559 /* Verify the arguments. */
6560 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6561 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6563 /* Allocate the semaphore structure. */
6564 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6567 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6570 /* Initialize the semaphore. */
6573 /* Return to caller. */
6574 *Semaphore = (gctPOINTER) sem;
6578 return gcvSTATUS_OK;
6581 /* Return the status. */
6586 /*******************************************************************************
6588 ** gckOS_AcquireSemaphore
6590 ** Acquire a semaphore.
6595 ** Pointer to the gckOS object.
6597 ** gctPOINTER Semaphore
6598 ** Pointer to the semaphore thet needs to be acquired.
6605 gckOS_AcquireSemaphore(
6607 IN gctPOINTER Semaphore
6612 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6614 /* Verify the arguments. */
6615 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6616 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6618 /* Acquire the semaphore. */
6619 if (down_interruptible((struct semaphore *) Semaphore))
6621 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6626 return gcvSTATUS_OK;
6629 /* Return the status. */
6634 /*******************************************************************************
6636 ** gckOS_TryAcquireSemaphore
6638 ** Try to acquire a semaphore.
6643 ** Pointer to the gckOS object.
6645 ** gctPOINTER Semaphore
6646 ** Pointer to the semaphore thet needs to be acquired.
6653 gckOS_TryAcquireSemaphore(
6655 IN gctPOINTER Semaphore
6660 gcmkHEADER_ARG("Os=0x%x", Os);
6662 /* Verify the arguments. */
6663 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6664 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6666 /* Acquire the semaphore. */
6667 if (down_trylock((struct semaphore *) Semaphore))
6670 status = gcvSTATUS_TIMEOUT;
6677 return gcvSTATUS_OK;
6680 /*******************************************************************************
6682 ** gckOS_ReleaseSemaphore
6684 ** Release a previously acquired semaphore.
6689 ** Pointer to the gckOS object.
6691 ** gctPOINTER Semaphore
6692 ** Pointer to the semaphore thet needs to be released.
6699 gckOS_ReleaseSemaphore(
6701 IN gctPOINTER Semaphore
6704 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6706 /* Verify the arguments. */
6707 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6708 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6710 /* Release the semaphore. */
6711 up((struct semaphore *) Semaphore);
6715 return gcvSTATUS_OK;
6718 /*******************************************************************************
6720 ** gckOS_DestroySemaphore
6722 ** Destroy a semaphore.
6727 ** Pointer to the gckOS object.
6729 ** gctPOINTER Semaphore
6730 ** Pointer to the semaphore thet needs to be destroyed.
6737 gckOS_DestroySemaphore(
6739 IN gctPOINTER Semaphore
6742 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6744 /* Verify the arguments. */
6745 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6746 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6748 /* Free the sempahore structure. */
6753 return gcvSTATUS_OK;
6756 /*******************************************************************************
6758 ** gckOS_GetProcessID
6760 ** Get current process ID.
6768 ** gctUINT32_PTR ProcessID
6769 ** Pointer to the variable that receives the process ID.
6773 OUT gctUINT32_PTR ProcessID
6776 /* Get process ID. */
6777 if (ProcessID != gcvNULL)
6779 *ProcessID = _GetProcessID();
6783 return gcvSTATUS_OK;
6786 /*******************************************************************************
6788 ** gckOS_GetThreadID
6790 ** Get current thread ID.
6798 ** gctUINT32_PTR ThreadID
6799 ** Pointer to the variable that receives the thread ID.
6803 OUT gctUINT32_PTR ThreadID
6806 /* Get thread ID. */
6807 if (ThreadID != gcvNULL)
6809 *ThreadID = _GetThreadID();
6813 return gcvSTATUS_OK;
6816 /*******************************************************************************
6818 ** gckOS_SetGPUPower
6820 ** Set the power of the GPU on or off.
6825 ** Pointer to a gckOS object.
6828 ** GPU whose power is set.
6831 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6834 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6848 struct clk *clk_3dcore = Os->device->clk_3d_core;
6849 struct clk *clk_3dshader = Os->device->clk_3d_shader;
6850 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
6851 struct clk *clk_3d_axi = Os->device->clk_3d_axi;
6853 struct clk *clk_2dcore = Os->device->clk_2d_core;
6854 struct clk *clk_2d_axi = Os->device->clk_2d_axi;
6855 struct clk *clk_vg_axi = Os->device->clk_vg_axi;
6857 gctBOOL oldClockState = gcvFALSE;
6858 gctBOOL oldPowerState = gcvFALSE;
6860 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6862 if (Os->device->kernels[Core] != NULL)
6865 if (Core == gcvCORE_VG)
6867 oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
6868 oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
6873 oldClockState = Os->device->kernels[Core]->hardware->clockState;
6874 oldPowerState = Os->device->kernels[Core]->hardware->powerState;
6879 if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
6881 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6882 if(!IS_ERR(Os->device->gpu_regulator))
6883 regulator_enable(Os->device->gpu_regulator);
6885 imx_gpc_power_up_pu(true);
6889 pm_runtime_get_sync(Os->device->pmdev);
6893 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6894 if (Clock == gcvTRUE) {
6895 if (oldClockState == gcvFALSE) {
6898 clk_enable(clk_3dcore);
6900 clk_enable(clk_3dshader);
6903 clk_enable(clk_2dcore);
6904 clk_enable(clk_2d_axi);
6907 clk_enable(clk_2dcore);
6908 clk_enable(clk_vg_axi);
6915 if (oldClockState == gcvTRUE) {
6919 clk_disable(clk_3dshader);
6920 clk_disable(clk_3dcore);
6923 clk_disable(clk_2dcore);
6924 clk_disable(clk_2d_axi);
6927 clk_disable(clk_2dcore);
6928 clk_disable(clk_vg_axi);
6936 if (Clock == gcvTRUE) {
6937 if (oldClockState == gcvFALSE) {
6940 clk_prepare(clk_3dcore);
6941 clk_enable(clk_3dcore);
6942 clk_prepare(clk_3dshader);
6943 clk_enable(clk_3dshader);
6944 clk_prepare(clk_3d_axi);
6945 clk_enable(clk_3d_axi);
6948 clk_prepare(clk_2dcore);
6949 clk_enable(clk_2dcore);
6950 clk_prepare(clk_2d_axi);
6951 clk_enable(clk_2d_axi);
6954 clk_prepare(clk_2dcore);
6955 clk_enable(clk_2dcore);
6956 clk_prepare(clk_vg_axi);
6957 clk_enable(clk_vg_axi);
6964 if (oldClockState == gcvTRUE) {
6967 clk_disable(clk_3dshader);
6968 clk_unprepare(clk_3dshader);
6969 clk_disable(clk_3dcore);
6970 clk_unprepare(clk_3dcore);
6971 clk_disable(clk_3d_axi);
6972 clk_unprepare(clk_3d_axi);
6975 clk_disable(clk_2dcore);
6976 clk_unprepare(clk_2dcore);
6977 clk_disable(clk_2d_axi);
6978 clk_unprepare(clk_2d_axi);
6981 clk_disable(clk_2dcore);
6982 clk_unprepare(clk_2dcore);
6983 clk_disable(clk_vg_axi);
6984 clk_unprepare(clk_vg_axi);
6992 if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
6995 pm_runtime_put_sync(Os->device->pmdev);
6998 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
6999 if(!IS_ERR(Os->device->gpu_regulator))
7000 regulator_disable(Os->device->gpu_regulator);
7002 imx_gpc_power_up_pu(false);
7006 /* TODO: Put your code here. */
7008 return gcvSTATUS_OK;
7011 /*******************************************************************************
7020 ** Pointer to a gckOS object.
7023 ** GPU whose power is set.
7035 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7036 #define SRC_SCR_OFFSET 0
7037 #define BP_SRC_SCR_GPU3D_RST 1
7038 #define BP_SRC_SCR_GPU2D_RST 4
7039 void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
7040 gctUINT32 bit_offset,val;
7042 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
7044 if(Core == gcvCORE_MAJOR) {
7045 bit_offset = BP_SRC_SCR_GPU3D_RST;
7046 } else if((Core == gcvCORE_VG)
7047 ||(Core == gcvCORE_2D)) {
7048 bit_offset = BP_SRC_SCR_GPU2D_RST;
7050 return gcvSTATUS_INVALID_CONFIG;
7052 val = __raw_readl(src_base + SRC_SCR_OFFSET);
7053 val &= ~(1 << (bit_offset));
7054 val |= (1 << (bit_offset));
7055 __raw_writel(val, src_base + SRC_SCR_OFFSET);
7057 while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
7058 (1 << (bit_offset))) != 0) {
7063 imx_src_reset_gpu((int)Core);
7065 return gcvSTATUS_OK;
7068 /*******************************************************************************
7070 ** gckOS_PrepareGPUFrequency
7072 ** Prepare to set GPU frequency and voltage.
7077 ** Pointer to a gckOS object.
7080 ** GPU whose frequency and voltage will be set.
7087 gckOS_PrepareGPUFrequency(
7092 return gcvSTATUS_OK;
7095 /*******************************************************************************
7097 ** gckOS_FinishGPUFrequency
7099 ** Finish GPU frequency setting.
7104 ** Pointer to a gckOS object.
7107 ** GPU whose frequency and voltage is set.
7114 gckOS_FinishGPUFrequency(
7119 return gcvSTATUS_OK;
7122 /*******************************************************************************
7124 ** gckOS_QueryGPUFrequency
7126 ** Query the current frequency of the GPU.
7131 ** Pointer to a gckOS object.
7134 ** GPU whose power is set.
7136 ** gctUINT32 * Frequency
7137 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
7140 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
7147 gckOS_QueryGPUFrequency(
7150 OUT gctUINT32 * Frequency,
7151 OUT gctUINT8 * Scale
7154 return gcvSTATUS_OK;
7157 /*******************************************************************************
7159 ** gckOS_SetGPUFrequency
7161 ** Set frequency and voltage of the GPU.
7163 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
7164 ** a real frequency according to this scale and board's configure.
7166 ** 2. BSP should find a suitable voltage for this frequency.
7168 ** 3. BSP must make sure setting take effect before this function returns.
7173 ** Pointer to a gckOS object.
7176 ** GPU whose power is set.
7179 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
7180 ** full frequency and 64 means 64/64 of full frequency.
7187 gckOS_SetGPUFrequency(
7193 return gcvSTATUS_OK;
7196 /*----------------------------------------------------------------------------*/
7197 /*----- Profile --------------------------------------------------------------*/
7200 gckOS_GetProfileTick(
7201 OUT gctUINT64_PTR Tick
7204 struct timespec time;
7206 ktime_get_ts(&time);
7208 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
7210 return gcvSTATUS_OK;
7214 gckOS_QueryProfileTickRate(
7215 OUT gctUINT64_PTR TickRate
7218 struct timespec res;
7220 hrtimer_get_res(CLOCK_MONOTONIC, &res);
7222 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
7224 return gcvSTATUS_OK;
7232 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
7233 return div_u64(Ticks, 1000000);
7235 gctUINT64 rem = Ticks;
7236 gctUINT64 b = 1000000;
7237 gctUINT64 res, d = 1;
7238 gctUINT32 high = rem >> 32;
7240 /* Reduce the thing a bit first */
7242 if (high >= 1000000)
7245 res = (gctUINT64) high << 32;
7246 rem -= (gctUINT64) (high * 1000000) << 32;
7249 while (((gctINT64) b > 0) && (b < rem))
7268 return (gctUINT32) res;
7272 /******************************************************************************\
7273 ******************************* Signal Management ******************************
7274 \******************************************************************************/
7277 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
7279 /*******************************************************************************
7281 ** gckOS_CreateSignal
7283 ** Create a new signal.
7288 ** Pointer to an gckOS object.
7290 ** gctBOOL ManualReset
7291 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7292 ** order to set the signal to nonsignaled state.
7293 ** If set to gcvFALSE, the signal will automatically be set to
7294 ** nonsignaled state by gckOS_WaitSignal function.
7298 ** gctSIGNAL * Signal
7299 ** Pointer to a variable receiving the created gctSIGNAL.
7304 IN gctBOOL ManualReset,
7305 OUT gctSIGNAL * Signal
7309 gcsSIGNAL_PTR signal;
7311 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
7313 /* Verify the arguments. */
7314 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7315 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7317 /* Create an event structure. */
7318 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
7320 if (signal == gcvNULL)
7322 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7325 /* Save the process ID. */
7326 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
7327 signal->manualReset = ManualReset;
7328 signal->hardware = gcvNULL;
7329 init_completion(&signal->obj);
7330 atomic_set(&signal->ref, 1);
7332 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
7334 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
7336 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
7337 return gcvSTATUS_OK;
7340 if (signal != gcvNULL)
7350 gckOS_SignalQueryHardware(
7352 IN gctSIGNAL Signal,
7353 OUT gckHARDWARE * Hardware
7357 gcsSIGNAL_PTR signal;
7359 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7361 /* Verify the arguments. */
7362 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7363 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7364 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7366 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7368 *Hardware = signal->hardware;
7371 return gcvSTATUS_OK;
7378 gckOS_SignalSetHardware(
7380 IN gctSIGNAL Signal,
7381 IN gckHARDWARE Hardware
7385 gcsSIGNAL_PTR signal;
7387 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7389 /* Verify the arguments. */
7390 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7391 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7393 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7395 signal->hardware = Hardware;
7398 return gcvSTATUS_OK;
7404 /*******************************************************************************
7406 ** gckOS_DestroySignal
7408 ** Destroy a signal.
7413 ** Pointer to an gckOS object.
7416 ** Pointer to the gctSIGNAL.
7423 gckOS_DestroySignal(
7429 gcsSIGNAL_PTR signal;
7430 gctBOOL acquired = gcvFALSE;
7432 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7434 /* Verify the arguments. */
7435 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7436 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7438 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7441 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7443 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7445 if (atomic_dec_and_test(&signal->ref))
7447 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7449 /* Free the sgianl. */
7453 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7454 acquired = gcvFALSE;
7458 return gcvSTATUS_OK;
7463 /* Release the mutex. */
7464 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7471 /*******************************************************************************
7475 ** Set a state of the specified signal.
7480 ** Pointer to an gckOS object.
7483 ** Pointer to the gctSIGNAL.
7486 ** If gcvTRUE, the signal will be set to signaled state.
7487 ** If gcvFALSE, the signal will be set to nonsignaled state.
7496 IN gctSIGNAL Signal,
7501 gcsSIGNAL_PTR signal;
7502 gctBOOL acquired = gcvFALSE;
7504 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7506 /* Verify the arguments. */
7507 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7508 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7510 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7513 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7515 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7519 /* unbind the signal from hardware. */
7520 signal->hardware = gcvNULL;
7522 /* Set the event to a signaled state. */
7523 complete(&signal->obj);
7527 /* Set the event to an unsignaled state. */
7528 INIT_COMPLETION(signal->obj);
7531 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7532 acquired = gcvFALSE;
7536 return gcvSTATUS_OK;
7541 /* Release the mutex. */
7542 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7553 IN gctHANDLE Process,
7559 struct task_struct * userTask;
7560 struct siginfo info;
7562 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7564 if (userTask != gcvNULL)
7567 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7570 info.si_ptr = (gctPOINTER) Signal;
7572 /* Signals with numbers between 32 and 63 are real-time,
7573 send a real-time signal to the user process. */
7574 result = send_sig_info(48, &info, userTask);
7576 printk("gckOS_SetSignalVG:0x%x\n", result);
7580 status = gcvSTATUS_GENERIC_IO;
7584 "%s(%d): an error has occurred.\n",
7585 __FUNCTION__, __LINE__
7590 status = gcvSTATUS_OK;
7595 status = gcvSTATUS_GENERIC_IO;
7599 "%s(%d): an error has occurred.\n",
7600 __FUNCTION__, __LINE__
7604 /* Return status. */
7609 /*******************************************************************************
7613 ** Set the specified signal which is owned by a process to signaled state.
7618 ** Pointer to an gckOS object.
7621 ** Pointer to the gctSIGNAL.
7623 ** gctHANDLE Process
7624 ** Handle of process owning the signal.
7633 IN gctSIGNAL Signal,
7634 IN gctHANDLE Process
7640 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7641 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7643 /* Map the signal into kernel space. */
7644 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7647 status = gckOS_Signal(Os, signal, gcvTRUE);
7649 /* Unmap the signal */
7650 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7656 /* Return the status. */
7661 /*******************************************************************************
7665 ** Wait for a signal to become signaled.
7670 ** Pointer to an gckOS object.
7673 ** Pointer to the gctSIGNAL.
7676 ** Number of milliseconds to wait.
7677 ** Pass the value of gcvINFINITE for an infinite wait.
7686 IN gctSIGNAL Signal,
7690 gceSTATUS status = gcvSTATUS_OK;
7691 gcsSIGNAL_PTR signal;
7693 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7695 /* Verify the arguments. */
7696 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7697 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7699 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7701 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7705 spin_lock_irq(&signal->obj.wait.lock);
7707 if (signal->obj.done)
7709 if (!signal->manualReset)
7711 signal->obj.done = 0;
7714 status = gcvSTATUS_OK;
7718 status = gcvSTATUS_TIMEOUT;
7722 /* Convert wait to milliseconds. */
7723 #if gcdDETECT_TIMEOUT
7724 gctINT timeout = (Wait == gcvINFINITE)
7725 ? gcdINFINITE_TIMEOUT * HZ / 1000
7728 gctUINT complained = 0;
7730 gctINT timeout = (Wait == gcvINFINITE)
7731 ? MAX_SCHEDULE_TIMEOUT
7735 DECLARE_WAITQUEUE(wait, current);
7736 wait.flags |= WQ_FLAG_EXCLUSIVE;
7737 __add_wait_queue_tail(&signal->obj.wait, &wait);
7741 if (signal_pending(current))
7743 /* Interrupt received. */
7744 status = gcvSTATUS_INTERRUPTED;
7748 __set_current_state(TASK_INTERRUPTIBLE);
7749 spin_unlock_irq(&signal->obj.wait.lock);
7750 timeout = schedule_timeout(timeout);
7751 spin_lock_irq(&signal->obj.wait.lock);
7753 if (signal->obj.done)
7755 if (!signal->manualReset)
7757 signal->obj.done = 0;
7760 status = gcvSTATUS_OK;
7764 #if gcdDETECT_TIMEOUT
7765 if ((Wait == gcvINFINITE) && (timeout == 0))
7767 gctUINT32 dmaAddress1, dmaAddress2;
7768 gctUINT32 dmaState1, dmaState2;
7770 dmaState1 = dmaState2 =
7771 dmaAddress1 = dmaAddress2 = 0;
7773 /* Verify whether DMA is running. */
7774 gcmkVERIFY_OK(_VerifyDMA(
7775 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7778 #if gcdDETECT_DMA_ADDRESS
7779 /* Dump only if DMA appears stuck. */
7781 (dmaAddress1 == dmaAddress2)
7782 #if gcdDETECT_DMA_STATE
7783 && (dmaState1 == dmaState2)
7788 /* Increment complain count. */
7791 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
7794 "%s(%d): signal 0x%X; forced message flush (%d).",
7795 __FUNCTION__, __LINE__, Signal, complained
7798 /* Flush the debug cache. */
7799 gcmkDEBUGFLUSH(dmaAddress2);
7802 /* Reset timeout. */
7803 timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
7810 status = gcvSTATUS_TIMEOUT;
7815 __remove_wait_queue(&signal->obj.wait, &wait);
7817 #if gcdDETECT_TIMEOUT
7821 "%s(%d): signal=0x%X; waiting done; status=%d",
7822 __FUNCTION__, __LINE__, Signal, status
7828 spin_unlock_irq(&signal->obj.wait.lock);
7831 /* Return status. */
7832 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7836 /*******************************************************************************
7840 ** Map a signal in to the current process space.
7845 ** Pointer to an gckOS object.
7848 ** Pointer to tha gctSIGNAL to map.
7850 ** gctHANDLE Process
7851 ** Handle of process owning the signal.
7855 ** gctSIGNAL * MappedSignal
7856 ** Pointer to a variable receiving the mapped gctSIGNAL.
7861 IN gctSIGNAL Signal,
7862 IN gctHANDLE Process,
7863 OUT gctSIGNAL * MappedSignal
7867 gcsSIGNAL_PTR signal;
7868 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7870 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7871 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7873 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7875 if(atomic_inc_return(&signal->ref) <= 1)
7877 /* The previous value is 0, it has been deleted. */
7878 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7881 *MappedSignal = (gctSIGNAL) Signal;
7884 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
7885 return gcvSTATUS_OK;
7892 /*******************************************************************************
7894 ** gckOS_UnmapSignal
7901 ** Pointer to an gckOS object.
7904 ** Pointer to that gctSIGNAL mapped.
7912 return gckOS_DestroySignal(Os, Signal);
7915 /*******************************************************************************
7917 ** gckOS_CreateUserSignal
7919 ** Create a new signal to be used in the user space.
7924 ** Pointer to an gckOS object.
7926 ** gctBOOL ManualReset
7927 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7928 ** order to set the signal to nonsignaled state.
7929 ** If set to gcvFALSE, the signal will automatically be set to
7930 ** nonsignaled state by gckOS_WaitSignal function.
7934 ** gctINT * SignalID
7935 ** Pointer to a variable receiving the created signal's ID.
7938 gckOS_CreateUserSignal(
7940 IN gctBOOL ManualReset,
7941 OUT gctINT * SignalID
7947 /* Create a new signal. */
7948 status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
7949 *SignalID = (gctINT) signal;
7954 /*******************************************************************************
7956 ** gckOS_DestroyUserSignal
7958 ** Destroy a signal to be used in the user space.
7963 ** Pointer to an gckOS object.
7973 gckOS_DestroyUserSignal(
7978 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
7981 /*******************************************************************************
7983 ** gckOS_WaitUserSignal
7985 ** Wait for a signal used in the user mode to become signaled.
7990 ** Pointer to an gckOS object.
7996 ** Number of milliseconds to wait.
7997 ** Pass the value of gcvINFINITE for an infinite wait.
8004 gckOS_WaitUserSignal(
8010 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
8013 /*******************************************************************************
8015 ** gckOS_SignalUserSignal
8017 ** Set a state of the specified signal to be used in the user space.
8022 ** Pointer to an gckOS object.
8028 ** If gcvTRUE, the signal will be set to signaled state.
8029 ** If gcvFALSE, the signal will be set to nonsignaled state.
8036 gckOS_SignalUserSignal(
8042 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
8047 gckOS_CreateSemaphoreVG(
8049 OUT gctSEMAPHORE * Semaphore
8053 struct semaphore * newSemaphore;
8055 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8056 /* Verify the arguments. */
8057 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8058 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8062 /* Allocate the semaphore structure. */
8063 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
8064 if (newSemaphore == gcvNULL)
8066 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
8069 /* Initialize the semaphore. */
8070 sema_init(newSemaphore, 0);
8072 /* Set the handle. */
8073 * Semaphore = (gctSEMAPHORE) newSemaphore;
8076 status = gcvSTATUS_OK;
8081 /* Return the status. */
8087 gckOS_IncrementSemaphore(
8089 IN gctSEMAPHORE Semaphore
8092 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8093 /* Verify the arguments. */
8094 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8095 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8097 /* Increment the semaphore's count. */
8098 up((struct semaphore *) Semaphore);
8102 return gcvSTATUS_OK;
8106 gckOS_DecrementSemaphore(
8108 IN gctSEMAPHORE Semaphore
8114 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8115 /* Verify the arguments. */
8116 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8117 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8121 /* Decrement the semaphore's count. If the count is zero, wait
8122 until it gets incremented. */
8123 result = down_interruptible((struct semaphore *) Semaphore);
8125 /* Signal received? */
8128 status = gcvSTATUS_TERMINATE;
8133 status = gcvSTATUS_OK;
8138 /* Return the status. */
8142 /*******************************************************************************
8146 ** Set the specified signal to signaled state.
8151 ** Pointer to the gckOS object.
8153 ** gctHANDLE Process
8154 ** Handle of process owning the signal.
8157 ** Pointer to the gctSIGNAL.
8166 IN gctHANDLE Process,
8172 struct task_struct * userTask;
8173 struct siginfo info;
8175 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
8177 if (userTask != gcvNULL)
8180 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
8183 info.si_ptr = (gctPOINTER) Signal;
8185 /* Signals with numbers between 32 and 63 are real-time,
8186 send a real-time signal to the user process. */
8187 result = send_sig_info(48, &info, userTask);
8192 status = gcvSTATUS_GENERIC_IO;
8196 "%s(%d): an error has occurred.\n",
8197 __FUNCTION__, __LINE__
8202 status = gcvSTATUS_OK;
8207 status = gcvSTATUS_GENERIC_IO;
8211 "%s(%d): an error has occurred.\n",
8212 __FUNCTION__, __LINE__
8216 /* Return status. */
8220 /******************************************************************************\
8221 ******************************** Thread Object *********************************
8222 \******************************************************************************/
8227 IN gctTHREADFUNC ThreadFunction,
8228 IN gctPOINTER ThreadParameter,
8229 OUT gctTHREAD * Thread
8233 struct task_struct * thread;
8235 gcmkHEADER_ARG("Os=0x%X ", Os);
8236 /* Verify the arguments. */
8237 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8238 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
8239 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8243 /* Create the thread. */
8244 thread = kthread_create(
8247 "Vivante Kernel Thread"
8253 status = gcvSTATUS_GENERIC_IO;
8257 /* Start the thread. */
8258 wake_up_process(thread);
8260 /* Set the thread handle. */
8261 * Thread = (gctTHREAD) thread;
8264 status = gcvSTATUS_OK;
8269 /* Return the status. */
8279 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8280 /* Verify the arguments. */
8281 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8282 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8284 /* Thread should have already been enabled to terminate. */
8285 kthread_stop((struct task_struct *) Thread);
8289 return gcvSTATUS_OK;
8298 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8299 /* Verify the arguments. */
8300 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8301 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8305 return gcvSTATUS_OK;
8309 /******************************************************************************\
8310 ******************************** Software Timer ********************************
8311 \******************************************************************************/
8315 struct work_struct * work
8318 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
8320 gctTIMERFUNCTION function = timer->function;
8322 function(timer->data);
8325 /*******************************************************************************
8327 ** gckOS_CreateTimer
8329 ** Create a software timer.
8334 ** Pointer to the gckOS object.
8336 ** gctTIMERFUNCTION Function.
8337 ** Pointer to a call back function which will be called when timer is
8341 ** Private data which will be passed to call back function.
8345 ** gctPOINTER * Timer
8346 ** Pointer to a variable receiving the created timer.
8351 IN gctTIMERFUNCTION Function,
8353 OUT gctPOINTER * Timer
8357 gcsOSTIMER_PTR pointer;
8358 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
8360 /* Verify the arguments. */
8361 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8362 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8364 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
8366 pointer->function = Function;
8367 pointer->data = Data;
8369 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
8374 return gcvSTATUS_OK;
8381 /*******************************************************************************
8383 ** gckOS_DestroyTimer
8385 ** Destory a software timer.
8390 ** Pointer to the gckOS object.
8393 ** Pointer to the timer to be destoryed.
8405 gcsOSTIMER_PTR timer;
8406 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8408 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8409 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8411 timer = (gcsOSTIMER_PTR)Timer;
8413 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8414 cancel_delayed_work_sync(&timer->work);
8416 cancel_delayed_work(&timer->work);
8417 flush_workqueue(Os->workqueue);
8420 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8423 return gcvSTATUS_OK;
8426 /*******************************************************************************
8430 ** Schedule a software timer.
8435 ** Pointer to the gckOS object.
8438 ** Pointer to the timer to be scheduled.
8441 ** Delay in milliseconds.
8450 IN gctPOINTER Timer,
8454 gcsOSTIMER_PTR timer;
8456 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8458 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8459 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8460 gcmkVERIFY_ARGUMENT(Delay != 0);
8462 timer = (gcsOSTIMER_PTR)Timer;
8464 if (unlikely(delayed_work_pending(&timer->work)))
8466 cancel_delayed_work(&timer->work);
8469 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8472 return gcvSTATUS_OK;
8475 /*******************************************************************************
8479 ** Cancel a unscheduled timer.
8484 ** Pointer to the gckOS object.
8487 ** Pointer to the timer to be cancel.
8499 gcsOSTIMER_PTR timer;
8500 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8502 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8503 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8505 timer = (gcsOSTIMER_PTR)Timer;
8507 cancel_delayed_work(&timer->work);
8510 return gcvSTATUS_OK;
8515 gckOS_DumpCallStack(
8519 gcmkHEADER_ARG("Os=0x%X", Os);
8521 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8526 return gcvSTATUS_OK;
8531 gckOS_GetProcessNameByPid(
8533 IN gctSIZE_T Length,
8534 OUT gctUINT8_PTR String
8537 struct task_struct *task;
8539 /* Get the task_struct of the task with pid. */
8542 task = FIND_TASK_BY_PID(Pid);
8544 if (task == gcvNULL)
8547 return gcvSTATUS_NOT_FOUND;
8550 /* Get name of process. */
8551 strncpy(String, task->comm, Length);
8555 return gcvSTATUS_OK;