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 <asm/atomic.h>
32 #include <linux/dma-mapping.h>
33 #include <linux/slab.h>
34 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
35 #include <linux/math64.h>
38 #define _GC_OBJ_ZONE gcvZONE_OS
40 /*******************************************************************************
41 ***** Version Signature *******************************************************/
44 const char * _PLATFORM
= "\n\0$PLATFORM$Android$\n";
46 const char * _PLATFORM
= "\n\0$PLATFORM$Linux$\n";
49 #define USER_SIGNAL_TABLE_LEN_INIT 64
51 #define MEMORY_LOCK(os) \
52 gcmkVERIFY_OK(gckOS_AcquireMutex( \
57 #define MEMORY_UNLOCK(os) \
58 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
60 #define MEMORY_MAP_LOCK(os) \
61 gcmkVERIFY_OK(gckOS_AcquireMutex( \
63 (os)->memoryMapLock, \
66 #define MEMORY_MAP_UNLOCK(os) \
67 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
69 #define gcdINFINITE_TIMEOUT (60 * 1000)
70 #define gcdDETECT_TIMEOUT 0
71 #define gcdDETECT_DMA_ADDRESS 1
72 #define gcdDETECT_DMA_STATE 1
74 /******************************************************************************\
75 ********************************** Structures **********************************
76 \******************************************************************************/
78 typedef struct _gcsUSER_MAPPING
* gcsUSER_MAPPING_PTR
;
79 typedef struct _gcsUSER_MAPPING
81 /* Pointer to next mapping structure. */
82 gcsUSER_MAPPING_PTR next
;
84 /* Physical address of this mapping. */
87 /* Logical address of this mapping. */
90 /* Number of bytes of this mapping. */
93 /* Starting address of this mapping. */
96 /* Ending address of this mapping. */
109 /* Pointer to device */
112 /* Memory management */
113 gctPOINTER memoryLock
;
114 gctPOINTER memoryMapLock
;
116 struct _LINUX_MDL
*mdlHead
;
117 struct _LINUX_MDL
*mdlTail
;
119 /* Kernel process ID. */
120 gctUINT32 kernelProcessID
;
122 /* Signal management. */
125 /* Unused signal ID number. */
128 /* The pointer to the table. */
131 /* Signal table length. */
134 /* The current unused signal ID. */
142 gcsUSER_MAPPING_PTR userMap
;
143 gctPOINTER debugLock
;
146 typedef struct _gcsSIGNAL
* gcsSIGNAL_PTR
;
147 typedef struct _gcsSIGNAL
149 /* Kernel sync primitive. */
150 struct completion obj
;
152 /* Manual reset flag. */
155 /* The reference counter. */
158 /* The owner of the signal. */
163 typedef struct _gcsPageInfo
* gcsPageInfo_PTR
;
164 typedef struct _gcsPageInfo
167 gctUINT32_PTR pageTable
;
171 typedef struct _gcsiDEBUG_REGISTERS
* gcsiDEBUG_REGISTERS_PTR
;
172 typedef struct _gcsiDEBUG_REGISTERS
184 /******************************************************************************\
185 ******************************* Private Functions ******************************
186 \******************************************************************************/
192 gctUINT32_PTR Address1
,
193 gctUINT32_PTR Address2
,
194 gctUINT32_PTR State1
,
201 gcmkONERROR(gckOS_ReadRegisterEx(Os
, Core
, 0x660, State1
));
202 gcmkONERROR(gckOS_ReadRegisterEx(Os
, Core
, 0x664, Address1
));
204 for (i
= 0; i
< 500; i
+= 1)
206 gcmkONERROR(gckOS_ReadRegisterEx(Os
, Core
, 0x660, State2
));
207 gcmkONERROR(gckOS_ReadRegisterEx(Os
, Core
, 0x664, Address2
));
209 if (*Address1
!= *Address2
)
214 #if gcdDETECT_DMA_STATE
215 if (*State1
!= *State2
)
229 IN gcsiDEBUG_REGISTERS_PTR Descriptor
237 gcmkHEADER_ARG("Os=0x%X Descriptor=0x%X", Os
, Descriptor
);
239 gcmkPRINT_N(4, " %s debug registers:\n", Descriptor
->module
);
241 select
= 0xF << Descriptor
->shift
;
243 for (i
= 0; i
< 500; i
+= 1)
245 gcmkONERROR(gckOS_WriteRegister(Os
, Descriptor
->index
, select
));
246 gcmkONERROR(gckOS_Delay(Os
, 1000));
247 gcmkONERROR(gckOS_ReadRegister(Os
, Descriptor
->data
, &data
));
249 if (data
== Descriptor
->signature
)
257 gcmkPRINT_N(4, " failed to obtain the signature (read 0x%08X).\n", data
);
261 gcmkPRINT_N(8, " signature = 0x%08X (%d read attempt(s))\n", data
, i
+ 1);
264 for (i
= 0; i
< Descriptor
->count
; i
+= 1)
266 select
= i
<< Descriptor
->shift
;
268 gcmkONERROR(gckOS_WriteRegister(Os
, Descriptor
->index
, select
));
269 gcmkONERROR(gckOS_Delay(Os
, 1000));
270 gcmkONERROR(gckOS_ReadRegister(Os
, Descriptor
->data
, &data
));
272 gcmkPRINT_N(12, " [0x%02X] 0x%08X\n", i
, data
);
276 /* Return the error. */
286 static gctCONST_STRING _cmdState
[] =
288 "PAR_IDLE_ST", "PAR_DEC_ST", "PAR_ADR0_ST", "PAR_LOAD0_ST",
289 "PAR_ADR1_ST", "PAR_LOAD1_ST", "PAR_3DADR_ST", "PAR_3DCMD_ST",
290 "PAR_3DCNTL_ST", "PAR_3DIDXCNTL_ST", "PAR_INITREQDMA_ST",
291 "PAR_DRAWIDX_ST", "PAR_DRAW_ST", "PAR_2DRECT0_ST", "PAR_2DRECT1_ST",
292 "PAR_2DDATA0_ST", "PAR_2DDATA1_ST", "PAR_WAITFIFO_ST", "PAR_WAIT_ST",
293 "PAR_LINK_ST", "PAR_END_ST", "PAR_STALL_ST"
296 static gctCONST_STRING _cmdDmaState
[] =
298 "CMD_IDLE_ST", "CMD_START_ST", "CMD_REQ_ST", "CMD_END_ST"
301 static gctCONST_STRING _cmdFetState
[] =
303 "FET_IDLE_ST", "FET_RAMVALID_ST", "FET_VALID_ST"
306 static gctCONST_STRING _reqDmaState
[] =
308 "REQ_IDLE_ST", "REQ_WAITIDX_ST", "REQ_CAL_ST"
311 static gctCONST_STRING _calState
[] =
313 "CAL_IDLE_ST", "CAL_LDADR_ST", "CAL_IDXCALC_ST"
316 static gctCONST_STRING _veReqState
[] =
318 "VER_IDLE_ST", "VER_CKCACHE_ST", "VER_MISS_ST"
321 static gcsiDEBUG_REGISTERS _dbgRegs
[] =
323 { "RA", 0x474, 16, 0x448, 4, 0x12344321 },
324 { "TX", 0x474, 24, 0x44C, 4, 0x12211221 },
325 { "FE", 0x470, 0, 0x450, 4, 0xBABEF00D },
326 { "PE", 0x470, 16, 0x454, 4, 0xBABEF00D },
327 { "DE", 0x470, 8, 0x458, 4, 0xBABEF00D },
328 { "SH", 0x470, 24, 0x45C, 15, 0xDEADBEEF },
329 { "PA", 0x474, 0, 0x460, 4, 0x0000AAAA },
330 { "SE", 0x474, 8, 0x464, 4, 0x5E5E5E5E },
331 { "MC", 0x478, 0, 0x468, 4, 0x12345678 },
332 { "HI", 0x478, 8, 0x46C, 4, 0xAAAAAAAA }
336 gctBOOL acquired
= gcvFALSE
;
340 gctUINT32 dmaAddress1
, dmaAddress2
;
341 gctUINT32 dmaState1
, dmaState2
;
342 gctUINT32 dmaLow
, dmaHigh
;
343 gctUINT32 cmdState
, cmdDmaState
, cmdFetState
;
344 gctUINT32 dmaReqState
, calState
, veReqState
;
347 gcmkHEADER_ARG("Os=0x%X", Os
);
349 gcmkONERROR(gckOS_AcquireMutex(Os
, Os
->debugLock
, gcvINFINITE
));
352 /* Extract the pointer to the gckGALDEVICE class. */
353 device
= (gckGALDEVICE
) Os
->device
;
355 /* TODO: Kernel shortcut. */
356 kernel
= device
->kernels
[gcvCORE_MAJOR
];
358 if (kernel
== gcvNULL
) return gcvSTATUS_OK
;
360 /* Reset register values. */
362 dmaState1
= dmaState2
=
363 dmaAddress1
= dmaAddress2
=
364 dmaLow
= dmaHigh
= 0;
366 /* Verify whether DMA is running. */
367 gcmkONERROR(_VerifyDMA(
368 Os
, kernel
->core
, &dmaAddress1
, &dmaAddress2
, &dmaState1
, &dmaState2
371 cmdState
= dmaState2
& 0x1F;
372 cmdDmaState
= (dmaState2
>> 8) & 0x03;
373 cmdFetState
= (dmaState2
>> 10) & 0x03;
374 dmaReqState
= (dmaState2
>> 12) & 0x03;
375 calState
= (dmaState2
>> 14) & 0x03;
376 veReqState
= (dmaState2
>> 16) & 0x03;
378 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x004, &idle
));
379 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x00C, &axi
));
380 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x668, &dmaLow
));
381 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x66C, &dmaHigh
));
383 gcmkPRINT_N(0, "**************************\n");
384 gcmkPRINT_N(0, "*** GPU STATE DUMP ***\n");
385 gcmkPRINT_N(0, "**************************\n");
387 gcmkPRINT_N(4, " axi = 0x%08X\n", axi
);
389 gcmkPRINT_N(4, " idle = 0x%08X\n", idle
);
390 if ((idle
& 0x00000001) == 0) gcmkPRINT_N(0, " FE not idle\n");
391 if ((idle
& 0x00000002) == 0) gcmkPRINT_N(0, " DE not idle\n");
392 if ((idle
& 0x00000004) == 0) gcmkPRINT_N(0, " PE not idle\n");
393 if ((idle
& 0x00000008) == 0) gcmkPRINT_N(0, " SH not idle\n");
394 if ((idle
& 0x00000010) == 0) gcmkPRINT_N(0, " PA not idle\n");
395 if ((idle
& 0x00000020) == 0) gcmkPRINT_N(0, " SE not idle\n");
396 if ((idle
& 0x00000040) == 0) gcmkPRINT_N(0, " RA not idle\n");
397 if ((idle
& 0x00000080) == 0) gcmkPRINT_N(0, " TX not idle\n");
398 if ((idle
& 0x00000100) == 0) gcmkPRINT_N(0, " VG not idle\n");
399 if ((idle
& 0x00000200) == 0) gcmkPRINT_N(0, " IM not idle\n");
400 if ((idle
& 0x00000400) == 0) gcmkPRINT_N(0, " FP not idle\n");
401 if ((idle
& 0x00000800) == 0) gcmkPRINT_N(0, " TS not idle\n");
402 if ((idle
& 0x80000000) != 0) gcmkPRINT_N(0, " AXI low power mode\n");
405 (dmaAddress1
== dmaAddress2
)
407 #if gcdDETECT_DMA_STATE
408 && (dmaState1
== dmaState2
)
412 gcmkPRINT_N(0, " DMA appears to be stuck at this address:\n");
413 gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1
);
417 if (dmaAddress1
== dmaAddress2
)
419 gcmkPRINT_N(0, " DMA address is constant, but state is changing:\n");
420 gcmkPRINT_N(4, " 0x%08X\n", dmaState1
);
421 gcmkPRINT_N(4, " 0x%08X\n", dmaState2
);
425 gcmkPRINT_N(0, " DMA is running; known addresses are:\n");
426 gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1
);
427 gcmkPRINT_N(4, " 0x%08X\n", dmaAddress2
);
431 gcmkPRINT_N(4, " dmaLow = 0x%08X\n", dmaLow
);
432 gcmkPRINT_N(4, " dmaHigh = 0x%08X\n", dmaHigh
);
433 gcmkPRINT_N(4, " dmaState = 0x%08X\n", dmaState2
);
434 gcmkPRINT_N(8, " command state = %d (%s)\n", cmdState
, _cmdState
[cmdState
]);
435 gcmkPRINT_N(8, " command DMA state = %d (%s)\n", cmdDmaState
, _cmdDmaState
[cmdDmaState
]);
436 gcmkPRINT_N(8, " command fetch state = %d (%s)\n", cmdFetState
, _cmdFetState
[cmdFetState
]);
437 gcmkPRINT_N(8, " DMA request state = %d (%s)\n", dmaReqState
, _reqDmaState
[dmaReqState
]);
438 gcmkPRINT_N(8, " cal state = %d (%s)\n", calState
, _calState
[calState
]);
439 gcmkPRINT_N(8, " VE request state = %d (%s)\n", veReqState
, _veReqState
[veReqState
]);
441 for (i
= 0; i
< gcmCOUNTOF(_dbgRegs
); i
+= 1)
443 gcmkONERROR(_DumpDebugRegisters(Os
, &_dbgRegs
[i
]));
446 if (kernel
->hardware
->chipFeatures
& (1 << 4))
448 gctUINT32 read0
, read1
, write
;
450 read0
= read1
= write
= 0;
452 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x43C, &read0
));
453 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x440, &read1
));
454 gcmkONERROR(gckOS_ReadRegisterEx(Os
, kernel
->core
, 0x444, &write
));
456 gcmkPRINT_N(4, " read0 = 0x%08X\n", read0
);
457 gcmkPRINT_N(4, " read1 = 0x%08X\n", read1
);
458 gcmkPRINT_N(4, " write = 0x%08X\n", write
);
464 /* Release the mutex. */
465 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os
, Os
->debugLock
));
468 /* Return the error. */
478 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
479 return task_tgid_vnr(current
);
481 return current
->tgid
;
490 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
491 return task_pid_vnr(current
);
504 gcmkHEADER_ARG("ProcessID=%d", ProcessID
);
506 mdl
= (PLINUX_MDL
)kmalloc(sizeof(struct _LINUX_MDL
), GFP_KERNEL
);
513 mdl
->pid
= ProcessID
;
518 gcmkFOOTER_ARG("0x%X", mdl
);
525 IN PLINUX_MDL_MAP MdlMap
533 PLINUX_MDL_MAP mdlMap
, next
;
535 gcmkHEADER_ARG("Mdl=0x%X", Mdl
);
537 /* Verify the arguments. */
538 gcmkVERIFY_ARGUMENT(Mdl
!= gcvNULL
);
542 while (mdlMap
!= gcvNULL
)
546 gcmkVERIFY_OK(_DestroyMdlMap(Mdl
, mdlMap
));
557 static PLINUX_MDL_MAP
563 PLINUX_MDL_MAP mdlMap
;
565 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl
, ProcessID
);
567 mdlMap
= (PLINUX_MDL_MAP
)kmalloc(sizeof(struct _LINUX_MDL_MAP
), GFP_KERNEL
);
568 if (mdlMap
== gcvNULL
)
574 mdlMap
->pid
= ProcessID
;
575 mdlMap
->vmaAddr
= gcvNULL
;
576 mdlMap
->vma
= gcvNULL
;
578 mdlMap
->next
= Mdl
->maps
;
581 gcmkFOOTER_ARG("0x%X", mdlMap
);
588 IN PLINUX_MDL_MAP MdlMap
591 PLINUX_MDL_MAP prevMdlMap
;
593 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl
, MdlMap
);
595 /* Verify the arguments. */
596 gcmkVERIFY_ARGUMENT(MdlMap
!= gcvNULL
);
597 gcmkASSERT(Mdl
->maps
!= gcvNULL
);
599 if (Mdl
->maps
== MdlMap
)
601 Mdl
->maps
= MdlMap
->next
;
605 prevMdlMap
= Mdl
->maps
;
607 while (prevMdlMap
->next
!= MdlMap
)
609 prevMdlMap
= prevMdlMap
->next
;
611 gcmkASSERT(prevMdlMap
!= gcvNULL
);
614 prevMdlMap
->next
= MdlMap
->next
;
623 extern PLINUX_MDL_MAP
629 PLINUX_MDL_MAP mdlMap
;
631 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl
, ProcessID
);
638 while (mdlMap
!= gcvNULL
)
640 if (mdlMap
->pid
== ProcessID
)
642 gcmkFOOTER_ARG("0x%X", mdlMap
);
646 mdlMap
= mdlMap
->next
;
661 /*******************************************************************************
665 ** Construct a new gckOS object.
669 ** gctPOINTER Context
670 ** Pointer to the gckGALDEVICE class.
675 ** Pointer to a variable that will hold the pointer to the gckOS object.
679 IN gctPOINTER Context
,
686 gcmkHEADER_ARG("Context=0x%X", Context
);
688 /* Verify the arguments. */
689 gcmkVERIFY_ARGUMENT(Os
!= gcvNULL
);
691 /* Allocate the gckOS object. */
692 os
= (gckOS
) kmalloc(gcmSIZEOF(struct _gckOS
), GFP_KERNEL
);
697 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY
);
698 return gcvSTATUS_OUT_OF_MEMORY
;
701 /* Zero the memory. */
702 gckOS_ZeroMemory(os
, gcmSIZEOF(struct _gckOS
));
704 /* Initialize the gckOS object. */
705 os
->object
.type
= gcvOBJ_OS
;
707 /* Set device device. */
708 os
->device
= Context
;
710 /* IMPORTANT! No heap yet. */
713 /* Initialize the memory lock. */
714 gcmkONERROR(gckOS_CreateMutex(os
, &os
->memoryLock
));
715 gcmkONERROR(gckOS_CreateMutex(os
, &os
->memoryMapLock
));
717 /* Create debug lock mutex. */
718 gcmkONERROR(gckOS_CreateMutex(os
, &os
->debugLock
));
720 /* Create the gckHEAP object. */
721 gcmkONERROR(gckHEAP_Construct(os
, gcdHEAP_SIZE
, &os
->heap
));
723 os
->mdlHead
= os
->mdlTail
= gcvNULL
;
725 /* Get the kernel process ID. */
726 gcmkONERROR(gckOS_GetProcessID(&os
->kernelProcessID
));
729 * Initialize the signal manager.
730 * It creates the signals to be used in
734 /* Initialize mutex. */
736 gckOS_CreateMutex(os
, &os
->signal
.lock
));
738 /* Initialize the signal table. */
740 kmalloc(gcmSIZEOF(gctPOINTER
) * USER_SIGNAL_TABLE_LEN_INIT
, GFP_KERNEL
);
742 if (os
->signal
.table
== gcvNULL
)
745 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
748 gckOS_ZeroMemory(os
->signal
.table
,
749 gcmSIZEOF(gctPOINTER
) * USER_SIGNAL_TABLE_LEN_INIT
);
751 /* Set the signal table length. */
752 os
->signal
.tableLen
= USER_SIGNAL_TABLE_LEN_INIT
;
754 /* The table is empty. */
755 os
->signal
.unused
= os
->signal
.tableLen
;
757 /* Initial signal ID. */
758 os
->signal
.currentID
= 0;
760 /* Return pointer to the gckOS object. */
764 gcmkFOOTER_ARG("*Os=0x%X", *Os
);
768 /* Roll back any allocation. */
769 if (os
->signal
.table
!= gcvNULL
)
771 kfree(os
->signal
.table
);
774 if (os
->signal
.lock
!= gcvNULL
)
777 gckOS_DeleteMutex(os
, os
->signal
.lock
));
780 if (os
->heap
!= gcvNULL
)
783 gckHEAP_Destroy(os
->heap
));
786 if (os
->memoryMapLock
!= gcvNULL
)
789 gckOS_DeleteMutex(os
, os
->memoryMapLock
));
792 if (os
->memoryLock
!= gcvNULL
)
795 gckOS_DeleteMutex(os
, os
->memoryLock
));
798 if (os
->debugLock
!= gcvNULL
)
801 gckOS_DeleteMutex(os
, os
->debugLock
));
806 /* Return the error. */
811 /*******************************************************************************
815 ** Destroy an gckOS object.
820 ** Pointer to an gckOS object that needs to be destroyed.
833 gcmkHEADER_ARG("Os=0x%X", Os
);
835 /* Verify the arguments. */
836 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
839 * Destroy the signal manager.
842 /* Destroy the mutex. */
843 gcmkVERIFY_OK(gckOS_DeleteMutex(Os
, Os
->signal
.lock
));
845 /* Free the signal table. */
846 kfree(Os
->signal
.table
);
848 if (Os
->heap
!= gcvNULL
)
850 /* Mark gckHEAP as gone. */
854 /* Destroy the gckHEAP object. */
855 gcmkVERIFY_OK(gckHEAP_Destroy(heap
));
858 /* Destroy the memory lock. */
859 gcmkVERIFY_OK(gckOS_DeleteMutex(Os
, Os
->memoryMapLock
));
860 gcmkVERIFY_OK(gckOS_DeleteMutex(Os
, Os
->memoryLock
));
862 /* Destroy debug lock mutex. */
863 gcmkVERIFY_OK(gckOS_DeleteMutex(Os
, Os
->debugLock
));
865 /* Flush the debug cache. */
868 /* Mark the gckOS object as unknown. */
869 Os
->object
.type
= gcvOBJ_UNKNOWN
;
871 /* Free the gckOS object. */
879 /*******************************************************************************
888 ** Pointer to an gckOS object.
891 ** Number of bytes to allocate.
895 ** gctPOINTER * Memory
896 ** Pointer to a variable that will hold the allocated memory location.
902 OUT gctPOINTER
* Memory
907 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os
, Bytes
);
909 /* Verify the arguments. */
910 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
911 gcmkVERIFY_ARGUMENT(Bytes
> 0);
912 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
914 /* Do we have a heap? */
915 if (Os
->heap
!= gcvNULL
)
917 /* Allocate from the heap. */
918 gcmkONERROR(gckHEAP_Allocate(Os
->heap
, Bytes
, Memory
));
922 gcmkONERROR(gckOS_AllocateMemory(Os
, Bytes
, Memory
));
926 gcmkFOOTER_ARG("*Memory=0x%X", *Memory
);
930 /* Return the status. */
935 /*******************************************************************************
939 ** Free allocated memory.
944 ** Pointer to an gckOS object.
947 ** Pointer to memory allocation to free.
961 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os
, Memory
);
963 /* Verify the arguments. */
964 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
965 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
967 /* Do we have a heap? */
968 if (Os
->heap
!= gcvNULL
)
970 /* Free from the heap. */
971 gcmkONERROR(gckHEAP_Free(Os
->heap
, Memory
));
975 gcmkONERROR(gckOS_FreeMemory(Os
, Memory
));
983 /* Return the status. */
988 /*******************************************************************************
990 ** gckOS_AllocateMemory
992 ** Allocate memory wrapper.
997 ** Number of bytes to allocate.
1001 ** gctPOINTER * Memory
1002 ** Pointer to a variable that will hold the allocated memory location.
1005 gckOS_AllocateMemory(
1008 OUT gctPOINTER
* Memory
1014 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os
, Bytes
);
1016 /* Verify the arguments. */
1017 gcmkVERIFY_ARGUMENT(Bytes
> 0);
1018 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
1020 memory
= (gctPOINTER
) kmalloc(Bytes
, GFP_KERNEL
);
1022 if (memory
== gcvNULL
)
1024 /* Out of memory. */
1025 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
1028 /* Return pointer to the memory allocation. */
1032 gcmkFOOTER_ARG("*Memory=0x%X", *Memory
);
1033 return gcvSTATUS_OK
;
1036 /* Return the status. */
1041 /*******************************************************************************
1045 ** Free allocated memory wrapper.
1049 ** gctPOINTER Memory
1050 ** Pointer to memory allocation to free.
1059 IN gctPOINTER Memory
1062 gcmkHEADER_ARG("Memory=0x%X", Memory
);
1064 /* Verify the arguments. */
1065 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
1067 /* Free the memory from the OS pool. */
1072 return gcvSTATUS_OK
;
1075 /*******************************************************************************
1079 ** Map physical memory into the current process.
1084 ** Pointer to an gckOS object.
1086 ** gctPHYS_ADDR Physical
1087 ** Start of physical address memory.
1090 ** Number of bytes to map.
1094 ** gctPOINTER * Memory
1095 ** Pointer to a variable that will hold the logical address of the
1101 IN gctPHYS_ADDR Physical
,
1103 OUT gctPOINTER
* Logical
1106 PLINUX_MDL_MAP mdlMap
;
1107 PLINUX_MDL mdl
= (PLINUX_MDL
)Physical
;
1109 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os
, Physical
, Bytes
);
1111 /* Verify the arguments. */
1112 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1113 gcmkVERIFY_ARGUMENT(Physical
!= 0);
1114 gcmkVERIFY_ARGUMENT(Bytes
> 0);
1115 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
1119 mdlMap
= FindMdlMap(mdl
, _GetProcessID());
1121 if (mdlMap
== gcvNULL
)
1123 mdlMap
= _CreateMdlMap(mdl
, _GetProcessID());
1125 if (mdlMap
== gcvNULL
)
1129 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY
);
1130 return gcvSTATUS_OUT_OF_MEMORY
;
1134 if (mdlMap
->vmaAddr
== gcvNULL
)
1136 down_write(¤t
->mm
->mmap_sem
);
1138 mdlMap
->vmaAddr
= (char *)do_mmap_pgoff(gcvNULL
,
1140 mdl
->numPages
* PAGE_SIZE
,
1141 PROT_READ
| PROT_WRITE
,
1145 if (IS_ERR(mdlMap
->vmaAddr
))
1149 "%s(%d): do_mmap_pgoff error",
1150 __FUNCTION__
, __LINE__
1155 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1156 __FUNCTION__
, __LINE__
,
1161 mdlMap
->vmaAddr
= gcvNULL
;
1163 up_write(¤t
->mm
->mmap_sem
);
1167 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY
);
1168 return gcvSTATUS_OUT_OF_MEMORY
;
1171 mdlMap
->vma
= find_vma(current
->mm
, (unsigned long)mdlMap
->vmaAddr
);
1177 "%s(%d): find_vma error.",
1178 __FUNCTION__
, __LINE__
1181 mdlMap
->vmaAddr
= gcvNULL
;
1183 up_write(¤t
->mm
->mmap_sem
);
1187 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES
);
1188 return gcvSTATUS_OUT_OF_RESOURCES
;
1191 #ifndef NO_DMA_COHERENT
1192 if (dma_mmap_coherent(gcvNULL
,
1196 mdl
->numPages
* PAGE_SIZE
) < 0)
1198 up_write(¤t
->mm
->mmap_sem
);
1202 "%s(%d): dma_mmap_coherent error.",
1203 __FUNCTION__
, __LINE__
1206 mdlMap
->vmaAddr
= gcvNULL
;
1210 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES
);
1211 return gcvSTATUS_OUT_OF_RESOURCES
;
1214 #if !gcdPAGED_MEMORY_CACHEABLE
1215 mdlMap
->vma
->vm_page_prot
= pgprot_noncached(mdlMap
->vma
->vm_page_prot
);
1216 mdlMap
->vma
->vm_flags
|= VM_IO
| VM_DONTCOPY
| VM_DONTEXPAND
| VM_RESERVED
;
1218 mdlMap
->vma
->vm_pgoff
= 0;
1220 if (remap_pfn_range(mdlMap
->vma
,
1221 mdlMap
->vma
->vm_start
,
1222 mdl
->dmaHandle
>> PAGE_SHIFT
,
1223 mdl
->numPages
*PAGE_SIZE
,
1224 mdlMap
->vma
->vm_page_prot
) < 0)
1226 up_write(¤t
->mm
->mmap_sem
);
1230 "%s(%d): remap_pfn_range error.",
1231 __FUNCTION__
, __LINE__
1234 mdlMap
->vmaAddr
= gcvNULL
;
1238 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES
);
1239 return gcvSTATUS_OUT_OF_RESOURCES
;
1243 up_write(¤t
->mm
->mmap_sem
);
1248 *Logical
= mdlMap
->vmaAddr
;
1250 gcmkFOOTER_ARG("*Logical=0x%X", *Logical
);
1251 return gcvSTATUS_OK
;
1254 /*******************************************************************************
1256 ** gckOS_UnmapMemory
1258 ** Unmap physical memory out of the current process.
1263 ** Pointer to an gckOS object.
1265 ** gctPHYS_ADDR Physical
1266 ** Start of physical address memory.
1269 ** Number of bytes to unmap.
1271 ** gctPOINTER Memory
1272 ** Pointer to a previously mapped memory region.
1281 IN gctPHYS_ADDR Physical
,
1283 IN gctPOINTER Logical
1286 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1287 Os
, Physical
, Bytes
, Logical
);
1289 /* Verify the arguments. */
1290 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1291 gcmkVERIFY_ARGUMENT(Physical
!= 0);
1292 gcmkVERIFY_ARGUMENT(Bytes
> 0);
1293 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
1295 gckOS_UnmapMemoryEx(Os
, Physical
, Bytes
, Logical
, _GetProcessID());
1299 return gcvSTATUS_OK
;
1303 /*******************************************************************************
1305 ** gckOS_UnmapMemoryEx
1307 ** Unmap physical memory in the specified process.
1312 ** Pointer to an gckOS object.
1314 ** gctPHYS_ADDR Physical
1315 ** Start of physical address memory.
1318 ** Number of bytes to unmap.
1320 ** gctPOINTER Memory
1321 ** Pointer to a previously mapped memory region.
1324 ** Pid of the process that opened the device and mapped this memory.
1331 gckOS_UnmapMemoryEx(
1333 IN gctPHYS_ADDR Physical
,
1335 IN gctPOINTER Logical
,
1339 PLINUX_MDL_MAP mdlMap
;
1340 PLINUX_MDL mdl
= (PLINUX_MDL
)Physical
;
1341 struct task_struct
* task
;
1343 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1344 Os
, Physical
, Bytes
, Logical
, PID
);
1346 /* Verify the arguments. */
1347 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1348 gcmkVERIFY_ARGUMENT(Physical
!= 0);
1349 gcmkVERIFY_ARGUMENT(Bytes
> 0);
1350 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
1351 gcmkVERIFY_ARGUMENT(PID
!= 0);
1357 mdlMap
= FindMdlMap(mdl
, PID
);
1359 if (mdlMap
== gcvNULL
|| mdlMap
->vmaAddr
== gcvNULL
)
1363 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT
);
1364 return gcvSTATUS_INVALID_ARGUMENT
;
1367 /* Get the current pointer for the task with stored pid. */
1368 task
= FIND_TASK_BY_PID(mdlMap
->pid
);
1370 if (task
!= gcvNULL
&& task
->mm
!= gcvNULL
)
1372 down_write(&task
->mm
->mmap_sem
);
1373 do_munmap(task
->mm
, (unsigned long)Logical
, mdl
->numPages
*PAGE_SIZE
);
1374 up_write(&task
->mm
->mmap_sem
);
1379 gcvLEVEL_INFO
, gcvZONE_OS
,
1380 "%s(%d): can't find the task with pid->%d. No unmapping",
1381 __FUNCTION__
, __LINE__
,
1386 gcmkVERIFY_OK(_DestroyMdlMap(mdl
, mdlMap
));
1393 return gcvSTATUS_OK
;
1396 /*******************************************************************************
1398 ** gckOS_AllocateNonPagedMemory
1400 ** Allocate a number of pages from non-paged memory.
1405 ** Pointer to an gckOS object.
1407 ** gctBOOL InUserSpace
1408 ** gcvTRUE if the pages need to be mapped into user space.
1410 ** gctSIZE_T * Bytes
1411 ** Pointer to a variable that holds the number of bytes to allocate.
1415 ** gctSIZE_T * Bytes
1416 ** Pointer to a variable that hold the number of bytes allocated.
1418 ** gctPHYS_ADDR * Physical
1419 ** Pointer to a variable that will hold the physical address of the
1422 ** gctPOINTER * Logical
1423 ** Pointer to a variable that will hold the logical address of the
1427 gckOS_AllocateNonPagedMemory(
1429 IN gctBOOL InUserSpace
,
1430 IN OUT gctSIZE_T
* Bytes
,
1431 OUT gctPHYS_ADDR
* Physical
,
1432 OUT gctPOINTER
* Logical
1437 PLINUX_MDL mdl
= gcvNULL
;
1438 PLINUX_MDL_MAP mdlMap
= gcvNULL
;
1440 #ifdef NO_DMA_COHERENT
1445 gctBOOL locked
= gcvFALSE
;
1448 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1449 Os
, InUserSpace
, gcmOPT_VALUE(Bytes
));
1451 /* Verify the arguments. */
1452 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1453 gcmkVERIFY_ARGUMENT(Bytes
!= gcvNULL
);
1454 gcmkVERIFY_ARGUMENT(*Bytes
> 0);
1455 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
1456 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
1458 /* Align number of bytes to page size. */
1459 bytes
= gcmALIGN(*Bytes
, PAGE_SIZE
);
1461 /* Get total number of pages.. */
1462 numPages
= GetPageCount(bytes
, 0);
1464 /* Allocate mdl+vector structure */
1465 mdl
= _CreateMdl(_GetProcessID());
1468 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
1472 mdl
->numPages
= numPages
;
1477 #ifndef NO_DMA_COHERENT
1478 addr
= dma_alloc_coherent(gcvNULL
,
1479 mdl
->numPages
* PAGE_SIZE
,
1483 size
= mdl
->numPages
* PAGE_SIZE
;
1484 order
= get_order(size
);
1485 page
= alloc_pages(GFP_KERNEL
, order
);
1487 if (page
== gcvNULL
)
1489 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
1492 vaddr
= (gctPOINTER
)page_address(page
);
1494 #if gcdNONPAGED_MEMORY_CACHEABLE
1496 # elif gcdNONPAGED_MEMORY_BUFFERABLE
1497 addr
= ioremap_wc(virt_to_phys(vaddr
), size
);
1499 addr
= ioremap_nocache(virt_to_phys(vaddr
), size
);
1502 mdl
->dmaHandle
= virt_to_phys(vaddr
);
1505 /* Cache invalidate. */
1506 dma_sync_single_for_device(
1514 SetPageReserved(virt_to_page(vaddr
));
1521 if (addr
== gcvNULL
)
1523 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
1526 if ((Os
->device
->baseAddress
& 0x80000000) != (mdl
->dmaHandle
& 0x80000000))
1528 mdl
->dmaHandle
= (mdl
->dmaHandle
& ~0x80000000)
1529 | (Os
->device
->baseAddress
& 0x80000000);
1535 * We will not do any mapping from here.
1536 * Mapping will happen from mmap method.
1537 * mdl structure will be used.
1540 /* Return allocated memory. */
1542 *Physical
= (gctPHYS_ADDR
) mdl
;
1546 mdlMap
= _CreateMdlMap(mdl
, _GetProcessID());
1548 if (mdlMap
== gcvNULL
)
1550 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
1553 /* Only after mmap this will be valid. */
1555 /* We need to map this to user space. */
1556 down_write(¤t
->mm
->mmap_sem
);
1558 mdlMap
->vmaAddr
= (gctSTRING
) do_mmap_pgoff(gcvNULL
,
1560 mdl
->numPages
* PAGE_SIZE
,
1561 PROT_READ
| PROT_WRITE
,
1565 if (IS_ERR(mdlMap
->vmaAddr
))
1568 gcvLEVEL_WARNING
, gcvZONE_OS
,
1569 "%s(%d): do_mmap_pgoff error",
1570 __FUNCTION__
, __LINE__
1573 mdlMap
->vmaAddr
= gcvNULL
;
1575 up_write(¤t
->mm
->mmap_sem
);
1577 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
1580 mdlMap
->vma
= find_vma(current
->mm
, (unsigned long)mdlMap
->vmaAddr
);
1582 if (mdlMap
->vma
== gcvNULL
)
1585 gcvLEVEL_WARNING
, gcvZONE_OS
,
1586 "%s(%d): find_vma error",
1587 __FUNCTION__
, __LINE__
1590 up_write(¤t
->mm
->mmap_sem
);
1592 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES
);
1595 #ifndef NO_DMA_COHERENT
1596 if (dma_mmap_coherent(gcvNULL
,
1600 mdl
->numPages
* PAGE_SIZE
) < 0)
1603 gcvLEVEL_WARNING
, gcvZONE_OS
,
1604 "%s(%d): dma_mmap_coherent error",
1605 __FUNCTION__
, __LINE__
1608 up_write(¤t
->mm
->mmap_sem
);
1610 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES
);
1613 mdlMap
->vma
->vm_page_prot
= pgprot_noncached(mdlMap
->vma
->vm_page_prot
);
1614 mdlMap
->vma
->vm_flags
|= VM_IO
| VM_DONTCOPY
| VM_DONTEXPAND
| VM_RESERVED
;
1615 mdlMap
->vma
->vm_pgoff
= 0;
1617 if (remap_pfn_range(mdlMap
->vma
,
1618 mdlMap
->vma
->vm_start
,
1619 mdl
->dmaHandle
>> PAGE_SHIFT
,
1620 mdl
->numPages
* PAGE_SIZE
,
1621 mdlMap
->vma
->vm_page_prot
))
1624 gcvLEVEL_WARNING
, gcvZONE_OS
,
1625 "%s(%d): remap_pfn_range error",
1626 __FUNCTION__
, __LINE__
1629 up_write(¤t
->mm
->mmap_sem
);
1631 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES
);
1633 #endif /* NO_DMA_COHERENT */
1635 up_write(¤t
->mm
->mmap_sem
);
1637 *Logical
= mdlMap
->vmaAddr
;
1641 *Logical
= (gctPOINTER
)mdl
->addr
;
1645 * Add this to a global list.
1646 * Will be used by get physical address
1647 * and mapuser pointer functions.
1652 /* Initialize the queue. */
1653 Os
->mdlHead
= Os
->mdlTail
= mdl
;
1657 /* Add to the tail. */
1658 mdl
->prev
= Os
->mdlTail
;
1659 Os
->mdlTail
->next
= mdl
;
1666 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
1667 *Bytes
, *Physical
, *Logical
);
1668 return gcvSTATUS_OK
;
1671 if (mdlMap
!= gcvNULL
)
1673 /* Free LINUX_MDL_MAP. */
1674 gcmkVERIFY_OK(_DestroyMdlMap(mdl
, mdlMap
));
1679 /* Free LINUX_MDL. */
1680 gcmkVERIFY_OK(_DestroyMdl(mdl
));
1685 /* Unlock memory. */
1689 /* Return the status. */
1694 /*******************************************************************************
1696 ** gckOS_FreeNonPagedMemory
1698 ** Free previously allocated and mapped pages from non-paged memory.
1703 ** Pointer to an gckOS object.
1706 ** Number of bytes allocated.
1708 ** gctPHYS_ADDR Physical
1709 ** Physical address of the allocated memory.
1711 ** gctPOINTER Logical
1712 ** Logical address of the allocated memory.
1718 gceSTATUS
gckOS_FreeNonPagedMemory(
1721 IN gctPHYS_ADDR Physical
,
1722 IN gctPOINTER Logical
1726 PLINUX_MDL_MAP mdlMap
;
1727 struct task_struct
* task
;
1728 #ifdef NO_DMA_COHERENT
1731 #endif /* NO_DMA_COHERENT */
1733 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
1734 Os
, Bytes
, Physical
, Logical
);
1736 /* Verify the arguments. */
1737 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1738 gcmkVERIFY_ARGUMENT(Bytes
> 0);
1739 gcmkVERIFY_ARGUMENT(Physical
!= 0);
1740 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
1742 /* Convert physical address into a pointer to a MDL. */
1743 mdl
= (PLINUX_MDL
) Physical
;
1747 #ifndef NO_DMA_COHERENT
1748 dma_free_coherent(gcvNULL
,
1749 mdl
->numPages
* PAGE_SIZE
,
1753 size
= mdl
->numPages
* PAGE_SIZE
;
1758 ClearPageReserved(virt_to_page(vaddr
));
1764 free_pages((unsigned long)mdl
->kaddr
, get_order(mdl
->numPages
* PAGE_SIZE
));
1766 #if !gcdNONPAGED_MEMORY_CACHEABLE
1770 #endif /* NO_DMA_COHERENT */
1774 while (mdlMap
!= gcvNULL
)
1776 if (mdlMap
->vmaAddr
!= gcvNULL
)
1778 /* Get the current pointer for the task with stored pid. */
1779 task
= FIND_TASK_BY_PID(mdlMap
->pid
);
1781 if (task
!= gcvNULL
&& task
->mm
!= gcvNULL
)
1783 down_write(&task
->mm
->mmap_sem
);
1785 if (do_munmap(task
->mm
,
1786 (unsigned long)mdlMap
->vmaAddr
,
1787 mdl
->numPages
* PAGE_SIZE
) < 0)
1790 gcvLEVEL_WARNING
, gcvZONE_OS
,
1791 "%s(%d): do_munmap failed",
1792 __FUNCTION__
, __LINE__
1796 up_write(&task
->mm
->mmap_sem
);
1799 mdlMap
->vmaAddr
= gcvNULL
;
1802 mdlMap
= mdlMap
->next
;
1805 /* Remove the node from global list.. */
1806 if (mdl
== Os
->mdlHead
)
1808 if ((Os
->mdlHead
= mdl
->next
) == gcvNULL
)
1810 Os
->mdlTail
= gcvNULL
;
1815 mdl
->prev
->next
= mdl
->next
;
1816 if (mdl
== Os
->mdlTail
)
1818 Os
->mdlTail
= mdl
->prev
;
1822 mdl
->next
->prev
= mdl
->prev
;
1828 gcmkVERIFY_OK(_DestroyMdl(mdl
));
1832 return gcvSTATUS_OK
;
1835 /*******************************************************************************
1837 ** gckOS_ReadRegister
1839 ** Read data from a register.
1844 ** Pointer to an gckOS object.
1846 ** gctUINT32 Address
1847 ** Address of register.
1852 ** Pointer to a variable that receives the data read from the register.
1857 IN gctUINT32 Address
,
1858 OUT gctUINT32
* Data
1861 return gckOS_ReadRegisterEx(Os
, gcvCORE_MAJOR
, Address
, Data
);
1865 gckOS_ReadRegisterEx(
1868 IN gctUINT32 Address
,
1869 OUT gctUINT32
* Data
1872 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os
, Core
, Address
);
1874 /* Verify the arguments. */
1875 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1876 gcmkVERIFY_ARGUMENT(Data
!= gcvNULL
);
1878 *Data
= readl((gctUINT8
*)Os
->device
->registerBases
[Core
] + Address
);
1881 gcmkFOOTER_ARG("*Data=0x%08x", *Data
);
1882 return gcvSTATUS_OK
;
1885 /*******************************************************************************
1887 ** gckOS_WriteRegister
1889 ** Write data to a register.
1894 ** Pointer to an gckOS object.
1896 ** gctUINT32 Address
1897 ** Address of register.
1900 ** Data for register.
1907 gckOS_WriteRegister(
1909 IN gctUINT32 Address
,
1913 return gckOS_WriteRegisterEx(Os
, gcvCORE_MAJOR
, Address
, Data
);
1917 gckOS_WriteRegisterEx(
1920 IN gctUINT32 Address
,
1924 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os
, Core
, Address
, Data
);
1926 writel(Data
, (gctUINT8
*)Os
->device
->registerBases
[Core
] + Address
);
1930 return gcvSTATUS_OK
;
1933 /*******************************************************************************
1935 ** gckOS_GetPageSize
1937 ** Get the system's page size.
1942 ** Pointer to an gckOS object.
1946 ** gctSIZE_T * PageSize
1947 ** Pointer to a variable that will receive the system's page size.
1949 gceSTATUS
gckOS_GetPageSize(
1951 OUT gctSIZE_T
* PageSize
1954 gcmkHEADER_ARG("Os=0x%X", Os
);
1956 /* Verify the arguments. */
1957 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
1958 gcmkVERIFY_ARGUMENT(PageSize
!= gcvNULL
);
1960 /* Return the page size. */
1961 *PageSize
= (gctSIZE_T
) PAGE_SIZE
;
1964 gcmkFOOTER_ARG("*PageSize", *PageSize
);
1965 return gcvSTATUS_OK
;
1968 /*******************************************************************************
1970 ** gckOS_GetPhysicalAddress
1972 ** Get the physical system address of a corresponding virtual address.
1977 ** Pointer to an gckOS object.
1979 ** gctPOINTER Logical
1984 ** gctUINT32 * Address
1985 ** Poinetr to a variable that receives the 32-bit physical adress.
1988 gckOS_GetPhysicalAddress(
1990 IN gctPOINTER Logical
,
1991 OUT gctUINT32
* Address
1995 gctUINT32 processID
;
1997 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os
, Logical
);
1999 /* Verify the arguments. */
2000 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2001 gcmkVERIFY_ARGUMENT(Address
!= gcvNULL
);
2003 /* Get current process ID. */
2004 processID
= _GetProcessID();
2006 /* Route through other function. */
2008 gckOS_GetPhysicalAddressProcess(Os
, Logical
, processID
, Address
));
2011 gcmkFOOTER_ARG("*Address=0x%08x", *Address
);
2012 return gcvSTATUS_OK
;
2015 /* Return the status. */
2024 IN gctUINT32 Physical
,
2025 IN gctPOINTER Logical
,
2030 gcsUSER_MAPPING_PTR map
;
2032 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2033 Os
, Physical
, Logical
, Bytes
);
2035 gcmkONERROR(gckOS_Allocate(Os
,
2036 gcmSIZEOF(gcsUSER_MAPPING
),
2037 (gctPOINTER
*) &map
));
2039 map
->next
= Os
->userMap
;
2040 map
->physical
= Physical
- Os
->device
->baseAddress
;
2041 map
->logical
= Logical
;
2043 map
->start
= (gctINT8_PTR
) Logical
;
2044 map
->end
= map
->start
+ Bytes
;
2049 return gcvSTATUS_OK
;
2057 gckOS_RemoveMapping(
2059 IN gctPOINTER Logical
,
2064 gcsUSER_MAPPING_PTR map
, prev
;
2066 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os
, Logical
, Bytes
);
2068 for (map
= Os
->userMap
, prev
= gcvNULL
; map
!= gcvNULL
; map
= map
->next
)
2070 if ((map
->logical
== Logical
)
2071 && (map
->bytes
== Bytes
)
2082 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS
);
2085 if (prev
== gcvNULL
)
2087 Os
->userMap
= map
->next
;
2091 prev
->next
= map
->next
;
2094 gcmkONERROR(gcmkOS_SAFE_FREE(Os
, map
));
2097 return gcvSTATUS_OK
;
2106 _ConvertLogical2Physical(
2108 IN gctPOINTER Logical
,
2109 IN gctUINT32 ProcessID
,
2111 OUT gctUINT32_PTR Physical
2114 gctINT8_PTR base
, vBase
;
2117 gcsUSER_MAPPING_PTR userMap
;
2119 base
= (Mdl
== gcvNULL
) ? gcvNULL
: (gctINT8_PTR
) Mdl
->addr
;
2121 /* Check for the logical address match. */
2122 if ((base
!= gcvNULL
)
2123 && ((gctINT8_PTR
) Logical
>= base
)
2124 && ((gctINT8_PTR
) Logical
< base
+ Mdl
->numPages
* PAGE_SIZE
)
2127 offset
= (gctINT8_PTR
) Logical
- base
;
2129 if (Mdl
->dmaHandle
!= 0)
2131 /* The memory was from coherent area. */
2132 *Physical
= (gctUINT32
) Mdl
->dmaHandle
+ offset
;
2134 else if (Mdl
->pagedMem
&& !Mdl
->contiguous
)
2136 *Physical
= page_to_phys(vmalloc_to_page(base
+ offset
));
2140 *Physical
= gcmPTR2INT(virt_to_phys(base
)) + offset
;
2143 return gcvSTATUS_OK
;
2146 /* Walk user maps. */
2147 for (userMap
= Os
->userMap
; userMap
!= gcvNULL
; userMap
= userMap
->next
)
2149 if (((gctINT8_PTR
) Logical
>= userMap
->start
)
2150 && ((gctINT8_PTR
) Logical
< userMap
->end
)
2153 *Physical
= userMap
->physical
2154 + (gctUINT32
) ((gctINT8_PTR
) Logical
- userMap
->start
);
2156 return gcvSTATUS_OK
;
2160 if (ProcessID
!= Os
->kernelProcessID
)
2162 map
= FindMdlMap(Mdl
, (gctINT
) ProcessID
);
2163 vBase
= (map
== gcvNULL
) ? gcvNULL
: (gctINT8_PTR
) map
->vmaAddr
;
2165 /* Is the given address within that range. */
2166 if ((vBase
!= gcvNULL
)
2167 && ((gctINT8_PTR
) Logical
>= vBase
)
2168 && ((gctINT8_PTR
) Logical
< vBase
+ Mdl
->numPages
* PAGE_SIZE
)
2171 offset
= (gctINT8_PTR
) Logical
- vBase
;
2173 if (Mdl
->dmaHandle
!= 0)
2175 /* The memory was from coherent area. */
2176 *Physical
= (gctUINT32
) Mdl
->dmaHandle
+ offset
;
2178 else if (Mdl
->pagedMem
&& !Mdl
->contiguous
)
2180 *Physical
= page_to_phys(vmalloc_to_page(base
+ offset
));
2184 /* Return the kernel virtual pointer based on this. */
2185 *Physical
= gcmPTR2INT(virt_to_phys(base
)) + offset
;
2188 return gcvSTATUS_OK
;
2192 /* Address not yet found. */
2193 return gcvSTATUS_INVALID_ADDRESS
;
2196 /*******************************************************************************
2198 ** gckOS_GetPhysicalAddressProcess
2200 ** Get the physical system address of a corresponding virtual address for a
2206 ** Pointer to gckOS object.
2208 ** gctPOINTER Logical
2211 ** gctUINT32 ProcessID
2216 ** gctUINT32 * Address
2217 ** Poinetr to a variable that receives the 32-bit physical adress.
2220 gckOS_GetPhysicalAddressProcess(
2222 IN gctPOINTER Logical
,
2223 IN gctUINT32 ProcessID
,
2224 OUT gctUINT32
* Address
2229 gceSTATUS status
= gcvSTATUS_INVALID_ADDRESS
;
2231 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os
, Logical
, ProcessID
);
2233 /* Verify the arguments. */
2234 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2235 gcmkVERIFY_ARGUMENT(Address
!= gcvNULL
);
2239 /* First try the contiguous memory pool. */
2240 if (Os
->device
->contiguousMapped
)
2242 base
= (gctINT8_PTR
) Os
->device
->contiguousBase
;
2244 if (((gctINT8_PTR
) Logical
>= base
)
2245 && ((gctINT8_PTR
) Logical
< base
+ Os
->device
->contiguousSize
)
2248 /* Convert logical address into physical. */
2249 *Address
= Os
->device
->contiguousVidMem
->baseAddress
2250 + (gctINT8_PTR
) Logical
- base
;
2251 status
= gcvSTATUS_OK
;
2256 /* Try the contiguous memory pool. */
2257 mdl
= (PLINUX_MDL
) Os
->device
->contiguousPhysical
;
2258 status
= _ConvertLogical2Physical(Os
,
2265 if (gcmIS_ERROR(status
))
2267 /* Walk all MDLs. */
2268 for (mdl
= Os
->mdlHead
; mdl
!= gcvNULL
; mdl
= mdl
->next
)
2271 status
= _ConvertLogical2Physical(Os
,
2276 if (gcmIS_SUCCESS(status
))
2285 gcmkONERROR(status
);
2287 if (Os
->device
->baseAddress
!= 0)
2289 /* Subtract base address to get a GPU physical address. */
2290 gcmkASSERT(*Address
>= Os
->device
->baseAddress
);
2291 *Address
-= Os
->device
->baseAddress
;
2295 gcmkFOOTER_ARG("*Address=0x%08x", *Address
);
2296 return gcvSTATUS_OK
;
2299 /* Return the status. */
2304 /*******************************************************************************
2306 ** gckOS_MapPhysical
2308 ** Map a physical address into kernel space.
2313 ** Pointer to an gckOS object.
2315 ** gctUINT32 Physical
2316 ** Physical address of the memory to map.
2319 ** Number of bytes to map.
2323 ** gctPOINTER * Logical
2324 ** Pointer to a variable that receives the base address of the mapped
2330 IN gctUINT32 Physical
,
2332 OUT gctPOINTER
* Logical
2339 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os
, Physical
, Bytes
);
2341 /* Verify the arguments. */
2342 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2343 gcmkVERIFY_ARGUMENT(Bytes
> 0);
2344 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
2348 /* Compute true physical address (before subtraction of the baseAddress). */
2349 physical
= Physical
+ Os
->device
->baseAddress
;
2351 /* Go through our mapping to see if we know this physical address already. */
2354 while (mdl
!= gcvNULL
)
2356 if (mdl
->dmaHandle
!= 0)
2358 if ((physical
>= mdl
->dmaHandle
)
2359 && (physical
< mdl
->dmaHandle
+ mdl
->numPages
* PAGE_SIZE
)
2362 *Logical
= mdl
->addr
+ (physical
- mdl
->dmaHandle
);
2372 /* Map memory as cached memory. */
2373 request_mem_region(physical
, Bytes
, "MapRegion");
2374 logical
= (gctPOINTER
) ioremap_nocache(physical
, Bytes
);
2376 if (logical
== gcvNULL
)
2379 gcvLEVEL_INFO
, gcvZONE_OS
,
2380 "%s(%d): Failed to ioremap",
2381 __FUNCTION__
, __LINE__
2386 /* Out of resources. */
2387 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES
);
2388 return gcvSTATUS_OUT_OF_RESOURCES
;
2391 /* Return pointer to mapped memory. */
2398 gcmkFOOTER_ARG("*Logical=0x%X", *Logical
);
2399 return gcvSTATUS_OK
;
2402 /*******************************************************************************
2404 ** gckOS_UnmapPhysical
2406 ** Unmap a previously mapped memory region from kernel memory.
2411 ** Pointer to an gckOS object.
2413 ** gctPOINTER Logical
2414 ** Pointer to the base address of the memory to unmap.
2417 ** Number of bytes to unmap.
2424 gckOS_UnmapPhysical(
2426 IN gctPOINTER Logical
,
2432 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os
, Logical
, Bytes
);
2434 /* Verify the arguments. */
2435 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2436 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
2437 gcmkVERIFY_ARGUMENT(Bytes
> 0);
2443 while (mdl
!= gcvNULL
)
2445 if (mdl
->addr
!= gcvNULL
)
2447 if (Logical
>= (gctPOINTER
)mdl
->addr
2448 && Logical
< (gctPOINTER
)((gctSTRING
)mdl
->addr
+ mdl
->numPages
* PAGE_SIZE
))
2459 /* Unmap the memory. */
2467 return gcvSTATUS_OK
;
2470 /*******************************************************************************
2472 ** gckOS_CreateMutex
2474 ** Create a new mutex.
2479 ** Pointer to an gckOS object.
2483 ** gctPOINTER * Mutex
2484 ** Pointer to a variable that will hold a pointer to the mutex.
2489 OUT gctPOINTER
* Mutex
2492 gcmkHEADER_ARG("Os=0x%X", Os
);
2494 /* Validate the arguments. */
2495 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2496 gcmkVERIFY_ARGUMENT(Mutex
!= gcvNULL
);
2498 /* Allocate a FAST_MUTEX structure. */
2499 *Mutex
= (gctPOINTER
)kmalloc(sizeof(struct semaphore
), GFP_KERNEL
);
2501 if (*Mutex
== gcvNULL
)
2503 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY
);
2504 return gcvSTATUS_OUT_OF_MEMORY
;
2507 /* Initialize the semaphore.. Come up in unlocked state. */
2508 sema_init(*Mutex
, 1);
2510 /* Return status. */
2511 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex
);
2512 return gcvSTATUS_OK
;
2515 /*******************************************************************************
2517 ** gckOS_DeleteMutex
2524 ** Pointer to an gckOS object.
2527 ** Pointer to the mute to be deleted.
2539 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os
, Mutex
);
2541 /* Validate the arguments. */
2542 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2543 gcmkVERIFY_ARGUMENT(Mutex
!= gcvNULL
);
2545 /* Delete the fast mutex. */
2549 return gcvSTATUS_OK
;
2552 /*******************************************************************************
2554 ** gckOS_AcquireMutex
2561 ** Pointer to an gckOS object.
2564 ** Pointer to the mutex to be acquired.
2566 ** gctUINT32 Timeout
2567 ** Timeout value specified in milliseconds.
2568 ** Specify the value of gcvINFINITE to keep the thread suspended
2569 ** until the mutex has been acquired.
2578 IN gctPOINTER Mutex
,
2579 IN gctUINT32 Timeout
2582 #if gcdDETECT_TIMEOUT
2586 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os
, Mutex
, Timeout
);
2588 /* Validate the arguments. */
2589 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2590 gcmkVERIFY_ARGUMENT(Mutex
!= gcvNULL
);
2592 #if gcdDETECT_TIMEOUT
2597 /* Try to acquire the mutex. */
2598 if (!down_trylock((struct semaphore
*) Mutex
))
2602 return gcvSTATUS_OK
;
2605 /* Advance the timeout. */
2608 if (Timeout
== gcvINFINITE
)
2610 if (timeout
== gcdINFINITE_TIMEOUT
)
2612 gctUINT32 dmaAddress1
, dmaAddress2
;
2613 gctUINT32 dmaState1
, dmaState2
;
2615 dmaState1
= dmaState2
=
2616 dmaAddress1
= dmaAddress2
= 0;
2618 /* Verify whether DMA is running. */
2619 gcmkVERIFY_OK(_VerifyDMA(
2620 Os
, &dmaAddress1
, &dmaAddress2
, &dmaState1
, &dmaState2
2623 #if gcdDETECT_DMA_ADDRESS
2624 /* Dump only if DMA appears stuck. */
2626 (dmaAddress1
== dmaAddress2
)
2627 #if gcdDETECT_DMA_STATE
2628 && (dmaState1
== dmaState2
)
2633 gcmkVERIFY_OK(_DumpGPUState(Os
));
2636 "%s(%d): mutex 0x%X; forced message flush.",
2637 __FUNCTION__
, __LINE__
, Mutex
2640 /* Flush the debug cache. */
2641 gcmkDEBUGFLUSH(dmaAddress2
);
2650 if (timeout
>= Timeout
)
2656 /* Wait for 1 millisecond. */
2657 gcmkVERIFY_OK(gckOS_Delay(Os
, 1));
2660 if (Timeout
== gcvINFINITE
)
2662 down((struct semaphore
*) Mutex
);
2666 return gcvSTATUS_OK
;
2671 /* Try to acquire the mutex. */
2672 if (!down_trylock((struct semaphore
*) Mutex
))
2676 return gcvSTATUS_OK
;
2684 /* Wait for 1 millisecond. */
2685 gcmkVERIFY_OK(gckOS_Delay(Os
, 1));
2690 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT
);
2691 return gcvSTATUS_TIMEOUT
;
2694 /*******************************************************************************
2696 ** gckOS_ReleaseMutex
2698 ** Release an acquired mutex.
2703 ** Pointer to an gckOS object.
2706 ** Pointer to the mutex to be released.
2718 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os
, Mutex
);
2720 /* Validate the arguments. */
2721 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2722 gcmkVERIFY_ARGUMENT(Mutex
!= gcvNULL
);
2724 /* Release the fast mutex. */
2725 up((struct semaphore
*) Mutex
);
2729 return gcvSTATUS_OK
;
2732 /*******************************************************************************
2734 ** gckOS_AtomicExchange
2736 ** Atomically exchange a pair of 32-bit values.
2741 ** Pointer to an gckOS object.
2743 ** IN OUT gctINT32_PTR Target
2744 ** Pointer to the 32-bit value to exchange.
2746 ** IN gctINT32 NewValue
2747 ** Specifies a new value for the 32-bit value pointed to by Target.
2749 ** OUT gctINT32_PTR OldValue
2750 ** The old value of the 32-bit value pointed to by Target.
2757 gckOS_AtomicExchange(
2759 IN OUT gctUINT32_PTR Target
,
2760 IN gctUINT32 NewValue
,
2761 OUT gctUINT32_PTR OldValue
2764 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os
, Target
, NewValue
);
2766 /* Verify the arguments. */
2767 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2769 /* Exchange the pair of 32-bit values. */
2770 *OldValue
= (gctUINT32
) atomic_xchg((atomic_t
*) Target
, (int) NewValue
);
2773 gcmkFOOTER_ARG("*OldValue=%u", *OldValue
);
2774 return gcvSTATUS_OK
;
2777 /*******************************************************************************
2779 ** gckOS_AtomicExchangePtr
2781 ** Atomically exchange a pair of pointers.
2786 ** Pointer to an gckOS object.
2788 ** IN OUT gctPOINTER * Target
2789 ** Pointer to the 32-bit value to exchange.
2791 ** IN gctPOINTER NewValue
2792 ** Specifies a new value for the pointer pointed to by Target.
2794 ** OUT gctPOINTER * OldValue
2795 ** The old value of the pointer pointed to by Target.
2802 gckOS_AtomicExchangePtr(
2804 IN OUT gctPOINTER
* Target
,
2805 IN gctPOINTER NewValue
,
2806 OUT gctPOINTER
* OldValue
2809 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os
, Target
, NewValue
);
2811 /* Verify the arguments. */
2812 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2814 /* Exchange the pair of pointers. */
2815 *OldValue
= (gctPOINTER
) atomic_xchg((atomic_t
*) Target
, (int) NewValue
);
2818 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue
);
2819 return gcvSTATUS_OK
;
2822 /*******************************************************************************
2824 ** gckOS_AtomConstruct
2831 ** Pointer to a gckOS object.
2835 ** gctPOINTER * Atom
2836 ** Pointer to a variable receiving the constructed atom.
2839 gckOS_AtomConstruct(
2841 OUT gctPOINTER
* Atom
2846 gcmkHEADER_ARG("Os=0x%X", Os
);
2848 /* Verify the arguments. */
2849 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2850 gcmkVERIFY_ARGUMENT(Atom
!= gcvNULL
);
2852 /* Allocate the atom. */
2853 gcmkONERROR(gckOS_Allocate(Os
, gcmSIZEOF(atomic_t
), Atom
));
2855 /* Initialize the atom. */
2856 atomic_set((atomic_t
*) *Atom
, 0);
2859 gcmkFOOTER_ARG("*Atom=0x%X", *Atom
);
2860 return gcvSTATUS_OK
;
2863 /* Return the status. */
2868 /*******************************************************************************
2870 ** gckOS_AtomDestroy
2877 ** Pointer to a gckOS object.
2880 ** Pointer to the atom to destroy.
2894 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os
, Atom
);
2896 /* Verify the arguments. */
2897 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2898 gcmkVERIFY_ARGUMENT(Atom
!= gcvNULL
);
2900 /* Free the atom. */
2901 gcmkONERROR(gcmkOS_SAFE_FREE(Os
, Atom
));
2905 return gcvSTATUS_OK
;
2908 /* Return the status. */
2913 /*******************************************************************************
2917 ** Get the 32-bit value protected by an atom.
2922 ** Pointer to a gckOS object.
2925 ** Pointer to the atom.
2929 ** gctINT32_PTR Value
2930 ** Pointer to a variable the receives the value of the atom.
2936 OUT gctINT32_PTR Value
2939 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os
, Atom
);
2941 /* Verify the arguments. */
2942 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2943 gcmkVERIFY_ARGUMENT(Atom
!= gcvNULL
);
2945 /* Return the current value of atom. */
2946 *Value
= atomic_read((atomic_t
*) Atom
);
2949 gcmkFOOTER_ARG("*Value=%d", *Value
);
2950 return gcvSTATUS_OK
;
2953 /*******************************************************************************
2957 ** Set the 32-bit value protected by an atom.
2962 ** Pointer to a gckOS object.
2965 ** Pointer to the atom.
2968 ** The value of the atom.
2981 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os
, Atom
);
2983 /* Verify the arguments. */
2984 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
2985 gcmkVERIFY_ARGUMENT(Atom
!= gcvNULL
);
2987 /* Set the current value of atom. */
2988 atomic_set((atomic_t
*) Atom
, Value
);
2992 return gcvSTATUS_OK
;
2995 /*******************************************************************************
2997 ** gckOS_AtomIncrement
2999 ** Atomically increment the 32-bit integer value inside an atom.
3004 ** Pointer to a gckOS object.
3007 ** Pointer to the atom.
3011 ** gctINT32_PTR Value
3012 ** Pointer to a variable that receives the original value of the atom.
3015 gckOS_AtomIncrement(
3018 OUT gctINT32_PTR Value
3021 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os
, Atom
);
3023 /* Verify the arguments. */
3024 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3025 gcmkVERIFY_ARGUMENT(Atom
!= gcvNULL
);
3027 /* Increment the atom. */
3028 *Value
= atomic_inc_return((atomic_t
*) Atom
) - 1;
3031 gcmkFOOTER_ARG("*Value=%d", *Value
);
3032 return gcvSTATUS_OK
;
3035 /*******************************************************************************
3037 ** gckOS_AtomDecrement
3039 ** Atomically decrement the 32-bit integer value inside an atom.
3044 ** Pointer to a gckOS object.
3047 ** Pointer to the atom.
3051 ** gctINT32_PTR Value
3052 ** Pointer to a variable that receives the original value of the atom.
3055 gckOS_AtomDecrement(
3058 OUT gctINT32_PTR Value
3061 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os
, Atom
);
3063 /* Verify the arguments. */
3064 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3065 gcmkVERIFY_ARGUMENT(Atom
!= gcvNULL
);
3067 /* Decrement the atom. */
3068 *Value
= atomic_dec_return((atomic_t
*) Atom
) + 1;
3071 gcmkFOOTER_ARG("*Value=%d", *Value
);
3072 return gcvSTATUS_OK
;
3075 /*******************************************************************************
3079 ** Delay execution of the current thread for a number of milliseconds.
3084 ** Pointer to an gckOS object.
3087 ** Delay to sleep, specified in milliseconds.
3100 unsigned long jiffies
;
3102 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os
, Delay
);
3106 /* Convert milliseconds into seconds and microseconds. */
3107 now
.tv_sec
= Delay
/ 1000;
3108 now
.tv_usec
= (Delay
% 1000) * 1000;
3110 /* Convert timeval to jiffies. */
3111 jiffies
= timeval_to_jiffies(&now
);
3113 /* Schedule timeout. */
3114 schedule_timeout_interruptible(jiffies
);
3119 return gcvSTATUS_OK
;
3122 /*******************************************************************************
3126 ** Get the number of milliseconds since the system started.
3132 ** gctUINT32_PTR Time
3133 ** Pointer to a variable to get time.
3138 OUT gctUINT32_PTR Time
3143 *Time
= jiffies
* 1000 / HZ
;
3146 return gcvSTATUS_OK
;
3149 /*******************************************************************************
3153 ** Compare time values got from gckOS_GetTicks.
3157 ** First time value to be compared.
3160 ** Second time value to be compared.
3164 ** gctBOOL_PTR IsAfter
3165 ** Pointer to a variable to result.
3172 OUT gctBOOL_PTR IsAfter
3177 *IsAfter
= time_after((unsigned long)Time1
, (unsigned long)Time2
);
3180 return gcvSTATUS_OK
;
3183 /*******************************************************************************
3187 ** Get the number of microseconds since the system started.
3193 ** gctUINT64_PTR Time
3194 ** Pointer to a variable to get time.
3199 OUT gctUINT64_PTR Time
3207 return gcvSTATUS_OK
;
3210 /*******************************************************************************
3212 ** gckOS_MemoryBarrier
3214 ** Make sure the CPU has executed everything up to this point and the data got
3215 ** written to the specified pointer.
3220 ** Pointer to an gckOS object.
3222 ** gctPOINTER Address
3223 ** Address of memory that needs to be barriered.
3230 gckOS_MemoryBarrier(
3232 IN gctPOINTER Address
3235 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os
, Address
);
3237 /* Verify the arguments. */
3238 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3240 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3241 && defined (CONFIG_ARM) \
3242 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3243 /* drain write buffer */
3246 /* drain outer cache's write buffer? */
3253 return gcvSTATUS_OK
;
3256 /*******************************************************************************
3258 ** gckOS_AllocatePagedMemory
3260 ** Allocate memory from the paged pool.
3265 ** Pointer to an gckOS object.
3268 ** Number of bytes to allocate.
3272 ** gctPHYS_ADDR * Physical
3273 ** Pointer to a variable that receives the physical address of the
3274 ** memory allocation.
3277 gckOS_AllocatePagedMemory(
3280 OUT gctPHYS_ADDR
* Physical
3285 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os
, Bytes
);
3287 /* Verify the arguments. */
3288 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3289 gcmkVERIFY_ARGUMENT(Bytes
> 0);
3290 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
3292 /* Allocate the memory. */
3293 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os
, gcvFALSE
, Bytes
, Physical
));
3296 gcmkFOOTER_ARG("*Physical=0x%X", *Physical
);
3297 return gcvSTATUS_OK
;
3300 /* Return the status. */
3305 /*******************************************************************************
3307 ** gckOS_AllocatePagedMemoryEx
3309 ** Allocate memory from the paged pool.
3314 ** Pointer to an gckOS object.
3316 ** gctBOOL Contiguous
3317 ** Need contiguous memory or not.
3320 ** Number of bytes to allocate.
3324 ** gctPHYS_ADDR * Physical
3325 ** Pointer to a variable that receives the physical address of the
3326 ** memory allocation.
3329 gckOS_AllocatePagedMemoryEx(
3331 IN gctBOOL Contiguous
,
3333 OUT gctPHYS_ADDR
* Physical
3338 PLINUX_MDL mdl
= gcvNULL
;
3341 gctBOOL locked
= gcvFALSE
;
3344 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os
, Contiguous
, Bytes
);
3346 /* Verify the arguments. */
3347 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3348 gcmkVERIFY_ARGUMENT(Bytes
> 0);
3349 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
3351 bytes
= gcmALIGN(Bytes
, PAGE_SIZE
);
3353 numPages
= GetPageCount(bytes
, 0);
3358 mdl
= _CreateMdl(_GetProcessID());
3361 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
3366 /* Get free pages, and suppress warning (stack dump) from kernel when
3367 we run out of memory. */
3368 addr
= (char *)__get_free_pages(GFP_KERNEL
| __GFP_NOWARN
, GetOrder(numPages
));
3372 addr
= vmalloc(bytes
);
3375 if (addr
== gcvNULL
)
3377 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
3382 mdl
->numPages
= numPages
;
3384 mdl
->contiguous
= Contiguous
;
3386 for (i
= 0; i
< mdl
->numPages
; i
++)
3390 if (mdl
->contiguous
)
3392 page
= virt_to_page(addr
+ i
* PAGE_SIZE
);
3396 page
= vmalloc_to_page(addr
+ i
* PAGE_SIZE
);
3399 SetPageReserved(page
);
3400 flush_dcache_page(page
);
3403 /* Return physical address. */
3404 *Physical
= (gctPHYS_ADDR
) mdl
;
3407 * Add this to a global list.
3408 * Will be used by get physical address
3409 * and mapuser pointer functions.
3413 /* Initialize the queue. */
3414 Os
->mdlHead
= Os
->mdlTail
= mdl
;
3419 mdl
->prev
= Os
->mdlTail
;
3420 Os
->mdlTail
->next
= mdl
;
3427 gcmkFOOTER_ARG("*Physical=0x%X", *Physical
);
3428 return gcvSTATUS_OK
;
3433 /* Free the memory. */
3439 /* Unlock the memory. */
3443 /* Return the status. */
3448 /*******************************************************************************
3450 ** gckOS_FreePagedMemory
3452 ** Free memory allocated from the paged pool.
3457 ** Pointer to an gckOS object.
3459 ** gctPHYS_ADDR Physical
3460 ** Physical address of the allocation.
3463 ** Number of bytes of the allocation.
3470 gckOS_FreePagedMemory(
3472 IN gctPHYS_ADDR Physical
,
3476 PLINUX_MDL mdl
= (PLINUX_MDL
) Physical
;
3480 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os
, Physical
, Bytes
);
3482 /* Verify the arguments. */
3483 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3484 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
3485 gcmkVERIFY_ARGUMENT(Bytes
> 0);
3491 for (i
= 0; i
< mdl
->numPages
; i
++)
3493 if (mdl
->contiguous
)
3495 ClearPageReserved(virt_to_page((gctPOINTER
)(((unsigned long)addr
) + i
* PAGE_SIZE
)));
3499 ClearPageReserved(vmalloc_to_page((gctPOINTER
)(((unsigned long)addr
) + i
* PAGE_SIZE
)));
3503 if (mdl
->contiguous
)
3505 free_pages((unsigned long)mdl
->addr
, GetOrder(mdl
->numPages
));
3512 /* Remove the node from global list. */
3513 if (mdl
== Os
->mdlHead
)
3515 if ((Os
->mdlHead
= mdl
->next
) == gcvNULL
)
3517 Os
->mdlTail
= gcvNULL
;
3522 mdl
->prev
->next
= mdl
->next
;
3524 if (mdl
== Os
->mdlTail
)
3526 Os
->mdlTail
= mdl
->prev
;
3530 mdl
->next
->prev
= mdl
->prev
;
3536 /* Free the structure... */
3537 gcmkVERIFY_OK(_DestroyMdl(mdl
));
3541 return gcvSTATUS_OK
;
3544 /*******************************************************************************
3548 ** Lock memory allocated from the paged pool.
3553 ** Pointer to an gckOS object.
3555 ** gctPHYS_ADDR Physical
3556 ** Physical address of the allocation.
3559 ** Number of bytes of the allocation.
3561 ** gctBOOL Cacheable
3562 ** Cache mode of mapping.
3566 ** gctPOINTER * Logical
3567 ** Pointer to a variable that receives the address of the mapped
3570 ** gctSIZE_T * PageCount
3571 ** Pointer to a variable that receives the number of pages required for
3572 ** the page table according to the GPU page size.
3577 IN gctPHYS_ADDR Physical
,
3579 IN gctBOOL Cacheable
,
3580 OUT gctPOINTER
* Logical
,
3581 OUT gctSIZE_T
* PageCount
3585 PLINUX_MDL_MAP mdlMap
;
3587 unsigned long start
;
3591 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os
, Physical
, Logical
);
3593 /* Verify the arguments. */
3594 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3595 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
3596 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
3597 gcmkVERIFY_ARGUMENT(PageCount
!= gcvNULL
);
3599 mdl
= (PLINUX_MDL
) Physical
;
3603 mdlMap
= FindMdlMap(mdl
, _GetProcessID());
3605 if (mdlMap
== gcvNULL
)
3607 mdlMap
= _CreateMdlMap(mdl
, _GetProcessID());
3609 if (mdlMap
== gcvNULL
)
3613 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY
);
3614 return gcvSTATUS_OUT_OF_MEMORY
;
3618 if (mdlMap
->vmaAddr
== gcvNULL
)
3620 down_write(¤t
->mm
->mmap_sem
);
3622 mdlMap
->vmaAddr
= (gctSTRING
)do_mmap_pgoff(gcvNULL
,
3624 mdl
->numPages
* PAGE_SIZE
,
3625 PROT_READ
| PROT_WRITE
,
3630 gcvLEVEL_INFO
, gcvZONE_OS
,
3631 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
3632 __FUNCTION__
, __LINE__
,
3633 (gctUINT32
) mdlMap
->vmaAddr
,
3637 if (IS_ERR(mdlMap
->vmaAddr
))
3639 up_write(¤t
->mm
->mmap_sem
);
3642 gcvLEVEL_INFO
, gcvZONE_OS
,
3643 "%s(%d): do_mmap_pgoff error",
3644 __FUNCTION__
, __LINE__
3647 mdlMap
->vmaAddr
= gcvNULL
;
3651 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY
);
3652 return gcvSTATUS_OUT_OF_MEMORY
;
3655 mdlMap
->vma
= find_vma(current
->mm
, (unsigned long)mdlMap
->vmaAddr
);
3657 if (mdlMap
->vma
== gcvNULL
)
3659 up_write(¤t
->mm
->mmap_sem
);
3662 gcvLEVEL_INFO
, gcvZONE_OS
,
3663 "%s(%d): find_vma error",
3664 __FUNCTION__
, __LINE__
3667 mdlMap
->vmaAddr
= gcvNULL
;
3671 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES
);
3672 return gcvSTATUS_OUT_OF_RESOURCES
;
3675 mdlMap
->vma
->vm_flags
|= VM_RESERVED
;
3676 #if !gcdPAGED_MEMORY_CACHEABLE
3677 if (Cacheable
== gcvFALSE
)
3679 /* Make this mapping non-cached. */
3680 mdlMap
->vma
->vm_page_prot
= pgprot_noncached(mdlMap
->vma
->vm_page_prot
);
3685 /* Now map all the vmalloc pages to this user address. */
3686 if (mdl
->contiguous
)
3688 /* map kernel memory to user space.. */
3689 if (remap_pfn_range(mdlMap
->vma
,
3690 mdlMap
->vma
->vm_start
,
3691 virt_to_phys((gctPOINTER
)mdl
->addr
) >> PAGE_SHIFT
,
3692 mdlMap
->vma
->vm_end
- mdlMap
->vma
->vm_start
,
3693 mdlMap
->vma
->vm_page_prot
) < 0)
3695 up_write(¤t
->mm
->mmap_sem
);
3698 gcvLEVEL_INFO
, gcvZONE_OS
,
3699 "%s(%d): unable to mmap ret",
3700 __FUNCTION__
, __LINE__
3703 mdlMap
->vmaAddr
= gcvNULL
;
3707 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY
);
3708 return gcvSTATUS_OUT_OF_MEMORY
;
3713 start
= mdlMap
->vma
->vm_start
;
3715 for (i
= 0; i
< mdl
->numPages
; i
++)
3717 pfn
= vmalloc_to_pfn(addr
);
3719 if (remap_pfn_range(mdlMap
->vma
,
3723 mdlMap
->vma
->vm_page_prot
) < 0)
3725 up_write(¤t
->mm
->mmap_sem
);
3728 gcvLEVEL_INFO
, gcvZONE_OS
,
3729 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
3730 __FUNCTION__
, __LINE__
,
3731 (gctUINT32
) Physical
,
3732 (gctUINT32
) *Logical
,
3737 mdlMap
->vmaAddr
= gcvNULL
;
3741 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY
);
3742 return gcvSTATUS_OUT_OF_MEMORY
;
3750 up_write(¤t
->mm
->mmap_sem
);
3754 /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */
3757 gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED
, mdlMap
->vmaAddr
);
3758 return gcvSTATUS_MEMORY_LOCKED
;
3761 /* Convert pointer to MDL. */
3762 *Logical
= mdlMap
->vmaAddr
;
3764 /* Return the page number according to the GPU page size. */
3765 gcmkASSERT((PAGE_SIZE
% 4096) == 0);
3766 gcmkASSERT((PAGE_SIZE
/ 4096) >= 1);
3768 *PageCount
= mdl
->numPages
* (PAGE_SIZE
/ 4096);
3773 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical
, *PageCount
);
3774 return gcvSTATUS_OK
;
3777 /*******************************************************************************
3781 ** Map paged memory into a page table.
3786 ** Pointer to an gckOS object.
3788 ** gctPHYS_ADDR Physical
3789 ** Physical address of the allocation.
3791 ** gctSIZE_T PageCount
3792 ** Number of pages required for the physical address.
3794 ** gctPOINTER PageTable
3795 ** Pointer to the page table to fill in.
3804 IN gctPHYS_ADDR Physical
,
3805 IN gctSIZE_T PageCount
,
3806 IN gctPOINTER PageTable
3809 return gckOS_MapPagesEx(Os
,
3820 IN gctPHYS_ADDR Physical
,
3821 IN gctSIZE_T PageCount
,
3822 IN gctPOINTER PageTable
3825 gceSTATUS status
= gcvSTATUS_OK
;
3832 gctPHYS_ADDR pageTablePhysical
;
3834 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
3835 Os
, Core
, Physical
, PageCount
, PageTable
);
3837 /* Verify the arguments. */
3838 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
3839 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
3840 gcmkVERIFY_ARGUMENT(PageCount
> 0);
3841 gcmkVERIFY_ARGUMENT(PageTable
!= gcvNULL
);
3843 /* Convert pointer to MDL. */
3844 mdl
= (PLINUX_MDL
)Physical
;
3847 gcvLEVEL_INFO
, gcvZONE_OS
,
3848 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
3849 __FUNCTION__
, __LINE__
,
3850 (gctUINT32
) Physical
,
3851 (gctUINT32
) PageCount
,
3857 table
= (gctUINT32
*)PageTable
;
3858 bytes
= PageCount
* sizeof(*table
);
3859 mmu
= Os
->device
->kernels
[Core
]->mmu
;
3860 mmuMdl
= (PLINUX_MDL
)mmu
->pageTablePhysical
;
3862 /* Get all the physical addresses and store them in the page table. */
3868 /* Try to get the user pages so DMA can happen. */
3869 while (PageCount
-- > 0)
3872 if (Core
== gcvCORE_VG
)
3874 if (mdl
->contiguous
)
3877 gckVGMMU_SetPage(Os
->device
->kernels
[Core
]->vg
->mmu
,
3884 gckVGMMU_SetPage(Os
->device
->kernels
[Core
]->vg
->mmu
,
3885 page_to_phys(vmalloc_to_page(addr
)),
3892 if (mdl
->contiguous
)
3895 gckMMU_SetPage(Os
->device
->kernels
[Core
]->mmu
,
3902 gckMMU_SetPage(Os
->device
->kernels
[Core
]->mmu
,
3903 page_to_phys(vmalloc_to_page(addr
)),
3915 gcvLEVEL_INFO
, gcvZONE_OS
,
3916 "%s(%d): we should not get this call for Non Paged Memory!",
3917 __FUNCTION__
, __LINE__
3920 while (PageCount
-- > 0)
3923 if (Core
== gcvCORE_VG
)
3926 gckVGMMU_SetPage(Os
->device
->kernels
[Core
]->vg
->mmu
,
3927 (gctUINT32
)virt_to_phys(addr
),
3934 gckMMU_SetPage(Os
->device
->kernels
[Core
]->mmu
,
3935 (gctUINT32
)virt_to_phys(addr
),
3943 /* Get physical address of pageTable */
3944 pageTablePhysical
= (gctPHYS_ADDR
)(mmuMdl
->dmaHandle
+
3945 ((gctUINT32
*)PageTable
- mmu
->pageTableLogical
));
3947 #if gcdNONPAGED_MEMORY_CACHEABLE
3948 /* Flush the mmu page table cache. */
3949 gcmkONERROR(gckOS_CacheClean(
3963 /* Return the status. */
3968 /*******************************************************************************
3970 ** gckOS_UnlockPages
3972 ** Unlock memory allocated from the paged pool.
3977 ** Pointer to an gckOS object.
3979 ** gctPHYS_ADDR Physical
3980 ** Physical address of the allocation.
3983 ** Number of bytes of the allocation.
3985 ** gctPOINTER Logical
3986 ** Address of the mapped memory.
3995 IN gctPHYS_ADDR Physical
,
3997 IN gctPOINTER Logical
4000 PLINUX_MDL_MAP mdlMap
;
4001 PLINUX_MDL mdl
= (PLINUX_MDL
)Physical
;
4002 struct task_struct
* task
;
4004 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4005 Os
, Physical
, Bytes
, Logical
);
4007 /* Verify the arguments. */
4008 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4009 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
4010 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
4012 /* Make sure there is already a mapping...*/
4013 gcmkVERIFY_ARGUMENT(mdl
->addr
!= gcvNULL
);
4019 while (mdlMap
!= gcvNULL
)
4021 if ((mdlMap
->vmaAddr
!= gcvNULL
) && (_GetProcessID() == mdlMap
->pid
))
4023 /* Get the current pointer for the task with stored pid. */
4024 task
= FIND_TASK_BY_PID(mdlMap
->pid
);
4026 if (task
!= gcvNULL
&& task
->mm
!= gcvNULL
)
4028 down_write(&task
->mm
->mmap_sem
);
4029 do_munmap(task
->mm
, (unsigned long)mdlMap
->vmaAddr
, mdl
->numPages
* PAGE_SIZE
);
4030 up_write(&task
->mm
->mmap_sem
);
4033 mdlMap
->vmaAddr
= gcvNULL
;
4036 mdlMap
= mdlMap
->next
;
4043 return gcvSTATUS_OK
;
4047 /*******************************************************************************
4049 ** gckOS_AllocateContiguous
4051 ** Allocate memory from the contiguous pool.
4056 ** Pointer to an gckOS object.
4058 ** gctBOOL InUserSpace
4059 ** gcvTRUE if the pages need to be mapped into user space.
4061 ** gctSIZE_T * Bytes
4062 ** Pointer to the number of bytes to allocate.
4066 ** gctSIZE_T * Bytes
4067 ** Pointer to a variable that receives the number of bytes allocated.
4069 ** gctPHYS_ADDR * Physical
4070 ** Pointer to a variable that receives the physical address of the
4071 ** memory allocation.
4073 ** gctPOINTER * Logical
4074 ** Pointer to a variable that receives the logical address of the
4075 ** memory allocation.
4078 gckOS_AllocateContiguous(
4080 IN gctBOOL InUserSpace
,
4081 IN OUT gctSIZE_T
* Bytes
,
4082 OUT gctPHYS_ADDR
* Physical
,
4083 OUT gctPOINTER
* Logical
4088 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4089 Os
, InUserSpace
, gcmOPT_VALUE(Bytes
));
4091 /* Verify the arguments. */
4092 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4093 gcmkVERIFY_ARGUMENT(Bytes
!= gcvNULL
);
4094 gcmkVERIFY_ARGUMENT(*Bytes
> 0);
4095 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
4096 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
4098 /* Same as non-paged memory for now. */
4099 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os
,
4106 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4107 *Bytes
, *Physical
, *Logical
);
4108 return gcvSTATUS_OK
;
4111 /* Return the status. */
4116 /*******************************************************************************
4118 ** gckOS_FreeContiguous
4120 ** Free memory allocated from the contiguous pool.
4125 ** Pointer to an gckOS object.
4127 ** gctPHYS_ADDR Physical
4128 ** Physical address of the allocation.
4130 ** gctPOINTER Logical
4131 ** Logicval address of the allocation.
4134 ** Number of bytes of the allocation.
4141 gckOS_FreeContiguous(
4143 IN gctPHYS_ADDR Physical
,
4144 IN gctPOINTER Logical
,
4150 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4151 Os
, Physical
, Logical
, Bytes
);
4153 /* Verify the arguments. */
4154 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4155 gcmkVERIFY_ARGUMENT(Physical
!= gcvNULL
);
4156 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
4157 gcmkVERIFY_ARGUMENT(Bytes
> 0);
4159 /* Same of non-paged memory for now. */
4160 gcmkONERROR(gckOS_FreeNonPagedMemory(Os
, Bytes
, Physical
, Logical
));
4164 return gcvSTATUS_OK
;
4167 /* Return the status. */
4173 /******************************************************************************
4175 ** gckOS_GetKernelLogical
4177 ** Return the kernel logical pointer that corresponods to the specified
4178 ** hardware address.
4183 ** Pointer to an gckOS object.
4185 ** gctUINT32 Address
4186 ** Hardware physical address.
4190 ** gctPOINTER * KernelPointer
4191 ** Pointer to a variable receiving the pointer in kernel address space.
4194 gckOS_GetKernelLogical(
4196 IN gctUINT32 Address
,
4197 OUT gctPOINTER
* KernelPointer
4200 return gckOS_GetKernelLogicalEx(Os
, gcvCORE_MAJOR
, Address
, KernelPointer
);
4204 gckOS_GetKernelLogicalEx(
4207 IN gctUINT32 Address
,
4208 OUT gctPOINTER
* KernelPointer
4213 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os
, Core
, Address
);
4217 gckGALDEVICE device
;
4223 /* Extract the pointer to the gckGALDEVICE class. */
4224 device
= (gckGALDEVICE
) Os
->device
;
4226 /* Kernel shortcut. */
4227 kernel
= device
->kernels
[Core
];
4229 if (Core
== gcvCORE_VG
)
4231 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4232 kernel
->vg
->hardware
, Address
, &pool
, &offset
4238 /* Split the memory address into a pool type and offset. */
4239 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4240 kernel
->hardware
, Address
, &pool
, &offset
4244 /* Dispatch on pool. */
4247 case gcvPOOL_LOCAL_INTERNAL
:
4248 /* Internal memory. */
4249 logical
= device
->internalLogical
;
4252 case gcvPOOL_LOCAL_EXTERNAL
:
4253 /* External memory. */
4254 logical
= device
->externalLogical
;
4257 case gcvPOOL_SYSTEM
:
4258 /* System memory. */
4259 logical
= device
->contiguousBase
;
4263 /* Invalid memory pool. */
4264 return gcvSTATUS_INVALID_ARGUMENT
;
4267 /* Build logical address of specified address. */
4268 * KernelPointer
= ((gctUINT8_PTR
) logical
) + offset
;
4271 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer
);
4272 return gcvSTATUS_OK
;
4276 /* Return status. */
4282 /*******************************************************************************
4284 ** gckOS_MapUserPointer
4286 ** Map a pointer from the user process into the kernel address space.
4291 ** Pointer to an gckOS object.
4293 ** gctPOINTER Pointer
4294 ** Pointer in user process space that needs to be mapped.
4297 ** Number of bytes that need to be mapped.
4301 ** gctPOINTER * KernelPointer
4302 ** Pointer to a variable receiving the mapped pointer in kernel address
4306 gckOS_MapUserPointer(
4308 IN gctPOINTER Pointer
,
4310 OUT gctPOINTER
* KernelPointer
4313 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os
, Pointer
, Size
);
4315 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
4317 gctPOINTER buf
= gcvNULL
;
4320 /* Verify the arguments. */
4321 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4322 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
4323 gcmkVERIFY_ARGUMENT(Size
> 0);
4324 gcmkVERIFY_ARGUMENT(KernelPointer
!= gcvNULL
);
4326 buf
= kmalloc(Size
, GFP_KERNEL
);
4331 "%s(%d): Failed to allocate memory.",
4332 __FUNCTION__
, __LINE__
4335 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY
);
4336 return gcvSTATUS_OUT_OF_MEMORY
;
4339 len
= copy_from_user(buf
, Pointer
, Size
);
4344 "%s(%d): Failed to copy data from user.",
4345 __FUNCTION__
, __LINE__
4353 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO
);
4354 return gcvSTATUS_GENERIC_IO
;
4357 *KernelPointer
= buf
;
4360 *KernelPointer
= Pointer
;
4361 #endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
4363 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer
);
4364 return gcvSTATUS_OK
;
4367 /*******************************************************************************
4369 ** gckOS_UnmapUserPointer
4371 ** Unmap a user process pointer from the kernel address space.
4376 ** Pointer to an gckOS object.
4378 ** gctPOINTER Pointer
4379 ** Pointer in user process space that needs to be unmapped.
4382 ** Number of bytes that need to be unmapped.
4384 ** gctPOINTER KernelPointer
4385 ** Pointer in kernel address space that needs to be unmapped.
4392 gckOS_UnmapUserPointer(
4394 IN gctPOINTER Pointer
,
4396 IN gctPOINTER KernelPointer
4399 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
4400 Os
, Pointer
, Size
, KernelPointer
);
4402 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
4406 /* Verify the arguments. */
4407 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4408 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
4409 gcmkVERIFY_ARGUMENT(Size
> 0);
4410 gcmkVERIFY_ARGUMENT(KernelPointer
!= gcvNULL
);
4412 len
= copy_to_user(Pointer
, KernelPointer
, Size
);
4414 kfree(KernelPointer
);
4420 "%s(%d): Failed to copy data to user.",
4421 __FUNCTION__
, __LINE__
4424 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO
);
4425 return gcvSTATUS_GENERIC_IO
;
4428 #endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
4431 return gcvSTATUS_OK
;
4434 /*******************************************************************************
4436 ** gckOS_QueryNeedCopy
4438 ** Query whether the memory can be accessed or mapped directly or it has to be
4444 ** Pointer to an gckOS object.
4446 ** gctUINT32 ProcessID
4447 ** Process ID of the current process.
4451 ** gctBOOL_PTR NeedCopy
4452 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
4453 ** gcvFALSE if the memory can be accessed or mapped dircetly.
4456 gckOS_QueryNeedCopy(
4458 IN gctUINT32 ProcessID
,
4459 OUT gctBOOL_PTR NeedCopy
4462 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os
, ProcessID
);
4464 /* Verify the arguments. */
4465 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4466 gcmkVERIFY_ARGUMENT(NeedCopy
!= gcvNULL
);
4468 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
4469 /* We need to copy data. */
4470 *NeedCopy
= gcvTRUE
;
4472 /* No need to copy data. */
4473 *NeedCopy
= gcvFALSE
;
4477 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy
);
4478 return gcvSTATUS_OK
;
4481 /*******************************************************************************
4483 ** gckOS_CopyFromUserData
4485 ** Copy data from user to kernel memory.
4490 ** Pointer to an gckOS object.
4492 ** gctPOINTER KernelPointer
4493 ** Pointer to kernel memory.
4495 ** gctPOINTER Pointer
4496 ** Pointer to user memory.
4499 ** Number of bytes to copy.
4506 gckOS_CopyFromUserData(
4508 IN gctPOINTER KernelPointer
,
4509 IN gctPOINTER Pointer
,
4515 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
4516 Os
, KernelPointer
, Pointer
, Size
);
4518 /* Verify the arguments. */
4519 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4520 gcmkVERIFY_ARGUMENT(KernelPointer
!= gcvNULL
);
4521 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
4522 gcmkVERIFY_ARGUMENT(Size
> 0);
4524 /* Copy data from user. */
4525 if (copy_from_user(KernelPointer
, Pointer
, Size
) != 0)
4527 /* Could not copy all the bytes. */
4528 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES
);
4533 return gcvSTATUS_OK
;
4536 /* Return the status. */
4541 /*******************************************************************************
4543 ** gckOS_CopyToUserData
4545 ** Copy data from kernel to user memory.
4550 ** Pointer to an gckOS object.
4552 ** gctPOINTER KernelPointer
4553 ** Pointer to kernel memory.
4555 ** gctPOINTER Pointer
4556 ** Pointer to user memory.
4559 ** Number of bytes to copy.
4566 gckOS_CopyToUserData(
4568 IN gctPOINTER KernelPointer
,
4569 IN gctPOINTER Pointer
,
4575 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
4576 Os
, KernelPointer
, Pointer
, Size
);
4578 /* Verify the arguments. */
4579 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4580 gcmkVERIFY_ARGUMENT(KernelPointer
!= gcvNULL
);
4581 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
4582 gcmkVERIFY_ARGUMENT(Size
> 0);
4584 /* Copy data to user. */
4585 if (copy_to_user(Pointer
, KernelPointer
, Size
) != 0)
4587 /* Could not copy all the bytes. */
4588 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES
);
4593 return gcvSTATUS_OK
;
4596 /* Return the status. */
4601 /*******************************************************************************
4603 ** gckOS_WriteMemory
4605 ** Write data to a memory.
4610 ** Pointer to an gckOS object.
4612 ** gctPOINTER Address
4613 ** Address of the memory to write to.
4616 ** Data for register.
4625 IN gctPOINTER Address
,
4629 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os
, Address
, Data
);
4631 /* Verify the arguments. */
4632 gcmkVERIFY_ARGUMENT(Address
!= gcvNULL
);
4635 writel(Data
, (gctUINT8
*)Address
);
4639 return gcvSTATUS_OK
;
4642 /*******************************************************************************
4644 ** gckOS_MapUserMemory
4646 ** Lock down a user buffer and return an DMA'able address to be used by the
4647 ** hardware to access it.
4651 ** gctPOINTER Memory
4652 ** Pointer to memory to lock down.
4655 ** Size in bytes of the memory to lock down.
4659 ** gctPOINTER * Info
4660 ** Pointer to variable receiving the information record required by
4661 ** gckOS_UnmapUserMemory.
4663 ** gctUINT32_PTR Address
4664 ** Pointer to a variable that will receive the address DMA'able by the
4668 gckOS_MapUserMemory(
4670 IN gctPOINTER Memory
,
4672 OUT gctPOINTER
* Info
,
4673 OUT gctUINT32_PTR Address
4676 return gckOS_MapUserMemoryEx(Os
, gcvCORE_MAJOR
, Memory
, Size
, Info
, Address
);
4680 gckOS_MapUserMemoryEx(
4683 IN gctPOINTER Memory
,
4685 OUT gctPOINTER
* Info
,
4686 OUT gctUINT32_PTR Address
4691 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os
, Core
, Memory
, Size
);
4694 gcmkONERROR(gckOS_AddMapping(Os
, *Address
, Memory
, Size
));
4697 return gcvSTATUS_OK
;
4704 gctSIZE_T pageCount
, i
, j
;
4705 gctUINT32_PTR pageTable
;
4707 gctUINT32 start
, end
, memory
;
4710 gcsPageInfo_PTR info
= gcvNULL
;
4711 struct page
**pages
= gcvNULL
;
4713 /* Verify the arguments. */
4714 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
4715 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
4716 gcmkVERIFY_ARGUMENT(Size
> 0);
4717 gcmkVERIFY_ARGUMENT(Info
!= gcvNULL
);
4718 gcmkVERIFY_ARGUMENT(Address
!= gcvNULL
);
4722 memory
= (gctUINT32
) Memory
;
4724 /* Get the number of required pages. */
4725 end
= (memory
+ Size
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
;
4726 start
= memory
>> PAGE_SHIFT
;
4727 pageCount
= end
- start
;
4730 gcvLEVEL_INFO
, gcvZONE_OS
,
4731 "%s(%d): pageCount: %d.",
4732 __FUNCTION__
, __LINE__
,
4736 /* Invalid argument. */
4739 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT
);
4740 return gcvSTATUS_INVALID_ARGUMENT
;
4744 if ((memory
+ Size
) < memory
)
4746 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT
);
4747 return gcvSTATUS_INVALID_ARGUMENT
;
4750 MEMORY_MAP_LOCK(Os
);
4752 /* Allocate the Info struct. */
4753 info
= (gcsPageInfo_PTR
)kmalloc(sizeof(gcsPageInfo
), GFP_KERNEL
);
4755 if (info
== gcvNULL
)
4757 status
= gcvSTATUS_OUT_OF_MEMORY
;
4761 /* Allocate the array of page addresses. */
4762 pages
= (struct page
**)kmalloc(pageCount
* sizeof(struct page
*), GFP_KERNEL
);
4764 if (pages
== gcvNULL
)
4766 status
= gcvSTATUS_OUT_OF_MEMORY
;
4770 /* Get the user pages. */
4771 down_read(¤t
->mm
->mmap_sem
);
4772 result
= get_user_pages(current
,
4781 up_read(¤t
->mm
->mmap_sem
);
4783 if (result
<=0 || result
< pageCount
)
4785 struct vm_area_struct
*vma
;
4787 vma
= find_vma(current
->mm
, memory
);
4789 if (vma
&& (vma
->vm_flags
& VM_PFNMAP
) )
4797 pgd_t
* pgd
= pgd_offset(current
->mm
, memory
);
4798 pud_t
* pud
= pud_offset(pgd
, memory
);
4801 pmd_t
* pmd
= pmd_offset(pud
, memory
);
4802 pte
= pte_offset_map_lock(current
->mm
, pmd
, memory
, &ptl
);
4813 pfn
= pte_pfn(*pte
);
4814 *Address
= ((pfn
<< PAGE_SHIFT
) | (((unsigned long)Memory
) & ~PAGE_MASK
))
4815 - Os
->device
->baseAddress
;
4818 pte_unmap_unlock(pte
, ptl
);
4820 /* Release page info struct. */
4821 if (info
!= gcvNULL
)
4823 /* Free the page info struct. */
4827 /* Free the page table. */
4828 if (pages
!= gcvNULL
)
4830 /* Release the pages if any. */
4833 for (i
= 0; i
< result
; i
++)
4835 if (pages
[i
] == gcvNULL
)
4840 page_cache_release(pages
[i
]);
4847 MEMORY_MAP_UNLOCK(Os
);
4849 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
4851 return gcvSTATUS_OK
;
4858 status
= gcvSTATUS_OUT_OF_RESOURCES
;
4863 status
= gcvSTATUS_OUT_OF_RESOURCES
;
4868 for (i
= 0; i
< pageCount
; i
++)
4870 /* Flush(clean) the data cache. */
4871 #if !defined(ANDROID)
4872 dma_sync_single_for_device(
4874 page_to_phys(pages
[i
]),
4878 flush_dcache_page(pages
[i
]);
4883 if (Core
== gcvCORE_VG
)
4885 /* Allocate pages inside the page table. */
4886 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os
->device
->kernels
[Core
]->vg
->mmu
,
4887 pageCount
* (PAGE_SIZE
/4096),
4888 (gctPOINTER
*) &pageTable
,
4894 /* Allocate pages inside the page table. */
4895 gcmkERR_BREAK(gckMMU_AllocatePages(Os
->device
->kernels
[Core
]->mmu
,
4896 pageCount
* (PAGE_SIZE
/4096),
4897 (gctPOINTER
*) &pageTable
,
4900 /* Fill the page table. */
4901 for (i
= 0; i
< pageCount
; i
++)
4904 if (Core
== gcvCORE_VG
)
4906 /* Get the physical address from page struct. */
4908 gckVGMMU_SetPage(Os
->device
->kernels
[Core
]->vg
->mmu
,
4909 page_to_phys(pages
[i
]),
4910 pageTable
+ i
* (PAGE_SIZE
/4096)));
4915 /* Get the physical address from page struct. */
4917 gckMMU_SetPage(Os
->device
->kernels
[Core
]->mmu
,
4918 page_to_phys(pages
[i
]),
4919 pageTable
+ i
* (PAGE_SIZE
/4096)));
4922 for (j
= 1; j
< (PAGE_SIZE
/4096); j
++)
4924 pageTable
[i
* (PAGE_SIZE
/4096) + j
] = pageTable
[i
* (PAGE_SIZE
/4096)] + 4096 * j
;
4928 gcvLEVEL_INFO
, gcvZONE_OS
,
4929 "%s(%d): pages[%d]: 0x%X, pageTable[%d]: 0x%X.",
4930 __FUNCTION__
, __LINE__
,
4935 /* Save pointer to page table. */
4936 info
->pageTable
= pageTable
;
4937 info
->pages
= pages
;
4939 *Info
= (gctPOINTER
) info
;
4942 gcvLEVEL_INFO
, gcvZONE_OS
,
4943 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
4944 __FUNCTION__
, __LINE__
,
4950 /* Return address. */
4951 *Address
= address
+ (memory
& ~PAGE_MASK
);
4954 gcvLEVEL_INFO
, gcvZONE_OS
,
4955 "%s(%d): Address: 0x%X.",
4956 __FUNCTION__
, __LINE__
,
4961 status
= gcvSTATUS_OK
;
4967 if (gcmIS_ERROR(status
))
4971 "%s(%d): error occured: %d.",
4972 __FUNCTION__
, __LINE__
,
4976 /* Release page array. */
4977 if (result
> 0 && pages
!= gcvNULL
)
4981 "%s(%d): error: page table is freed.",
4982 __FUNCTION__
, __LINE__
4985 for (i
= 0; i
< result
; i
++)
4987 if (pages
[i
] == gcvNULL
)
4991 page_cache_release(pages
[i
]);
4995 if (info
!= gcvNULL
&& pages
!= gcvNULL
)
4999 "%s(%d): error: pages is freed.",
5000 __FUNCTION__
, __LINE__
5003 /* Free the page table. */
5005 info
->pages
= gcvNULL
;
5008 /* Release page info struct. */
5009 if (info
!= gcvNULL
)
5013 "%s(%d): error: info is freed.",
5014 __FUNCTION__
, __LINE__
5017 /* Free the page info struct. */
5023 MEMORY_MAP_UNLOCK(Os
);
5025 /* Return the status. */
5026 if (gcmIS_SUCCESS(status
))
5028 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info
, *Address
);
5039 /*******************************************************************************
5041 ** gckOS_UnmapUserMemory
5043 ** Unlock a user buffer and that was previously locked down by
5044 ** gckOS_MapUserMemory.
5048 ** gctPOINTER Memory
5049 ** Pointer to memory to unlock.
5052 ** Size in bytes of the memory to unlock.
5055 ** Information record returned by gckOS_MapUserMemory.
5057 ** gctUINT32_PTR Address
5058 ** The address returned by gckOS_MapUserMemory.
5065 gckOS_UnmapUserMemory(
5067 IN gctPOINTER Memory
,
5070 IN gctUINT32 Address
5073 return gckOS_UnmapUserMemoryEx(Os
, gcvCORE_MAJOR
, Memory
, Size
, Info
, Address
);
5077 gckOS_UnmapUserMemoryEx(
5080 IN gctPOINTER Memory
,
5083 IN gctUINT32 Address
5088 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5089 Os
, Core
, Memory
, Size
, Info
, Address
);
5092 gcmkONERROR(gckOS_RemoveMapping(Os
, Memory
, Size
));
5095 return gcvSTATUS_OK
;
5102 gctUINT32 memory
, start
, end
;
5103 gcsPageInfo_PTR info
;
5104 gctSIZE_T pageCount
, i
;
5105 struct page
**pages
;
5107 /* Verify the arguments. */
5108 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5109 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
5110 gcmkVERIFY_ARGUMENT(Size
> 0);
5111 gcmkVERIFY_ARGUMENT(Info
!= gcvNULL
);
5115 info
= (gcsPageInfo_PTR
) Info
;
5117 pages
= info
->pages
;
5120 gcvLEVEL_INFO
, gcvZONE_OS
,
5121 "%s(%d): info=0x%X, pages=0x%X.",
5122 __FUNCTION__
, __LINE__
,
5126 /* Invalid page array. */
5127 if (pages
== gcvNULL
)
5129 return gcvSTATUS_INVALID_ARGUMENT
;
5132 memory
= (gctUINT32
) Memory
;
5133 end
= (memory
+ Size
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
;
5134 start
= memory
>> PAGE_SHIFT
;
5135 pageCount
= end
- start
;
5138 if ((memory
+ Size
) < memory
)
5140 return gcvSTATUS_INVALID_ARGUMENT
;
5143 /* Invalid argument. */
5146 return gcvSTATUS_INVALID_ARGUMENT
;
5150 gcvLEVEL_INFO
, gcvZONE_OS
,
5151 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5152 __FUNCTION__
, __LINE__
,
5153 memory
, pageCount
, info
->pageTable
5156 MEMORY_MAP_LOCK(Os
);
5159 if (Core
== gcvCORE_VG
)
5161 /* Free the pages from the MMU. */
5162 gcmkERR_BREAK(gckVGMMU_FreePages(Os
->device
->kernels
[Core
]->vg
->mmu
,
5164 pageCount
* (PAGE_SIZE
/4096)
5170 /* Free the pages from the MMU. */
5171 gcmkERR_BREAK(gckMMU_FreePages(Os
->device
->kernels
[Core
]->mmu
,
5173 pageCount
* (PAGE_SIZE
/4096)
5177 /* Release the page cache. */
5178 for (i
= 0; i
< pageCount
; i
++)
5181 gcvLEVEL_INFO
, gcvZONE_OS
,
5182 "%s(%d): pages[%d]: 0x%X.",
5183 __FUNCTION__
, __LINE__
,
5187 if (!PageReserved(pages
[i
]))
5189 SetPageDirty(pages
[i
]);
5192 #if !defined(ANDROID)
5193 /* Invalidate the data cache. */
5194 dma_sync_single_for_device(
5196 page_to_phys(pages
[i
]),
5200 page_cache_release(pages
[i
]);
5204 status
= gcvSTATUS_OK
;
5208 if (info
!= gcvNULL
)
5210 /* Free the page array. */
5211 if (info
->pages
!= gcvNULL
)
5219 MEMORY_MAP_UNLOCK(Os
);
5221 /* Return the status. */
5228 /*******************************************************************************
5230 ** gckOS_GetBaseAddress
5232 ** Get the base address for the physical memory.
5237 ** Pointer to the gckOS object.
5241 ** gctUINT32_PTR BaseAddress
5242 ** Pointer to a variable that will receive the base address.
5245 gckOS_GetBaseAddress(
5247 OUT gctUINT32_PTR BaseAddress
5250 gcmkHEADER_ARG("Os=0x%X", Os
);
5252 /* Verify the arguments. */
5253 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5254 gcmkVERIFY_ARGUMENT(BaseAddress
!= gcvNULL
);
5256 /* Return base address. */
5257 *BaseAddress
= Os
->device
->baseAddress
;
5260 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress
);
5261 return gcvSTATUS_OK
;
5265 gckOS_SuspendInterrupt(
5269 return gckOS_SuspendInterruptEx(Os
, gcvCORE_MAJOR
);
5273 gckOS_SuspendInterruptEx(
5278 gcmkHEADER_ARG("Os=0x%X Core=%d", Os
, Core
);
5280 /* Verify the arguments. */
5281 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5283 disable_irq(Os
->device
->irqLines
[Core
]);
5286 return gcvSTATUS_OK
;
5290 gckOS_ResumeInterrupt(
5294 return gckOS_ResumeInterruptEx(Os
, gcvCORE_MAJOR
);
5298 gckOS_ResumeInterruptEx(
5303 gcmkHEADER_ARG("Os=0x%X Core=%d", Os
, Core
);
5305 /* Verify the arguments. */
5306 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5308 enable_irq(Os
->device
->irqLines
[Core
]);
5311 return gcvSTATUS_OK
;
5316 IN gctPOINTER Destination
,
5317 IN gctCONST_POINTER Source
,
5321 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
5322 Destination
, Source
, Bytes
);
5324 gcmkVERIFY_ARGUMENT(Destination
!= gcvNULL
);
5325 gcmkVERIFY_ARGUMENT(Source
!= gcvNULL
);
5326 gcmkVERIFY_ARGUMENT(Bytes
> 0);
5328 memcpy(Destination
, Source
, Bytes
);
5331 return gcvSTATUS_OK
;
5336 IN gctPOINTER Memory
,
5340 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory
, Bytes
);
5342 gcmkVERIFY_ARGUMENT(Memory
!= gcvNULL
);
5343 gcmkVERIFY_ARGUMENT(Bytes
> 0);
5345 memset(Memory
, 0, Bytes
);
5348 return gcvSTATUS_OK
;
5351 /*******************************************************************************
5352 ********************************* Cache Control ********************************
5353 *******************************************************************************/
5355 /*******************************************************************************
5356 ** _HandleOuterCache
5358 ** Handle the outer cache for the specified addresses.
5363 ** Pointer to gckOS object.
5365 ** gctUINT32 ProcessID
5366 ** Process ID Logical belongs.
5368 ** gctPHYS_ADDR Handle
5369 ** Physical address handle. If gcvNULL it is video memory.
5371 ** gctPOINTER Physical
5372 ** Physical address to flush.
5374 ** gctPOINTER Logical
5375 ** Logical address to flush.
5378 ** Size of the address range in bytes to flush.
5380 ** gceOUTERCACHE_OPERATION Type
5381 ** Operation need to be execute.
5383 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
5384 static inline gceSTATUS
5386 gceCACHEOPERATION Type
,
5387 unsigned long Start
,
5393 case gcvCACHE_CLEAN
:
5394 outer_clean_range(Start
, End
);
5396 case gcvCACHE_INVALIDATE
:
5397 outer_inv_range(Start
, End
);
5399 case gcvCACHE_FLUSH
:
5400 outer_flush_range(Start
, End
);
5403 return gcvSTATUS_INVALID_ARGUMENT
;
5406 return gcvSTATUS_OK
;
5412 IN gctUINT32 ProcessID
,
5413 IN gctPHYS_ADDR Handle
,
5414 IN gctPOINTER Physical
,
5415 IN gctPOINTER Logical
,
5417 IN gceCACHEOPERATION Type
5421 gctUINT32 i
, pageNum
;
5422 unsigned long paddr
;
5425 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5426 Os
, ProcessID
, Handle
, Logical
, Bytes
);
5428 if (Physical
!= gcvNULL
)
5430 /* Non paged memory or gcvPOOL_USER surface */
5431 paddr
= (unsigned long) Physical
;
5432 gcmkONERROR(outer_func(Type
, paddr
, paddr
+ Bytes
));
5434 else if ((Handle
== gcvNULL
)
5435 || (Handle
!= gcvNULL
&& ((PLINUX_MDL
)Handle
)->contiguous
)
5438 /* Video Memory or contiguous virtual memory */
5439 gcmkONERROR(gckOS_GetPhysicalAddress(Os
, Logical
, (gctUINT32
*)&paddr
));
5440 gcmkONERROR(outer_func(Type
, paddr
, paddr
+ Bytes
));
5444 /* Non contiguous virtual memory */
5445 vaddr
= (gctPOINTER
)gcmALIGN_BASE((gctUINT32
)Logical
, PAGE_SIZE
);
5446 pageNum
= GetPageCount(Bytes
, 0);
5448 for (i
= 0; i
< pageNum
; i
+= 1)
5450 gcmkONERROR(_ConvertLogical2Physical(
5452 vaddr
+ PAGE_SIZE
* i
,
5458 gcmkONERROR(outer_func(Type
, paddr
, paddr
+ PAGE_SIZE
));
5466 return gcvSTATUS_OK
;
5469 /* Return the status. */
5475 /*******************************************************************************
5478 ** Clean the cache for the specified addresses. The GPU is going to need the
5479 ** data. If the system is allocating memory as non-cachable, this function can
5485 ** Pointer to gckOS object.
5487 ** gctUINT32 ProcessID
5488 ** Process ID Logical belongs.
5490 ** gctPHYS_ADDR Handle
5491 ** Physical address handle. If gcvNULL it is video memory.
5493 ** gctPOINTER Physical
5494 ** Physical address to flush.
5496 ** gctPOINTER Logical
5497 ** Logical address to flush.
5500 ** Size of the address range in bytes to flush.
5505 IN gctUINT32 ProcessID
,
5506 IN gctPHYS_ADDR Handle
,
5507 IN gctPOINTER Physical
,
5508 IN gctPOINTER Logical
,
5512 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5513 Os
, ProcessID
, Handle
, Logical
, Bytes
);
5515 /* Verify the arguments. */
5516 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5517 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
5518 gcmkVERIFY_ARGUMENT(Bytes
> 0);
5520 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5524 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
5525 dmac_map_area(Logical
, Bytes
, DMA_TO_DEVICE
);
5527 dmac_clean_range(Logical
, Logical
+ Bytes
);
5530 #if defined(CONFIG_OUTER_CACHE)
5532 _HandleOuterCache(Os
, ProcessID
, Handle
, Physical
, Logical
, Bytes
, gcvCACHE_CLEAN
);
5535 #elif defined(CONFIG_MIPS)
5537 dma_cache_wback((unsigned long) Logical
, Bytes
);
5540 dma_sync_single_for_device(
5550 return gcvSTATUS_OK
;
5553 /*******************************************************************************
5554 ** gckOS_CacheInvalidate
5556 ** Invalidate the cache for the specified addresses. The GPU is going to need
5557 ** data. If the system is allocating memory as non-cachable, this function can
5563 ** Pointer to gckOS object.
5565 ** gctUINT32 ProcessID
5566 ** Process ID Logical belongs.
5568 ** gctPHYS_ADDR Handle
5569 ** Physical address handle. If gcvNULL it is video memory.
5571 ** gctPOINTER Logical
5572 ** Logical address to flush.
5575 ** Size of the address range in bytes to flush.
5578 gckOS_CacheInvalidate(
5580 IN gctUINT32 ProcessID
,
5581 IN gctPHYS_ADDR Handle
,
5582 IN gctPOINTER Physical
,
5583 IN gctPOINTER Logical
,
5587 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5588 Os
, ProcessID
, Handle
, Logical
, Bytes
);
5590 /* Verify the arguments. */
5591 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5592 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
5593 gcmkVERIFY_ARGUMENT(Bytes
> 0);
5595 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5599 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
5600 dmac_map_area(Logical
, Bytes
, DMA_FROM_DEVICE
);
5602 dmac_inv_range(Logical
, Logical
+ Bytes
);
5605 #if defined(CONFIG_OUTER_CACHE)
5607 _HandleOuterCache(Os
, ProcessID
, Handle
, Physical
, Logical
, Bytes
, gcvCACHE_INVALIDATE
);
5610 #elif defined(CONFIG_MIPS)
5611 dma_cache_inv((unsigned long) Logical
, Bytes
);
5613 dma_sync_single_for_device(
5623 return gcvSTATUS_OK
;
5626 /*******************************************************************************
5629 ** Clean the cache for the specified addresses and invalidate the lines as
5630 ** well. The GPU is going to need and modify the data. If the system is
5631 ** allocating memory as non-cachable, this function can be ignored.
5636 ** Pointer to gckOS object.
5638 ** gctUINT32 ProcessID
5639 ** Process ID Logical belongs.
5641 ** gctPHYS_ADDR Handle
5642 ** Physical address handle. If gcvNULL it is video memory.
5644 ** gctPOINTER Logical
5645 ** Logical address to flush.
5648 ** Size of the address range in bytes to flush.
5653 IN gctUINT32 ProcessID
,
5654 IN gctPHYS_ADDR Handle
,
5655 IN gctPOINTER Physical
,
5656 IN gctPOINTER Logical
,
5660 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5661 Os
, ProcessID
, Handle
, Logical
, Bytes
);
5663 /* Verify the arguments. */
5664 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5665 gcmkVERIFY_ARGUMENT(Logical
!= gcvNULL
);
5666 gcmkVERIFY_ARGUMENT(Bytes
> 0);
5668 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5671 dmac_flush_range(Logical
, Logical
+ Bytes
);
5673 #if defined(CONFIG_OUTER_CACHE)
5675 _HandleOuterCache(Os
, ProcessID
, Handle
, Physical
, Logical
, Bytes
, gcvCACHE_FLUSH
);
5678 #elif defined(CONFIG_MIPS)
5679 dma_cache_wback_inv((unsigned long) Logical
, Bytes
);
5681 dma_sync_single_for_device(
5691 return gcvSTATUS_OK
;
5694 /*******************************************************************************
5695 ********************************* Broadcasting *********************************
5696 *******************************************************************************/
5698 /*******************************************************************************
5702 ** System hook for broadcast events from the kernel driver.
5707 ** Pointer to the gckOS object.
5709 ** gckHARDWARE Hardware
5710 ** Pointer to the gckHARDWARE object.
5712 ** gceBROADCAST Reason
5713 ** Reason for the broadcast. Can be one of the following values:
5715 ** gcvBROADCAST_GPU_IDLE
5716 ** Broadcasted when the kernel driver thinks the GPU might be
5717 ** idle. This can be used to handle power management.
5719 ** gcvBROADCAST_GPU_COMMIT
5720 ** Broadcasted when any client process commits a command
5721 ** buffer. This can be used to handle power management.
5723 ** gcvBROADCAST_GPU_STUCK
5724 ** Broadcasted when the kernel driver hits the timeout waiting
5727 ** gcvBROADCAST_FIRST_PROCESS
5728 ** First process is trying to connect to the kernel.
5730 ** gcvBROADCAST_LAST_PROCESS
5731 ** Last process has detached from the kernel.
5740 IN gckHARDWARE Hardware
,
5741 IN gceBROADCAST Reason
5746 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os
, Hardware
, Reason
);
5748 /* Verify the arguments. */
5749 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5750 gcmkVERIFY_OBJECT(Hardware
, gcvOBJ_HARDWARE
);
5754 case gcvBROADCAST_FIRST_PROCESS
:
5755 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_OS
, "First process has attached");
5758 case gcvBROADCAST_LAST_PROCESS
:
5759 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_OS
, "Last process has detached");
5763 gckHARDWARE_SetPowerManagementState(Hardware
,
5764 gcvPOWER_OFF_BROADCAST
));
5767 case gcvBROADCAST_GPU_IDLE
:
5768 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_OS
, "GPU idle.");
5772 gckHARDWARE_SetPowerManagementState(Hardware
,
5773 gcvPOWER_IDLE_BROADCAST
));
5775 /* Add idle process DB. */
5776 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware
->kernel
,
5779 gcvNULL
, gcvNULL
, 0));
5782 case gcvBROADCAST_GPU_COMMIT
:
5783 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_OS
, "COMMIT has arrived.");
5785 /* Add busy process DB. */
5786 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware
->kernel
,
5789 gcvNULL
, gcvNULL
, 0));
5793 gckHARDWARE_SetPowerManagementState(Hardware
, gcvPOWER_ON_AUTO
));
5796 case gcvBROADCAST_GPU_STUCK
:
5797 gcmkTRACE_N(gcvLEVEL_ERROR
, 0, "gcvBROADCAST_GPU_STUCK\n");
5798 gcmkONERROR(_DumpGPUState(Os
));
5799 gcmkONERROR(gckKERNEL_Recovery(Hardware
->kernel
));
5802 case gcvBROADCAST_AXI_BUS_ERROR
:
5803 gcmkTRACE_N(gcvLEVEL_ERROR
, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
5804 gcmkONERROR(_DumpGPUState(Os
));
5805 /*gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));*/
5811 return gcvSTATUS_OK
;
5814 /* Return the status. */
5819 /*******************************************************************************
5821 ** gckOS_BroadcastHurry
5823 ** The GPU is running too slow.
5828 ** Pointer to the gckOS object.
5830 ** gckHARDWARE Hardware
5831 ** Pointer to the gckHARDWARE object.
5834 ** The higher the number, the higher the urgency to speed up the GPU.
5835 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
5842 gckOS_BroadcastHurry(
5844 IN gckHARDWARE Hardware
,
5848 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os
, Hardware
, Urgency
);
5850 /* Do whatever you need to do to speed up the GPU now. */
5854 return gcvSTATUS_OK
;
5857 /*******************************************************************************
5859 ** gckOS_BroadcastCalibrateSpeed
5861 ** Calibrate the speed of the GPU.
5866 ** Pointer to the gckOS object.
5868 ** gckHARDWARE Hardware
5869 ** Pointer to the gckHARDWARE object.
5871 ** gctUINT Idle, Time
5872 ** Idle/Time will give the percentage the GPU is idle, so you can use
5873 ** this to calibrate the working point of the GPU.
5880 gckOS_BroadcastCalibrateSpeed(
5882 IN gckHARDWARE Hardware
,
5887 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
5888 Os
, Hardware
, Idle
, Time
);
5890 /* Do whatever you need to do to callibrate the GPU speed. */
5894 return gcvSTATUS_OK
;
5897 /*******************************************************************************
5898 ********************************** Semaphores **********************************
5899 *******************************************************************************/
5901 /*******************************************************************************
5903 ** gckOS_CreateSemaphore
5905 ** Create a semaphore.
5910 ** Pointer to the gckOS object.
5914 ** gctPOINTER * Semaphore
5915 ** Pointer to the variable that will receive the created semaphore.
5918 gckOS_CreateSemaphore(
5920 OUT gctPOINTER
* Semaphore
5924 struct semaphore
*sem
= gcvNULL
;
5926 gcmkHEADER_ARG("Os=0x%X", Os
);
5928 /* Verify the arguments. */
5929 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5930 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
5932 /* Allocate the semaphore structure. */
5933 sem
= (struct semaphore
*)kmalloc(gcmSIZEOF(struct semaphore
), GFP_KERNEL
);
5936 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
5939 /* Initialize the semaphore. */
5942 /* Return to caller. */
5943 *Semaphore
= (gctPOINTER
) sem
;
5947 return gcvSTATUS_OK
;
5950 /* Return the status. */
5955 /*******************************************************************************
5957 ** gckOS_AcquireSemaphore
5959 ** Acquire a semaphore.
5964 ** Pointer to the gckOS object.
5966 ** gctPOINTER Semaphore
5967 ** Pointer to the semaphore thet needs to be acquired.
5974 gckOS_AcquireSemaphore(
5976 IN gctPOINTER Semaphore
5981 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os
, Semaphore
);
5983 /* Verify the arguments. */
5984 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
5985 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
5987 /* Acquire the semaphore. */
5988 if (down_interruptible((struct semaphore
*) Semaphore
))
5990 gcmkONERROR(gcvSTATUS_TIMEOUT
);
5995 return gcvSTATUS_OK
;
5998 /* Return the status. */
6003 /*******************************************************************************
6005 ** gckOS_TryAcquireSemaphore
6007 ** Try to acquire a semaphore.
6012 ** Pointer to the gckOS object.
6014 ** gctPOINTER Semaphore
6015 ** Pointer to the semaphore thet needs to be acquired.
6022 gckOS_TryAcquireSemaphore(
6024 IN gctPOINTER Semaphore
6029 gcmkHEADER_ARG("Os=0x%x", Os
);
6031 /* Verify the arguments. */
6032 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6033 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
6035 /* Acquire the semaphore. */
6036 if (down_trylock((struct semaphore
*) Semaphore
))
6039 status
= gcvSTATUS_TIMEOUT
;
6046 return gcvSTATUS_OK
;
6049 /*******************************************************************************
6051 ** gckOS_ReleaseSemaphore
6053 ** Release a previously acquired semaphore.
6058 ** Pointer to the gckOS object.
6060 ** gctPOINTER Semaphore
6061 ** Pointer to the semaphore thet needs to be released.
6068 gckOS_ReleaseSemaphore(
6070 IN gctPOINTER Semaphore
6073 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os
, Semaphore
);
6075 /* Verify the arguments. */
6076 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6077 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
6079 /* Release the semaphore. */
6080 up((struct semaphore
*) Semaphore
);
6084 return gcvSTATUS_OK
;
6087 /*******************************************************************************
6089 ** gckOS_DestroySemaphore
6091 ** Destroy a semaphore.
6096 ** Pointer to the gckOS object.
6098 ** gctPOINTER Semaphore
6099 ** Pointer to the semaphore thet needs to be destroyed.
6106 gckOS_DestroySemaphore(
6108 IN gctPOINTER Semaphore
6111 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os
, Semaphore
);
6113 /* Verify the arguments. */
6114 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6115 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
6117 /* Free the sempahore structure. */
6122 return gcvSTATUS_OK
;
6125 /*******************************************************************************
6127 ** gckOS_GetProcessID
6129 ** Get current process ID.
6137 ** gctUINT32_PTR ProcessID
6138 ** Pointer to the variable that receives the process ID.
6142 OUT gctUINT32_PTR ProcessID
6145 /* Get process ID. */
6146 if (ProcessID
!= gcvNULL
)
6148 *ProcessID
= _GetProcessID();
6152 return gcvSTATUS_OK
;
6155 /*******************************************************************************
6157 ** gckOS_GetThreadID
6159 ** Get current thread ID.
6167 ** gctUINT32_PTR ThreadID
6168 ** Pointer to the variable that receives the thread ID.
6172 OUT gctUINT32_PTR ThreadID
6175 /* Get thread ID. */
6176 if (ThreadID
!= gcvNULL
)
6178 *ThreadID
= _GetThreadID();
6182 return gcvSTATUS_OK
;
6185 /*******************************************************************************
6187 ** gckOS_SetGPUPower
6189 ** Set the power of the GPU on or off.
6194 ** Pointer to a gckOS object.
6197 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6200 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6213 gcmkHEADER_ARG("Os=0x%X Clock=%d Power=%d", Os
, Clock
, Power
);
6215 /* TODO: Put your code here. */
6218 return gcvSTATUS_OK
;
6221 /*----------------------------------------------------------------------------*/
6222 /*----- Profile --------------------------------------------------------------*/
6225 gckOS_GetProfileTick(
6226 OUT gctUINT64_PTR Tick
6229 struct timespec time
;
6231 ktime_get_ts(&time
);
6233 *Tick
= time
.tv_nsec
+ time
.tv_sec
* 1000000000ULL;
6235 return gcvSTATUS_OK
;
6239 gckOS_QueryProfileTickRate(
6240 OUT gctUINT64_PTR TickRate
6243 struct timespec res
;
6245 hrtimer_get_res(CLOCK_MONOTONIC
, &res
);
6247 *TickRate
= res
.tv_nsec
+ res
.tv_sec
* 1000000000ULL;
6249 return gcvSTATUS_OK
;
6257 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
6258 return div_u64(Ticks
, 1000000);
6260 gctUINT64 rem
= Ticks
;
6261 gctUINT64 b
= 1000000;
6262 gctUINT64 res
, d
= 1;
6263 gctUINT32 high
= rem
>> 32;
6265 /* Reduce the thing a bit first */
6267 if (high
>= 1000000)
6270 res
= (gctUINT64
) high
<< 32;
6271 rem
-= (gctUINT64
) (high
* 1000000) << 32;
6274 while (((gctINT64
) b
> 0) && (b
< rem
))
6293 return (gctUINT32
) res
;
6297 #if gcdENABLE_BANK_ALIGNMENT
6298 /*******************************************************************************
6299 ** gckOS_GetSurfaceBankAlignment
6301 ** Return the required offset alignment required to the make BaseAddress
6302 ** aligned properly.
6307 ** Pointer to gcoOS object.
6309 ** gceSURF_TYPE Type
6310 ** Type of allocation.
6312 ** gctUINT32 BaseAddress
6313 ** Base address of current video memory node.
6317 ** gctUINT32_PTR Alignment
6318 ** Pointer to a variable thah twil hold the number of bytes to skip in
6319 ** the current video memory node in order to make the alignment bank
6323 gckOS_GetSurfaceBankAlignment(
6325 IN gceSURF_TYPE Type
,
6326 IN gctUINT32 BaseAddress
,
6327 OUT gctUINT32_PTR Alignment
6330 gctUINT32 alignedBaseAddress
;
6332 gcmkHEADER_ARG("Os=0x%x Type=%d BaseAddress=0x%x ", Os
, Type
, BaseAddress
);
6334 /* Verify the arguments. */
6335 gcmkVERIFY_ARGUMENT(Alignment
!= gcvNULL
);
6339 case gcvSURF_RENDER_TARGET
:
6340 /* Align to first 4kB bank. */
6341 alignedBaseAddress
= (((BaseAddress
>> 15) << 3) + (0x8 + 0x0)) << 12;
6345 /* Align to third 4kB bank. */
6346 alignedBaseAddress
= (((BaseAddress
>> 15) << 3) + (0x8 + 0x2)) << 12;
6348 /* Add 64-byte offset to change channel bit 6. */
6349 alignedBaseAddress
+= 64;
6353 /* no alignment needed. */
6354 alignedBaseAddress
= BaseAddress
;
6357 /* Return alignment. */
6358 *Alignment
= alignedBaseAddress
- BaseAddress
;
6360 /* Return the status. */
6361 gcmkFOOTER_ARG("*Alignment=%u", *Alignment
);
6362 return gcvSTATUS_OK
;
6366 /******************************************************************************\
6367 ******************************* Signal Management ******************************
6368 \******************************************************************************/
6371 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
6373 /*******************************************************************************
6375 ** gckOS_CreateSignal
6377 ** Create a new signal.
6382 ** Pointer to an gckOS object.
6384 ** gctBOOL ManualReset
6385 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
6386 ** order to set the signal to nonsignaled state.
6387 ** If set to gcvFALSE, the signal will automatically be set to
6388 ** nonsignaled state by gckOS_WaitSignal function.
6392 ** gctSIGNAL * Signal
6393 ** Pointer to a variable receiving the created gctSIGNAL.
6398 IN gctBOOL ManualReset
,
6399 OUT gctSIGNAL
* Signal
6402 gcsSIGNAL_PTR signal
;
6404 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os
, ManualReset
);
6406 /* Verify the arguments. */
6407 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6408 gcmkVERIFY_ARGUMENT(Signal
!= gcvNULL
);
6410 /* Create an event structure. */
6411 signal
= (gcsSIGNAL_PTR
) kmalloc(sizeof(gcsSIGNAL
), GFP_KERNEL
);
6413 if (signal
== gcvNULL
)
6415 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY
);
6416 return gcvSTATUS_OUT_OF_MEMORY
;
6419 signal
->manualReset
= ManualReset
;
6420 init_completion(&signal
->obj
);
6421 atomic_set(&signal
->ref
, 1);
6423 *Signal
= (gctSIGNAL
) signal
;
6425 gcmkFOOTER_ARG("*Signal=0x%X", *Signal
);
6426 return gcvSTATUS_OK
;
6429 /*******************************************************************************
6431 ** gckOS_DestroySignal
6433 ** Destroy a signal.
6438 ** Pointer to an gckOS object.
6441 ** Pointer to the gctSIGNAL.
6448 gckOS_DestroySignal(
6453 gcsSIGNAL_PTR signal
;
6455 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os
, Signal
);
6457 /* Verify the arguments. */
6458 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6459 gcmkVERIFY_ARGUMENT(Signal
!= gcvNULL
);
6461 signal
= (gcsSIGNAL_PTR
) Signal
;
6463 if (atomic_dec_and_test(&signal
->ref
))
6465 /* Free the sgianl. */
6471 return gcvSTATUS_OK
;
6474 /*******************************************************************************
6478 ** Set a state of the specified signal.
6483 ** Pointer to an gckOS object.
6486 ** Pointer to the gctSIGNAL.
6489 ** If gcvTRUE, the signal will be set to signaled state.
6490 ** If gcvFALSE, the signal will be set to nonsignaled state.
6499 IN gctSIGNAL Signal
,
6503 gcsSIGNAL_PTR signal
;
6505 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os
, Signal
, State
);
6507 /* Verify the arguments. */
6508 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6509 gcmkVERIFY_ARGUMENT(Signal
!= gcvNULL
);
6511 signal
= (gcsSIGNAL_PTR
) Signal
;
6515 /* Set the event to a signaled state. */
6516 complete(&signal
->obj
);
6520 /* Set the event to an unsignaled state. */
6521 INIT_COMPLETION(signal
->obj
);
6526 return gcvSTATUS_OK
;
6533 IN gctHANDLE Process
,
6539 struct task_struct
* userTask
;
6540 struct siginfo info
;
6542 userTask
= FIND_TASK_BY_PID((pid_t
) Process
);
6544 if (userTask
!= gcvNULL
)
6547 info
.si_code
= __SI_CODE(__SI_RT
, SI_KERNEL
);
6550 info
.si_ptr
= (gctPOINTER
) Signal
;
6552 /* Signals with numbers between 32 and 63 are real-time,
6553 send a real-time signal to the user process. */
6554 result
= send_sig_info(48, &info
, userTask
);
6556 printk("gckOS_SetSignalVG:0x%x\n", result
);
6560 status
= gcvSTATUS_GENERIC_IO
;
6564 "%s(%d): an error has occurred.\n",
6565 __FUNCTION__
, __LINE__
6570 status
= gcvSTATUS_OK
;
6575 status
= gcvSTATUS_GENERIC_IO
;
6579 "%s(%d): an error has occurred.\n",
6580 __FUNCTION__
, __LINE__
6584 /* Return status. */
6589 /*******************************************************************************
6593 ** Set the specified signal which is owned by a process to signaled state.
6598 ** Pointer to an gckOS object.
6601 ** Pointer to the gctSIGNAL.
6603 ** gctHANDLE Process
6604 ** Handle of process owning the signal.
6613 IN gctSIGNAL Signal
,
6614 IN gctHANDLE Process
6620 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
6621 Os
, Signal
, (gctINT32
) Process
);
6623 /* Map the signal into kernel space. */
6624 gcmkONERROR(gckOS_MapSignal(Os
, Signal
, Process
, &signal
));
6627 status
= gckOS_Signal(Os
, signal
, gcvTRUE
);
6629 /* Unmap the signal */
6630 gcmkVERIFY_OK(gckOS_UnmapSignal(Os
, Signal
));
6636 /* Return the status. */
6641 /*******************************************************************************
6645 ** Wait for a signal to become signaled.
6650 ** Pointer to an gckOS object.
6653 ** Pointer to the gctSIGNAL.
6656 ** Number of milliseconds to wait.
6657 ** Pass the value of gcvINFINITE for an infinite wait.
6666 IN gctSIGNAL Signal
,
6670 gceSTATUS status
= gcvSTATUS_OK
;
6671 gcsSIGNAL_PTR signal
;
6673 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os
, Signal
, Wait
);
6675 /* Verify the arguments. */
6676 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
6677 gcmkVERIFY_ARGUMENT(Signal
!= gcvNULL
);
6679 signal
= (gcsSIGNAL_PTR
) Signal
;
6683 spin_lock_irq(&signal
->obj
.wait
.lock
);
6685 if (signal
->obj
.done
)
6687 if (!signal
->manualReset
)
6689 signal
->obj
.done
= 0;
6692 status
= gcvSTATUS_OK
;
6696 status
= gcvSTATUS_TIMEOUT
;
6700 /* Convert wait to milliseconds. */
6701 #if gcdDETECT_TIMEOUT
6702 gctINT timeout
= (Wait
== gcvINFINITE
)
6703 ? gcdINFINITE_TIMEOUT
* HZ
/ 1000
6706 gctUINT complained
= 0;
6708 gctINT timeout
= (Wait
== gcvINFINITE
)
6709 ? MAX_SCHEDULE_TIMEOUT
6713 DECLARE_WAITQUEUE(wait
, current
);
6714 wait
.flags
|= WQ_FLAG_EXCLUSIVE
;
6715 __add_wait_queue_tail(&signal
->obj
.wait
, &wait
);
6719 if (signal_pending(current
))
6721 /* Interrupt received. */
6722 status
= gcvSTATUS_INTERRUPTED
;
6726 __set_current_state(TASK_INTERRUPTIBLE
);
6727 spin_unlock_irq(&signal
->obj
.wait
.lock
);
6728 timeout
= schedule_timeout(timeout
);
6729 spin_lock_irq(&signal
->obj
.wait
.lock
);
6731 if (signal
->obj
.done
)
6733 if (!signal
->manualReset
)
6735 signal
->obj
.done
= 0;
6738 status
= gcvSTATUS_OK
;
6742 #if gcdDETECT_TIMEOUT
6743 if ((Wait
== gcvINFINITE
) && (timeout
== 0))
6745 gctUINT32 dmaAddress1
, dmaAddress2
;
6746 gctUINT32 dmaState1
, dmaState2
;
6748 dmaState1
= dmaState2
=
6749 dmaAddress1
= dmaAddress2
= 0;
6751 /* Verify whether DMA is running. */
6752 gcmkVERIFY_OK(_VerifyDMA(
6753 Os
, &dmaAddress1
, &dmaAddress2
, &dmaState1
, &dmaState2
6756 #if gcdDETECT_DMA_ADDRESS
6757 /* Dump only if DMA appears stuck. */
6759 (dmaAddress1
== dmaAddress2
)
6760 #if gcdDETECT_DMA_STATE
6761 && (dmaState1
== dmaState2
)
6766 /* Increment complain count. */
6769 gcmkVERIFY_OK(_DumpGPUState(Os
));
6772 "%s(%d): signal 0x%X; forced message flush (%d).",
6773 __FUNCTION__
, __LINE__
, Signal
, complained
6776 /* Flush the debug cache. */
6777 gcmkDEBUGFLUSH(dmaAddress2
);
6780 /* Reset timeout. */
6781 timeout
= gcdINFINITE_TIMEOUT
* HZ
/ 1000;
6788 status
= gcvSTATUS_TIMEOUT
;
6793 __remove_wait_queue(&signal
->obj
.wait
, &wait
);
6795 #if gcdDETECT_TIMEOUT
6799 "%s(%d): signal=0x%X; waiting done; status=%d",
6800 __FUNCTION__
, __LINE__
, Signal
, status
6806 spin_unlock_irq(&signal
->obj
.wait
.lock
);
6808 /* Return status. */
6809 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal
, status
);
6813 /*******************************************************************************
6817 ** Map a signal in to the current process space.
6822 ** Pointer to an gckOS object.
6825 ** Pointer to tha gctSIGNAL to map.
6827 ** gctHANDLE Process
6828 ** Handle of process owning the signal.
6832 ** gctSIGNAL * MappedSignal
6833 ** Pointer to a variable receiving the mapped gctSIGNAL.
6838 IN gctSIGNAL Signal
,
6839 IN gctHANDLE Process
,
6840 OUT gctSIGNAL
* MappedSignal
6844 gcsSIGNAL_PTR signal
;
6846 gctBOOL acquired
= gcvFALSE
;
6848 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os
, Signal
, Process
);
6850 gcmkVERIFY_ARGUMENT(Signal
!= gcvNULL
);
6851 gcmkVERIFY_ARGUMENT(MappedSignal
!= gcvNULL
);
6853 signalID
= (gctINT
) Signal
- 1;
6855 gcmkONERROR(gckOS_AcquireMutex(Os
, Os
->signal
.lock
, gcvINFINITE
));
6858 if (signalID
>= 0 && signalID
< Os
->signal
.tableLen
)
6860 /* It is a user space signal. */
6861 signal
= Os
->signal
.table
[signalID
];
6863 if (signal
== gcvNULL
)
6865 gcmkONERROR(gcvSTATUS_NOT_FOUND
);
6870 /* It is a kernel space signal structure. */
6871 signal
= (gcsSIGNAL_PTR
) Signal
;
6874 if (atomic_inc_return(&signal
->ref
) <= 1)
6876 /* The previous value is 0, it has been deleted. */
6877 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
6880 /* Release the mutex. */
6881 gcmkONERROR(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
6883 *MappedSignal
= (gctSIGNAL
) signal
;
6886 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal
);
6887 return gcvSTATUS_OK
;
6892 /* Release the mutex. */
6893 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
6896 /* Return the staus. */
6901 /*******************************************************************************
6903 ** gckOS_UnmapSignal
6910 ** Pointer to an gckOS object.
6913 ** Pointer to that gctSIGNAL mapped.
6922 gcsSIGNAL_PTR signal
;
6924 gctBOOL acquired
= gcvFALSE
;
6926 gcmkHEADER_ARG("Os=0x%X Signal=0x%X ", Os
, Signal
);
6928 gcmkVERIFY_ARGUMENT(Signal
!= gcvNULL
);
6930 signalID
= (gctINT
) Signal
- 1;
6932 gcmkONERROR(gckOS_AcquireMutex(Os
, Os
->signal
.lock
, gcvINFINITE
));
6935 if (signalID
>= 0 && signalID
< Os
->signal
.tableLen
)
6937 /* It is a user space signal. */
6938 signal
= Os
->signal
.table
[signalID
];
6940 if (signal
== gcvNULL
)
6942 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
6945 if (atomic_read(&signal
->ref
) == 1)
6947 /* Update the table. */
6948 Os
->signal
.table
[signalID
] = gcvNULL
;
6950 if (Os
->signal
.unused
++ == 0)
6952 Os
->signal
.currentID
= signalID
;
6956 gcmkONERROR(gckOS_DestroySignal(Os
, signal
));
6960 /* It is a kernel space signal structure. */
6961 signal
= (gcsSIGNAL_PTR
) Signal
;
6963 gcmkONERROR(gckOS_DestroySignal(Os
, signal
));
6966 /* Release the mutex. */
6967 gcmkONERROR(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
6971 return gcvSTATUS_OK
;
6976 /* Release the mutex. */
6977 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
6980 /* Return the staus. */
6985 /*******************************************************************************
6987 ** gckOS_CreateUserSignal
6989 ** Create a new signal to be used in the user space.
6994 ** Pointer to an gckOS object.
6996 ** gctBOOL ManualReset
6997 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
6998 ** order to set the signal to nonsignaled state.
6999 ** If set to gcvFALSE, the signal will automatically be set to
7000 ** nonsignaled state by gckOS_WaitSignal function.
7004 ** gctINT * SignalID
7005 ** Pointer to a variable receiving the created signal's ID.
7008 gckOS_CreateUserSignal(
7010 IN gctBOOL ManualReset
,
7011 OUT gctINT
* SignalID
7014 gcsSIGNAL_PTR signal
= gcvNULL
;
7015 gctINT unused
, currentID
, tableLen
;
7019 gctBOOL acquired
= gcvFALSE
;
7021 gcmkHEADER_ARG("Os=0x%0x ManualReset=%d", Os
, ManualReset
);
7023 /* Verify the arguments. */
7024 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7025 gcmkVERIFY_ARGUMENT(SignalID
!= gcvNULL
);
7027 /* Lock the table. */
7028 gcmkONERROR(gckOS_AcquireMutex(Os
, Os
->signal
.lock
, gcvINFINITE
));
7032 if (Os
->signal
.unused
< 1)
7034 /* Enlarge the table. */
7035 table
= (gctPOINTER
*) kmalloc(
7036 sizeof(gctPOINTER
) * (Os
->signal
.tableLen
+ USER_SIGNAL_TABLE_LEN_INIT
),
7039 if (table
== gcvNULL
)
7041 /* Out of memory. */
7042 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
7045 memset(table
+ Os
->signal
.tableLen
, 0, sizeof(gctPOINTER
) * USER_SIGNAL_TABLE_LEN_INIT
);
7046 memcpy(table
, Os
->signal
.table
, sizeof(gctPOINTER
) * Os
->signal
.tableLen
);
7048 /* Release the old table. */
7049 kfree(Os
->signal
.table
);
7051 /* Update the table. */
7052 Os
->signal
.table
= table
;
7053 Os
->signal
.currentID
= Os
->signal
.tableLen
;
7054 Os
->signal
.tableLen
+= USER_SIGNAL_TABLE_LEN_INIT
;
7055 Os
->signal
.unused
+= USER_SIGNAL_TABLE_LEN_INIT
;
7058 table
= Os
->signal
.table
;
7059 currentID
= Os
->signal
.currentID
;
7060 tableLen
= Os
->signal
.tableLen
;
7061 unused
= Os
->signal
.unused
;
7063 /* Create a new signal. */
7065 gckOS_CreateSignal(Os
, ManualReset
, (gctSIGNAL
*) &signal
));
7067 /* Save the process ID. */
7068 signal
->process
= (gctHANDLE
) _GetProcessID();
7070 table
[currentID
] = signal
;
7072 /* Plus 1 to avoid gcvNULL claims. */
7073 *SignalID
= currentID
+ 1;
7075 /* Update the currentID. */
7078 for (i
= 0; i
< tableLen
; i
++)
7080 if (++currentID
>= tableLen
)
7082 /* Wrap to the begin. */
7086 if (table
[currentID
] == gcvNULL
)
7093 Os
->signal
.table
= table
;
7094 Os
->signal
.currentID
= currentID
;
7095 Os
->signal
.tableLen
= tableLen
;
7096 Os
->signal
.unused
= unused
;
7099 gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7101 gcmkFOOTER_ARG("*SignalID=%d", gcmOPT_VALUE(SignalID
));
7102 return gcvSTATUS_OK
;
7107 /* Release the mutex. */
7109 gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7112 /* Return the staus. */
7117 /*******************************************************************************
7119 ** gckOS_DestroyUserSignal
7121 ** Destroy a signal to be used in the user space.
7126 ** Pointer to an gckOS object.
7136 gckOS_DestroyUserSignal(
7142 gcsSIGNAL_PTR signal
;
7143 gctBOOL acquired
= gcvFALSE
;
7145 gcmkHEADER_ARG("Os=0x%X SignalID=%d", Os
, SignalID
);
7147 /* Verify the arguments. */
7148 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7151 gckOS_AcquireMutex(Os
, Os
->signal
.lock
, gcvINFINITE
));
7155 if (SignalID
< 1 || SignalID
> Os
->signal
.tableLen
)
7159 "%s(%d): invalid signal->%d.",
7160 __FUNCTION__
, __LINE__
,
7164 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
7169 signal
= Os
->signal
.table
[SignalID
];
7171 if (signal
== gcvNULL
)
7175 "%s(%d): signal is gcvNULL.",
7176 __FUNCTION__
, __LINE__
7179 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
7183 if (atomic_read(&signal
->ref
) == 1)
7185 /* Update the table. */
7186 Os
->signal
.table
[SignalID
] = gcvNULL
;
7188 if (Os
->signal
.unused
++ == 0)
7190 Os
->signal
.currentID
= SignalID
;
7195 gckOS_DestroySignal(Os
, signal
));
7198 gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7202 return gcvSTATUS_OK
;
7207 /* Release the mutex. */
7209 gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7212 /* Return the status. */
7217 /*******************************************************************************
7219 ** gckOS_WaitUserSignal
7221 ** Wait for a signal used in the user mode to become signaled.
7226 ** Pointer to an gckOS object.
7232 ** Number of milliseconds to wait.
7233 ** Pass the value of gcvINFINITE for an infinite wait.
7240 gckOS_WaitUserSignal(
7247 gcsSIGNAL_PTR signal
;
7248 gctBOOL acquired
= gcvFALSE
;
7250 gcmkHEADER_ARG("Os=0x%X SignalID=%d Wait=%u", Os
, SignalID
, Wait
);
7252 /* Verify the arguments. */
7253 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7255 gcmkONERROR(gckOS_AcquireMutex(Os
, Os
->signal
.lock
, gcvINFINITE
));
7258 if (SignalID
< 1 || SignalID
> Os
->signal
.tableLen
)
7262 "%s(%d): invalid signal %d",
7263 __FUNCTION__
, __LINE__
,
7267 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
7272 signal
= Os
->signal
.table
[SignalID
];
7274 gcmkONERROR(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7275 acquired
= gcvFALSE
;
7277 if (signal
== gcvNULL
)
7281 "%s(%d): signal is gcvNULL.",
7282 __FUNCTION__
, __LINE__
7285 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
7289 status
= gckOS_WaitSignal(Os
, signal
, Wait
);
7291 /* Return the status. */
7298 /* Release the mutex. */
7299 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7302 /* Return the staus. */
7307 /*******************************************************************************
7309 ** gckOS_SignalUserSignal
7311 ** Set a state of the specified signal to be used in the user space.
7316 ** Pointer to an gckOS object.
7322 ** If gcvTRUE, the signal will be set to signaled state.
7323 ** If gcvFALSE, the signal will be set to nonsignaled state.
7330 gckOS_SignalUserSignal(
7337 gcsSIGNAL_PTR signal
;
7338 gctBOOL acquired
= gcvFALSE
;
7340 gcmkHEADER_ARG("Os=0x%X SignalID=%d State=%d", Os
, SignalID
, State
);
7342 /* Verify the arguments. */
7343 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7345 gcmkONERROR(gckOS_AcquireMutex(Os
, Os
->signal
.lock
, gcvINFINITE
));
7349 || (SignalID
> Os
->signal
.tableLen
)
7354 "%s(%d): invalid signal->%d.",
7355 __FUNCTION__
, __LINE__
,
7359 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
7364 signal
= Os
->signal
.table
[SignalID
];
7366 gcmkONERROR(gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7367 acquired
= gcvFALSE
;
7369 if (signal
== gcvNULL
)
7373 "%s(%d): signal is gcvNULL.",
7374 __FUNCTION__
, __LINE__
7377 gcmkONERROR(gcvSTATUS_INVALID_REQUEST
);
7381 status
= gckOS_Signal(Os
, signal
, State
);
7390 /* Release the mutex. */
7392 gckOS_ReleaseMutex(Os
, Os
->signal
.lock
));
7395 /* Return the staus. */
7401 gckOS_CleanProcessSignal(
7408 gcmkHEADER_ARG("Os=0x%X Process=%d", Os
, Process
);
7410 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7412 gcmkVERIFY_OK(gckOS_AcquireMutex(Os
,
7417 if (Os
->signal
.unused
== Os
->signal
.tableLen
)
7419 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os
,
7424 return gcvSTATUS_OK
;
7427 for (signal
= 0; signal
< Os
->signal
.tableLen
; signal
++)
7429 if (Os
->signal
.table
[signal
] != gcvNULL
&&
7430 ((gcsSIGNAL_PTR
)Os
->signal
.table
[signal
])->process
== Process
)
7432 gckOS_DestroySignal(Os
, Os
->signal
.table
[signal
]);
7434 /* Update the signal table. */
7435 Os
->signal
.table
[signal
] = gcvNULL
;
7436 if (Os
->signal
.unused
++ == 0)
7438 Os
->signal
.currentID
= signal
;
7443 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os
,
7448 return gcvSTATUS_OK
;
7453 gckOS_CreateSemaphoreVG(
7455 OUT gctSEMAPHORE
* Semaphore
7459 struct semaphore
* newSemaphore
;
7461 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os
, Semaphore
);
7462 /* Verify the arguments. */
7463 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7464 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
7468 /* Allocate the semaphore structure. */
7469 newSemaphore
= (struct semaphore
*)kmalloc(gcmSIZEOF(struct semaphore
), GFP_KERNEL
);
7470 if (newSemaphore
== gcvNULL
)
7472 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY
);
7475 /* Initialize the semaphore. */
7476 sema_init(newSemaphore
, 0);
7478 /* Set the handle. */
7479 * Semaphore
= (gctSEMAPHORE
) newSemaphore
;
7482 status
= gcvSTATUS_OK
;
7487 /* Return the status. */
7493 gckOS_IncrementSemaphore(
7495 IN gctSEMAPHORE Semaphore
7498 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os
, Semaphore
);
7499 /* Verify the arguments. */
7500 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7501 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
7503 /* Increment the semaphore's count. */
7504 up((struct semaphore
*) Semaphore
);
7508 return gcvSTATUS_OK
;
7512 gckOS_DecrementSemaphore(
7514 IN gctSEMAPHORE Semaphore
7520 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os
, Semaphore
);
7521 /* Verify the arguments. */
7522 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7523 gcmkVERIFY_ARGUMENT(Semaphore
!= gcvNULL
);
7527 /* Decrement the semaphore's count. If the count is zero, wait
7528 until it gets incremented. */
7529 result
= down_interruptible((struct semaphore
*) Semaphore
);
7531 /* Signal received? */
7534 status
= gcvSTATUS_TERMINATE
;
7539 status
= gcvSTATUS_OK
;
7544 /* Return the status. */
7548 /*******************************************************************************
7552 ** Set the specified signal to signaled state.
7557 ** Pointer to the gckOS object.
7559 ** gctHANDLE Process
7560 ** Handle of process owning the signal.
7563 ** Pointer to the gctSIGNAL.
7572 IN gctHANDLE Process
,
7578 struct task_struct
* userTask
;
7579 struct siginfo info
;
7581 userTask
= FIND_TASK_BY_PID((pid_t
) Process
);
7583 if (userTask
!= gcvNULL
)
7586 info
.si_code
= __SI_CODE(__SI_RT
, SI_KERNEL
);
7589 info
.si_ptr
= (gctPOINTER
) Signal
;
7591 /* Signals with numbers between 32 and 63 are real-time,
7592 send a real-time signal to the user process. */
7593 result
= send_sig_info(48, &info
, userTask
);
7598 status
= gcvSTATUS_GENERIC_IO
;
7602 "%s(%d): an error has occurred.\n",
7603 __FUNCTION__
, __LINE__
7608 status
= gcvSTATUS_OK
;
7613 status
= gcvSTATUS_GENERIC_IO
;
7617 "%s(%d): an error has occurred.\n",
7618 __FUNCTION__
, __LINE__
7622 /* Return status. */
7626 /******************************************************************************\
7627 ******************************** Thread Object *********************************
7628 \******************************************************************************/
7633 IN gctTHREADFUNC ThreadFunction
,
7634 IN gctPOINTER ThreadParameter
,
7635 OUT gctTHREAD
* Thread
7639 struct task_struct
* thread
;
7641 gcmkHEADER_ARG("Os=0x%X ", Os
);
7642 /* Verify the arguments. */
7643 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7644 gcmkVERIFY_ARGUMENT(ThreadFunction
!= gcvNULL
);
7645 gcmkVERIFY_ARGUMENT(Thread
!= gcvNULL
);
7649 /* Create the thread. */
7650 thread
= kthread_create(
7653 "Vivante Kernel Thread"
7659 status
= gcvSTATUS_GENERIC_IO
;
7663 /* Start the thread. */
7664 wake_up_process(thread
);
7666 /* Set the thread handle. */
7667 * Thread
= (gctTHREAD
) thread
;
7670 status
= gcvSTATUS_OK
;
7675 /* Return the status. */
7685 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os
, Thread
);
7686 /* Verify the arguments. */
7687 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7688 gcmkVERIFY_ARGUMENT(Thread
!= gcvNULL
);
7690 /* Thread should have already been enabled to terminate. */
7691 kthread_stop((struct task_struct
*) Thread
);
7695 return gcvSTATUS_OK
;
7704 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os
, Thread
);
7705 /* Verify the arguments. */
7706 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
7707 gcmkVERIFY_ARGUMENT(Thread
!= gcvNULL
);
7711 return gcvSTATUS_OK
;