1 /****************************************************************************
3 * Copyright (C) 2005 - 2011 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 *****************************************************************************/
24 #include "gc_hal_kernel_linux.h"
26 #include <linux/pagemap.h>
27 #include <linux/seq_file.h>
29 #include <linux/mman.h>
30 #include <linux/sched.h>
31 #include <linux/slab.h>
32 #include <asm/atomic.h>
33 #ifdef NO_DMA_COHERENT
34 #include <linux/dma-mapping.h>
35 #endif /* NO_DMA_COHERENT */
38 #include <linux/delay.h>
42 #if !USE_NEW_LINUX_SIGNAL
43 #define USER_SIGNAL_TABLE_LEN_INIT 64
46 #define _GC_OBJ_ZONE gcvZONE_OS
48 #define PAGE_ALLOC_LIMIT 0 // ÏÞÖÆPageÉêÇë
49 #define PAGE_ALLOC_LIMIT_SIZE 0 // ÏÞÖÆPageÉêÇëµÄ´óС,µ¥Î»ÎªM
52 int g_pages_alloced = 0;
55 #define MEMORY_LOCK(os) \
56 gcmkVERIFY_OK(gckOS_AcquireMutex( \
61 #define MEMORY_UNLOCK(os) \
62 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
64 #define MEMORY_MAP_LOCK(os) \
65 gcmkVERIFY_OK(gckOS_AcquireMutex( \
67 (os)->memoryMapLock, \
70 #define MEMORY_MAP_UNLOCK(os) \
71 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
73 #if gcdkREPORT_VIDMEM_USAGE
74 static gctUINT64 AllocatedSurfaceTotal[12] = {0};
76 * AllocatedSurfaceMax[12]: Current total memory
77 * AllocatedSurfaceMax[13]: Current total memory in history
79 static gctUINT64 AllocatedSurfaceMax[12 + 2] = {0};
80 static char *pszSurfaceType[12] = {"UNKNOWN", "INDEX", "VERTEX", "TEXTURE", "RENDER_TARGET", \
81 "DEPTH", "BITMAP", "TILE_STATUS", "MASK", "SCISSOR", "HIERARCHICAL_DEPTH", \
85 /******************************************************************************\
86 ********************************** Structures **********************************
87 \******************************************************************************/
97 /* Pointer to device */
100 /* Memory management */
101 gctPOINTER memoryLock;
102 gctPOINTER memoryMapLock;
104 struct _LINUX_MDL *mdlHead;
105 struct _LINUX_MDL *mdlTail;
107 gctUINT32 baseAddress;
109 /* Kernel process ID. */
110 gctUINT32 kernelProcessID;
112 #if !USE_NEW_LINUX_SIGNAL
113 /* Signal management. */
115 /* Unused signal ID number. */
118 /* The pointer to the table. */
121 /* Signal table length. */
124 /* The current unused signal ID. */
133 #if !USE_NEW_LINUX_SIGNAL
134 typedef struct _gcsSIGNAL
136 /* Kernel sync primitive. */
137 struct completion event;
139 /* Manual reset flag. */
142 /* The reference counter. */
145 /* The owner of the signal. */
150 typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
153 typedef struct _gcsPageInfo * gcsPageInfo_PTR;
155 typedef struct _gcsPageInfo
158 gctUINT32_PTR pageTable;
170 mdl = (PLINUX_MDL)kmalloc(sizeof(struct _LINUX_MDL), GFP_ATOMIC);
171 if (mdl == gcvNULL) return gcvNULL;
184 IN PLINUX_MDL_MAP MdlMap
192 PLINUX_MDL_MAP mdlMap, next;
194 /* Verify the arguments. */
195 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
199 while (mdlMap != gcvNULL)
203 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
213 static PLINUX_MDL_MAP
219 PLINUX_MDL_MAP mdlMap;
221 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_ATOMIC);
222 if (mdlMap == gcvNULL) return gcvNULL;
225 mdlMap->vmaAddr = gcvNULL;
226 mdlMap->vma = gcvNULL;
228 mdlMap->next = Mdl->maps;
237 IN PLINUX_MDL_MAP MdlMap
240 PLINUX_MDL_MAP prevMdlMap;
242 /* Verify the arguments. */
243 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
244 gcmkASSERT(Mdl->maps != gcvNULL);
246 if (Mdl->maps == MdlMap)
248 Mdl->maps = MdlMap->next;
252 prevMdlMap = Mdl->maps;
254 while (prevMdlMap->next != MdlMap)
256 prevMdlMap = prevMdlMap->next;
258 gcmkASSERT(prevMdlMap != gcvNULL);
261 prevMdlMap->next = MdlMap->next;
269 extern PLINUX_MDL_MAP
275 PLINUX_MDL_MAP mdlMap;
279 while (mdlMap != gcvNULL)
281 if (mdlMap->pid == PID) return mdlMap;
283 mdlMap = mdlMap->next;
290 FreeProcessMemoryOnExit(
295 PLINUX_MDL mdl, nextMdl;
296 PLINUX_MDL_MAP mdlMap;
302 while (mdl != gcvNULL)
304 if (mdl != Os->mdlTail)
317 if (mdlMap != gcvNULL
318 && mdlMap->pid == current->tgid
319 && mdlMap->next == gcvNULL)
323 gcmkVERIFY_OK(gckOS_FreePagedMemory(Os, mdl, mdl->numPages * PAGE_SIZE));
327 nextMdl = Os->mdlHead;
343 PLINUX_MDL mdl, nextMdl;
344 PLINUX_MDL_MAP mdlMap;
350 while (mdl != gcvNULL)
352 if (mdl != Os->mdlTail)
361 printk("Unfreed mdl: %p, pid: %d -> pagedMem: %s, addr: %p, dmaHandle: 0x%x, pages: %d",
364 mdl->pagedMem? "true" : "false",
371 while (mdlMap != gcvNULL)
373 printk("\tmap: %p, pid: %d -> vmaAddr: %p, vma: %p",
379 mdlMap = mdlMap->next;
394 /* PrintInfoOnExit(Os, Kernel); */
397 FreeProcessMemoryOnExit(Os, Kernel);
401 /*******************************************************************************
405 ** Construct a new gckOS object.
409 ** gctPOINTER Context
410 ** Pointer to the gckGALDEVICE class.
415 ** Pointer to a variable that will hold the pointer to the gckOS object.
419 IN gctPOINTER Context,
426 /* Verify the arguments. */
427 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
429 /* Allocate the gckOS object. */
430 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_ATOMIC);
435 return gcvSTATUS_OUT_OF_MEMORY;
438 /* Zero the memory. */
439 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
441 /* Initialize the gckOS object. */
442 os->object.type = gcvOBJ_OS;
444 /* Set device device. */
445 os->device = Context;
447 /* IMPORTANT! No heap yet. */
450 /* Initialize the memory lock. */
451 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
453 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
455 /* Create the gckHEAP object. */
456 gcmkONERROR(gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
458 os->mdlHead = os->mdlTail = gcvNULL;
460 /* Find the base address of the physical memory. */
461 os->baseAddress = os->device->baseAddress;
463 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
464 "Physical base address set to 0x%08X.",
467 /* Get the kernel process ID. */
468 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
470 #if !USE_NEW_LINUX_SIGNAL
472 * Initialize the signal manager.
473 * It creates the signals to be used in
477 /* Initialize mutex. */
479 gckOS_CreateMutex(os, &os->signal.lock));
481 /* Initialize the signal table. */
483 kmalloc(gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT, GFP_KERNEL);
485 if (os->signal.table == gcvNULL)
488 status = gcvSTATUS_OUT_OF_MEMORY;
492 gckOS_ZeroMemory(os->signal.table,
493 gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
495 /* Set the signal table length. */
496 os->signal.tableLen = USER_SIGNAL_TABLE_LEN_INIT;
498 /* The table is empty. */
499 os->signal.unused = os->signal.tableLen;
501 /* Initial signal ID. */
502 os->signal.currentID = 0;
505 /* Return pointer to the gckOS object. */
512 #if !USE_NEW_LINUX_SIGNAL
513 /* Roll back any allocation. */
514 if (os->signal.table != gcvNULL)
516 kfree(os->signal.table);
519 if (os->signal.lock != gcvNULL)
522 gckOS_DeleteMutex(os, os->signal.lock));
526 if (os->heap != gcvNULL)
529 gckHEAP_Destroy(os->heap));
532 if (os->memoryMapLock != gcvNULL)
535 gckOS_DeleteMutex(os, os->memoryMapLock));
538 if (os->memoryLock != gcvNULL)
541 gckOS_DeleteMutex(os, os->memoryLock));
546 /* Return the error. */
550 /*******************************************************************************
554 ** Destroy an gckOS object.
559 ** Pointer to an gckOS object that needs to be destroyed.
572 /* Verify the arguments. */
573 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
575 #if !USE_NEW_LINUX_SIGNAL
577 * Destroy the signal manager.
580 /* Destroy the mutex. */
582 gckOS_DeleteMutex(Os, Os->signal.lock));
584 /* Free the signal table. */
585 kfree(Os->signal.table);
588 if (Os->heap != NULL)
590 /* Mark gckHEAP as gone. */
594 /* Destroy the gckHEAP object. */
596 gckHEAP_Destroy(heap));
599 /* Destroy the memory lock. */
601 gckOS_DeleteMutex(Os, Os->memoryMapLock));
604 gckOS_DeleteMutex(Os, Os->memoryLock));
606 gcmkPRINT("$$FLUSH$$");
608 /* Mark the gckOS object as unknown. */
609 Os->object.type = gcvOBJ_UNKNOWN;
611 /* Free the gckOS object. */
618 /*******************************************************************************
627 ** Pointer to an gckOS object.
630 ** Number of bytes to allocate.
634 ** gctPOINTER * Memory
635 ** Pointer to a variable that will hold the allocated memory location.
641 OUT gctPOINTER * Memory
646 //gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
648 /* Verify the arguments. */
649 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
650 gcmkVERIFY_ARGUMENT(Bytes > 0);
651 gcmkVERIFY_ARGUMENT(Memory != NULL);
653 /* Do we have a heap? */
654 if (Os->heap != NULL)
656 /* Allocate from the heap. */
657 gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
661 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
665 //gcmkFOOTER_ARG("*memory=0x%x", *Memory);
669 /* Return the status. */
674 /*******************************************************************************
678 ** Free allocated memory.
683 ** Pointer to an gckOS object.
686 ** Pointer to memory allocation to free.
700 /* Verify the arguments. */
701 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
702 gcmkVERIFY_ARGUMENT(Memory != NULL);
704 //gcmkHEADER_ARG("Os=0x%x Memory=0x%x", Os, memory);
706 /* Do we have a heap? */
707 if (Os->heap != NULL)
709 /* Free from the heap. */
710 gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
714 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
722 /* Return the status. */
727 /*******************************************************************************
729 ** gckOS_AllocateMemory
731 ** Allocate memory wrapper.
736 ** Number of bytes to allocate.
740 ** gctPOINTER * Memory
741 ** Pointer to a variable that will hold the allocated memory location.
744 gckOS_AllocateMemory(
747 OUT gctPOINTER * Memory
753 gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
755 /* Verify the arguments. */
756 gcmkVERIFY_ARGUMENT(Bytes > 0);
757 gcmkVERIFY_ARGUMENT(Memory != NULL);
759 memory = (gctPOINTER) kmalloc(Bytes, GFP_ATOMIC);
764 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
767 /* Return pointer to the memory allocation. */
771 gcmkFOOTER_ARG("*Memory=%p", *Memory);
775 /* Return the status. */
780 /*******************************************************************************
784 ** Free allocated memory wrapper.
789 ** Pointer to memory allocation to free.
801 gcmkHEADER_ARG("Memory=%p", Memory);
803 /* Verify the arguments. */
804 gcmkVERIFY_ARGUMENT(Memory != NULL);
806 /* Free the memory from the OS pool. */
814 /*******************************************************************************
816 ** gckOS_AllocateVirtualMemory
818 ** Allocate virtual memory wrapper.
823 ** Number of bytes to allocate.
827 ** gctPOINTER * Memory
828 ** Pointer to a variable that will hold the allocated memory location.
831 gckOS_AllocateVirtualMemory(
834 OUT gctPOINTER * Memory
840 gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
842 /* Verify the arguments. */
843 gcmkVERIFY_ARGUMENT(Bytes > 0);
844 gcmkVERIFY_ARGUMENT(Memory != NULL);
846 memory = (gctPOINTER) vmalloc(Bytes);
851 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
854 /* Return pointer to the memory allocation. */
858 gcmkFOOTER_ARG("*Memory=%p", *Memory);
862 /* Return the status. */
867 /*******************************************************************************
869 ** gckOS_FreeVirtualMemory
871 ** Free allocated virtual memory wrapper.
876 ** Pointer to memory allocation to free.
883 gckOS_FreeVirtualMemory(
888 gcmkHEADER_ARG("Memory=%p", Memory);
890 /* Verify the arguments. */
891 gcmkVERIFY_ARGUMENT(Memory != NULL);
893 /* Free the memory from the OS pool. */
901 /*******************************************************************************
905 ** Map physical memory into the current process.
910 ** Pointer to an gckOS object.
912 ** gctPHYS_ADDR Physical
913 ** Start of physical address memory.
916 ** Number of bytes to map.
920 ** gctPOINTER * Memory
921 ** Pointer to a variable that will hold the logical address of the
927 IN gctPHYS_ADDR Physical,
929 OUT gctPOINTER * Logical
932 PLINUX_MDL_MAP mdlMap;
933 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
935 /* Verify the arguments. */
936 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
937 gcmkVERIFY_ARGUMENT(Physical != 0);
938 gcmkVERIFY_ARGUMENT(Bytes > 0);
939 gcmkVERIFY_ARGUMENT(Logical != NULL);
943 mdlMap = FindMdlMap(mdl, current->tgid);
945 if (mdlMap == gcvNULL)
947 mdlMap = _CreateMdlMap(mdl, current->tgid);
949 if (mdlMap == gcvNULL)
953 return gcvSTATUS_OUT_OF_MEMORY;
957 if (mdlMap->vmaAddr == gcvNULL)
959 down_write(¤t->mm->mmap_sem);
961 mdlMap->vmaAddr = (char *)do_mmap_pgoff(NULL,
963 mdl->numPages * PAGE_SIZE,
964 PROT_READ | PROT_WRITE,
968 if (mdlMap->vmaAddr == gcvNULL)
970 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
972 "gckOS_MapMemory: do_mmap_pgoff error");
974 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
976 "[gckOS_MapMemory] mdl->numPages: %d",
977 "[gckOS_MapMemory] mdl->vmaAddr: 0x%x",
982 up_write(¤t->mm->mmap_sem);
986 return gcvSTATUS_OUT_OF_MEMORY;
989 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
993 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
995 "gckOS_MapMemory: find_vma error.");
997 mdlMap->vmaAddr = gcvNULL;
999 up_write(¤t->mm->mmap_sem);
1003 return gcvSTATUS_OUT_OF_RESOURCES;
1006 #ifndef NO_DMA_COHERENT
1007 if (dma_mmap_coherent(NULL,
1011 mdl->numPages * PAGE_SIZE) < 0)
1013 up_write(¤t->mm->mmap_sem);
1015 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
1017 "gckOS_MapMemory: dma_mmap_coherent error.");
1019 mdlMap->vmaAddr = gcvNULL;
1023 return gcvSTATUS_OUT_OF_RESOURCES;
1027 #if (2==gcdENABLE_MEM_CACHE)
1028 mdlMap->vma->vm_page_prot = pgprot_writecombine(mdlMap->vma->vm_page_prot);
1029 #elif (1==gcdENABLE_MEM_CACHE)
1032 mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
1034 mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
1035 mdlMap->vma->vm_pgoff = 0;
1037 if (remap_pfn_range(mdlMap->vma,
1038 mdlMap->vma->vm_start,
1039 mdl->dmaHandle >> PAGE_SHIFT,
1040 mdl->numPages*PAGE_SIZE,
1041 mdlMap->vma->vm_page_prot) < 0)
1043 up_write(¤t->mm->mmap_sem);
1045 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
1047 "gckOS_MapMemory: remap_pfn_range error.");
1049 mdlMap->vmaAddr = gcvNULL;
1053 return gcvSTATUS_OUT_OF_RESOURCES;
1057 up_write(¤t->mm->mmap_sem);
1062 *Logical = mdlMap->vmaAddr;
1064 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
1065 "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x pid->%d",
1066 (gctUINT32)mdl->addr,
1067 (gctUINT32)*Logical,
1070 return gcvSTATUS_OK;
1073 /*******************************************************************************
1075 ** gckOS_UnmapMemory
1077 ** Unmap physical memory out of the current process.
1082 ** Pointer to an gckOS object.
1084 ** gctPHYS_ADDR Physical
1085 ** Start of physical address memory.
1088 ** Number of bytes to unmap.
1090 ** gctPOINTER Memory
1091 ** Pointer to a previously mapped memory region.
1100 IN gctPHYS_ADDR Physical,
1102 IN gctPOINTER Logical
1105 PLINUX_MDL_MAP mdlMap;
1106 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1107 struct task_struct * task;
1108 struct mm_struct * mm;
1110 /* Verify the arguments. */
1111 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1112 gcmkVERIFY_ARGUMENT(Physical != 0);
1113 gcmkVERIFY_ARGUMENT(Bytes > 0);
1114 gcmkVERIFY_ARGUMENT(Logical != NULL);
1116 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1118 "in gckOS_UnmapMemory");
1120 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1122 "gckOS_UnmapMemory Will be unmapping 0x%x mdl->0x%x",
1130 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
1132 "[gckOS_UnmapMemory] Logical: 0x%x",
1136 mdlMap = FindMdlMap(mdl, current->tgid);
1138 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1142 return gcvSTATUS_INVALID_ARGUMENT;
1145 /* Get the current pointer for the task with stored pid. */
1146 task = FIND_TASK_BY_PID(mdlMap->pid);
1148 mm = get_task_mm(task);
1149 put_task_struct(task);
1156 down_write(&mm->mmap_sem);
1157 do_munmap(mm, (unsigned long)Logical, mdl->numPages*PAGE_SIZE);
1158 up_write(&mm->mmap_sem);
1163 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1165 "Can't find the task with pid->%d. No unmapping",
1169 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1175 return gcvSTATUS_OK;
1178 /*******************************************************************************
1180 ** gckOS_AllocateNonPagedMemory
1182 ** Allocate a number of pages from non-paged memory.
1187 ** Pointer to an gckOS object.
1189 ** gctBOOL InUserSpace
1190 ** gcvTRUE if the pages need to be mapped into user space.
1192 ** gctSIZE_T * Bytes
1193 ** Pointer to a variable that holds the number of bytes to allocate.
1197 ** gctSIZE_T * Bytes
1198 ** Pointer to a variable that hold the number of bytes allocated.
1200 ** gctPHYS_ADDR * Physical
1201 ** Pointer to a variable that will hold the physical address of the
1204 ** gctPOINTER * Logical
1205 ** Pointer to a variable that will hold the logical address of the
1209 gckOS_AllocateNonPagedMemory(
1211 IN gctBOOL InUserSpace,
1212 IN OUT gctSIZE_T * Bytes,
1213 OUT gctPHYS_ADDR * Physical,
1214 OUT gctPOINTER * Logical
1220 PLINUX_MDL_MAP mdlMap = 0;
1223 #ifdef NO_DMA_COHERENT
1229 /* Verify the arguments. */
1230 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1231 gcmkVERIFY_ARGUMENT((Bytes != NULL) && (*Bytes > 0));
1232 gcmkVERIFY_ARGUMENT(Physical != NULL);
1233 gcmkVERIFY_ARGUMENT(Logical != NULL);
1235 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1237 "in gckOS_AllocateNonPagedMemory");
1239 /* Align number of bytes to page size. */
1240 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1242 /* Get total number of pages.. */
1243 numPages = GetPageCount(bytes, 0);
1245 /* Allocate mdl+vector structure */
1246 mdl = _CreateMdl(current->tgid);
1250 return gcvSTATUS_OUT_OF_MEMORY;
1254 mdl->numPages = numPages;
1258 #ifndef NO_DMA_COHERENT
1259 addr = dma_alloc_coherent(NULL,
1260 mdl->numPages * PAGE_SIZE,
1264 size = mdl->numPages * PAGE_SIZE;
1265 order = get_order(size);
1266 //page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
1267 page = alloc_pages(GFP_KERNEL , order); // dkm modify 110330 ½«GFP_DMAÈ¥µô,±ÜÃâ·ÖÅä²»µ½DMAÄÚ´æ
1269 if (page == gcvNULL)
1273 return gcvSTATUS_OUT_OF_MEMORY;
1276 vaddr = (gctPOINTER)page_address(page);
1277 #if gcdENABLE_MEM_CACHE
1278 addr = ioremap_cached(virt_to_phys(vaddr), size);
1280 addr = ioremap_nocache(virt_to_phys(vaddr), size);
1282 mdl->dmaHandle = virt_to_phys(vaddr);
1285 #if ENABLE_ARM_L2_CACHE
1286 dma_cache_maint(vaddr, size, DMA_FROM_DEVICE);
1291 SetPageReserved(virt_to_page(vaddr));
1298 if (addr == gcvNULL)
1300 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1302 "galcore: Can't allocate memorry for size->0x%x",
1305 gcmkVERIFY_OK(_DestroyMdl(mdl));
1309 return gcvSTATUS_OUT_OF_MEMORY;
1312 if ((Os->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
1314 mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1315 | (Os->baseAddress & 0x80000000);
1321 * We will not do any mapping from here.
1322 * Mapping will happen from mmap method.
1323 * mdl structure will be used.
1326 /* Return allocated memory. */
1328 *Physical = (gctPHYS_ADDR) mdl;
1332 mdlMap = _CreateMdlMap(mdl, current->tgid);
1334 if (mdlMap == gcvNULL)
1336 gcmkVERIFY_OK(_DestroyMdl(mdl));
1340 return gcvSTATUS_OUT_OF_MEMORY;
1343 /* Only after mmap this will be valid. */
1345 /* We need to map this to user space. */
1346 down_write(¤t->mm->mmap_sem);
1348 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
1350 mdl->numPages * PAGE_SIZE,
1351 PROT_READ | PROT_WRITE,
1355 if (mdlMap->vmaAddr == gcvNULL)
1357 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1359 "galcore: do_mmap_pgoff error");
1361 up_write(¤t->mm->mmap_sem);
1363 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1364 gcmkVERIFY_OK(_DestroyMdl(mdl));
1368 return gcvSTATUS_OUT_OF_MEMORY;
1371 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1373 if (mdlMap->vma == gcvNULL)
1375 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1379 up_write(¤t->mm->mmap_sem);
1381 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1382 gcmkVERIFY_OK(_DestroyMdl(mdl));
1386 return gcvSTATUS_OUT_OF_RESOURCES;
1389 #ifndef NO_DMA_COHERENT
1390 if (dma_mmap_coherent(NULL,
1394 mdl->numPages * PAGE_SIZE) < 0)
1396 up_write(¤t->mm->mmap_sem);
1398 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1400 "dma_mmap_coherent error");
1402 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1403 gcmkVERIFY_OK(_DestroyMdl(mdl));
1407 return gcvSTATUS_OUT_OF_RESOURCES;
1411 #if (2==gcdENABLE_MEM_CACHE)
1412 mdlMap->vma->vm_page_prot = pgprot_writecombine(mdlMap->vma->vm_page_prot);
1413 #elif (1==gcdENABLE_MEM_CACHE)
1416 mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
1418 mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
1419 mdlMap->vma->vm_pgoff = 0;
1421 if (remap_pfn_range(mdlMap->vma,
1422 mdlMap->vma->vm_start,
1423 mdl->dmaHandle >> PAGE_SHIFT,
1424 mdl->numPages * PAGE_SIZE,
1425 mdlMap->vma->vm_page_prot))
1427 up_write(¤t->mm->mmap_sem);
1429 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1431 "remap_pfn_range error");
1433 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1434 gcmkVERIFY_OK(_DestroyMdl(mdl));
1438 return gcvSTATUS_OUT_OF_RESOURCES;
1440 #endif /* NO_DMA_COHERENT */
1442 up_write(¤t->mm->mmap_sem);
1444 *Logical = mdlMap->vmaAddr;
1448 *Logical = (gctPOINTER)mdl->addr;
1452 * Add this to a global list.
1453 * Will be used by get physical address
1454 * and mapuser pointer functions.
1459 /* Initialize the queue. */
1460 Os->mdlHead = Os->mdlTail = mdl;
1464 /* Add to the tail. */
1465 mdl->prev = Os->mdlTail;
1466 Os->mdlTail->next = mdl;
1472 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1474 "gckOS_AllocateNonPagedMemory: "
1475 "Bytes->0x%x, Mdl->%p, Logical->0x%x dmaHandle->0x%x",
1478 (gctUINT32)mdl->addr,
1483 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1485 "vmaAddr->0x%x pid->%d",
1486 (gctUINT32)mdlMap->vmaAddr,
1491 return gcvSTATUS_OK;
1494 /*******************************************************************************
1496 ** gckOS_FreeNonPagedMemory
1498 ** Free previously allocated and mapped pages from non-paged memory.
1503 ** Pointer to an gckOS object.
1506 ** Number of bytes allocated.
1508 ** gctPHYS_ADDR Physical
1509 ** Physical address of the allocated memory.
1511 ** gctPOINTER Logical
1512 ** Logical address of the allocated memory.
1518 gceSTATUS gckOS_FreeNonPagedMemory(
1521 IN gctPHYS_ADDR Physical,
1522 IN gctPOINTER Logical
1526 PLINUX_MDL_MAP mdlMap;
1527 struct task_struct * task;
1528 struct mm_struct * mm;
1530 #ifdef NO_DMA_COHERENT
1533 #endif /* NO_DMA_COHERENT */
1535 /* Verify the arguments. */
1536 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1537 gcmkVERIFY_ARGUMENT(Bytes > 0);
1538 gcmkVERIFY_ARGUMENT(Physical != 0);
1539 gcmkVERIFY_ARGUMENT(Logical != NULL);
1541 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1543 "in gckOS_FreeNonPagedMemory");
1545 /* Convert physical address into a pointer to a MDL. */
1546 mdl = (PLINUX_MDL) Physical;
1550 #ifndef NO_DMA_COHERENT
1551 dma_free_coherent(gcvNULL,
1552 mdl->numPages * PAGE_SIZE,
1556 size = mdl->numPages * PAGE_SIZE;
1561 ClearPageReserved(virt_to_page(vaddr));
1567 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
1570 #endif /* NO_DMA_COHERENT */
1574 while (mdlMap != gcvNULL)
1576 if (mdlMap->vmaAddr != gcvNULL)
1578 /* Get the current pointer for the task with stored pid. */
1579 task = FIND_TASK_BY_PID(mdlMap->pid);
1581 mm = get_task_mm(task);
1582 put_task_struct(task);
1589 down_write(&mm->mmap_sem);
1592 (unsigned long)mdlMap->vmaAddr,
1593 mdl->numPages * PAGE_SIZE) < 0)
1595 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1597 "gckOS_FreeNonPagedMemory: "
1598 "Unmap Failed ->Mdl->0x%x Logical->0x%x vmaAddr->0x%x",
1600 (gctUINT32)mdl->addr,
1601 (gctUINT32)mdlMap->vmaAddr);
1604 up_write(&mm->mmap_sem);
1608 mdlMap->vmaAddr = gcvNULL;
1611 mdlMap = mdlMap->next;
1614 /* Remove the node from global list.. */
1615 if (mdl == Os->mdlHead)
1617 if ((Os->mdlHead = mdl->next) == gcvNULL)
1619 Os->mdlTail = gcvNULL;
1624 mdl->prev->next = mdl->next;
1625 if (mdl == Os->mdlTail)
1627 Os->mdlTail = mdl->prev;
1631 mdl->next->prev = mdl->prev;
1637 gcmkTRACE_ZONE(gcvLEVEL_INFO,
1639 "gckOS_FreeNonPagedMemory: "
1640 "Mdl->0x%x Logical->0x%x",
1642 (gctUINT32)mdl->addr);
1644 gcmkVERIFY_OK(_DestroyMdl(mdl));
1647 return gcvSTATUS_OK;
1650 /*******************************************************************************
1652 ** gckOS_ReadRegister
1654 ** Read data from a register.
1659 ** Pointer to an gckOS object.
1661 ** gctUINT32 Address
1662 ** Address of register.
1667 ** Pointer to a variable that receives the data read from the register.
1669 gceSTATUS gckOS_ReadRegister(
1671 IN gctUINT32 Address,
1672 OUT gctUINT32 * Data
1675 /* Verify the arguments. */
1676 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1677 gcmkVERIFY_ARGUMENT(Data != NULL);
1679 *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
1682 return gcvSTATUS_OK;
1685 /*******************************************************************************
1687 ** gckOS_WriteRegister
1689 ** Write data to a register.
1694 ** Pointer to an gckOS object.
1696 ** gctUINT32 Address
1697 ** Address of register.
1700 ** Data for register.
1706 gceSTATUS gckOS_WriteRegister(
1708 IN gctUINT32 Address,
1712 writel(Data, (gctUINT8 *)Os->device->registerBase + Address);
1715 return gcvSTATUS_OK;
1718 /*******************************************************************************
1720 ** gckOS_GetPageSize
1722 ** Get the system's page size.
1727 ** Pointer to an gckOS object.
1731 ** gctSIZE_T * PageSize
1732 ** Pointer to a variable that will receive the system's page size.
1734 gceSTATUS gckOS_GetPageSize(
1736 OUT gctSIZE_T * PageSize
1739 /* Verify the arguments. */
1740 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1741 gcmkVERIFY_ARGUMENT(PageSize != NULL);
1743 /* Return the page size. */
1744 *PageSize = (gctSIZE_T) PAGE_SIZE;
1747 return gcvSTATUS_OK;
1750 /*******************************************************************************
1752 ** gckOS_GetPhysicalAddressProcess
1754 ** Get the physical system address of a corresponding virtual address for a
1760 ** Pointer to an gckOS object.
1762 ** gctPOINTER Logical
1765 ** gctUINT ProcessID
1770 ** gctUINT32 * Address
1771 ** Poinetr to a variable that receives the 32-bit physical adress.
1774 gckOS_GetPhysicalAddressProcess(
1776 IN gctPOINTER Logical,
1777 IN gctUINT ProcessID,
1778 OUT gctUINT32 * Address
1781 return gckOS_GetPhysicalAddress(Os, Logical, Address);
1784 /*******************************************************************************
1786 ** gckOS_GetPhysicalAddress
1788 ** Get the physical system address of a corresponding virtual address.
1793 ** Pointer to an gckOS object.
1795 ** gctPOINTER Logical
1800 ** gctUINT32 * Address
1801 ** Poinetr to a variable that receives the 32-bit physical adress.
1803 gceSTATUS gckOS_GetPhysicalAddress(
1805 IN gctPOINTER Logical,
1806 OUT gctUINT32 * Address
1810 PLINUX_MDL_MAP mdlMap;
1812 /* Verify the arguments. */
1813 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1814 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1817 * Try to search the address in our list.
1818 * This could be an mmaped memory.
1819 * Search in our list.
1826 while (mdl != gcvNULL)
1828 /* Check for the logical address match. */
1830 && (gctUINT32)Logical >= (gctUINT32)mdl->addr
1831 && (gctUINT32)Logical < ((gctUINT32)mdl->addr + mdl->numPages*PAGE_SIZE))
1835 /* The memory was from coherent area. */
1836 *Address = (gctUINT32)mdl->dmaHandle
1837 + (gctUINT32)((gctUINT32)Logical - (gctUINT32)mdl->addr);
1839 else if (mdl->pagedMem)
1841 if (mdl->contiguous)
1843 *Address = (gctUINT32)virt_to_phys(mdl->addr)
1844 + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
1848 *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
1849 + ((gctUINT32)Logical - (gctUINT32)mdl->addr)));
1854 *Address = (gctUINT32)virt_to_phys(mdl->addr)
1855 + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
1860 mdlMap = FindMdlMap(mdl, current->tgid);
1862 /* Is the given address within that range. */
1863 if (mdlMap != gcvNULL
1864 && mdlMap->vmaAddr != gcvNULL
1865 && Logical >= mdlMap->vmaAddr
1866 && Logical < (mdlMap->vmaAddr + mdl->numPages * PAGE_SIZE))
1870 /* The memory was from coherent area. */
1871 *Address = (gctUINT32)mdl->dmaHandle
1872 + (gctUINT32)((gctUINT32)Logical
1873 - (gctUINT32)mdlMap->vmaAddr);
1875 else if (mdl->pagedMem)
1877 if (mdl->contiguous)
1879 *Address = (gctUINT32)virt_to_phys(mdl->addr)
1880 + (gctUINT32)(Logical - mdlMap->vmaAddr);
1884 *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
1885 + ((gctUINT32)Logical - (gctUINT32)mdlMap->vmaAddr)));
1890 /* Return the kernel virtual pointer based on this. */
1891 *Address = (gctUINT32)virt_to_phys(mdl->addr)
1892 + (gctUINT32)(Logical - mdlMap->vmaAddr);
1900 /* Subtract base address to get a GPU physical address. */
1901 gcmkASSERT(*Address >= Os->baseAddress);
1902 *Address -= Os->baseAddress;
1908 return gcvSTATUS_INVALID_ARGUMENT;
1912 return gcvSTATUS_OK;
1915 /*******************************************************************************
1917 ** gckOS_MapPhysical
1919 ** Map a physical address into kernel space.
1924 ** Pointer to an gckOS object.
1926 ** gctUINT32 Physical
1927 ** Physical address of the memory to map.
1930 ** Number of bytes to map.
1934 ** gctPOINTER * Logical
1935 ** Pointer to a variable that receives the base address of the mapped
1938 gceSTATUS gckOS_MapPhysical(
1940 IN gctUINT32 Physical,
1942 OUT gctPOINTER * Logical
1949 /* Verify the arguments. */
1950 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1951 gcmkVERIFY_ARGUMENT(Bytes > 0);
1952 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1956 /* Compute true physical address (before subtraction of the baseAddress). */
1957 physical = Physical + Os->baseAddress;
1959 /* Go through our mapping to see if we know this physical address already. */
1962 while (mdl != gcvNULL)
1964 if (mdl->dmaHandle != 0)
1966 if ((physical >= mdl->dmaHandle)
1967 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
1970 *Logical = mdl->addr + (physical - mdl->dmaHandle);
1980 /* Map memory as cached memory. */
1981 request_mem_region(physical, Bytes, "MapRegion");
1982 #if gcdENABLE_MEM_CACHE
1983 logical = (gctPOINTER) ioremap_cached(physical, Bytes);
1985 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
1987 if (logical == NULL)
1989 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
1990 "gckOS_MapMemory: Failed to ioremap");
1994 /* Out of resources. */
1995 return gcvSTATUS_OUT_OF_RESOURCES;
1998 /* Return pointer to mapped memory. */
2004 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
2005 "gckOS_MapPhysical: "
2006 "Physical->0x%X Bytes->0x%X Logical->0x%X MappingFound->%d",
2007 (gctUINT32) Physical,
2009 (gctUINT32) *Logical,
2013 return gcvSTATUS_OK;
2016 /*******************************************************************************
2018 ** gckOS_UnmapPhysical
2020 ** Unmap a previously mapped memory region from kernel memory.
2025 ** Pointer to an gckOS object.
2027 ** gctPOINTER Logical
2028 ** Pointer to the base address of the memory to unmap.
2031 ** Number of bytes to unmap.
2037 gceSTATUS gckOS_UnmapPhysical(
2039 IN gctPOINTER Logical,
2045 /* Verify the arguments. */
2046 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2047 gcmkVERIFY_ARGUMENT(Logical != NULL);
2048 gcmkVERIFY_ARGUMENT(Bytes > 0);
2054 while (mdl != gcvNULL)
2056 if (mdl->addr != gcvNULL)
2058 if (Logical >= (gctPOINTER)mdl->addr
2059 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2070 /* Unmap the memory. */
2076 gcmkTRACE_ZONE(gcvLEVEL_INFO,
2078 "gckOS_UnmapPhysical: "
2079 "Logical->0x%x Bytes->0x%x MappingFound(?)->%d",
2085 return gcvSTATUS_OK;
2088 /*******************************************************************************
2090 ** gckOS_CreateMutex
2092 ** Create a new mutex.
2097 ** Pointer to an gckOS object.
2101 ** gctPOINTER * Mutex
2102 ** Pointer to a variable that will hold a pointer to the mutex.
2104 gceSTATUS gckOS_CreateMutex(
2106 OUT gctPOINTER * Mutex
2109 /* Validate the arguments. */
2110 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2111 gcmkVERIFY_ARGUMENT(Mutex != NULL);
2113 /* Allocate a FAST_MUTEX structure. */
2114 *Mutex = (gctPOINTER)kmalloc(sizeof(struct semaphore), GFP_KERNEL);
2116 if (*Mutex == gcvNULL)
2118 return gcvSTATUS_OUT_OF_MEMORY;
2121 /* Initialize the semaphore.. Come up in unlocked state. */
2124 /* Return status. */
2125 return gcvSTATUS_OK;
2128 /*******************************************************************************
2130 ** gckOS_DeleteMutex
2137 ** Pointer to an gckOS object.
2140 ** Pointer to the mute to be deleted.
2146 gceSTATUS gckOS_DeleteMutex(
2151 /* Validate the arguments. */
2152 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2153 gcmkVERIFY_ARGUMENT(Mutex != NULL);
2155 /* Delete the fast mutex. */
2158 return gcvSTATUS_OK;
2161 /*******************************************************************************
2163 ** gckOS_AcquireMutex
2170 ** Pointer to an gckOS object.
2173 ** Pointer to the mutex to be acquired.
2175 ** gctUINT32 Timeout
2176 ** Timeout value specified in milliseconds.
2177 ** Specify the value of gcvINFINITE to keep the thread suspended
2178 ** until the mutex has been acquired.
2187 IN gctPOINTER Mutex,
2188 IN gctUINT32 Timeout
2191 /* Validate the arguments. */
2192 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2193 gcmkVERIFY_ARGUMENT(Mutex != NULL);
2195 if (Timeout == gcvINFINITE)
2197 down((struct semaphore *) Mutex);
2200 return gcvSTATUS_OK;
2205 /* Try to acquire the fast mutex. */
2206 if (!down_trylock((struct semaphore *) Mutex))
2209 return gcvSTATUS_OK;
2212 if (Timeout-- == 0) break;
2214 /* Wait for 1 millisecond. */
2215 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
2219 return gcvSTATUS_TIMEOUT;
2222 /*******************************************************************************
2224 ** gckOS_ReleaseMutex
2226 ** Release an acquired mutex.
2231 ** Pointer to an gckOS object.
2234 ** Pointer to the mutex to be released.
2240 gceSTATUS gckOS_ReleaseMutex(
2245 /* Validate the arguments. */
2246 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2247 gcmkVERIFY_ARGUMENT(Mutex != NULL);
2249 /* Release the fast mutex. */
2250 up((struct semaphore *) Mutex);
2253 return gcvSTATUS_OK;
2256 /*******************************************************************************
2258 ** gckOS_AtomicExchange
2260 ** Atomically exchange a pair of 32-bit values.
2265 ** Pointer to an gckOS object.
2267 ** IN OUT gctINT32_PTR Target
2268 ** Pointer to the 32-bit value to exchange.
2270 ** IN gctINT32 NewValue
2271 ** Specifies a new value for the 32-bit value pointed to by Target.
2273 ** OUT gctINT32_PTR OldValue
2274 ** The old value of the 32-bit value pointed to by Target.
2281 gckOS_AtomicExchange(
2283 IN OUT gctUINT32_PTR Target,
2284 IN gctUINT32 NewValue,
2285 OUT gctUINT32_PTR OldValue
2288 /* Verify the arguments. */
2289 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2291 /* Exchange the pair of 32-bit values. */
2292 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
2295 return gcvSTATUS_OK;
2298 /*******************************************************************************
2300 ** gckOS_AtomicExchangePtr
2302 ** Atomically exchange a pair of pointers.
2307 ** Pointer to an gckOS object.
2309 ** IN OUT gctPOINTER * Target
2310 ** Pointer to the 32-bit value to exchange.
2312 ** IN gctPOINTER NewValue
2313 ** Specifies a new value for the pointer pointed to by Target.
2315 ** OUT gctPOINTER * OldValue
2316 ** The old value of the pointer pointed to by Target.
2323 gckOS_AtomicExchangePtr(
2325 IN OUT gctPOINTER * Target,
2326 IN gctPOINTER NewValue,
2327 OUT gctPOINTER * OldValue
2330 /* Verify the arguments. */
2331 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2333 /* Exchange the pair of pointers. */
2334 *OldValue = (gctPOINTER) atomic_xchg((atomic_t *) Target, (int) NewValue);
2337 return gcvSTATUS_OK;
2340 /*******************************************************************************
2342 ** gckOS_AtomConstruct
2349 ** Pointer to a gckOS object.
2353 ** gctPOINTER * Atom
2354 ** Pointer to a variable receiving the constructed atom.
2357 gckOS_AtomConstruct(
2359 OUT gctPOINTER * Atom
2364 gcmkHEADER_ARG("Os=0x%x", Os);
2366 /* Verify the arguments. */
2367 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2368 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2370 /* Allocate the atom. */
2371 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
2373 /* Initialize the atom. */
2374 atomic_set((atomic_t *) *Atom, 0);
2377 gcmkFOOTER_ARG("*Atom=0x%x", *Atom);
2378 return gcvSTATUS_OK;
2381 /* Return the status. */
2386 /*******************************************************************************
2388 ** gckOS_AtomDestroy
2395 ** Pointer to a gckOS object.
2398 ** Pointer to the atom to destroy.
2412 gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2414 /* Verify the arguments. */
2415 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2416 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2418 /* Free the atom. */
2419 gcmkONERROR(gckOS_Free(Os, Atom));
2423 return gcvSTATUS_OK;
2426 /* Return the status. */
2431 /*******************************************************************************
2435 ** Get the 32-bit value protected by an atom.
2440 ** Pointer to a gckOS object.
2443 ** Pointer to the atom.
2447 ** gctINT32_PTR Value
2448 ** Pointer to a variable the receives the value of the atom.
2454 OUT gctINT32_PTR Value
2457 gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2459 /* Verify the arguments. */
2460 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2461 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2463 /* Return the current value of atom. */
2464 *Value = atomic_read((atomic_t *) Atom);
2467 gcmkFOOTER_ARG("*Value=%d", *Value);
2468 return gcvSTATUS_OK;
2471 /*******************************************************************************
2473 ** gckOS_AtomIncrement
2475 ** Atomically increment the 32-bit integer value inside an atom.
2480 ** Pointer to a gckOS object.
2483 ** Pointer to the atom.
2487 ** gctINT32_PTR Value
2488 ** Pointer to a variable the receives the original value of the atom.
2491 gckOS_AtomIncrement(
2494 OUT gctINT32_PTR Value
2497 gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2499 /* Verify the arguments. */
2500 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2501 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2503 /* Increment the atom. */
2504 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
2507 gcmkFOOTER_ARG("*Value=%d", *Value);
2508 return gcvSTATUS_OK;
2511 /*******************************************************************************
2513 ** gckOS_AtomDecrement
2515 ** Atomically decrement the 32-bit integer value inside an atom.
2520 ** Pointer to a gckOS object.
2523 ** Pointer to the atom.
2527 ** gctINT32_PTR Value
2528 ** Pointer to a variable the receives the original value of the atom.
2531 gckOS_AtomDecrement(
2534 OUT gctINT32_PTR Value
2537 gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2539 /* Verify the arguments. */
2540 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2541 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2543 /* Decrement the atom. */
2544 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
2547 gcmkFOOTER_ARG("*Value=%d", *Value);
2548 return gcvSTATUS_OK;
2551 /*******************************************************************************
2555 ** Delay execution of the current thread for a number of milliseconds.
2560 ** Pointer to an gckOS object.
2563 ** Delay to sleep, specified in milliseconds.
2576 unsigned long jiffies;
2580 /* Convert milliseconds into seconds and microseconds. */
2581 now.tv_sec = Delay / 1000;
2582 now.tv_usec = (Delay % 1000) * 1000;
2584 /* Convert timeval to jiffies. */
2585 jiffies = timeval_to_jiffies(&now);
2587 /* Schedule timeout. */
2588 schedule_timeout_interruptible(jiffies);
2592 return gcvSTATUS_OK;
2595 /*******************************************************************************
2597 ** gckOS_MemoryBarrier
2599 ** Make sure the CPU has executed everything up to this point and the data got
2600 ** written to the specified pointer.
2605 ** Pointer to an gckOS object.
2607 ** gctPOINTER Address
2608 ** Address of memory that needs to be barriered.
2614 gceSTATUS gckOS_MemoryBarrier(
2616 IN gctPOINTER Address
2619 /* Verify thearguments. */
2620 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2626 return gcvSTATUS_OK;
2629 /*******************************************************************************
2631 ** gckOS_AllocatePagedMemory
2633 ** Allocate memory from the paged pool.
2638 ** Pointer to an gckOS object.
2641 ** Number of bytes to allocate.
2645 ** gctPHYS_ADDR * Physical
2646 ** Pointer to a variable that receives the physical address of the
2647 ** memory allocation.
2650 gckOS_AllocatePagedMemory(
2653 OUT gctPHYS_ADDR * Physical
2656 return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
2659 /*******************************************************************************
2661 ** gckOS_AllocatePagedMemoryEx
2663 ** Allocate memory from the paged pool.
2668 ** Pointer to an gckOS object.
2670 ** gctBOOL Contiguous
2671 ** Need contiguous memory or not.
2674 ** Number of bytes to allocate.
2678 ** gctPHYS_ADDR * Physical
2679 ** Pointer to a variable that receives the physical address of the
2680 ** memory allocation.
2682 gceSTATUS gckOS_AllocatePagedMemoryEx(
2684 IN gctBOOL Contiguous,
2686 OUT gctPHYS_ADDR * Physical
2695 gcmkHEADER_ARG("Os=0x%0x Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
2697 /* Verify the arguments. */
2698 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2699 gcmkVERIFY_ARGUMENT(Bytes > 0);
2700 gcmkVERIFY_ARGUMENT(Physical != NULL);
2702 bytes = gcmALIGN(Bytes, PAGE_SIZE);
2704 numPages = GetPageCount(bytes, 0);
2710 #if PAGE_ALLOC_LIMIT
2711 if( (g_pages_alloced + numPages) > (256*PAGE_ALLOC_LIMIT_SIZE) ) {
2712 //printk("full %d! \n", g_pages_alloced);
2715 addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA | __GFP_NOWARN, GetOrder(numPages));
2717 g_pages_alloced += numPages;
2718 //printk("alloc %d / %d \n", numPages, g_pages_alloced);
2720 printk("gpu : alloc %d fail! (%d/%d)\n", numPages, g_pages_alloced, (256*PAGE_ALLOC_LIMIT_SIZE) );
2724 addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA | __GFP_NOWARN, GetOrder(numPages));
2729 addr = vmalloc(bytes);
2734 gcmkTRACE_ZONE(gcvLEVEL_INFO,
2736 "gckOS_AllocatePagedMemoryEx: "
2737 "Can't allocate memorry for size->0x%x",
2742 gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
2743 return gcvSTATUS_OUT_OF_MEMORY;
2746 mdl = _CreateMdl(current->tgid);
2752 free_pages((unsigned int) addr, GetOrder(mdl->numPages));
2761 gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
2762 return gcvSTATUS_OUT_OF_MEMORY;
2767 mdl->numPages = numPages;
2769 mdl->contiguous = Contiguous;
2771 for (i = 0; i < mdl->numPages; i++)
2775 if (mdl->contiguous)
2777 page = virt_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
2781 page = vmalloc_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
2784 SetPageReserved(page);
2785 flush_dcache_page(page);
2788 /* Return physical address. */
2789 *Physical = (gctPHYS_ADDR) mdl;
2792 * Add this to a global list.
2793 * Will be used by get physical address
2794 * and mapuser pointer functions.
2798 /* Initialize the queue. */
2799 Os->mdlHead = Os->mdlTail = mdl;
2804 mdl->prev = Os->mdlTail;
2805 Os->mdlTail->next = mdl;
2811 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
2812 "%s: Bytes=%lu Mdl=0x%08x Logical=0x%08x",
2813 __FUNCTION__, bytes, mdl, mdl->addr);
2816 gcmkHEADER_ARG("*Physical=0x%08x", *Physical);
2817 return gcvSTATUS_OK;
2820 /*******************************************************************************
2822 ** gckOS_FreePagedMemory
2824 ** Free memory allocated from the paged pool.
2829 ** Pointer to an gckOS object.
2831 ** gctPHYS_ADDR Physical
2832 ** Physical address of the allocation.
2835 ** Number of bytes of the allocation.
2841 gceSTATUS gckOS_FreePagedMemory(
2843 IN gctPHYS_ADDR Physical,
2847 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
2851 /* Verify the arguments. */
2852 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2853 gcmkVERIFY_ARGUMENT(Physical != NULL);
2855 gcmkTRACE_ZONE(gcvLEVEL_INFO,
2857 "in gckOS_FreePagedMemory");
2863 for (i = 0; i < mdl->numPages; i++)
2865 if (mdl->contiguous)
2867 ClearPageReserved(virt_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
2871 ClearPageReserved(vmalloc_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
2875 if (mdl->contiguous)
2877 free_pages((unsigned long)mdl->addr, GetOrder(mdl->numPages));
2878 #if PAGE_ALLOC_LIMIT
2879 g_pages_alloced -= mdl->numPages;
2880 //printk("free %d / %d \n", mdl->numPages, g_pages_alloced);
2881 if(g_pages_alloced<0) g_pages_alloced = 0;
2889 /* Remove the node from global list. */
2890 if (mdl == Os->mdlHead)
2892 if ((Os->mdlHead = mdl->next) == gcvNULL)
2894 Os->mdlTail = gcvNULL;
2899 mdl->prev->next = mdl->next;
2901 if (mdl == Os->mdlTail)
2903 Os->mdlTail = mdl->prev;
2907 mdl->next->prev = mdl->prev;
2913 /* Free the structure... */
2914 gcmkVERIFY_OK(_DestroyMdl(mdl));
2916 gcmkTRACE_ZONE(gcvLEVEL_INFO,
2918 "gckOS_FreePagedMemory: Bytes->0x%x, Mdl->0x%x",
2923 return gcvSTATUS_OK;
2926 /*******************************************************************************
2930 ** Lock memory allocated from the paged pool.
2935 ** Pointer to an gckOS object.
2937 ** gctPHYS_ADDR Physical
2938 ** Physical address of the allocation.
2941 ** Number of bytes of the allocation.
2945 ** gctPOINTER * Logical
2946 ** Pointer to a variable that receives the address of the mapped
2949 ** gctSIZE_T * PageCount
2950 ** Pointer to a variable that receives the number of pages required for
2951 ** the page table according to the GPU page size.
2953 gceSTATUS gckOS_LockPages(
2955 IN gctPHYS_ADDR Physical,
2957 OUT gctPOINTER * Logical,
2958 OUT gctSIZE_T * PageCount
2962 PLINUX_MDL_MAP mdlMap;
2964 unsigned long start;
2968 /* Verify the arguments. */
2969 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2970 gcmkVERIFY_ARGUMENT(Physical != NULL);
2971 gcmkVERIFY_ARGUMENT(Logical != NULL);
2972 gcmkVERIFY_ARGUMENT(PageCount != NULL);
2974 gcmkTRACE_ZONE(gcvLEVEL_INFO,
2976 "in gckOS_LockPages");
2978 mdl = (PLINUX_MDL) Physical;
2982 mdlMap = FindMdlMap(mdl, current->tgid);
2984 if (mdlMap == gcvNULL)
2986 mdlMap = _CreateMdlMap(mdl, current->tgid);
2988 if (mdlMap == gcvNULL)
2992 return gcvSTATUS_OUT_OF_MEMORY;
2996 if (mdlMap->vmaAddr == gcvNULL)
2998 down_write(¤t->mm->mmap_sem);
3000 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(NULL,
3002 mdl->numPages * PAGE_SIZE,
3003 PROT_READ | PROT_WRITE,
3007 up_write(¤t->mm->mmap_sem);
3009 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3012 "vmaAddr->0x%x for phys_addr->0x%x",
3013 (gctUINT32)mdlMap->vmaAddr,
3016 if (mdlMap->vmaAddr == gcvNULL)
3018 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3020 "gckOS_LockPages: do_mmap_pgoff error");
3024 return gcvSTATUS_OUT_OF_MEMORY;
3027 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
3029 if (mdlMap->vma == gcvNULL)
3031 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3035 mdlMap->vmaAddr = gcvNULL;
3039 return gcvSTATUS_OUT_OF_RESOURCES;
3042 mdlMap->vma->vm_flags |= VM_RESERVED;
3043 /* Make this mapping non-cached. */
3044 #if (2==gcdENABLE_MEM_CACHE)
3045 mdlMap->vma->vm_page_prot = pgprot_writecombine(mdlMap->vma->vm_page_prot);
3046 #elif (1==gcdENABLE_MEM_CACHE)
3049 mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
3054 /* Now map all the vmalloc pages to this user address. */
3055 down_write(¤t->mm->mmap_sem);
3057 if (mdl->contiguous)
3059 /* map kernel memory to user space.. */
3060 if (remap_pfn_range(mdlMap->vma,
3061 mdlMap->vma->vm_start,
3062 virt_to_phys((gctPOINTER)mdl->addr) >> PAGE_SHIFT,
3063 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
3064 mdlMap->vma->vm_page_prot) < 0)
3066 up_write(¤t->mm->mmap_sem);
3068 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3070 "gckOS_LockPages: unable to mmap ret");
3072 mdlMap->vmaAddr = gcvNULL;
3076 return gcvSTATUS_OUT_OF_MEMORY;
3081 start = mdlMap->vma->vm_start;
3083 for (i = 0; i < mdl->numPages; i++)
3085 pfn = vmalloc_to_pfn(addr);
3087 if (remap_pfn_range(mdlMap->vma,
3091 mdlMap->vma->vm_page_prot) < 0)
3093 up_write(¤t->mm->mmap_sem);
3095 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3098 "gctPHYS_ADDR->0x%x Logical->0x%x Unable to map addr->0x%x to start->0x%x",
3099 (gctUINT32)Physical,
3100 (gctUINT32)*Logical,
3104 mdlMap->vmaAddr = gcvNULL;
3108 return gcvSTATUS_OUT_OF_MEMORY;
3116 up_write(¤t->mm->mmap_sem);
3119 /* Convert pointer to MDL. */
3120 *Logical = mdlMap->vmaAddr;
3122 /* Return the page number according to the GPU page size. */
3123 gcmkASSERT((PAGE_SIZE % 4096) == 0);
3124 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
3126 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
3130 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3133 "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d",
3134 (gctUINT32)Physical,
3136 (gctUINT32)*Logical,
3140 return gcvSTATUS_OK;
3143 /*******************************************************************************
3147 ** Map paged memory into a page table.
3152 ** Pointer to an gckOS object.
3154 ** gctPHYS_ADDR Physical
3155 ** Physical address of the allocation.
3157 ** gctSIZE_T PageCount
3158 ** Number of pages required for the physical address.
3160 ** gctPOINTER PageTable
3161 ** Pointer to the page table to fill in.
3170 IN gctPHYS_ADDR Physical,
3171 IN gctSIZE_T PageCount,
3172 IN gctPOINTER PageTable
3180 /* Verify the arguments. */
3181 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3182 gcmkVERIFY_ARGUMENT(Physical != NULL);
3183 gcmkVERIFY_ARGUMENT(PageCount > 0);
3184 gcmkVERIFY_ARGUMENT(PageTable != NULL);
3186 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3188 "in gckOS_MapPages");
3190 /* Convert pointer to MDL. */
3191 mdl = (PLINUX_MDL)Physical;
3193 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3196 "Physical->0x%x PageCount->0x%x PagedMemory->?%d",
3197 (gctUINT32)Physical,
3198 (gctUINT32)PageCount,
3203 table = (gctUINT32 *)PageTable;
3205 /* Get all the physical addresses and store them in the page table. */
3211 /* Try to get the user pages so DMA can happen. */
3212 while (PageCount-- > 0)
3214 if (mdl->contiguous)
3216 *table++ = virt_to_phys(addr);
3220 *table++ = page_to_phys(vmalloc_to_page(addr));
3229 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3231 "We should not get this call for Non Paged Memory!");
3233 while (PageCount-- > 0)
3235 *table++ = (gctUINT32)virt_to_phys(addr);
3243 return gcvSTATUS_OK;
3246 /*******************************************************************************
3248 ** gckOS_UnlockPages
3250 ** Unlock memory allocated from the paged pool.
3255 ** Pointer to an gckOS object.
3257 ** gctPHYS_ADDR Physical
3258 ** Physical address of the allocation.
3261 ** Number of bytes of the allocation.
3263 ** gctPOINTER Logical
3264 ** Address of the mapped memory.
3270 gceSTATUS gckOS_UnlockPages(
3272 IN gctPHYS_ADDR Physical,
3274 IN gctPOINTER Logical
3277 PLINUX_MDL_MAP mdlMap;
3278 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
3279 struct task_struct * task;
3280 struct mm_struct * mm;
3282 /* Verify the arguments. */
3283 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3284 gcmkVERIFY_ARGUMENT(Physical != NULL);
3285 gcmkVERIFY_ARGUMENT(Logical != NULL);
3287 /* Make sure there is already a mapping...*/
3288 gcmkVERIFY_ARGUMENT(mdl->addr != NULL);
3290 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3292 "in gckOS_UnlockPages");
3298 while (mdlMap != gcvNULL)
3300 if (mdlMap->vmaAddr != gcvNULL)
3302 /* Get the current pointer for the task with stored pid. */
3303 task = FIND_TASK_BY_PID(mdlMap->pid);
3305 mm = get_task_mm(task);
3306 put_task_struct(task);
3313 down_write(&mm->mmap_sem);
3314 do_munmap(mm, (unsigned long)Logical, mdl->numPages * PAGE_SIZE);
3315 up_write(&mm->mmap_sem);
3319 mdlMap->vmaAddr = gcvNULL;
3322 mdlMap = mdlMap->next;
3328 return gcvSTATUS_OK;
3332 /*******************************************************************************
3334 ** gckOS_AllocateContiguous
3336 ** Allocate memory from the contiguous pool.
3341 ** Pointer to an gckOS object.
3343 ** gctBOOL InUserSpace
3344 ** gcvTRUE if the pages need to be mapped into user space.
3346 ** gctSIZE_T * Bytes
3347 ** Pointer to the number of bytes to allocate.
3351 ** gctSIZE_T * Bytes
3352 ** Pointer to a variable that receives the number of bytes allocated.
3354 ** gctPHYS_ADDR * Physical
3355 ** Pointer to a variable that receives the physical address of the
3356 ** memory allocation.
3358 ** gctPOINTER * Logical
3359 ** Pointer to a variable that receives the logical address of the
3360 ** memory allocation.
3362 gceSTATUS gckOS_AllocateContiguous(
3364 IN gctBOOL InUserSpace,
3365 IN OUT gctSIZE_T * Bytes,
3366 OUT gctPHYS_ADDR * Physical,
3367 OUT gctPOINTER * Logical
3370 /* Same as non-paged memory for now. */
3371 return gckOS_AllocateNonPagedMemory(Os,
3379 /*******************************************************************************
3381 ** gckOS_FreeContiguous
3383 ** Free memory allocated from the contiguous pool.
3388 ** Pointer to an gckOS object.
3390 ** gctPHYS_ADDR Physical
3391 ** Physical address of the allocation.
3393 ** gctPOINTER Logical
3394 ** Logicval address of the allocation.
3397 ** Number of bytes of the allocation.
3403 gceSTATUS gckOS_FreeContiguous(
3405 IN gctPHYS_ADDR Physical,
3406 IN gctPOINTER Logical,
3410 /* Same of non-paged memory for now. */
3411 return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
3414 /******************************************************************************
3416 ** gckOS_GetKernelLogical
3418 ** Return the kernel logical pointer that corresponods to the specified
3419 ** hardware address.
3424 ** Pointer to an gckOS object.
3426 ** gctUINT32 Address
3427 ** Hardware physical address.
3431 ** gctPOINTER * KernelPointer
3432 ** Pointer to a variable receiving the pointer in kernel address space.
3435 gckOS_GetKernelLogical(
3437 IN gctUINT32 Address,
3438 OUT gctPOINTER * KernelPointer
3445 gckGALDEVICE device;
3451 /* Extract the pointer to the gckGALDEVICE class. */
3452 device = (gckGALDEVICE) Os->device;
3454 /* Kernel shortcut. */
3455 kernel = device->kernel;
3457 /* Split the memory address into a pool type and offset. */
3458 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
3459 kernel->hardware, Address, &pool, &offset
3462 /* Dispatch on pool. */
3465 case gcvPOOL_LOCAL_INTERNAL:
3466 /* Internal memory. */
3467 logical = device->internalLogical;
3470 case gcvPOOL_LOCAL_EXTERNAL:
3471 /* External memory. */
3472 logical = device->externalLogical;
3475 case gcvPOOL_SYSTEM:
3476 /* System memory. */
3477 logical = device->contiguousBase;
3481 /* Invalid memory pool. */
3482 return gcvSTATUS_INVALID_ARGUMENT;
3485 /* Build logical address of specified address. */
3486 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
3489 return gcvSTATUS_OK;
3493 /* Return status. */
3497 /*******************************************************************************
3499 ** gckOS_MapUserPointer
3501 ** Map a pointer from the user process into the kernel address space.
3506 ** Pointer to an gckOS object.
3508 ** gctPOINTER Pointer
3509 ** Pointer in user process space that needs to be mapped.
3512 ** Number of bytes that need to be mapped.
3516 ** gctPOINTER * KernelPointer
3517 ** Pointer to a variable receiving the mapped pointer in kernel address
3521 gckOS_MapUserPointer(
3523 IN gctPOINTER Pointer,
3525 OUT gctPOINTER * KernelPointer
3528 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
3529 gctPOINTER buf = gcvNULL;
3532 /* Verify the arguments. */
3533 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3534 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
3535 gcmkVERIFY_ARGUMENT(Size > 0);
3536 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
3538 buf = kmalloc(Size, GFP_KERNEL);
3541 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
3543 "Failed to allocate memory at line %d in %s.",
3547 return gcvSTATUS_OUT_OF_MEMORY;
3550 len = copy_from_user(buf, Pointer, Size);
3553 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
3555 "Failed to copy data from user at line %d in %s.",
3564 return gcvSTATUS_GENERIC_IO;
3567 *KernelPointer = buf;
3569 *KernelPointer = Pointer;
3570 #endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
3572 return gcvSTATUS_OK;
3575 /*******************************************************************************
3577 ** gckOS_UnmapUserPointer
3579 ** Unmap a user process pointer from the kernel address space.
3584 ** Pointer to an gckOS object.
3586 ** gctPOINTER Pointer
3587 ** Pointer in user process space that needs to be unmapped.
3590 ** Number of bytes that need to be unmapped.
3592 ** gctPOINTER KernelPointer
3593 ** Pointer in kernel address space that needs to be unmapped.
3600 gckOS_UnmapUserPointer(
3602 IN gctPOINTER Pointer,
3604 IN gctPOINTER KernelPointer
3607 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
3610 /* Verify the arguments. */
3611 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3612 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
3613 gcmkVERIFY_ARGUMENT(Size > 0);
3614 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
3616 len = copy_to_user(Pointer, KernelPointer, Size);
3618 kfree(KernelPointer);
3622 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
3624 "Failed to copy data to user at line %d in %s.",
3627 return gcvSTATUS_GENERIC_IO;
3629 #endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
3631 return gcvSTATUS_OK;
3634 /*******************************************************************************
3636 ** gckOS_WriteMemory
3638 ** Write data to a memory.
3643 ** Pointer to an gckOS object.
3645 ** gctPOINTER Address
3646 ** Address of the memory to write to.
3649 ** Data for register.
3658 IN gctPOINTER Address,
3662 /* Verify the arguments. */
3663 gcmkVERIFY_ARGUMENT(Address != NULL);
3666 writel(Data, (gctUINT8 *)Address);
3669 return gcvSTATUS_OK;
3672 /*******************************************************************************
3674 ** gckOS_CreateSignal
3676 ** Create a new signal.
3681 ** Pointer to an gckOS object.
3683 ** gctBOOL ManualReset
3684 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
3685 ** order to set the signal to nonsignaled state.
3686 ** If set to gcvFALSE, the signal will automatically be set to
3687 ** nonsignaled state by gckOS_WaitSignal function.
3691 ** gctSIGNAL * Signal
3692 ** Pointer to a variable receiving the created gctSIGNAL.
3697 IN gctBOOL ManualReset,
3698 OUT gctSIGNAL * Signal
3701 #if USE_NEW_LINUX_SIGNAL
3702 return gcvSTATUS_NOT_SUPPORTED;
3704 gcsSIGNAL_PTR signal;
3706 /* Verify the arguments. */
3707 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3708 gcmkVERIFY_ARGUMENT(Signal != NULL);
3710 /* Create an event structure. */
3711 signal = (gcsSIGNAL_PTR)kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL);
3713 if (signal == gcvNULL)
3715 return gcvSTATUS_OUT_OF_MEMORY;
3718 signal->manualReset = ManualReset;
3720 init_completion(&signal->event);
3722 atomic_set(&signal->ref, 1);
3724 *Signal = (gctSIGNAL) signal;
3726 return gcvSTATUS_OK;
3730 /*******************************************************************************
3732 ** gckOS_DestroySignal
3734 ** Destroy a signal.
3739 ** Pointer to an gckOS object.
3742 ** Pointer to the gctSIGNAL.
3749 gckOS_DestroySignal(
3754 #if USE_NEW_LINUX_SIGNAL
3755 return gcvSTATUS_NOT_SUPPORTED;
3757 gcsSIGNAL_PTR signal;
3759 /* Verify the arguments. */
3760 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3761 gcmkVERIFY_ARGUMENT(Signal != NULL);
3763 signal = (gcsSIGNAL_PTR) Signal;
3765 if (atomic_dec_and_test(&signal->ref))
3767 /* Free the sgianl. */
3772 return gcvSTATUS_OK;
3776 /*******************************************************************************
3780 ** Set a state of the specified signal.
3785 ** Pointer to an gckOS object.
3788 ** Pointer to the gctSIGNAL.
3791 ** If gcvTRUE, the signal will be set to signaled state.
3792 ** If gcvFALSE, the signal will be set to nonsignaled state.
3801 IN gctSIGNAL Signal,
3805 #if USE_NEW_LINUX_SIGNAL
3806 return gcvSTATUS_NOT_SUPPORTED;
3808 gcsSIGNAL_PTR signal;
3810 gcmkHEADER_ARG("Os=0x%x Signal=0x%x State=%d", Os, Signal, State);
3812 /* Verify the arguments. */
3813 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3814 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
3816 signal = (gcsSIGNAL_PTR) Signal;
3818 /* Set the new state of the event. */
3819 if (signal->manualReset)
3823 /* Set the event to a signaled state. */
3824 complete_all(&signal->event);
3828 /* Set the event to an unsignaled state. */
3829 INIT_COMPLETION(signal->event);
3836 /* Set the event to a signaled state. */
3837 complete(&signal->event);
3844 return gcvSTATUS_OK;
3848 #if USE_NEW_LINUX_SIGNAL
3849 /*******************************************************************************
3853 ** Set the specified signal which is owned by a process to signaled state.
3858 ** Pointer to an gckOS object.
3861 ** Pointer to the gctSIGNAL.
3863 ** gctHANDLE Process
3864 ** Handle of process owning the signal.
3873 IN gctSIGNAL Signal,
3874 IN gctHANDLE Process
3879 struct task_struct * task;
3880 struct siginfo info;
3882 task = FIND_TASK_BY_PID((pid_t) Process);
3884 if (task != gcvNULL)
3886 /* Fill in the siginfo structure. */
3887 info.si_signo = Os->device->signal;
3889 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
3890 info.si_ptr = Signal;
3892 /* Send the signal. */
3893 if ((result = send_sig_info(Os->device->signal, &info, task)) < 0)
3895 status = gcvSTATUS_GENERIC_IO;
3897 gcmkTRACE(gcvLEVEL_ERROR,
3898 "%s(%d): send_sig_info failed.",
3899 __FUNCTION__, __LINE__);
3904 status = gcvSTATUS_OK;
3906 put_task_struct(task);
3910 status = gcvSTATUS_GENERIC_IO;
3912 gcmkTRACE(gcvLEVEL_ERROR,
3913 "%s(%d): find_task_by_pid failed.",
3914 __FUNCTION__, __LINE__);
3917 /* Return status. */
3921 /*******************************************************************************
3925 ** Wait for a signal to become signaled.
3930 ** Pointer to an gckOS object.
3933 ** Pointer to the gctSIGNAL.
3936 ** Number of milliseconds to wait.
3937 ** Pass the value of gcvINFINITE for an infinite wait.
3946 IN gctSIGNAL Signal,
3950 return gcvSTATUS_NOT_SUPPORTED;
3953 /*******************************************************************************
3957 ** Map a signal in to the current process space.
3962 ** Pointer to an gckOS object.
3965 ** Pointer to tha gctSIGNAL to map.
3967 ** gctHANDLE Process
3968 ** Handle of process owning the signal.
3972 ** gctSIGNAL * MappedSignal
3973 ** Pointer to a variable receiving the mapped gctSIGNAL.
3978 IN gctSIGNAL Signal,
3979 IN gctHANDLE Process,
3980 OUT gctSIGNAL * MappedSignal
3983 return gcvSTATUS_NOT_SUPPORTED;
3988 /*******************************************************************************
3992 ** Set the specified signal which is owned by a process to signaled state.
3997 ** Pointer to an gckOS object.
4000 ** Pointer to the gctSIGNAL.
4002 ** gctHANDLE Process
4003 ** Handle of process owning the signal.
4012 IN gctSIGNAL Signal,
4013 IN gctHANDLE Process
4019 gcmkHEADER_ARG("Os=0x%x Signal=%d Process=0x%x",
4020 Os, (gctINT) Signal, Process);
4022 /* Map the signal into kernel space. */
4023 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
4026 status = gckOS_Signal(Os, signal, gcvTRUE);
4031 /* Return the status. */
4036 /*******************************************************************************
4040 ** Wait for a signal to become signaled.
4045 ** Pointer to an gckOS object.
4048 ** Pointer to the gctSIGNAL.
4051 ** Number of milliseconds to wait.
4052 ** Pass the value of gcvINFINITE for an infinite wait.
4061 IN gctSIGNAL Signal,
4066 gcsSIGNAL_PTR signal;
4070 gcmkHEADER_ARG("Os=0x%x Signal=0x%x Wait=%u", Os, Signal, Wait);
4072 /* Verify the arguments. */
4073 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4074 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
4076 signal = (gcsSIGNAL_PTR) Signal;
4078 /* Convert wait to milliseconds. */
4079 timeout = (Wait == gcvINFINITE) ? MAX_SCHEDULE_TIMEOUT : Wait*HZ/1000;
4082 if (!signal->manualReset && timeout == 0) timeout = 1;
4084 rc = wait_for_completion_interruptible_timeout(&signal->event, timeout);
4085 status = ((rc == 0) && !signal->event.done) ? gcvSTATUS_TIMEOUT
4088 /* Return status. */
4093 /*******************************************************************************
4097 ** Map a signal in to the current process space.
4102 ** Pointer to an gckOS object.
4105 ** Pointer to tha gctSIGNAL to map.
4107 ** gctHANDLE Process
4108 ** Handle of process owning the signal.
4112 ** gctSIGNAL * MappedSignal
4113 ** Pointer to a variable receiving the mapped gctSIGNAL.
4118 IN gctSIGNAL Signal,
4119 IN gctHANDLE Process,
4120 OUT gctSIGNAL * MappedSignal
4124 gcsSIGNAL_PTR signal;
4126 gctBOOL acquired = gcvFALSE;
4128 gcmkHEADER_ARG("Os=0x%x Signal=0x%x Process=0x%x", Os, Signal, Process);
4130 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
4131 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
4133 signalID = (gctINT) Signal - 1;
4135 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4138 if (signalID >= 0 && signalID < Os->signal.tableLen)
4140 /* It is a user space signal. */
4141 signal = Os->signal.table[signalID];
4143 if (signal == gcvNULL)
4145 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4150 /* It is a kernel space signal structure. */
4151 signal = (gcsSIGNAL_PTR) Signal;
4154 if (atomic_inc_return(&signal->ref) <= 1)
4156 /* The previous value is 0, it has been deleted. */
4157 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4160 /* Release the mutex. */
4161 gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
4163 *MappedSignal = (gctSIGNAL) signal;
4166 gcmkFOOTER_ARG("*MappedSignal=0x%x", *MappedSignal);
4167 return gcvSTATUS_OK;
4172 /* Release the mutex. */
4173 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
4176 /* Return the staus. */
4181 /*******************************************************************************
4183 ** gckOS_CreateUserSignal
4185 ** Create a new signal to be used in the user space.
4190 ** Pointer to an gckOS object.
4192 ** gctBOOL ManualReset
4193 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
4194 ** order to set the signal to nonsignaled state.
4195 ** If set to gcvFALSE, the signal will automatically be set to
4196 ** nonsignaled state by gckOS_WaitSignal function.
4200 ** gctINT * SignalID
4201 ** Pointer to a variable receiving the created signal's ID.
4204 gckOS_CreateUserSignal(
4206 IN gctBOOL ManualReset,
4207 OUT gctINT * SignalID
4210 gcsSIGNAL_PTR signal;
4211 gctINT unused, currentID, tableLen;
4215 gctBOOL acquired = gcvFALSE;
4217 gcmkHEADER_ARG("Os=0x%0x ManualReset=%d", Os, ManualReset);
4219 /* Verify the arguments. */
4220 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4221 gcmkVERIFY_ARGUMENT(SignalID != gcvNULL);
4223 /* Lock the table. */
4225 gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4229 if (Os->signal.unused < 1)
4231 /* Enlarge the table. */
4232 table = (gctPOINTER *) kmalloc(
4233 sizeof(gctPOINTER) * (Os->signal.tableLen + USER_SIGNAL_TABLE_LEN_INIT),
4236 if (table == gcvNULL)
4238 /* Out of memory. */
4239 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4242 memset(table + Os->signal.tableLen, 0, sizeof(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
4243 memcpy(table, Os->signal.table, sizeof(gctPOINTER) * Os->signal.tableLen);
4245 /* Release the old table. */
4246 kfree(Os->signal.table);
4248 /* Update the table. */
4249 Os->signal.table = table;
4250 Os->signal.currentID = Os->signal.tableLen;
4251 Os->signal.tableLen += USER_SIGNAL_TABLE_LEN_INIT;
4252 Os->signal.unused += USER_SIGNAL_TABLE_LEN_INIT;
4255 table = Os->signal.table;
4256 currentID = Os->signal.currentID;
4257 tableLen = Os->signal.tableLen;
4258 unused = Os->signal.unused;
4260 /* Create a new signal. */
4262 gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
4264 /* Save the process ID. */
4265 signal->process = (gctHANDLE) current->tgid;
4267 table[currentID] = signal;
4269 /* Plus 1 to avoid NULL claims. */
4270 *SignalID = currentID + 1;
4272 /* Update the currentID. */
4275 for (i = 0; i < tableLen; i++)
4277 if (++currentID >= tableLen)
4279 /* Wrap to the begin. */
4283 if (table[currentID] == gcvNULL)
4290 Os->signal.table = table;
4291 Os->signal.currentID = currentID;
4292 Os->signal.tableLen = tableLen;
4293 Os->signal.unused = unused;
4296 gckOS_ReleaseMutex(Os, Os->signal.lock));
4298 gcmkFOOTER_ARG("*SignalID=%d", gcmOPT_VALUE(SignalID));
4299 return gcvSTATUS_OK;
4304 /* Release the mutex. */
4306 gckOS_ReleaseMutex(Os, Os->signal.lock));
4309 /* Return the staus. */
4314 /*******************************************************************************
4316 ** gckOS_DestroyUserSignal
4318 ** Destroy a signal to be used in the user space.
4323 ** Pointer to an gckOS object.
4333 gckOS_DestroyUserSignal(
4339 gcsSIGNAL_PTR signal;
4340 gctBOOL acquired = gcvFALSE;
4342 gcmkHEADER_ARG("Os=0x%x SignalID=%d", Os, SignalID);
4344 /* Verify the arguments. */
4345 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4348 gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4352 if (SignalID < 1 || SignalID > Os->signal.tableLen)
4354 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4356 "gckOS_DestroyUserSignal: invalid signal->%d.",
4360 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4365 signal = Os->signal.table[SignalID];
4367 if (signal == gcvNULL)
4369 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4371 "gckOS_DestroyUserSignal: signal is NULL."
4374 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4377 /* Check to see if the process is the owner of the signal. */
4378 if (signal->process != (gctHANDLE) current->tgid)
4380 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4382 "gckOS_DestroyUserSignal: process id doesn't match. ",
4383 "signal->process: %d, current->tgid: %d",
4387 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4391 gckOS_DestroySignal(Os, signal));
4393 /* Update the table. */
4394 Os->signal.table[SignalID] = gcvNULL;
4395 if (Os->signal.unused++ == 0)
4397 Os->signal.currentID = SignalID;
4401 gckOS_ReleaseMutex(Os, Os->signal.lock));
4405 return gcvSTATUS_OK;
4410 /* Release the mutex. */
4412 gckOS_ReleaseMutex(Os, Os->signal.lock));
4415 /* Return the status. */
4420 /*******************************************************************************
4422 ** gckOS_WaitUserSignal
4424 ** Wait for a signal used in the user mode to become signaled.
4429 ** Pointer to an gckOS object.
4435 ** Number of milliseconds to wait.
4436 ** Pass the value of gcvINFINITE for an infinite wait.
4443 gckOS_WaitUserSignal(
4450 gcsSIGNAL_PTR signal;
4451 gctBOOL acquired = gcvFALSE;
4453 gcmkHEADER_ARG("Os=0x%x SignalID=%d Wait=%u", Os, SignalID, Wait);
4455 /* Verify the arguments. */
4456 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4458 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4461 if (SignalID < 1 || SignalID > Os->signal.tableLen)
4463 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4465 "gckOS_WaitSignal: invalid signal.",
4469 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4474 signal = Os->signal.table[SignalID];
4476 gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
4477 acquired = gcvFALSE;
4479 if (signal == gcvNULL)
4481 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4483 "gckOS_WaitSignal: signal is NULL."
4486 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4489 if (signal->process != (gctHANDLE) current->tgid)
4491 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4493 "gckOS_WaitUserSignal: process id doesn't match. "
4494 "signal->process: %d, current->tgid: %d",
4498 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4503 status = gckOS_WaitSignal(Os, signal, Wait==gcvINFINITE?5000:Wait);
4504 if(Wait==gcvINFINITE&&status==gcvSTATUS_TIMEOUT){gcmkPRINT("$$FLUSH$$");}
4505 }while(status==gcvSTATUS_TIMEOUT&&Wait==gcvINFINITE);
4507 /* Return the status. */
4514 /* Release the mutex. */
4516 gckOS_ReleaseMutex(Os, Os->signal.lock));
4519 /* Return the staus. */
4524 /*******************************************************************************
4526 ** gckOS_SignalUserSignal
4528 ** Set a state of the specified signal to be used in the user space.
4533 ** Pointer to an gckOS object.
4539 ** If gcvTRUE, the signal will be set to signaled state.
4540 ** If gcvFALSE, the signal will be set to nonsignaled state.
4547 gckOS_SignalUserSignal(
4554 gcsSIGNAL_PTR signal;
4555 gctBOOL acquired = gcvFALSE;
4557 gcmkHEADER_ARG("Os=0x%x SignalID=%d State=%d", Os, SignalID, State);
4559 /* Verify the arguments. */
4560 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4562 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4566 || (SignalID > Os->signal.tableLen)
4569 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
4570 "gckOS_WaitSignal: invalid signal->%d.", SignalID);
4572 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4577 signal = Os->signal.table[SignalID];
4579 gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
4580 acquired = gcvFALSE;
4582 if (signal == gcvNULL)
4584 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4586 "gckOS_WaitSignal: signal is NULL."
4589 gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
4592 if (signal->process != (gctHANDLE) current->tgid)
4594 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4596 "gckOS_DestroyUserSignal: process id doesn't match. ",
4597 "signal->process: %d, current->tgid: %d",
4601 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4604 status = gckOS_Signal(Os, signal, State);
4613 /* Release the mutex. */
4615 gckOS_ReleaseMutex(Os, Os->signal.lock));
4618 /* Return the staus. */
4624 gckOS_DestroyAllUserSignals(
4630 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4632 gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
4637 if (Os->signal.unused == Os->signal.tableLen)
4639 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
4643 return gcvSTATUS_OK;
4646 for (signal = 0; signal < Os->signal.tableLen; signal++)
4648 if (Os->signal.table[signal] != gcvNULL &&
4649 ((gcsSIGNAL_PTR)Os->signal.table[signal])->process == (gctHANDLE) current->tgid)
4651 gckOS_DestroySignal(Os, Os->signal.table[signal]);
4653 /* Update the signal table. */
4654 Os->signal.table[signal] = gcvNULL;
4655 if (Os->signal.unused++ == 0)
4657 Os->signal.currentID = signal;
4662 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
4666 return gcvSTATUS_OK;
4669 #endif /* USE_NEW_LINUX_SIGNAL */
4671 /*******************************************************************************
4673 ** gckOS_MapUserMemory
4675 ** Lock down a user buffer and return an DMA'able address to be used by the
4676 ** hardware to access it.
4680 ** gctPOINTER Memory
4681 ** Pointer to memory to lock down.
4684 ** Size in bytes of the memory to lock down.
4688 ** gctPOINTER * Info
4689 ** Pointer to variable receiving the information record required by
4690 ** gckOS_UnmapUserMemory.
4692 ** gctUINT32_PTR Address
4693 ** Pointer to a variable that will receive the address DMA'able by the
4697 gckOS_MapUserMemory(
4699 IN gctPOINTER Memory,
4701 OUT gctPOINTER * Info,
4702 OUT gctUINT32_PTR Address
4706 gctSIZE_T pageCount, i, j;
4707 gctUINT32_PTR pageTable;
4709 gctUINT32 start, end, memory;
4712 gcsPageInfo_PTR info = gcvNULL;
4713 struct page **pages = gcvNULL;
4715 /* Verify the arguments. */
4716 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4717 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
4718 gcmkVERIFY_ARGUMENT(Size > 0);
4719 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
4720 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4722 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
4724 "[gckOS_MapUserMemory] enter."
4729 memory = (gctUINT32) Memory;
4731 /* Get the number of required pages. */
4732 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
4733 start = memory >> PAGE_SHIFT;
4734 pageCount = end - start;
4736 gcmkTRACE_ZONE(gcvLEVEL_INFO,
4738 "[gckOS_MapUserMemory] pageCount: %d.",
4742 /* Invalid argument. */
4745 return gcvSTATUS_INVALID_ARGUMENT;
4749 if ((memory + Size) < memory)
4751 return gcvSTATUS_INVALID_ARGUMENT;
4754 MEMORY_MAP_LOCK(Os);
4756 /* Allocate the Info struct. */
4757 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL);
4759 if (info == gcvNULL)
4761 status = gcvSTATUS_OUT_OF_MEMORY;
4765 /* Allocate the array of page addresses. */
4766 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL);
4768 if (pages == gcvNULL)
4770 status = gcvSTATUS_OUT_OF_MEMORY;
4774 /* Get the user pages. */
4775 down_read(¤t->mm->mmap_sem);
4776 result = get_user_pages(current,
4785 up_read(¤t->mm->mmap_sem);
4787 if (result <=0 || result < pageCount)
4789 struct vm_area_struct *vma;
4791 vma = find_vma(current->mm, memory);
4793 if (vma && (vma->vm_flags & VM_PFNMAP) )
4801 pgd_t * pgd = pgd_offset(current->mm, memory);
4802 pud_t * pud = pud_alloc(current->mm, pgd, memory);
4805 pmd_t * pmd = pmd_alloc(current->mm, pud, memory);
4808 pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
4824 pfn = pte_pfn(*pte);
4825 *Address = ((pfn << PAGE_SHIFT) | (((unsigned long)Memory) & ~PAGE_MASK))
4829 pte_unmap_unlock(pte, ptl);
4831 /* Release page info struct. */
4832 if (info != gcvNULL)
4834 /* Free the page info struct. */
4838 if (pages != gcvNULL)
4840 /* Free the page table. */
4844 MEMORY_MAP_UNLOCK(Os);
4846 return gcvSTATUS_OK;
4853 status = gcvSTATUS_OUT_OF_RESOURCES;
4858 status = gcvSTATUS_OUT_OF_RESOURCES;
4863 for (i = 0; i < pageCount; i++)
4865 /* Flush the data cache. */
4867 dma_sync_single_for_device(
4869 page_to_phys(pages[i]),
4873 flush_dcache_page(pages[i]);
4877 /* Allocate pages inside the page table. */
4878 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernel->mmu,
4879 pageCount * (PAGE_SIZE/4096),
4880 (gctPOINTER *) &pageTable,
4883 /* Fill the page table. */
4884 for (i = 0; i < pageCount; i++)
4886 /* Get the physical address from page struct. */
4887 pageTable[i * (PAGE_SIZE/4096)] = page_to_phys(pages[i]);
4889 for (j = 1; j < (PAGE_SIZE/4096); j++)
4891 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
4894 gcmkTRACE_ZONE(gcvLEVEL_INFO,
4896 "[gckOS_MapUserMemory] pages[%d]: 0x%x, pageTable[%d]: 0x%x.",
4901 /* Save pointer to page table. */
4902 info->pageTable = pageTable;
4903 info->pages = pages;
4905 *Info = (gctPOINTER) info;
4907 gcmkTRACE_ZONE(gcvLEVEL_INFO,
4909 "[gckOS_MapUserMemory] info->pages: 0x%x, info->pageTable: 0x%x, info: 0x%x.",
4915 /* Return address. */
4916 *Address = address + (memory & ~PAGE_MASK);
4918 gcmkTRACE_ZONE(gcvLEVEL_INFO,
4920 "[gckOS_MapUserMemory] Address: 0x%x.",
4925 status = gcvSTATUS_OK;
4929 if (gcmIS_ERROR(status))
4931 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4933 "[gckOS_MapUserMemory] error occured: %d.",
4937 /* Release page array. */
4938 if (result > 0 && pages != gcvNULL)
4940 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4942 "[gckOS_MapUserMemory] error: page table is freed."
4945 for (i = 0; i < result; i++)
4947 if (pages[i] == gcvNULL)
4952 dma_sync_single_for_device(
4954 page_to_phys(pages[i]),
4958 page_cache_release(pages[i]);
4962 if (pages != gcvNULL)
4964 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4966 "[gckOS_MapUserMemory] error: pages is freed."
4969 /* Free the page table. */
4971 info->pages = gcvNULL;
4974 /* Release page info struct. */
4975 if (info != gcvNULL)
4977 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4979 "[gckOS_MapUserMemory] error: info is freed."
4982 /* Free the page info struct. */
4988 MEMORY_MAP_UNLOCK(Os);
4990 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
4992 "[gckOS_MapUserMemory] leave."
4995 /* Return the status. */
4999 /*******************************************************************************
5001 ** gckOS_UnmapUserMemory
5003 ** Unlock a user buffer and that was previously locked down by
5004 ** gckOS_MapUserMemory.
5008 ** gctPOINTER Memory
5009 ** Pointer to memory to unlock.
5012 ** Size in bytes of the memory to unlock.
5015 ** Information record returned by gckOS_MapUserMemory.
5017 ** gctUINT32_PTR Address
5018 ** The address returned by gckOS_MapUserMemory.
5025 gckOS_UnmapUserMemory(
5027 IN gctPOINTER Memory,
5030 IN gctUINT32 Address
5034 gctUINT32 memory, start, end;
5035 gcsPageInfo_PTR info;
5036 gctSIZE_T pageCount, i;
5037 struct page **pages;
5039 /* Verify the arguments. */
5040 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5041 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5042 gcmkVERIFY_ARGUMENT(Size > 0);
5043 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5045 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
5047 "[gckOS_UnmapUserMemory] enter."
5052 info = (gcsPageInfo_PTR) Info;
5054 if (info == gcvNULL)
5056 return gcvSTATUS_OK;
5059 pages = info->pages;
5061 gcmkTRACE_ZONE(gcvLEVEL_INFO,
5063 "[gckOS_UnmapUserMemory] info: 0x%x, pages: 0x%x.",
5068 /* Invalid page array. */
5069 if (pages == gcvNULL)
5071 return gcvSTATUS_INVALID_ARGUMENT;
5074 memory = (gctUINT32) Memory;
5075 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5076 start = memory >> PAGE_SHIFT;
5077 pageCount = end - start;
5080 if ((memory + Size) < memory)
5082 return gcvSTATUS_INVALID_ARGUMENT;
5085 /* Invalid argument. */
5088 return gcvSTATUS_INVALID_ARGUMENT;
5091 gcmkTRACE_ZONE(gcvLEVEL_INFO,
5093 "[gckOS_UnmapUserMemory] memory: 0x%x, pageCount: %d, pageTable: 0x%x.",
5099 MEMORY_MAP_LOCK(Os);
5101 /* Free the pages from the MMU. */
5102 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernel->mmu,
5104 pageCount * (PAGE_SIZE/4096)
5107 /* Release the page cache. */
5108 for (i = 0; i < pageCount; i++)
5110 gcmkTRACE_ZONE(gcvLEVEL_INFO,
5112 "[gckOS_UnmapUserMemory] pages[%d]: 0x%x.",
5117 if (!PageReserved(pages[i]))
5119 SetPageDirty(pages[i]);
5123 dma_sync_single_for_device(
5125 page_to_phys(pages[i]),
5129 page_cache_release(pages[i]);
5133 status = gcvSTATUS_OK;
5137 if (info != gcvNULL)
5139 /* Free the page array. */
5140 if (info->pages != gcvNULL)
5148 MEMORY_MAP_UNLOCK(Os);
5150 /* Return the status. */
5154 /*******************************************************************************
5156 ** gckOS_GetBaseAddress
5158 ** Get the base address for the physical memory.
5163 ** Pointer to the gckOS object.
5167 ** gctUINT32_PTR BaseAddress
5168 ** Pointer to a variable that will receive the base address.
5171 gckOS_GetBaseAddress(
5173 OUT gctUINT32_PTR BaseAddress
5176 /* Verify the arguments. */
5177 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5178 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5180 /* Return base address. */
5181 *BaseAddress = Os->baseAddress;
5184 return gcvSTATUS_OK;
5188 gckOS_SuspendInterrupt(
5192 /* Verify the arguments. */
5193 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5195 disable_irq(Os->device->irqLine);
5197 return gcvSTATUS_OK;
5201 gckOS_ResumeInterrupt(
5205 /* Verify the arguments. */
5206 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5208 enable_irq(Os->device->irqLine);
5210 return gcvSTATUS_OK;
5215 IN gctPOINTER Destination,
5216 IN gctCONST_POINTER Source,
5220 gcmkVERIFY_ARGUMENT(Destination != NULL);
5221 gcmkVERIFY_ARGUMENT(Source != NULL);
5222 gcmkVERIFY_ARGUMENT(Bytes > 0);
5224 memcpy(Destination, Source, Bytes);
5226 return gcvSTATUS_OK;
5231 IN gctPOINTER Memory,
5235 gcmkHEADER_ARG("Memory=0x%x Bytes=%lu", Memory, Bytes);
5237 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5238 gcmkVERIFY_ARGUMENT(Bytes > 0);
5240 memset(Memory, 0, Bytes);
5243 return gcvSTATUS_OK;
5246 #if gcdkUSE_MEMORY_RECORD
5250 MEMORY_RECORD_PTR List,
5251 gcuVIDMEM_NODE_PTR Node,
5256 MEMORY_RECORD_PTR mr;
5258 mr = (MEMORY_RECORD_PTR)kmalloc(sizeof(struct MEMORY_RECORD), GFP_ATOMIC);
5259 if (mr == gcvNULL) return gcvNULL;
5267 #if gcdkREPORT_VIDMEM_USAGE
5268 AllocatedSurfaceTotal[Type] += Bytes;
5269 AllocatedSurfaceMax[Type] = (AllocatedSurfaceMax[Type] > AllocatedSurfaceTotal[Type])
5270 ? AllocatedSurfaceMax[Type] : AllocatedSurfaceTotal[Type];
5271 AllocatedSurfaceMax[12] += Bytes;
5272 if(AllocatedSurfaceMax[12] > AllocatedSurfaceMax[13])
5274 AllocatedSurfaceMax[13] = AllocatedSurfaceMax[12];
5278 mr->prev = List->prev;
5280 List->prev->next = mr;
5289 DestoryMemoryRecord(
5291 MEMORY_RECORD_PTR Mr
5296 #if gcdkREPORT_VIDMEM_USAGE
5297 AllocatedSurfaceTotal[Mr->type] -= Mr->bytes;
5298 AllocatedSurfaceMax[12] -= Mr->bytes;
5301 Mr->prev->next = Mr->next;
5302 Mr->next->prev = Mr->prev;
5312 MEMORY_RECORD_PTR List,
5313 gcuVIDMEM_NODE_PTR Node
5316 MEMORY_RECORD_PTR mr;
5324 if (mr->node == Node)
5340 FreeAllMemoryRecord(
5342 MEMORY_RECORD_PTR List
5345 MEMORY_RECORD_PTR mr;
5350 #if gcdkREPORT_VIDMEM_USAGE
5351 for (; i < 12; i++) {
5352 printk("AllocatedSurfaceTotal[%s]:\t %12lluK, AllocatedSurfaceMax[%s]:\t %12lluK\n",
5353 pszSurfaceType[i], AllocatedSurfaceTotal[i]/1024,
5354 pszSurfaceType[i], AllocatedSurfaceMax[i]/1024);
5356 AllocatedSurfaceTotal[i] = 0;
5357 AllocatedSurfaceMax[i] = 0;
5359 printk("AllocatedSurfaceMax[unfreed]:\t %12lluK\n", AllocatedSurfaceMax[12]/1024);
5360 printk("AllocatedSurfaceMax[total]:\t %12lluK\n", AllocatedSurfaceMax[13]/1024);
5361 AllocatedSurfaceMax[12] = AllocatedSurfaceMax[13] = 0;
5365 while (List->next != List)
5369 mr->prev->next = mr->next;
5370 mr->next->prev = mr->prev;
5376 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
5378 "Unfreed %s memory: node: %p",
5379 (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)?
5380 "video" : (mr->node->Virtual.contiguous)?
5381 "contiguous" : "virtual",
5386 if (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
5388 if (mr->node->VidMem.locked == 0) break;
5392 if (mr->node->Virtual.locked == 0) break;
5395 gckVIDMEM_Unlock(mr->node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
5398 gckVIDMEM_Free(mr->node);
5409 gcmkTRACE_ZONE(gcvLEVEL_ERROR,
5411 "======== Total %d unfreed video/contiguous/virtual memory ========", i);
5416 /*******************************************************************************
5419 ** Flush the cache for the specified addresses. The GPU is going to need the
5420 ** data. If the system is allocating memory as non-cachable, this function can
5426 ** Pointer to gckOS object.
5428 ** gctHANDLE Process
5429 ** Process handle Logical belongs to or gcvNULL if Logical belongs to
5432 ** gctPOINTER Logical
5433 ** Logical address to flush.
5436 ** Size of the address range in bytes to flush.
5441 IN gctHANDLE Process,
5442 IN gctPOINTER Logical,
5446 #if (1==gcdENABLE_MEM_CACHE)
5447 dmac_clean_range(Logical, Logical+Bytes);
5448 #elif (2==gcdENABLE_MEM_CACHE)
5451 return gcvSTATUS_OK;
5454 /*******************************************************************************
5455 ** gckOS_CacheInvalidate
5457 ** Flush the cache for the specified addresses and invalidate the lines as
5458 ** well. The GPU is going to need and modify the data. If the system is
5459 ** allocating memory as non-cachable, this function can be ignored.
5464 ** Pointer to gckOS object.
5466 ** gctHANDLE Process
5467 ** Process handle Logical belongs to or gcvNULL if Logical belongs to
5470 ** gctPOINTER Logical
5471 ** Logical address to flush.
5474 ** Size of the address range in bytes to flush.
5477 gckOS_CacheInvalidate(
5479 IN gctHANDLE Process,
5480 IN gctPOINTER Logical,
5484 #if (1==gcdENABLE_MEM_CACHE)
5485 dmac_flush_range(Logical, Logical+Bytes);
5486 #elif (2==gcdENABLE_MEM_CACHE)
5489 return gcvSTATUS_OK;
5492 /*******************************************************************************
5493 ********************************* Broadcasting *********************************
5494 *******************************************************************************/
5496 /*******************************************************************************
5500 ** System hook for broadcast events from the kernel driver.
5505 ** Pointer to the gckOS object.
5507 ** gckHARDWARE Hardware
5508 ** Pointer to the gckHARDWARE object.
5510 ** gceBROADCAST Reason
5511 ** Reason for the broadcast. Can be one of the following values:
5513 ** gcvBROADCAST_GPU_IDLE
5514 ** Broadcasted when the kernel driver thinks the GPU might be
5515 ** idle. This can be used to handle power management.
5517 ** gcvBROADCAST_GPU_COMMIT
5518 ** Broadcasted when any client process commits a command
5519 ** buffer. This can be used to handle power management.
5521 ** gcvBROADCAST_GPU_STUCK
5522 ** Broadcasted when the kernel driver hits the timeout waiting
5525 ** gcvBROADCAST_FIRST_PROCESS
5526 ** First process is trying to connect to the kernel.
5528 ** gcvBROADCAST_LAST_PROCESS
5529 ** Last process has detached from the kernel.
5538 IN gckHARDWARE Hardware,
5539 IN gceBROADCAST Reason
5543 gctUINT32 idle = 0, dma = 0, axi = 0, read0 = 0, read1 = 0, write = 0;
5544 gctUINT32 debugState = 0, memoryDebug = 0;
5545 gctUINT32 debugCmdLow = 0, debugCmdHi = 0;
5546 gctUINT32 i, debugSignalsPe, debugSignalsMc;
5548 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Reason=%d", Os, Hardware, Reason);
5550 /* Verify the arguments. */
5551 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5552 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5556 case gcvBROADCAST_FIRST_PROCESS:
5557 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
5560 case gcvBROADCAST_LAST_PROCESS:
5561 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
5565 gckHARDWARE_SetPowerManagementState(Hardware,
5566 gcvPOWER_OFF_BROADCAST));
5569 case gcvBROADCAST_GPU_IDLE:
5570 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
5574 gckHARDWARE_SetPowerManagementState(Hardware,
5575 gcvPOWER_IDLE_BROADCAST));
5578 case gcvBROADCAST_GPU_COMMIT:
5579 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
5583 gckHARDWARE_SetPowerManagementState(Hardware,
5584 gcvPOWER_ON_BROADCAST));
5587 case gcvBROADCAST_GPU_STUCK:
5588 gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
5589 gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
5590 gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
5591 gcmkPRINT("!!FATAL!! GPU Stuck");
5592 gcmkPRINT(" idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
5594 if (Hardware->chipFeatures & (1 << 4))
5596 gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
5597 gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
5598 gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
5599 gcmkPRINT(" read0=0x%08X read1=0x%08X write=0x%08X",
5600 read0, read1, write);
5603 gcmkONERROR(gckOS_ReadRegister(Os, 0x660, &debugState));
5604 gcmkONERROR(gckOS_ReadRegister(Os, 0x414, &memoryDebug));
5605 gcmkPRINT(" debugState(0x660)=0x%08X memoryDebug(0x414)=0x%08X",
5606 debugState, memoryDebug);
5608 gcmkONERROR(gckOS_ReadRegister(Os, 0x668, &debugCmdLow));
5609 gcmkONERROR(gckOS_ReadRegister(Os, 0x66C, &debugCmdHi));
5610 gcmkPRINT(" debugCmdLow(0x668)=0x%08X debugCmdHi(0x66C)=0x%08X",
5611 debugCmdLow, debugCmdHi);
5613 for (i = 0; i < 16; i++)
5615 gcmkONERROR(gckOS_WriteRegister(Os, 0x470, i << 16));
5616 gcmkPRINT("%d: Write 0x%08X to DebugControl0(0x470)", i, i << 16);
5618 gcmkONERROR(gckOS_ReadRegister(Os, 0x454, &debugSignalsPe));
5619 gcmkPRINT("%d: debugSignalsPe(0x454)=0x%08X", i, debugSignalsPe);
5624 for (i = 0; i < 16; i++)
5626 gcmkONERROR(gckOS_WriteRegister(Os, 0x478, i));
5627 gcmkPRINT("%d: Write 0x%08X to DebugControl2(0x478)", i, i);
5629 gcmkONERROR(gckOS_ReadRegister(Os, 0x468, &debugSignalsMc));
5630 gcmkPRINT("%d: debugSignalsMc(0x468)=0x%08X", i, debugSignalsMc);
5636 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
5639 case gcvBROADCAST_AXI_BUS_ERROR:
5640 gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
5641 gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
5642 gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
5643 gcmkPRINT("!!FATAL!! AXI Bus Error");
5644 gcmkPRINT(" idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
5646 if (Hardware->chipFeatures & (1 << 4))
5648 gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
5649 gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
5650 gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
5651 gcmkPRINT(" read0=0x%08X read1=0x%08X write=0x%08X",
5652 read0, read1, write);
5655 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
5661 return gcvSTATUS_OK;
5664 /* Return the status. */
5669 /*******************************************************************************
5670 ********************************** Semaphores **********************************
5671 *******************************************************************************/
5673 /*******************************************************************************
5675 ** gckOS_CreateSemaphore
5677 ** Create a semaphore.
5682 ** Pointer to the gckOS object.
5686 ** gctPOINTER * Semaphore
5687 ** Pointer to the variable that will receive the created semaphore.
5690 gckOS_CreateSemaphore(
5692 OUT gctPOINTER * Semaphore
5696 struct semaphore *sem;
5698 gcmkHEADER_ARG("Os=0x%x", Os);
5700 /* Verify the arguments. */
5701 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5702 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5704 /* Allocate the semaphore structure. */
5706 gckOS_Allocate(Os, gcmSIZEOF(struct semaphore), (gctPOINTER *) &sem));
5708 /* Initialize the semaphore. */
5711 /* Return to caller. */
5712 *Semaphore = (gctPOINTER) sem;
5716 return gcvSTATUS_OK;
5719 /* Return the status. */
5724 /*******************************************************************************
5726 ** gckOS_AcquireSemaphore
5728 ** Acquire a semaphore.
5733 ** Pointer to the gckOS object.
5735 ** gctPOINTER Semaphore
5736 ** Pointer to the semaphore thet needs to be acquired.
5743 gckOS_AcquireSemaphore(
5745 IN gctPOINTER Semaphore
5750 gcmkHEADER_ARG("Os=0x%x", Os);
5752 /* Verify the arguments. */
5753 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5754 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5756 /* Acquire the semaphore. */
5757 if (down_interruptible((struct semaphore *) Semaphore))
5759 gcmkONERROR(gcvSTATUS_TIMEOUT);
5764 return gcvSTATUS_OK;
5767 /* Return the status. */
5772 /*******************************************************************************
5774 ** gckOS_ReleaseSemaphore
5776 ** Release a previously acquired semaphore.
5781 ** Pointer to the gckOS object.
5783 ** gctPOINTER Semaphore
5784 ** Pointer to the semaphore thet needs to be released.
5791 gckOS_ReleaseSemaphore(
5793 IN gctPOINTER Semaphore
5796 gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
5798 /* Verify the arguments. */
5799 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5800 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5802 /* Release the semaphore. */
5803 up((struct semaphore *) Semaphore);
5807 return gcvSTATUS_OK;
5810 /*******************************************************************************
5812 ** gckOS_DestroySemaphore
5814 ** Destroy a semaphore.
5819 ** Pointer to the gckOS object.
5821 ** gctPOINTER Semaphore
5822 ** Pointer to the semaphore thet needs to be destroyed.
5829 gckOS_DestroySemaphore(
5831 IN gctPOINTER Semaphore
5836 gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
5838 /* Verify the arguments. */
5839 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5840 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5842 /* Free the sempahore structure. */
5843 gcmkONERROR(gckOS_Free(Os, Semaphore));
5847 return gcvSTATUS_OK;
5850 /* Return the status. */
5855 /*******************************************************************************
5857 ** gckOS_GetProcessID
5859 ** Get current process ID.
5867 ** gctUINT32_PTR ProcessID
5868 ** Pointer to the variable that receives the process ID.
5872 OUT gctUINT32_PTR ProcessID
5877 /* Verify the arguments. */
5878 gcmkVERIFY_ARGUMENT(ProcessID != gcvNULL);
5880 /* Get process ID. */
5881 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
5882 *ProcessID = task_tgid_vnr(current);
5884 *ProcessID = current->tgid;
5888 gcmkFOOTER_ARG("*ProcessID=%u", *ProcessID);
5889 return gcvSTATUS_OK;
5892 /*******************************************************************************
5894 ** gckOS_GetThreadID
5896 ** Get current thread ID.
5904 ** gctUINT32_PTR ThreadID
5905 ** Pointer to the variable that receives the thread ID.
5909 OUT gctUINT32_PTR ThreadID
5914 /* Verify the arguments. */
5915 gcmkVERIFY_ARGUMENT(ThreadID != gcvNULL);
5917 /* Get thread ID. */
5918 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
5919 *ThreadID = task_pid_vnr(current);
5921 *ThreadID = current->pid;
5925 gcmkFOOTER_ARG("*ThreadID=%u", *ThreadID);
5926 return gcvSTATUS_OK;
5929 /*******************************************************************************
5931 ** gckOS_SetGPUPower
5933 ** Set the power of the GPU on or off.
5938 ** Pointer to a gckOS object.
5941 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
5944 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
5957 //gcmkHEADER_ARG("Os=0x%x Clock=%d Power=%d", Os, Clock, Power);
5959 /* TODO: Put your code here. */
5960 #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
5962 struct clk * clk_gpu = clk_get(NULL, "gpu");
5963 struct clk * clk_aclk_gpu = clk_get(NULL, "aclk_gpu");
5964 struct clk * clk_aclk_ddr_gpu = clk_get(NULL, "aclk_ddr_gpu");
5965 struct clk * clk_hclk_gpu = clk_get(NULL, "hclk_gpu");
5966 static int lastpower = 0;
5967 static int lastclock = 0;
5969 //printk("---------- gckOS_SetGPUPower Clock=%d Power=%d \n", Clock, Power);
5972 if(lastclock!=Clock)
5975 printk("gpu: clk_enable... ");
5976 clk_enable(clk_gpu);
5977 clk_enable(clk_aclk_gpu);
5978 clk_enable(clk_aclk_ddr_gpu);
5979 clk_enable(clk_hclk_gpu);
5982 printk("gpu: clk_disable... ");
5983 clk_disable(clk_hclk_gpu);
5984 clk_disable(clk_aclk_ddr_gpu);
5985 clk_disable(clk_aclk_gpu);
5986 clk_disable(clk_gpu);
5994 if(lastpower!=Power)
5997 printk("gpu: power on... ");
5998 if(lastclock) clk_disable(clk_aclk_ddr_gpu);
6000 pmu_set_power_domain(PD_GPU, true);
6002 if(lastclock) clk_enable(clk_aclk_ddr_gpu);
6005 printk("gpu: power off... ");
6006 pmu_set_power_domain(PD_GPU, false);
6016 return gcvSTATUS_OK;