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_precomp.h"
26 #define _GC_OBJ_ZONE gcvZONE_KERNEL
28 /*******************************************************************************
29 ***** Version Signature *******************************************************/
31 #define _gcmTXT2STR(t) #t
32 #define gcmTXT2STR(t) _gcmTXT2STR(t)
33 const char * _VERSION
= "\n\0$VERSION$"
34 gcmTXT2STR(gcvVERSION_MAJOR
) "."
35 gcmTXT2STR(gcvVERSION_MINOR
) "."
36 gcmTXT2STR(gcvVERSION_PATCH
) ":"
37 gcmTXT2STR(gcvVERSION_BUILD
) "$\n";
39 /******************************************************************************\
40 ******************************* gckKERNEL API Code ******************************
41 \******************************************************************************/
43 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
44 #define gcmDEFINE2TEXT(d) #d
45 gctCONST_STRING _DispatchText
[] =
47 gcmDEFINE2TEXT(gcvHAL_QUERY_VIDEO_MEMORY
),
48 gcmDEFINE2TEXT(gcvHAL_QUERY_CHIP_IDENTITY
),
49 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_NON_PAGED_MEMORY
),
50 gcmDEFINE2TEXT(gcvHAL_FREE_NON_PAGED_MEMORY
),
51 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY
),
52 gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY
),
53 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY
),
54 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
),
55 gcmDEFINE2TEXT(gcvHAL_FREE_VIDEO_MEMORY
),
56 gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY
),
57 gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY
),
58 gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY
),
59 gcmDEFINE2TEXT(gcvHAL_UNMAP_USER_MEMORY
),
60 gcmDEFINE2TEXT(gcvHAL_LOCK_VIDEO_MEMORY
),
61 gcmDEFINE2TEXT(gcvHAL_UNLOCK_VIDEO_MEMORY
),
62 gcmDEFINE2TEXT(gcvHAL_EVENT_COMMIT
),
63 gcmDEFINE2TEXT(gcvHAL_USER_SIGNAL
),
64 gcmDEFINE2TEXT(gcvHAL_SIGNAL
),
65 gcmDEFINE2TEXT(gcvHAL_WRITE_DATA
),
66 gcmDEFINE2TEXT(gcvHAL_COMMIT
),
67 gcmDEFINE2TEXT(gcvHAL_STALL
),
68 gcmDEFINE2TEXT(gcvHAL_READ_REGISTER
),
69 gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER
),
70 gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING
),
71 gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING
),
72 gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS
),
73 gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D
),
74 gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE
),
75 gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE
),
76 gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS
),
77 gcmDEFINE2TEXT(gcvHAL_SET_IDLE
),
78 gcmDEFINE2TEXT(gcvHAL_QUERY_KERNEL_SETTINGS
),
79 gcmDEFINE2TEXT(gcvHAL_RESET
),
80 gcmDEFINE2TEXT(gcvHAL_MAP_PHYSICAL
),
81 gcmDEFINE2TEXT(gcvHAL_DEBUG
),
82 gcmDEFINE2TEXT(gcvHAL_CACHE
),
83 gcmDEFINE2TEXT(gcvHAL_TIMESTAMP
),
84 gcmDEFINE2TEXT(gcvHAL_DATABASE
),
85 gcmDEFINE2TEXT(gcvHAL_VERSION
),
86 gcmDEFINE2TEXT(gcvHAL_ATTACH
),
87 gcmDEFINE2TEXT(gcvHAL_DETACH
)
91 /*******************************************************************************
93 ** gckKERNEL_Construct
95 ** Construct a new gckKERNEL object.
100 ** Pointer to an gckOS object.
105 ** IN gctPOINTER Context
106 ** Pointer to a driver defined context.
108 ** IN gckDB SharedDB,
109 ** Pointer to a shared DB.
113 ** gckKERNEL * Kernel
114 ** Pointer to a variable that will hold the pointer to the gckKERNEL
118 #if gcdNEW_PROFILER_FILE
119 #define DEFAULT_PROFILE_FILE_NAME "/sdcard/vprofiler.vpd"
121 #define DEFAULT_PROFILE_FILE_NAME "/sdcard/vprofiler.xml"
124 #if gcdNEW_PROFILER_FILE
125 #define DEFAULT_PROFILE_FILE_NAME "vprofiler.vpd"
127 #define DEFAULT_PROFILE_FILE_NAME "vprofiler.xml"
135 IN gctPOINTER Context
,
137 OUT gckKERNEL
* Kernel
140 gckKERNEL kernel
= gcvNULL
;
143 gctPOINTER pointer
= gcvNULL
;
145 gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os
, Context
);
147 /* Verify the arguments. */
148 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
149 gcmkVERIFY_ARGUMENT(Kernel
!= gcvNULL
);
151 /* Allocate the gckKERNEL object. */
152 gcmkONERROR(gckOS_Allocate(Os
,
153 gcmSIZEOF(struct _gckKERNEL
),
158 /* Zero the object pointers. */
159 kernel
->hardware
= gcvNULL
;
160 kernel
->command
= gcvNULL
;
161 kernel
->eventObj
= gcvNULL
;
162 kernel
->mmu
= gcvNULL
;
164 if (SharedDB
== gcvNULL
)
166 gcmkONERROR(gckOS_Allocate(Os
,
167 gcmSIZEOF(struct _gckDB
),
170 kernel
->db
= pointer
;
171 kernel
->dbCreated
= gcvTRUE
;
172 kernel
->db
->freeDatabase
= gcvNULL
;
173 kernel
->db
->freeRecord
= gcvNULL
;
174 kernel
->db
->dbMutex
= gcvNULL
;
175 kernel
->db
->lastDatabase
= gcvNULL
;
176 kernel
->db
->idleTime
= 0;
177 kernel
->db
->lastIdle
= 0;
178 kernel
->db
->lastSlowdown
= 0;
180 for (i
= 0; i
< gcmCOUNTOF(kernel
->db
->db
); ++i
)
182 kernel
->db
->db
[i
] = gcvNULL
;
185 /* Construct a database mutex. */
186 gcmkONERROR(gckOS_CreateMutex(Os
, &kernel
->db
->dbMutex
));
190 kernel
->db
= SharedDB
;
191 kernel
->dbCreated
= gcvFALSE
;
194 for (i
= 0; i
< gcmCOUNTOF(kernel
->timers
); ++i
)
196 kernel
->timers
[i
].startTime
= 0;
197 kernel
->timers
[i
].stopTime
= 0;
200 kernel
->timeOut
= gcdGPU_TIMEOUT
;
202 /* Initialize the gckKERNEL object. */
203 kernel
->object
.type
= gcvOBJ_KERNEL
;
208 kernel
->context
= Context
;
210 /* Construct atom holding number of clients. */
211 kernel
->atomClients
= gcvNULL
;
212 gcmkONERROR(gckOS_AtomConstruct(Os
, &kernel
->atomClients
));
215 kernel
->vg
= gcvNULL
;
217 if (Core
== gcvCORE_VG
)
219 /* Construct the gckMMU object. */
221 gckVGKERNEL_Construct(Os
, Context
, kernel
, &kernel
->vg
));
226 /* Construct the gckHARDWARE object. */
228 gckHARDWARE_Construct(Os
, kernel
->core
, &kernel
->hardware
));
230 /* Set pointer to gckKERNEL object in gckHARDWARE object. */
231 kernel
->hardware
->kernel
= kernel
;
233 /* Initialize the hardware. */
235 gckHARDWARE_InitializeHardware(kernel
->hardware
));
237 /* Construct the gckCOMMAND object. */
239 gckCOMMAND_Construct(kernel
, &kernel
->command
));
241 /* Construct the gckEVENT object. */
243 gckEVENT_Construct(kernel
, &kernel
->eventObj
));
245 /* Construct the gckMMU object. */
247 gckMMU_Construct(kernel
, gcdMMU_SIZE
, &kernel
->mmu
));
251 /* Initialize profile setting */
253 kernel
->profileEnable
= gcvFALSE
;
255 kernel
->profileEnable
= gcvTRUE
;
259 gckOS_MemCopy(kernel
->profileFileName
,
260 DEFAULT_PROFILE_FILE_NAME
,
261 gcmSIZEOF(DEFAULT_PROFILE_FILE_NAME
) + 1));
264 /* Return pointer to the gckKERNEL object. */
268 gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel
);
272 if (kernel
!= gcvNULL
)
275 if (Core
!= gcvCORE_VG
)
278 if (kernel
->eventObj
!= gcvNULL
)
280 gcmkVERIFY_OK(gckEVENT_Destroy(kernel
->eventObj
));
283 if (kernel
->command
!= gcvNULL
)
285 gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel
->command
));
288 if (kernel
->hardware
!= gcvNULL
)
290 gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel
->hardware
));
294 if (kernel
->atomClients
!= gcvNULL
)
296 gcmkVERIFY_OK(gckOS_AtomDestroy(Os
, kernel
->atomClients
));
299 if (kernel
->dbCreated
&& kernel
->db
!= gcvNULL
)
301 if (kernel
->db
->dbMutex
!= gcvNULL
)
303 /* Destroy the database mutex. */
304 gcmkVERIFY_OK(gckOS_DeleteMutex(Os
, kernel
->db
->dbMutex
));
307 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os
, kernel
->db
));
310 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os
, kernel
));
313 /* Return the error. */
318 /*******************************************************************************
322 ** Destroy an gckKERNEL object.
327 ** Pointer to an gckKERNEL object to destroy.
339 gcsDATABASE_PTR database
, databaseNext
;
340 gcsDATABASE_RECORD_PTR record
, recordNext
;
342 gcmkHEADER_ARG("Kernel=0x%x", Kernel
);
344 /* Verify the arguments. */
345 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
346 #if QNX_SINGLE_THREADED_DEBUGGING
347 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel
->os
, Kernel
->debugMutex
));
350 /* Destroy the database. */
351 if (Kernel
->dbCreated
)
353 for (i
= 0; i
< gcmCOUNTOF(Kernel
->db
->db
); ++i
)
355 if (Kernel
->db
->db
[i
] != gcvNULL
)
358 gckKERNEL_DestroyProcessDB(Kernel
, Kernel
->db
->db
[i
]->processID
));
362 /* Free all databases. */
363 for (database
= Kernel
->db
->freeDatabase
;
365 database
= databaseNext
)
367 databaseNext
= database
->next
;
368 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel
->os
, database
));
371 if (Kernel
->db
->lastDatabase
!= gcvNULL
)
373 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel
->os
, Kernel
->db
->lastDatabase
));
376 /* Free all database records. */
377 for (record
= Kernel
->db
->freeRecord
; record
!= gcvNULL
; record
= recordNext
)
379 recordNext
= record
->next
;
380 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel
->os
, record
));
383 /* Destroy the database mutex. */
384 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
390 gcmkVERIFY_OK(gckVGKERNEL_Destroy(Kernel
->vg
));
395 /* Destroy the gckMMU object. */
396 gcmkVERIFY_OK(gckMMU_Destroy(Kernel
->mmu
));
398 /* Destroy the gckCOMMNAND object. */
399 gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel
->command
));
401 /* Destroy the gckEVENT object. */
402 gcmkVERIFY_OK(gckEVENT_Destroy(Kernel
->eventObj
));
404 /* Destroy the gckHARDWARE object. */
405 gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel
->hardware
));
408 /* Detsroy the client atom. */
409 gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel
->os
, Kernel
->atomClients
));
411 /* Mark the gckKERNEL object as unknown. */
412 Kernel
->object
.type
= gcvOBJ_UNKNOWN
;
414 /* Free the gckKERNEL object. */
415 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel
->os
, Kernel
));
423 /*******************************************************************************
427 ** Private function to walk all required memory pools to allocate the requested
428 ** amount of video memory.
433 ** Pointer to an gckKERNEL object.
435 ** gcsHAL_INTERFACE * Interface
436 ** Pointer to a gcsHAL_INTERFACE structure that defines the command to
441 ** gcsHAL_INTERFACE * Interface
442 ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
448 IN OUT gcePOOL
* Pool
,
450 IN gctSIZE_T Alignment
,
451 IN gceSURF_TYPE Type
,
452 OUT gcuVIDMEM_NODE_PTR
* Node
457 gckVIDMEM videoMemory
;
459 gcuVIDMEM_NODE_PTR node
= gcvNULL
;
461 gcmkHEADER_ARG("Kernel=0x%x *Pool=%d Bytes=%lu Alignment=%lu Type=%d",
462 Kernel
, *Pool
, Bytes
, Alignment
, Type
);
464 gcmkVERIFY_ARGUMENT(Pool
!= gcvNULL
);
466 /* Get initial pool. */
467 switch (pool
= *Pool
)
469 case gcvPOOL_DEFAULT
:
471 pool
= gcvPOOL_LOCAL_INTERNAL
;
472 loopCount
= (gctINT
) gcvPOOL_NUMBER_OF_POOLS
;
475 case gcvPOOL_UNIFIED
:
476 pool
= gcvPOOL_SYSTEM
;
477 loopCount
= (gctINT
) gcvPOOL_NUMBER_OF_POOLS
;
480 case gcvPOOL_CONTIGUOUS
:
481 loopCount
= (gctINT
) gcvPOOL_NUMBER_OF_POOLS
;
489 /* Verify the number of bytes to allocate. */
492 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
495 while (loopCount
-- > 0)
497 if (pool
== gcvPOOL_VIRTUAL
)
499 /* Create a gcuVIDMEM_NODE for virtual memory. */
501 gckVIDMEM_ConstructVirtual(Kernel
, gcvFALSE
, Bytes
, &node
));
508 if (pool
== gcvPOOL_CONTIGUOUS
)
510 /* Create a gcuVIDMEM_NODE for contiguous memory. */
511 status
= gckVIDMEM_ConstructVirtual(Kernel
, gcvTRUE
, Bytes
, &node
);
512 if (gcmIS_SUCCESS(status
))
514 /* Memory allocated. */
521 /* Get pointer to gckVIDMEM object for pool. */
522 #if gcdUSE_VIDMEM_PER_PID
524 gckOS_GetProcessID(&pid
);
526 status
= gckKERNEL_GetVideoMemoryPoolPid(Kernel
, pool
, pid
, &videoMemory
);
527 if (status
== gcvSTATUS_NOT_FOUND
)
529 /* Create VidMem pool for this process. */
530 status
= gckKERNEL_CreateVideoMemoryPoolPid(Kernel
, pool
, pid
, &videoMemory
);
533 status
= gckKERNEL_GetVideoMemoryPool(Kernel
, pool
, &videoMemory
);
536 if (gcmIS_SUCCESS(status
))
538 /* Allocate memory. */
539 status
= gckVIDMEM_AllocateLinear(videoMemory
,
545 if (gcmIS_SUCCESS(status
))
547 /* Memory allocated. */
548 node
->VidMem
.pool
= pool
;
554 if (pool
== gcvPOOL_LOCAL_INTERNAL
)
556 /* Advance to external memory. */
557 pool
= gcvPOOL_LOCAL_EXTERNAL
;
561 if (pool
== gcvPOOL_LOCAL_EXTERNAL
)
563 /* Advance to contiguous system memory. */
564 pool
= gcvPOOL_SYSTEM
;
568 if (pool
== gcvPOOL_SYSTEM
)
570 /* Advance to contiguous memory. */
571 pool
= gcvPOOL_CONTIGUOUS
;
575 if ((pool
== gcvPOOL_CONTIGUOUS
)
576 && (Type
!= gcvSURF_TILE_STATUS
)
579 /* Advance to virtual memory. */
580 pool
= gcvPOOL_VIRTUAL
;
586 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
592 /* Nothing allocated. */
593 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
597 /* Return node and pool used for allocation. */
602 gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool
, *Node
);
606 /* Return the status. */
611 /*******************************************************************************
613 ** gckKERNEL_Dispatch
615 ** Dispatch a command received from the user HAL layer.
620 ** Pointer to an gckKERNEL object.
623 ** whether the call is from the user space.
625 ** gcsHAL_INTERFACE * Interface
626 ** Pointer to a gcsHAL_INTERFACE structure that defines the command to
631 ** gcsHAL_INTERFACE * Interface
632 ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
640 IN OUT gcsHAL_INTERFACE
* Interface
643 gceSTATUS status
= gcvSTATUS_OK
;
644 gctUINT32 bitsPerPixel
;
646 gcuVIDMEM_NODE_PTR node
;
647 gctBOOL locked
= gcvFALSE
;
648 gctPHYS_ADDR physical
= gcvNULL
;
652 gcskSECURE_CACHE_PTR cache
;
655 gctBOOL asynchronous
;
656 gctPOINTER paddr
= gcvNULL
;
657 #if !USE_NEW_LINUX_SIGNAL
661 gcsDATABASE_RECORD record
;
664 gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
665 Kernel
, FromUser
, Interface
);
667 /* Verify the arguments. */
668 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
669 gcmkVERIFY_ARGUMENT(Interface
!= gcvNULL
);
671 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
672 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_KERNEL
,
673 "Dispatching command %d (%s)",
674 Interface
->command
, _DispatchText
[Interface
->command
]);
676 #if QNX_SINGLE_THREADED_DEBUGGING
677 gckOS_AcquireMutex(Kernel
->os
, Kernel
->debugMutex
, gcvINFINITE
);
680 /* Get the current process ID. */
681 gcmkONERROR(gckOS_GetProcessID(&processID
));
686 gcmkONERROR(gckOS_GetCurrentProcessID(&processID
));
691 gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel
, processID
, &cache
));
694 /* Dispatch on command. */
695 switch (Interface
->command
)
697 case gcvHAL_GET_BASE_ADDRESS
:
698 /* Get base address. */
700 gckOS_GetBaseAddress(Kernel
->os
,
701 &Interface
->u
.GetBaseAddress
.baseAddress
));
704 case gcvHAL_QUERY_VIDEO_MEMORY
:
705 /* Query video memory size. */
706 gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel
, Interface
));
709 case gcvHAL_QUERY_CHIP_IDENTITY
:
710 /* Query chip identity. */
712 gckHARDWARE_QueryChipIdentity(
714 &Interface
->u
.QueryChipIdentity
.chipModel
,
715 &Interface
->u
.QueryChipIdentity
.chipRevision
,
716 &Interface
->u
.QueryChipIdentity
.chipFeatures
,
717 &Interface
->u
.QueryChipIdentity
.chipMinorFeatures
,
718 &Interface
->u
.QueryChipIdentity
.chipMinorFeatures1
,
719 &Interface
->u
.QueryChipIdentity
.chipMinorFeatures2
,
720 &Interface
->u
.QueryChipIdentity
.chipMinorFeatures3
));
722 /* Query chip specifications. */
724 gckHARDWARE_QueryChipSpecs(
726 &Interface
->u
.QueryChipIdentity
.streamCount
,
727 &Interface
->u
.QueryChipIdentity
.registerMax
,
728 &Interface
->u
.QueryChipIdentity
.threadCount
,
729 &Interface
->u
.QueryChipIdentity
.shaderCoreCount
,
730 &Interface
->u
.QueryChipIdentity
.vertexCacheSize
,
731 &Interface
->u
.QueryChipIdentity
.vertexOutputBufferSize
,
732 &Interface
->u
.QueryChipIdentity
.pixelPipes
,
733 &Interface
->u
.QueryChipIdentity
.instructionCount
,
734 &Interface
->u
.QueryChipIdentity
.numConstants
,
735 &Interface
->u
.QueryChipIdentity
.bufferSize
));
738 case gcvHAL_MAP_MEMORY
:
739 physical
= Interface
->u
.MapMemory
.physical
;
743 gckKERNEL_MapMemory(Kernel
,
745 Interface
->u
.MapMemory
.bytes
,
746 &Interface
->u
.MapMemory
.logical
));
748 gckKERNEL_AddProcessDB(Kernel
,
749 processID
, gcvDB_MAP_MEMORY
,
750 Interface
->u
.MapMemory
.logical
,
752 Interface
->u
.MapMemory
.bytes
));
755 case gcvHAL_UNMAP_MEMORY
:
756 physical
= Interface
->u
.UnmapMemory
.physical
;
760 gckKERNEL_UnmapMemory(Kernel
,
762 Interface
->u
.UnmapMemory
.bytes
,
763 Interface
->u
.UnmapMemory
.logical
));
765 gckKERNEL_RemoveProcessDB(Kernel
,
766 processID
, gcvDB_MAP_MEMORY
,
767 Interface
->u
.UnmapMemory
.logical
));
770 case gcvHAL_ALLOCATE_NON_PAGED_MEMORY
:
771 /* Allocate non-paged memory. */
773 gckOS_AllocateNonPagedMemory(
776 &Interface
->u
.AllocateNonPagedMemory
.bytes
,
777 &Interface
->u
.AllocateNonPagedMemory
.physical
,
778 &Interface
->u
.AllocateNonPagedMemory
.logical
));
781 gckKERNEL_AddProcessDB(Kernel
,
782 processID
, gcvDB_NON_PAGED
,
783 Interface
->u
.AllocateNonPagedMemory
.logical
,
784 Interface
->u
.AllocateNonPagedMemory
.physical
,
785 Interface
->u
.AllocateNonPagedMemory
.bytes
));
788 case gcvHAL_FREE_NON_PAGED_MEMORY
:
789 physical
= Interface
->u
.FreeNonPagedMemory
.physical
;
791 /* Free non-paged memory. */
793 gckOS_FreeNonPagedMemory(Kernel
->os
,
794 Interface
->u
.FreeNonPagedMemory
.bytes
,
796 Interface
->u
.FreeNonPagedMemory
.logical
));
799 gckKERNEL_RemoveProcessDB(Kernel
,
800 processID
, gcvDB_NON_PAGED
,
801 Interface
->u
.FreeNonPagedMemory
.logical
));
804 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
807 Interface
->u
.FreeNonPagedMemory
.logical
,
808 Interface
->u
.FreeNonPagedMemory
.bytes
));
812 case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY
:
813 /* Allocate contiguous memory. */
814 gcmkONERROR(gckOS_AllocateContiguous(
817 &Interface
->u
.AllocateContiguousMemory
.bytes
,
818 &Interface
->u
.AllocateContiguousMemory
.physical
,
819 &Interface
->u
.AllocateContiguousMemory
.logical
));
821 gcmkONERROR(gckHARDWARE_ConvertLogical(
823 Interface
->u
.AllocateContiguousMemory
.logical
,
824 &Interface
->u
.AllocateContiguousMemory
.address
));
826 gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
828 processID
, gcvDB_CONTIGUOUS
,
829 Interface
->u
.AllocateContiguousMemory
.logical
,
830 Interface
->u
.AllocateContiguousMemory
.physical
,
831 Interface
->u
.AllocateContiguousMemory
.bytes
));
834 case gcvHAL_FREE_CONTIGUOUS_MEMORY
:
835 physical
= Interface
->u
.FreeContiguousMemory
.physical
;
837 /* Free contiguous memory. */
839 gckOS_FreeContiguous(Kernel
->os
,
841 Interface
->u
.FreeContiguousMemory
.logical
,
842 Interface
->u
.FreeContiguousMemory
.bytes
));
845 gckKERNEL_RemoveProcessDB(Kernel
,
846 processID
, gcvDB_CONTIGUOUS
,
847 Interface
->u
.FreeNonPagedMemory
.logical
));
850 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
853 Interface
->u
.FreeContiguousMemory
.logical
,
854 Interface
->u
.FreeContiguousMemory
.bytes
));
858 case gcvHAL_ALLOCATE_VIDEO_MEMORY
:
859 /* Align width and height to tiles. */
861 gckHARDWARE_AlignToTile(Kernel
->hardware
,
862 Interface
->u
.AllocateVideoMemory
.type
,
863 &Interface
->u
.AllocateVideoMemory
.width
,
864 &Interface
->u
.AllocateVideoMemory
.height
,
867 /* Convert format into bytes per pixel and bytes per tile. */
869 gckHARDWARE_ConvertFormat(Kernel
->hardware
,
870 Interface
->u
.AllocateVideoMemory
.format
,
874 /* Compute number of bytes for the allocation. */
875 bytes
= Interface
->u
.AllocateVideoMemory
.width
* bitsPerPixel
876 * Interface
->u
.AllocateVideoMemory
.height
877 * Interface
->u
.AllocateVideoMemory
.depth
/ 8;
879 /* Allocate memory. */
881 _AllocateMemory(Kernel
,
882 &Interface
->u
.AllocateVideoMemory
.pool
,
885 Interface
->u
.AllocateVideoMemory
.type
,
886 &Interface
->u
.AllocateVideoMemory
.node
));
888 /* Get actual size of node. */
889 node
= Interface
->u
.AllocateLinearVideoMemory
.node
;
890 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
892 bytes
= node
->VidMem
.bytes
;
896 bytes
= node
->Virtual
.bytes
;
900 gckKERNEL_AddProcessDB(Kernel
,
901 processID
, gcvDB_VIDEO_MEMORY
,
902 Interface
->u
.AllocateVideoMemory
.node
,
907 case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
:
908 /* Allocate memory. */
910 _AllocateMemory(Kernel
,
911 &Interface
->u
.AllocateLinearVideoMemory
.pool
,
912 Interface
->u
.AllocateLinearVideoMemory
.bytes
,
913 Interface
->u
.AllocateLinearVideoMemory
.alignment
,
914 Interface
->u
.AllocateLinearVideoMemory
.type
,
915 &Interface
->u
.AllocateLinearVideoMemory
.node
));
917 /* Get actual size of node. */
918 node
= Interface
->u
.AllocateLinearVideoMemory
.node
;
919 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
921 bytes
= node
->VidMem
.bytes
;
925 bytes
= node
->Virtual
.bytes
;
929 gckKERNEL_AddProcessDB(Kernel
,
930 processID
, gcvDB_VIDEO_MEMORY
,
931 Interface
->u
.AllocateLinearVideoMemory
.node
,
936 case gcvHAL_FREE_VIDEO_MEMORY
:
938 node
= Interface
->u
.FreeVideoMemory
.node
;
939 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
940 && node
->VidMem
.logical
!= gcvNULL
)
943 gckKERNEL_UnmapVideoMemory(Kernel
,
944 node
->VidMem
.logical
,
946 node
->VidMem
.bytes
));
947 node
->VidMem
.logical
= gcvNULL
;
950 /* Free video memory. */
952 gckVIDMEM_Free(Interface
->u
.FreeVideoMemory
.node
));
955 gckKERNEL_RemoveProcessDB(Kernel
,
956 processID
, gcvDB_VIDEO_MEMORY
,
957 Interface
->u
.FreeVideoMemory
.node
));
960 case gcvHAL_LOCK_VIDEO_MEMORY
:
961 /* Lock video memory. */
963 gckVIDMEM_Lock(Kernel
,
964 Interface
->u
.LockVideoMemory
.node
,
965 Interface
->u
.LockVideoMemory
.cacheable
,
966 &Interface
->u
.LockVideoMemory
.address
));
970 node
= Interface
->u
.LockVideoMemory
.node
;
971 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
973 /* Map video memory address into user space. */
975 if (node
->VidMem
.logical
== gcvNULL
)
978 gckKERNEL_MapVideoMemory(Kernel
,
980 Interface
->u
.LockVideoMemory
.address
,
983 &node
->VidMem
.logical
));
985 gcmkASSERT(node
->VidMem
.logical
!= gcvNULL
);
987 Interface
->u
.LockVideoMemory
.memory
= node
->VidMem
.logical
;
990 gckKERNEL_MapVideoMemory(Kernel
,
992 Interface
->u
.LockVideoMemory
.address
,
993 &Interface
->u
.LockVideoMemory
.memory
));
994 gckOS_ZeroMemory(Interface
->u
.LockVideoMemory
.memory
, node
->VidMem
.bytes
);
999 Interface
->u
.LockVideoMemory
.memory
= node
->Virtual
.logical
;
1002 status
= gcvSTATUS_OK
;
1006 /* Return logical address as physical address. */
1007 Interface
->u
.LockVideoMemory
.address
=
1008 gcmPTR2INT(Interface
->u
.LockVideoMemory
.memory
);
1011 gckKERNEL_AddProcessDB(Kernel
,
1012 processID
, gcvDB_VIDEO_MEMORY_LOCKED
,
1013 Interface
->u
.LockVideoMemory
.node
,
1019 case gcvHAL_UNLOCK_VIDEO_MEMORY
:
1020 /* Unlock video memory. */
1021 node
= Interface
->u
.UnlockVideoMemory
.node
;
1024 /* Save node information before it disappears. */
1025 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
1032 logical
= node
->Virtual
.logical
;
1033 bytes
= node
->Virtual
.bytes
;
1037 /* Unlock video memory. */
1039 gckVIDMEM_Unlock(Kernel
,
1041 Interface
->u
.UnlockVideoMemory
.type
,
1042 &Interface
->u
.UnlockVideoMemory
.asynchroneous
));
1045 /* Flush the translation cache for virtual surfaces. */
1046 if (logical
!= gcvNULL
)
1048 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel
,
1054 if (Interface
->u
.UnlockVideoMemory
.asynchroneous
== gcvFALSE
)
1056 /* There isn't a event to unlock this node, remove record now */
1058 gckKERNEL_RemoveProcessDB(Kernel
,
1059 processID
, gcvDB_VIDEO_MEMORY_LOCKED
,
1060 Interface
->u
.UnlockVideoMemory
.node
));
1065 case gcvHAL_EVENT_COMMIT
:
1066 /* Commit an event queue. */
1068 gckEVENT_Commit(Kernel
->eventObj
,
1069 Interface
->u
.Event
.queue
));
1073 /* Commit a command and context buffer. */
1075 gckCOMMAND_Commit(Kernel
->command
,
1076 Interface
->u
.Commit
.context
,
1077 Interface
->u
.Commit
.commandBuffer
,
1078 Interface
->u
.Commit
.delta
,
1079 Interface
->u
.Commit
.queue
,
1084 /* Stall the command queue. */
1085 gcmkONERROR(gckCOMMAND_Stall(Kernel
->command
, gcvFALSE
));
1088 case gcvHAL_MAP_USER_MEMORY
:
1089 /* Map user memory to DMA. */
1091 gckOS_MapUserMemoryEx(Kernel
->os
,
1093 Interface
->u
.MapUserMemory
.memory
,
1094 Interface
->u
.MapUserMemory
.size
,
1095 &Interface
->u
.MapUserMemory
.info
,
1096 &Interface
->u
.MapUserMemory
.address
));
1098 gckKERNEL_AddProcessDB(Kernel
,
1099 processID
, gcvDB_MAP_USER_MEMORY
,
1100 Interface
->u
.MapUserMemory
.memory
,
1101 Interface
->u
.MapUserMemory
.info
,
1102 Interface
->u
.MapUserMemory
.size
));
1105 case gcvHAL_UNMAP_USER_MEMORY
:
1106 address
= Interface
->u
.MapUserMemory
.address
;
1108 /* Unmap user memory. */
1110 gckOS_UnmapUserMemoryEx(Kernel
->os
,
1112 Interface
->u
.UnmapUserMemory
.memory
,
1113 Interface
->u
.UnmapUserMemory
.size
,
1114 Interface
->u
.UnmapUserMemory
.info
,
1118 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
1121 Interface
->u
.UnmapUserMemory
.memory
,
1122 Interface
->u
.UnmapUserMemory
.size
));
1125 gckKERNEL_RemoveProcessDB(Kernel
,
1126 processID
, gcvDB_MAP_USER_MEMORY
,
1127 Interface
->u
.UnmapUserMemory
.memory
));
1130 #if !USE_NEW_LINUX_SIGNAL
1131 case gcvHAL_USER_SIGNAL
:
1132 /* Dispatch depends on the user signal subcommands. */
1133 switch(Interface
->u
.UserSignal
.command
)
1135 case gcvUSER_SIGNAL_CREATE
:
1136 /* Create a signal used in the user space. */
1138 gckOS_CreateUserSignal(Kernel
->os
,
1139 Interface
->u
.UserSignal
.manualReset
,
1140 &Interface
->u
.UserSignal
.id
));
1143 gckKERNEL_AddProcessDB(Kernel
,
1144 processID
, gcvDB_SIGNAL
,
1145 gcmINT2PTR(Interface
->u
.UserSignal
.id
),
1150 case gcvUSER_SIGNAL_DESTROY
:
1151 /* Destroy the signal. */
1153 gckOS_DestroyUserSignal(Kernel
->os
,
1154 Interface
->u
.UserSignal
.id
));
1156 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
1158 processID
, gcvDB_SIGNAL
,
1159 gcmINT2PTR(Interface
->u
.UserSignal
.id
)));
1162 case gcvUSER_SIGNAL_SIGNAL
:
1163 /* Signal the signal. */
1165 gckOS_SignalUserSignal(Kernel
->os
,
1166 Interface
->u
.UserSignal
.id
,
1167 Interface
->u
.UserSignal
.state
));
1170 case gcvUSER_SIGNAL_WAIT
:
1171 /* Wait on the signal. */
1172 status
= gckOS_WaitUserSignal(Kernel
->os
,
1173 Interface
->u
.UserSignal
.id
,
1174 Interface
->u
.UserSignal
.wait
);
1177 case gcvUSER_SIGNAL_MAP
:
1179 gckOS_MapSignal(Kernel
->os
,
1180 (gctSIGNAL
)Interface
->u
.UserSignal
.id
,
1181 (gctHANDLE
)processID
,
1185 gckKERNEL_AddProcessDB(Kernel
,
1186 processID
, gcvDB_SIGNAL
,
1187 gcmINT2PTR(Interface
->u
.UserSignal
.id
),
1192 case gcvUSER_SIGNAL_UNMAP
:
1193 /* Destroy the signal. */
1195 gckOS_DestroyUserSignal(Kernel
->os
,
1196 Interface
->u
.UserSignal
.id
));
1198 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
1200 processID
, gcvDB_SIGNAL
,
1201 gcmINT2PTR(Interface
->u
.UserSignal
.id
)));
1205 /* Invalid user signal command. */
1206 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
1211 case gcvHAL_SET_POWER_MANAGEMENT_STATE
:
1212 /* Set the power management state. */
1214 gckHARDWARE_SetPowerManagementState(
1216 Interface
->u
.SetPowerManagement
.state
));
1219 case gcvHAL_QUERY_POWER_MANAGEMENT_STATE
:
1220 /* Chip is not idle. */
1221 Interface
->u
.QueryPowerManagement
.isIdle
= gcvFALSE
;
1223 /* Query the power management state. */
1224 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
1226 &Interface
->u
.QueryPowerManagement
.state
));
1228 /* Query the idle state. */
1230 gckHARDWARE_QueryIdle(Kernel
->hardware
,
1231 &Interface
->u
.QueryPowerManagement
.isIdle
));
1234 case gcvHAL_READ_REGISTER
:
1235 #if gcdREGISTER_ACCESS_FROM_USER
1237 gceCHIPPOWERSTATE power
;
1238 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel
->hardware
,
1241 if (power
== gcvPOWER_ON
)
1243 /* Read a register. */
1244 gcmkONERROR(gckOS_ReadRegisterEx(
1247 Interface
->u
.ReadRegisterData
.address
,
1248 &Interface
->u
.ReadRegisterData
.data
));
1252 /* Chip is in power-state. */
1253 Interface
->u
.ReadRegisterData
.data
= 0;
1254 status
= gcvSTATUS_CHIP_NOT_READY
;
1258 /* No access from user land to read registers. */
1259 Interface
->u
.ReadRegisterData
.data
= 0;
1260 status
= gcvSTATUS_NOT_SUPPORTED
;
1264 case gcvHAL_WRITE_REGISTER
:
1265 #if gcdREGISTER_ACCESS_FROM_USER
1266 /* Write a register. */
1268 gckOS_WriteRegisterEx(Kernel
->os
,
1270 Interface
->u
.WriteRegisterData
.address
,
1271 Interface
->u
.WriteRegisterData
.data
));
1273 /* No access from user land to write registers. */
1274 status
= gcvSTATUS_NOT_SUPPORTED
;
1278 case gcvHAL_READ_ALL_PROFILE_REGISTERS
:
1279 #if VIVANTE_PROFILER
1280 /* Read all 3D profile registers. */
1282 gckHARDWARE_QueryProfileRegisters(
1284 &Interface
->u
.RegisterProfileData
.counters
));
1286 status
= gcvSTATUS_OK
;
1290 case gcvHAL_PROFILE_REGISTERS_2D
:
1291 #if VIVANTE_PROFILER
1292 /* Read all 2D profile registers. */
1294 gckHARDWARE_ProfileEngine2D(
1296 Interface
->u
.RegisterProfileData2D
.hwProfile2D
));
1298 status
= gcvSTATUS_OK
;
1302 case gcvHAL_GET_PROFILE_SETTING
:
1303 #if VIVANTE_PROFILER
1304 /* Get profile setting */
1305 Interface
->u
.GetProfileSetting
.enable
= Kernel
->profileEnable
;
1308 gckOS_MemCopy(Interface
->u
.GetProfileSetting
.fileName
,
1309 Kernel
->profileFileName
,
1310 gcdMAX_PROFILE_FILE_NAME
));
1313 status
= gcvSTATUS_OK
;
1316 case gcvHAL_SET_PROFILE_SETTING
:
1317 #if VIVANTE_PROFILER
1318 /* Set profile setting */
1319 Kernel
->profileEnable
= Interface
->u
.SetProfileSetting
.enable
;
1322 gckOS_MemCopy(Kernel
->profileFileName
,
1323 Interface
->u
.SetProfileSetting
.fileName
,
1324 gcdMAX_PROFILE_FILE_NAME
));
1327 status
= gcvSTATUS_OK
;
1330 case gcvHAL_QUERY_KERNEL_SETTINGS
:
1331 /* Get kernel settings. */
1333 gckKERNEL_QuerySettings(Kernel
,
1334 &Interface
->u
.QueryKernelSettings
.settings
));
1338 /* Reset the hardware. */
1340 gckHARDWARE_Reset(Kernel
->hardware
));
1344 /* Set debug level and zones. */
1345 if (Interface
->u
.Debug
.set
)
1347 gckOS_SetDebugLevel(Interface
->u
.Debug
.level
);
1348 gckOS_SetDebugZones(Interface
->u
.Debug
.zones
,
1349 Interface
->u
.Debug
.enable
);
1352 if (Interface
->u
.Debug
.message
[0] != '\0')
1354 /* Print a message to the debugger. */
1355 if (Interface
->u
.Debug
.type
== gcvMESSAGE_TEXT
)
1357 gckOS_CopyPrint(Interface
->u
.Debug
.message
);
1361 gckOS_DumpBuffer(Kernel
->os
,
1362 Interface
->u
.Debug
.message
,
1363 Interface
->u
.Debug
.messageSize
,
1364 gceDUMP_BUFFER_FROM_USER
,
1368 status
= gcvSTATUS_OK
;
1372 if (Interface
->u
.Cache
.node
== gcvNULL
)
1374 /* FIXME Surface wrap some memory which is not allocated by us,
1375 ** So we don't have physical address to handle outer cache, ignore it*/
1376 status
= gcvSTATUS_OK
;
1379 else if (Interface
->u
.Cache
.node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
1381 /* Video memory has no physical handles. */
1386 /* Grab physical handle. */
1387 physical
= Interface
->u
.Cache
.node
->Virtual
.physical
;
1390 switch(Interface
->u
.Cache
.operation
)
1392 case gcvCACHE_FLUSH
:
1393 /* Clean and invalidate the cache. */
1394 status
= gckOS_CacheFlush(Kernel
->os
,
1398 Interface
->u
.Cache
.logical
,
1399 Interface
->u
.Cache
.bytes
);
1401 case gcvCACHE_CLEAN
:
1402 /* Clean the cache. */
1403 status
= gckOS_CacheClean(Kernel
->os
,
1407 Interface
->u
.Cache
.logical
,
1408 Interface
->u
.Cache
.bytes
);
1410 case gcvCACHE_INVALIDATE
:
1411 /* Invalidate the cache. */
1412 status
= gckOS_CacheInvalidate(Kernel
->os
,
1416 Interface
->u
.Cache
.logical
,
1417 Interface
->u
.Cache
.bytes
);
1420 status
= gcvSTATUS_INVALID_ARGUMENT
;
1425 case gcvHAL_TIMESTAMP
:
1426 /* Check for invalid timer. */
1427 if ((Interface
->u
.TimeStamp
.timer
>= gcmCOUNTOF(Kernel
->timers
))
1428 || (Interface
->u
.TimeStamp
.request
!= 2))
1430 Interface
->u
.TimeStamp
.timeDelta
= 0;
1431 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
1434 /* Return timer results and reset timer. */
1436 gcsTIMER_PTR timer
= &(Kernel
->timers
[Interface
->u
.TimeStamp
.timer
]);
1437 gctUINT64 timeDelta
= 0;
1439 if (timer
->stopTime
< timer
->startTime
)
1441 Interface
->u
.TimeStamp
.timeDelta
= 0;
1442 gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW
);
1445 timeDelta
= timer
->stopTime
- timer
->startTime
;
1447 /* Check truncation overflow. */
1448 Interface
->u
.TimeStamp
.timeDelta
= (gctINT32
) timeDelta
;
1449 /*bit0~bit30 is available*/
1452 Interface
->u
.TimeStamp
.timeDelta
= 0;
1453 gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW
);
1456 status
= gcvSTATUS_OK
;
1460 case gcvHAL_DATABASE
:
1461 /* Query video memory. */
1463 gckKERNEL_QueryProcessDB(Kernel
,
1464 Interface
->u
.Database
.processID
,
1465 !Interface
->u
.Database
.validProcessID
,
1467 &Interface
->u
.Database
.vidMem
));
1469 /* Query non-paged memory. */
1471 gckKERNEL_QueryProcessDB(Kernel
,
1472 Interface
->u
.Database
.processID
,
1473 !Interface
->u
.Database
.validProcessID
,
1475 &Interface
->u
.Database
.nonPaged
));
1477 /* Query contiguous memory. */
1479 gckKERNEL_QueryProcessDB(Kernel
,
1480 Interface
->u
.Database
.processID
,
1481 !Interface
->u
.Database
.validProcessID
,
1483 &Interface
->u
.Database
.contiguous
));
1485 /* Query GPU idle time. */
1487 gckKERNEL_QueryProcessDB(Kernel
,
1488 Interface
->u
.Database
.processID
,
1489 !Interface
->u
.Database
.validProcessID
,
1491 &Interface
->u
.Database
.gpuIdle
));
1494 case gcvHAL_VERSION
:
1495 Interface
->u
.Version
.major
= gcvVERSION_MAJOR
;
1496 Interface
->u
.Version
.minor
= gcvVERSION_MINOR
;
1497 Interface
->u
.Version
.patch
= gcvVERSION_PATCH
;
1498 Interface
->u
.Version
.build
= gcvVERSION_BUILD
;
1499 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
1500 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_KERNEL
,
1501 "KERNEL version %d.%d.%d build %u %s %s",
1502 gcvVERSION_MAJOR
, gcvVERSION_MINOR
, gcvVERSION_PATCH
,
1503 gcvVERSION_BUILD
, gcvVERSION_DATE
, gcvVERSION_TIME
);
1507 case gcvHAL_CHIP_INFO
:
1508 /* Only if not support multi-core */
1509 Interface
->u
.ChipInfo
.count
= 1;
1510 Interface
->u
.ChipInfo
.types
[0] = Kernel
->hardware
->type
;
1514 /* Attach user process. */
1516 gckCOMMAND_Attach(Kernel
->command
,
1517 &Interface
->u
.Attach
.context
,
1518 &Interface
->u
.Attach
.stateCount
,
1522 gckKERNEL_AddProcessDB(Kernel
,
1523 processID
, gcvDB_CONTEXT
,
1524 Interface
->u
.Attach
.context
,
1530 /* Detach user process. */
1532 gckCOMMAND_Detach(Kernel
->command
,
1533 Interface
->u
.Detach
.context
));
1536 gckKERNEL_RemoveProcessDB(Kernel
,
1537 processID
, gcvDB_CONTEXT
,
1538 Interface
->u
.Detach
.context
));
1541 case gcvHAL_COMPOSE
:
1542 /* Start composition. */
1544 gckEVENT_Compose(Kernel
->eventObj
,
1545 &Interface
->u
.Compose
));
1548 case gcvHAL_SET_TIMEOUT
:
1549 /* set timeOut value from user */
1550 gckKERNEL_SetTimeOut(Kernel
, Interface
->u
.SetTimeOut
.timeOut
);
1554 case gcvHAL_GET_FRAME_INFO
:
1555 gcmkONERROR(gckHARDWARE_GetFrameInfo(
1557 Interface
->u
.GetFrameInfo
.frameInfo
));
1561 case gcvHAL_GET_SHARED_INFO
:
1562 if (Interface
->u
.GetSharedInfo
.dataId
!= 0)
1564 gcmkONERROR(gckKERNEL_FindProcessDB(Kernel
,
1565 Interface
->u
.GetSharedInfo
.pid
,
1568 gcmINT2PTR(Interface
->u
.GetSharedInfo
.dataId
),
1571 /* find a record in db, check size */
1572 if (record
.bytes
!= Interface
->u
.GetSharedInfo
.size
)
1574 /* Size change is not allowed */
1575 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
1579 gcmkONERROR(gckOS_CopyToUserData(
1582 Interface
->u
.GetSharedInfo
.data
,
1583 Interface
->u
.GetSharedInfo
.size
1588 if ((node
= Interface
->u
.GetSharedInfo
.node
) != gcvNULL
)
1590 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
1592 data
= &node
->VidMem
.sharedInfo
;
1596 data
= &node
->Virtual
.sharedInfo
;
1599 gcmkONERROR(gckOS_CopyToUserData(
1602 Interface
->u
.GetSharedInfo
.nodeData
,
1603 sizeof(gcsVIDMEM_NODE_SHARED_INFO
)
1609 case gcvHAL_SET_SHARED_INFO
:
1610 if (Interface
->u
.SetSharedInfo
.dataId
!= 0)
1612 status
= gckKERNEL_FindProcessDB(Kernel
, processID
, 0,
1614 gcmINT2PTR(Interface
->u
.SetSharedInfo
.dataId
),
1617 if (status
== gcvSTATUS_INVALID_DATA
)
1619 /* private data has not been created yet */
1620 /* Note: we count on DestoryProcessDB to free it */
1621 gcmkONERROR(gckOS_AllocateMemory(
1623 Interface
->u
.SetSharedInfo
.size
,
1628 gckKERNEL_AddProcessDB(Kernel
, processID
,
1630 gcmINT2PTR(Interface
->u
.SetSharedInfo
.dataId
),
1632 Interface
->u
.SetSharedInfo
.size
1637 /* bail on other errors */
1638 gcmkONERROR(status
);
1640 /* find a record in db, check size */
1641 if (record
.bytes
!= Interface
->u
.SetSharedInfo
.size
)
1643 /* Size change is not allowed */
1644 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
1647 /* get storage address */
1648 data
= record
.physical
;
1651 gcmkONERROR(gckOS_CopyFromUserData(
1654 Interface
->u
.SetSharedInfo
.data
,
1655 Interface
->u
.SetSharedInfo
.size
1659 if ((node
= Interface
->u
.SetSharedInfo
.node
) != gcvNULL
)
1661 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
1663 data
= &node
->VidMem
.sharedInfo
;
1667 data
= &node
->Virtual
.sharedInfo
;
1670 gcmkONERROR(gckOS_CopyFromUserData(
1673 Interface
->u
.SetSharedInfo
.nodeData
,
1674 sizeof(gcsVIDMEM_NODE_SHARED_INFO
)
1681 /* Invalid command. */
1682 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT
);
1687 Interface
->status
= status
;
1689 if (gcmIS_ERROR(status
))
1693 /* Roll back the lock. */
1695 gckVIDMEM_Unlock(Kernel
,
1696 Interface
->u
.LockVideoMemory
.node
,
1697 gcvSURF_TYPE_UNKNOWN
,
1700 if (gcvTRUE
== asynchronous
)
1704 gckVIDMEM_Unlock(Kernel
,
1705 Interface
->u
.LockVideoMemory
.node
,
1706 gcvSURF_TYPE_UNKNOWN
,
1712 #if QNX_SINGLE_THREADED_DEBUGGING
1713 gckOS_ReleaseMutex(Kernel
->os
, Kernel
->debugMutex
);
1716 /* Return the status. */
1721 /*******************************************************************************
1722 ** gckKERNEL_AttachProcess
1724 ** Attach or detach a process.
1729 ** Pointer to an gckKERNEL object.
1732 ** gcvTRUE if a new process gets attached or gcFALSE when a process
1740 gckKERNEL_AttachProcess(
1741 IN gckKERNEL Kernel
,
1746 gctUINT32 processID
;
1748 gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel
, Attach
);
1750 /* Verify the arguments. */
1751 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1753 /* Get current process ID. */
1754 gcmkONERROR(gckOS_GetProcessID(&processID
));
1756 gcmkONERROR(gckKERNEL_AttachProcessEx(Kernel
, Attach
, processID
));
1760 return gcvSTATUS_OK
;
1763 /* Return the status. */
1768 /*******************************************************************************
1769 ** gckKERNEL_AttachProcessEx
1771 ** Attach or detach a process with the given PID. Can be paired with gckKERNEL_AttachProcess
1772 ** provided the programmer is aware of the consequences.
1777 ** Pointer to an gckKERNEL object.
1780 ** gcvTRUE if a new process gets attached or gcFALSE when a process
1784 ** PID of the process to attach or detach.
1791 gckKERNEL_AttachProcessEx(
1792 IN gckKERNEL Kernel
,
1800 gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel
, Attach
, PID
);
1802 /* Verify the arguments. */
1803 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1807 /* Increment the number of clients attached. */
1809 gckOS_AtomIncrement(Kernel
->os
, Kernel
->atomClients
, &old
));
1814 if (Kernel
->vg
== gcvNULL
)
1817 gcmkONERROR(gckOS_Broadcast(Kernel
->os
,
1819 gcvBROADCAST_FIRST_PROCESS
));
1823 if (Kernel
->dbCreated
)
1825 /* Create the process database. */
1826 gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel
, PID
));
1831 if (Kernel
->dbCreated
)
1833 /* Clean up the process database. */
1834 gcmkONERROR(gckKERNEL_DestroyProcessDB(Kernel
, PID
));
1836 /* Save the last know process ID. */
1837 Kernel
->db
->lastProcessID
= PID
;
1840 /* Decrement the number of clients attached. */
1842 gckOS_AtomDecrement(Kernel
->os
, Kernel
->atomClients
, &old
));
1847 if (Kernel
->vg
== gcvNULL
)
1850 /* Last client detached, switch to SUSPEND power state. */
1851 gcmkONERROR(gckOS_Broadcast(Kernel
->os
,
1853 gcvBROADCAST_LAST_PROCESS
));
1856 /* Flush the debug cache. */
1857 gcmkDEBUGFLUSH(~0U);
1863 return gcvSTATUS_OK
;
1866 /* Return the status. */
1873 gckKERNEL_MapLogicalToPhysical(
1874 IN gckKERNEL Kernel
,
1875 IN gcskSECURE_CACHE_PTR Cache
,
1876 IN OUT gctPOINTER
* Data
1880 static gctBOOL baseAddressValid
= gcvFALSE
;
1881 static gctUINT32 baseAddress
;
1883 gcskLOGICAL_CACHE_PTR slot
;
1885 gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x *Data=0x%x",
1886 Kernel
, Cache
, gcmOPT_POINTER(Data
));
1888 /* Verify the arguments. */
1889 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1891 if (!baseAddressValid
)
1893 /* Get base address. */
1894 gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel
->hardware
, &baseAddress
));
1896 baseAddressValid
= gcvTRUE
;
1899 /* Does this state load need a base address? */
1900 gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel
->hardware
,
1901 ((gctUINT32_PTR
) Data
)[-1],
1904 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
1906 gcskLOGICAL_CACHE_PTR next
;
1909 /* Walk all used cache slots. */
1910 for (i
= 1, slot
= Cache
->cache
[0].next
, next
= gcvNULL
;
1911 (i
<= gcdSECURE_CACHE_SLOTS
) && (slot
->logical
!= gcvNULL
);
1912 ++i
, slot
= slot
->next
1915 if (slot
->logical
== *Data
)
1923 /* See if we had a miss. */
1924 if (next
== gcvNULL
)
1926 /* Use the tail of the cache. */
1927 slot
= Cache
->cache
[0].prev
;
1929 /* Initialize the cache line. */
1930 slot
->logical
= *Data
;
1932 /* Map the logical address to a DMA address. */
1934 gckOS_GetPhysicalAddress(Kernel
->os
, *Data
, &slot
->dma
));
1937 /* Move slot to head of list. */
1938 if (slot
!= Cache
->cache
[0].next
)
1941 slot
->prev
->next
= slot
->next
;
1942 slot
->next
->prev
= slot
->prev
;
1944 /* Move to head of chain. */
1945 slot
->prev
= &Cache
->cache
[0];
1946 slot
->next
= Cache
->cache
[0].next
;
1947 slot
->prev
->next
= slot
;
1948 slot
->next
->prev
= slot
;
1951 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
1954 gcskLOGICAL_CACHE_PTR next
= gcvNULL
;
1955 gcskLOGICAL_CACHE_PTR oldestSlot
= gcvNULL
;
1958 if (Cache
->cacheIndex
!= gcvNULL
)
1960 /* Walk the cache forwards. */
1961 for (i
= 1, slot
= Cache
->cacheIndex
;
1962 (i
<= gcdSECURE_CACHE_SLOTS
) && (slot
->logical
!= gcvNULL
);
1963 ++i
, slot
= slot
->next
)
1965 if (slot
->logical
== *Data
)
1972 /* Determine age of this slot. */
1973 if ((oldestSlot
== gcvNULL
)
1974 || (oldestSlot
->stamp
> slot
->stamp
)
1981 if (next
== gcvNULL
)
1983 /* Walk the cache backwards. */
1984 for (slot
= Cache
->cacheIndex
->prev
;
1985 (i
<= gcdSECURE_CACHE_SLOTS
) && (slot
->logical
!= gcvNULL
);
1986 ++i
, slot
= slot
->prev
)
1988 if (slot
->logical
== *Data
)
1995 /* Determine age of this slot. */
1996 if ((oldestSlot
== gcvNULL
)
1997 || (oldestSlot
->stamp
> slot
->stamp
)
2006 /* See if we had a miss. */
2007 if (next
== gcvNULL
)
2009 if (Cache
->cacheFree
!= 0)
2011 slot
= &Cache
->cache
[Cache
->cacheFree
];
2012 gcmkASSERT(slot
->logical
== gcvNULL
);
2014 ++ Cache
->cacheFree
;
2015 if (Cache
->cacheFree
>= gcmCOUNTOF(Cache
->cache
))
2017 Cache
->cacheFree
= 0;
2022 /* Use the oldest cache slot. */
2023 gcmkASSERT(oldestSlot
!= gcvNULL
);
2026 /* Unlink from the chain. */
2027 slot
->prev
->next
= slot
->next
;
2028 slot
->next
->prev
= slot
->prev
;
2030 /* Append to the end. */
2031 slot
->prev
= Cache
->cache
[0].prev
;
2032 slot
->next
= &Cache
->cache
[0];
2033 slot
->prev
->next
= slot
;
2034 slot
->next
->prev
= slot
;
2037 /* Initialize the cache line. */
2038 slot
->logical
= *Data
;
2040 /* Map the logical address to a DMA address. */
2042 gckOS_GetPhysicalAddress(Kernel
->os
, *Data
, &slot
->dma
));
2045 /* Save time stamp. */
2046 slot
->stamp
= ++ Cache
->cacheStamp
;
2048 /* Save current slot for next lookup. */
2049 Cache
->cacheIndex
= slot
;
2051 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
2054 gctUINT32 data
= gcmPTR2INT(*Data
);
2055 gctUINT32 key
, index
;
2056 gcskLOGICAL_CACHE_PTR hash
;
2058 /* Generate a hash key. */
2059 key
= (data
>> 24) + (data
>> 16) + (data
>> 8) + data
;
2060 index
= key
% gcmCOUNTOF(Cache
->hash
);
2062 /* Get the hash entry. */
2063 hash
= &Cache
->hash
[index
];
2065 for (slot
= hash
->nextHash
, i
= 0;
2066 (slot
!= gcvNULL
) && (i
< gcdSECURE_CACHE_SLOTS
);
2067 slot
= slot
->nextHash
, ++i
2070 if (slot
->logical
== (*Data
))
2076 if (slot
== gcvNULL
)
2078 /* Grab from the tail of the cache. */
2079 slot
= Cache
->cache
[0].prev
;
2081 /* Unlink slot from any hash table it is part of. */
2082 if (slot
->prevHash
!= gcvNULL
)
2084 slot
->prevHash
->nextHash
= slot
->nextHash
;
2086 if (slot
->nextHash
!= gcvNULL
)
2088 slot
->nextHash
->prevHash
= slot
->prevHash
;
2091 /* Initialize the cache line. */
2092 slot
->logical
= *Data
;
2094 /* Map the logical address to a DMA address. */
2096 gckOS_GetPhysicalAddress(Kernel
->os
, *Data
, &slot
->dma
));
2098 if (hash
->nextHash
!= gcvNULL
)
2100 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_KERNEL
,
2101 "Hash Collision: logical=0x%x key=0x%08x",
2105 /* Insert the slot at the head of the hash list. */
2106 slot
->nextHash
= hash
->nextHash
;
2107 if (slot
->nextHash
!= gcvNULL
)
2109 slot
->nextHash
->prevHash
= slot
;
2111 slot
->prevHash
= hash
;
2112 hash
->nextHash
= slot
;
2115 /* Move slot to head of list. */
2116 if (slot
!= Cache
->cache
[0].next
)
2119 slot
->prev
->next
= slot
->next
;
2120 slot
->next
->prev
= slot
->prev
;
2122 /* Move to head of chain. */
2123 slot
->prev
= &Cache
->cache
[0];
2124 slot
->next
= Cache
->cache
[0].next
;
2125 slot
->prev
->next
= slot
;
2126 slot
->next
->prev
= slot
;
2129 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
2131 gctUINT32 index
= (gcmPTR2INT(*Data
) % gcdSECURE_CACHE_SLOTS
) + 1;
2133 /* Get cache slot. */
2134 slot
= &Cache
->cache
[index
];
2136 /* Check for cache miss. */
2137 if (slot
->logical
!= *Data
)
2139 /* Initialize the cache line. */
2140 slot
->logical
= *Data
;
2142 /* Map the logical address to a DMA address. */
2144 gckOS_GetPhysicalAddress(Kernel
->os
, *Data
, &slot
->dma
));
2149 /* Return DMA address. */
2150 *Data
= gcmINT2PTR(slot
->dma
+ (needBase
? baseAddress
: 0));
2153 gcmkFOOTER_ARG("*Data=0x%08x", *Data
);
2154 return gcvSTATUS_OK
;
2157 /* Return the status. */
2163 gckKERNEL_FlushTranslationCache(
2164 IN gckKERNEL Kernel
,
2165 IN gcskSECURE_CACHE_PTR Cache
,
2166 IN gctPOINTER Logical
,
2171 gcskLOGICAL_CACHE_PTR slot
;
2174 gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
2175 Kernel
, Cache
, Logical
, Bytes
);
2177 /* Do we need to flush the entire cache? */
2178 if (Logical
== gcvNULL
)
2180 /* Clear all cache slots. */
2181 for (i
= 1; i
<= gcdSECURE_CACHE_SLOTS
; ++i
)
2183 Cache
->cache
[i
].logical
= gcvNULL
;
2185 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
2186 Cache
->cache
[i
].nextHash
= gcvNULL
;
2187 Cache
->cache
[i
].prevHash
= gcvNULL
;
2191 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
2192 /* Zero the hash table. */
2193 for (i
= 0; i
< gcmCOUNTOF(Cache
->hash
); ++i
)
2195 Cache
->hash
[i
].nextHash
= gcvNULL
;
2199 /* Reset the cache functionality. */
2200 Cache
->cacheIndex
= gcvNULL
;
2201 Cache
->cacheFree
= 1;
2202 Cache
->cacheStamp
= 0;
2207 gctUINT8_PTR low
= (gctUINT8_PTR
) Logical
;
2208 gctUINT8_PTR high
= low
+ Bytes
;
2210 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
2211 gcskLOGICAL_CACHE_PTR next
;
2213 /* Walk all used cache slots. */
2214 for (i
= 1, slot
= Cache
->cache
[0].next
;
2215 (i
<= gcdSECURE_CACHE_SLOTS
) && (slot
->logical
!= gcvNULL
);
2219 /* Save pointer to next slot. */
2222 /* Test if this slot falls within the range to flush. */
2223 ptr
= (gctUINT8_PTR
) slot
->logical
;
2224 if ((ptr
>= low
) && (ptr
< high
))
2227 slot
->prev
->next
= slot
->next
;
2228 slot
->next
->prev
= slot
->prev
;
2230 /* Append slot to tail of cache. */
2231 slot
->prev
= Cache
->cache
[0].prev
;
2232 slot
->next
= &Cache
->cache
[0];
2233 slot
->prev
->next
= slot
;
2234 slot
->next
->prev
= slot
;
2236 /* Mark slot as empty. */
2237 slot
->logical
= gcvNULL
;
2241 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
2242 gcskLOGICAL_CACHE_PTR next
;
2244 for (i
= 1, slot
= Cache
->cache
[0].next
;
2245 (i
<= gcdSECURE_CACHE_SLOTS
) && (slot
->logical
!= gcvNULL
);
2248 /* Save pointer to next slot. */
2251 /* Test if this slot falls within the range to flush. */
2252 ptr
= (gctUINT8_PTR
) slot
->logical
;
2253 if ((ptr
>= low
) && (ptr
< high
))
2255 /* Test if this slot is the current slot. */
2256 if (slot
== Cache
->cacheIndex
)
2258 /* Move to next or previous slot. */
2259 Cache
->cacheIndex
= (slot
->next
->logical
!= gcvNULL
)
2261 : (slot
->prev
->logical
!= gcvNULL
)
2266 /* Unlink slot from cache. */
2267 slot
->prev
->next
= slot
->next
;
2268 slot
->next
->prev
= slot
->prev
;
2270 /* Insert slot to head of cache. */
2271 slot
->prev
= &Cache
->cache
[0];
2272 slot
->next
= Cache
->cache
[0].next
;
2273 slot
->prev
->next
= slot
;
2274 slot
->next
->prev
= slot
;
2276 /* Mark slot as empty. */
2277 slot
->logical
= gcvNULL
;
2282 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
2284 gcskLOGICAL_CACHE_PTR hash
, next
;
2286 /* Walk all hash tables. */
2287 for (i
= 0, hash
= Cache
->hash
;
2288 i
< gcmCOUNTOF(Cache
->hash
);
2291 /* Walk all slots in the hash. */
2292 for (j
= 0, slot
= hash
->nextHash
;
2293 (j
< gcdSECURE_CACHE_SLOTS
) && (slot
!= gcvNULL
);
2296 /* Save pointer to next slot. */
2299 /* Test if this slot falls within the range to flush. */
2300 ptr
= (gctUINT8_PTR
) slot
->logical
;
2301 if ((ptr
>= low
) && (ptr
< high
))
2303 /* Unlink slot from hash table. */
2304 if (slot
->prevHash
== hash
)
2306 hash
->nextHash
= slot
->nextHash
;
2310 slot
->prevHash
->nextHash
= slot
->nextHash
;
2313 if (slot
->nextHash
!= gcvNULL
)
2315 slot
->nextHash
->prevHash
= slot
->prevHash
;
2318 /* Unlink slot from cache. */
2319 slot
->prev
->next
= slot
->next
;
2320 slot
->next
->prev
= slot
->prev
;
2322 /* Append slot to tail of cache. */
2323 slot
->prev
= Cache
->cache
[0].prev
;
2324 slot
->next
= &Cache
->cache
[0];
2325 slot
->prev
->next
= slot
;
2326 slot
->next
->prev
= slot
;
2328 /* Mark slot as empty. */
2329 slot
->logical
= gcvNULL
;
2330 slot
->prevHash
= gcvNULL
;
2331 slot
->nextHash
= gcvNULL
;
2336 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
2339 /* Loop while inside the range. */
2340 for (i
= 1; (low
< high
) && (i
<= gcdSECURE_CACHE_SLOTS
); ++i
)
2342 /* Get index into cache for this range. */
2343 index
= (gcmPTR2INT(low
) % gcdSECURE_CACHE_SLOTS
) + 1;
2344 slot
= &Cache
->cache
[index
];
2346 /* Test if this slot falls within the range to flush. */
2347 ptr
= (gctUINT8_PTR
) slot
->logical
;
2348 if ((ptr
>= low
) && (ptr
< high
))
2350 /* Remove entry from cache. */
2351 slot
->logical
= gcvNULL
;
2355 low
+= gcdSECURE_CACHE_SLOTS
;
2362 return gcvSTATUS_OK
;
2366 /*******************************************************************************
2368 ** gckKERNEL_Recovery
2370 ** Try to recover the GPU from a fatal error.
2375 ** Pointer to an gckKERNEL object.
2386 #if gcdENABLE_RECOVERY
2389 gckHARDWARE hardware
;
2391 gctUINT32 processID
;
2392 gcskSECURE_CACHE_PTR cache
;
2395 gcmkHEADER_ARG("Kernel=0x%x", Kernel
);
2397 /* Validate the arguemnts. */
2398 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
2400 /* Grab gckEVENT object. */
2401 eventObj
= Kernel
->eventObj
;
2402 gcmkVERIFY_OBJECT(eventObj
, gcvOBJ_EVENT
);
2404 /* Grab gckHARDWARE object. */
2405 hardware
= Kernel
->hardware
;
2406 gcmkVERIFY_OBJECT(hardware
, gcvOBJ_HARDWARE
);
2408 /* Handle all outstanding events now. */
2409 eventObj
->pending
= ~0U;
2410 gcmkONERROR(gckEVENT_Notify(eventObj
, 1));
2412 /* Again in case more events got submitted. */
2413 eventObj
->pending
= ~0U;
2414 gcmkONERROR(gckEVENT_Notify(eventObj
, 2));
2417 /* Flush the secure mapping cache. */
2418 gcmkONERROR(gckOS_GetProcessID(&processID
));
2419 gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel
, processID
, &cache
));
2420 gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel
, cache
, gcvNULL
, 0));
2423 /* Try issuing a soft reset for the GPU. */
2424 status
= gckHARDWARE_Reset(hardware
);
2425 if (status
== gcvSTATUS_NOT_SUPPORTED
)
2427 /* Switch to OFF power. The next submit should return the GPU to ON
2430 gckHARDWARE_SetPowerManagementState(hardware
,
2431 gcvPOWER_OFF_RECOVERY
));
2435 /* Bail out on reset error. */
2436 gcmkONERROR(status
);
2441 return gcvSTATUS_OK
;
2444 /* Return the status. */
2448 return gcvSTATUS_OK
;
2452 /*******************************************************************************
2454 ** gckKERNEL_OpenUserData
2456 ** Get access to the user data.
2461 ** Pointer to an gckKERNEL object.
2464 ** The flag indicating whether or not the data should be copied.
2466 ** gctPOINTER StaticStorage
2467 ** Pointer to the kernel storage where the data is to be copied if
2468 ** NeedCopy is gcvTRUE.
2470 ** gctPOINTER UserPointer
2471 ** User pointer to the data.
2474 ** Size of the data.
2478 ** gctPOINTER * KernelPointer
2479 ** Pointer to the kernel pointer that will be pointing to the data.
2482 gckKERNEL_OpenUserData(
2483 IN gckKERNEL Kernel
,
2484 IN gctBOOL NeedCopy
,
2485 IN gctPOINTER StaticStorage
,
2486 IN gctPOINTER UserPointer
,
2488 OUT gctPOINTER
* KernelPointer
2494 "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
2495 "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
2496 Kernel
, NeedCopy
, StaticStorage
, UserPointer
, Size
, KernelPointer
2499 /* Validate the arguemnts. */
2500 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
2501 gcmkVERIFY_ARGUMENT(!NeedCopy
|| (StaticStorage
!= gcvNULL
));
2502 gcmkVERIFY_ARGUMENT(UserPointer
!= gcvNULL
);
2503 gcmkVERIFY_ARGUMENT(KernelPointer
!= gcvNULL
);
2504 gcmkVERIFY_ARGUMENT(Size
> 0);
2508 /* Copy the user data to the static storage. */
2509 gcmkONERROR(gckOS_CopyFromUserData(
2510 Kernel
->os
, StaticStorage
, UserPointer
, Size
2513 /* Set the kernel pointer. */
2514 * KernelPointer
= StaticStorage
;
2518 gctPOINTER pointer
= gcvNULL
;
2520 /* Map the user pointer. */
2521 gcmkONERROR(gckOS_MapUserPointer(
2522 Kernel
->os
, UserPointer
, Size
, &pointer
2525 /* Set the kernel pointer. */
2526 * KernelPointer
= pointer
;
2530 /* Return the status. */
2535 /*******************************************************************************
2537 ** gckKERNEL_CloseUserData
2539 ** Release resources associated with the user data connection opened by
2540 ** gckKERNEL_OpenUserData.
2545 ** Pointer to an gckKERNEL object.
2548 ** The flag indicating whether or not the data should be copied.
2550 ** gctBOOL FlushData
2551 ** If gcvTRUE, the data is written back to the user.
2553 ** gctPOINTER UserPointer
2554 ** User pointer to the data.
2557 ** Size of the data.
2561 ** gctPOINTER * KernelPointer
2562 ** Kernel pointer to the data.
2565 gckKERNEL_CloseUserData(
2566 IN gckKERNEL Kernel
,
2567 IN gctBOOL NeedCopy
,
2568 IN gctBOOL FlushData
,
2569 IN gctPOINTER UserPointer
,
2571 OUT gctPOINTER
* KernelPointer
2574 gceSTATUS status
= gcvSTATUS_OK
;
2578 "Kernel=0x%08X NeedCopy=%d FlushData=%d "
2579 "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
2580 Kernel
, NeedCopy
, FlushData
, UserPointer
, Size
, KernelPointer
2583 /* Validate the arguemnts. */
2584 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
2585 gcmkVERIFY_ARGUMENT(UserPointer
!= gcvNULL
);
2586 gcmkVERIFY_ARGUMENT(KernelPointer
!= gcvNULL
);
2587 gcmkVERIFY_ARGUMENT(Size
> 0);
2589 /* Get a shortcut to the kernel pointer. */
2590 pointer
= * KernelPointer
;
2592 if (pointer
!= gcvNULL
)
2598 gcmkONERROR(gckOS_CopyToUserData(
2599 Kernel
->os
, * KernelPointer
, UserPointer
, Size
2605 /* Unmap record from kernel memory. */
2606 gcmkONERROR(gckOS_UnmapUserPointer(
2614 /* Reset the kernel pointer. */
2615 * KernelPointer
= gcvNULL
;
2619 /* Return the status. */
2625 gckKERNEL_SetTimeOut(
2626 IN gckKERNEL Kernel
,
2627 IN gctUINT32 timeOut
2630 gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel
, timeOut
);
2632 Kernel
->timeOut
= timeOut
;
2639 /*******************************************************************************
2640 ***** Test Code ****************************************************************
2641 *******************************************************************************/