ENGR00156850 gpu-viv: add gpu-viv driver source
[wandboard.git] / drivers / mxc / gpu-viv / hal / kernel / gc_hal_kernel.c
blob967266a3327680d68f4f9233459d811ce096f0cd
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)
89 #endif
91 /*******************************************************************************
93 ** gckKERNEL_Construct
95 ** Construct a new gckKERNEL object.
97 ** INPUT:
99 ** gckOS Os
100 ** Pointer to an gckOS object.
102 ** gceCORE Core
103 ** Specified core.
105 ** IN gctPOINTER Context
106 ** Pointer to a driver defined context.
108 ** IN gckDB SharedDB,
109 ** Pointer to a shared DB.
111 ** OUTPUT:
113 ** gckKERNEL * Kernel
114 ** Pointer to a variable that will hold the pointer to the gckKERNEL
115 ** object.
117 #ifdef ANDROID
118 #if gcdNEW_PROFILER_FILE
119 #define DEFAULT_PROFILE_FILE_NAME "/sdcard/vprofiler.vpd"
120 #else
121 #define DEFAULT_PROFILE_FILE_NAME "/sdcard/vprofiler.xml"
122 #endif
123 #else
124 #if gcdNEW_PROFILER_FILE
125 #define DEFAULT_PROFILE_FILE_NAME "vprofiler.vpd"
126 #else
127 #define DEFAULT_PROFILE_FILE_NAME "vprofiler.xml"
128 #endif
129 #endif
131 gceSTATUS
132 gckKERNEL_Construct(
133 IN gckOS Os,
134 IN gceCORE Core,
135 IN gctPOINTER Context,
136 IN gckDB SharedDB,
137 OUT gckKERNEL * Kernel
140 gckKERNEL kernel = gcvNULL;
141 gceSTATUS status;
142 gctSIZE_T i;
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),
154 &pointer));
156 kernel = pointer;
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),
168 &pointer));
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));
188 else
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;
204 kernel->os = Os;
205 kernel->core = Core;
207 /* Save context. */
208 kernel->context = Context;
210 /* Construct atom holding number of clients. */
211 kernel->atomClients = gcvNULL;
212 gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
214 #if gcdENABLE_VG
215 kernel->vg = gcvNULL;
217 if (Core == gcvCORE_VG)
219 /* Construct the gckMMU object. */
220 gcmkONERROR(
221 gckVGKERNEL_Construct(Os, Context, kernel, &kernel->vg));
223 else
224 #endif
226 /* Construct the gckHARDWARE object. */
227 gcmkONERROR(
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. */
234 gcmkONERROR(
235 gckHARDWARE_InitializeHardware(kernel->hardware));
237 /* Construct the gckCOMMAND object. */
238 gcmkONERROR(
239 gckCOMMAND_Construct(kernel, &kernel->command));
241 /* Construct the gckEVENT object. */
242 gcmkONERROR(
243 gckEVENT_Construct(kernel, &kernel->eventObj));
245 /* Construct the gckMMU object. */
246 gcmkONERROR(
247 gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
250 #if VIVANTE_PROFILER
251 /* Initialize profile setting */
252 #if defined ANDROID
253 kernel->profileEnable = gcvFALSE;
254 #else
255 kernel->profileEnable = gcvTRUE;
256 #endif
258 gcmkVERIFY_OK(
259 gckOS_MemCopy(kernel->profileFileName,
260 DEFAULT_PROFILE_FILE_NAME,
261 gcmSIZEOF(DEFAULT_PROFILE_FILE_NAME) + 1));
262 #endif
264 /* Return pointer to the gckKERNEL object. */
265 *Kernel = kernel;
267 /* Success. */
268 gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
269 return gcvSTATUS_OK;
271 OnError:
272 if (kernel != gcvNULL)
274 #if gcdENABLE_VG
275 if (Core != gcvCORE_VG)
276 #endif
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. */
314 gcmkFOOTER();
315 return status;
318 /*******************************************************************************
320 ** gckKERNEL_Destroy
322 ** Destroy an gckKERNEL object.
324 ** INPUT:
326 ** gckKERNEL Kernel
327 ** Pointer to an gckKERNEL object to destroy.
329 ** OUTPUT:
331 ** Nothing.
333 gceSTATUS
334 gckKERNEL_Destroy(
335 IN gckKERNEL Kernel
338 gctSIZE_T i;
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));
348 #endif
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)
357 gcmkVERIFY_OK(
358 gckKERNEL_DestroyProcessDB(Kernel, Kernel->db->db[i]->processID));
362 /* Free all databases. */
363 for (database = Kernel->db->freeDatabase;
364 database != gcvNULL;
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));
387 #if gcdENABLE_VG
388 if (Kernel->vg)
390 gcmkVERIFY_OK(gckVGKERNEL_Destroy(Kernel->vg));
392 else
393 #endif
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));
417 /* Success. */
418 gcmkFOOTER_NO();
419 return gcvSTATUS_OK;
423 /*******************************************************************************
425 ** _AllocateMemory
427 ** Private function to walk all required memory pools to allocate the requested
428 ** amount of video memory.
430 ** INPUT:
432 ** gckKERNEL Kernel
433 ** Pointer to an gckKERNEL object.
435 ** gcsHAL_INTERFACE * Interface
436 ** Pointer to a gcsHAL_INTERFACE structure that defines the command to
437 ** be dispatched.
439 ** OUTPUT:
441 ** gcsHAL_INTERFACE * Interface
442 ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
443 ** returned.
445 static gceSTATUS
446 _AllocateMemory(
447 IN gckKERNEL Kernel,
448 IN OUT gcePOOL * Pool,
449 IN gctSIZE_T Bytes,
450 IN gctSIZE_T Alignment,
451 IN gceSURF_TYPE Type,
452 OUT gcuVIDMEM_NODE_PTR * Node
455 gcePOOL pool;
456 gceSTATUS status;
457 gckVIDMEM videoMemory;
458 gctINT loopCount;
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:
470 case gcvPOOL_LOCAL:
471 pool = gcvPOOL_LOCAL_INTERNAL;
472 loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
473 break;
475 case gcvPOOL_UNIFIED:
476 pool = gcvPOOL_SYSTEM;
477 loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
478 break;
480 case gcvPOOL_CONTIGUOUS:
481 loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
482 break;
484 default:
485 loopCount = 1;
486 break;
489 /* Verify the number of bytes to allocate. */
490 if (Bytes == 0)
492 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
495 while (loopCount-- > 0)
497 if (pool == gcvPOOL_VIRTUAL)
499 /* Create a gcuVIDMEM_NODE for virtual memory. */
500 gcmkONERROR(
501 gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, &node));
503 /* Success. */
504 break;
507 else
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. */
515 break;
519 else
521 /* Get pointer to gckVIDMEM object for pool. */
522 #if gcdUSE_VIDMEM_PER_PID
523 gctUINT32 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);
532 #else
533 status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
534 #endif
536 if (gcmIS_SUCCESS(status))
538 /* Allocate memory. */
539 status = gckVIDMEM_AllocateLinear(videoMemory,
540 Bytes,
541 Alignment,
542 Type,
543 &node);
545 if (gcmIS_SUCCESS(status))
547 /* Memory allocated. */
548 node->VidMem.pool = pool;
549 break;
554 if (pool == gcvPOOL_LOCAL_INTERNAL)
556 /* Advance to external memory. */
557 pool = gcvPOOL_LOCAL_EXTERNAL;
560 else
561 if (pool == gcvPOOL_LOCAL_EXTERNAL)
563 /* Advance to contiguous system memory. */
564 pool = gcvPOOL_SYSTEM;
567 else
568 if (pool == gcvPOOL_SYSTEM)
570 /* Advance to contiguous memory. */
571 pool = gcvPOOL_CONTIGUOUS;
574 else
575 if ((pool == gcvPOOL_CONTIGUOUS)
576 && (Type != gcvSURF_TILE_STATUS)
579 /* Advance to virtual memory. */
580 pool = gcvPOOL_VIRTUAL;
583 else
585 /* Out of pools. */
586 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
590 if (node == gcvNULL)
592 /* Nothing allocated. */
593 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
597 /* Return node and pool used for allocation. */
598 *Node = node;
599 *Pool = pool;
601 /* Return status. */
602 gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool, *Node);
603 return gcvSTATUS_OK;
605 OnError:
606 /* Return the status. */
607 gcmkFOOTER();
608 return status;
611 /*******************************************************************************
613 ** gckKERNEL_Dispatch
615 ** Dispatch a command received from the user HAL layer.
617 ** INPUT:
619 ** gckKERNEL Kernel
620 ** Pointer to an gckKERNEL object.
622 ** gctBOOL FromUser
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
627 ** be dispatched.
629 ** OUTPUT:
631 ** gcsHAL_INTERFACE * Interface
632 ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
633 ** returned.
636 gceSTATUS
637 gckKERNEL_Dispatch(
638 IN gckKERNEL Kernel,
639 IN gctBOOL FromUser,
640 IN OUT gcsHAL_INTERFACE * Interface
643 gceSTATUS status = gcvSTATUS_OK;
644 gctUINT32 bitsPerPixel;
645 gctSIZE_T bytes;
646 gcuVIDMEM_NODE_PTR node;
647 gctBOOL locked = gcvFALSE;
648 gctPHYS_ADDR physical = gcvNULL;
649 gctUINT32 address;
650 gctUINT32 processID;
651 #if gcdSECURE_USER
652 gcskSECURE_CACHE_PTR cache;
653 gctPOINTER logical;
654 #endif
655 gctBOOL asynchronous;
656 gctPOINTER paddr = gcvNULL;
657 #if !USE_NEW_LINUX_SIGNAL
658 gctSIGNAL signal;
659 #endif
661 gcsDATABASE_RECORD record;
662 gctPOINTER data;
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]);
675 #endif
676 #if QNX_SINGLE_THREADED_DEBUGGING
677 gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
678 #endif
680 /* Get the current process ID. */
681 gcmkONERROR(gckOS_GetProcessID(&processID));
683 #ifdef UNDER_CE
684 if (!FromUser)
686 gcmkONERROR(gckOS_GetCurrentProcessID(&processID));
688 #endif
690 #if gcdSECURE_USER
691 gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
692 #endif
694 /* Dispatch on command. */
695 switch (Interface->command)
697 case gcvHAL_GET_BASE_ADDRESS:
698 /* Get base address. */
699 gcmkONERROR(
700 gckOS_GetBaseAddress(Kernel->os,
701 &Interface->u.GetBaseAddress.baseAddress));
702 break;
704 case gcvHAL_QUERY_VIDEO_MEMORY:
705 /* Query video memory size. */
706 gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
707 break;
709 case gcvHAL_QUERY_CHIP_IDENTITY:
710 /* Query chip identity. */
711 gcmkONERROR(
712 gckHARDWARE_QueryChipIdentity(
713 Kernel->hardware,
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. */
723 gcmkONERROR(
724 gckHARDWARE_QueryChipSpecs(
725 Kernel->hardware,
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));
736 break;
738 case gcvHAL_MAP_MEMORY:
739 physical = Interface->u.MapMemory.physical;
741 /* Map memory. */
742 gcmkONERROR(
743 gckKERNEL_MapMemory(Kernel,
744 physical,
745 Interface->u.MapMemory.bytes,
746 &Interface->u.MapMemory.logical));
747 gcmkVERIFY_OK(
748 gckKERNEL_AddProcessDB(Kernel,
749 processID, gcvDB_MAP_MEMORY,
750 Interface->u.MapMemory.logical,
751 physical,
752 Interface->u.MapMemory.bytes));
753 break;
755 case gcvHAL_UNMAP_MEMORY:
756 physical = Interface->u.UnmapMemory.physical;
758 /* Unmap memory. */
759 gcmkONERROR(
760 gckKERNEL_UnmapMemory(Kernel,
761 physical,
762 Interface->u.UnmapMemory.bytes,
763 Interface->u.UnmapMemory.logical));
764 gcmkVERIFY_OK(
765 gckKERNEL_RemoveProcessDB(Kernel,
766 processID, gcvDB_MAP_MEMORY,
767 Interface->u.UnmapMemory.logical));
768 break;
770 case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
771 /* Allocate non-paged memory. */
772 gcmkONERROR(
773 gckOS_AllocateNonPagedMemory(
774 Kernel->os,
775 FromUser,
776 &Interface->u.AllocateNonPagedMemory.bytes,
777 &Interface->u.AllocateNonPagedMemory.physical,
778 &Interface->u.AllocateNonPagedMemory.logical));
780 gcmkVERIFY_OK(
781 gckKERNEL_AddProcessDB(Kernel,
782 processID, gcvDB_NON_PAGED,
783 Interface->u.AllocateNonPagedMemory.logical,
784 Interface->u.AllocateNonPagedMemory.physical,
785 Interface->u.AllocateNonPagedMemory.bytes));
786 break;
788 case gcvHAL_FREE_NON_PAGED_MEMORY:
789 physical = Interface->u.FreeNonPagedMemory.physical;
791 /* Free non-paged memory. */
792 gcmkONERROR(
793 gckOS_FreeNonPagedMemory(Kernel->os,
794 Interface->u.FreeNonPagedMemory.bytes,
795 physical,
796 Interface->u.FreeNonPagedMemory.logical));
798 gcmkVERIFY_OK(
799 gckKERNEL_RemoveProcessDB(Kernel,
800 processID, gcvDB_NON_PAGED,
801 Interface->u.FreeNonPagedMemory.logical));
803 #if gcdSECURE_USER
804 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
805 Kernel,
806 cache,
807 Interface->u.FreeNonPagedMemory.logical,
808 Interface->u.FreeNonPagedMemory.bytes));
809 #endif
810 break;
812 case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
813 /* Allocate contiguous memory. */
814 gcmkONERROR(gckOS_AllocateContiguous(
815 Kernel->os,
816 FromUser,
817 &Interface->u.AllocateContiguousMemory.bytes,
818 &Interface->u.AllocateContiguousMemory.physical,
819 &Interface->u.AllocateContiguousMemory.logical));
821 gcmkONERROR(gckHARDWARE_ConvertLogical(
822 Kernel->hardware,
823 Interface->u.AllocateContiguousMemory.logical,
824 &Interface->u.AllocateContiguousMemory.address));
826 gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
827 Kernel,
828 processID, gcvDB_CONTIGUOUS,
829 Interface->u.AllocateContiguousMemory.logical,
830 Interface->u.AllocateContiguousMemory.physical,
831 Interface->u.AllocateContiguousMemory.bytes));
832 break;
834 case gcvHAL_FREE_CONTIGUOUS_MEMORY:
835 physical = Interface->u.FreeContiguousMemory.physical;
837 /* Free contiguous memory. */
838 gcmkONERROR(
839 gckOS_FreeContiguous(Kernel->os,
840 physical,
841 Interface->u.FreeContiguousMemory.logical,
842 Interface->u.FreeContiguousMemory.bytes));
844 gcmkVERIFY_OK(
845 gckKERNEL_RemoveProcessDB(Kernel,
846 processID, gcvDB_CONTIGUOUS,
847 Interface->u.FreeNonPagedMemory.logical));
849 #if gcdSECURE_USER
850 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
851 Kernel,
852 cache,
853 Interface->u.FreeContiguousMemory.logical,
854 Interface->u.FreeContiguousMemory.bytes));
855 #endif
856 break;
858 case gcvHAL_ALLOCATE_VIDEO_MEMORY:
859 /* Align width and height to tiles. */
860 gcmkONERROR(
861 gckHARDWARE_AlignToTile(Kernel->hardware,
862 Interface->u.AllocateVideoMemory.type,
863 &Interface->u.AllocateVideoMemory.width,
864 &Interface->u.AllocateVideoMemory.height,
865 gcvNULL));
867 /* Convert format into bytes per pixel and bytes per tile. */
868 gcmkONERROR(
869 gckHARDWARE_ConvertFormat(Kernel->hardware,
870 Interface->u.AllocateVideoMemory.format,
871 &bitsPerPixel,
872 gcvNULL));
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. */
880 gcmkONERROR(
881 _AllocateMemory(Kernel,
882 &Interface->u.AllocateVideoMemory.pool,
883 bytes,
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;
894 else
896 bytes = node->Virtual.bytes;
899 gcmkONERROR(
900 gckKERNEL_AddProcessDB(Kernel,
901 processID, gcvDB_VIDEO_MEMORY,
902 Interface->u.AllocateVideoMemory.node,
903 gcvNULL,
904 bytes));
905 break;
907 case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
908 /* Allocate memory. */
909 gcmkONERROR(
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;
923 else
925 bytes = node->Virtual.bytes;
928 gcmkONERROR(
929 gckKERNEL_AddProcessDB(Kernel,
930 processID, gcvDB_VIDEO_MEMORY,
931 Interface->u.AllocateLinearVideoMemory.node,
932 gcvNULL,
933 bytes));
934 break;
936 case gcvHAL_FREE_VIDEO_MEMORY:
937 #ifdef __QNXNTO__
938 node = Interface->u.FreeVideoMemory.node;
939 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
940 && node->VidMem.logical != gcvNULL)
942 gcmkONERROR(
943 gckKERNEL_UnmapVideoMemory(Kernel,
944 node->VidMem.logical,
945 processID,
946 node->VidMem.bytes));
947 node->VidMem.logical = gcvNULL;
949 #endif
950 /* Free video memory. */
951 gcmkONERROR(
952 gckVIDMEM_Free(Interface->u.FreeVideoMemory.node));
954 gcmkONERROR(
955 gckKERNEL_RemoveProcessDB(Kernel,
956 processID, gcvDB_VIDEO_MEMORY,
957 Interface->u.FreeVideoMemory.node));
958 break;
960 case gcvHAL_LOCK_VIDEO_MEMORY:
961 /* Lock video memory. */
962 gcmkONERROR(
963 gckVIDMEM_Lock(Kernel,
964 Interface->u.LockVideoMemory.node,
965 Interface->u.LockVideoMemory.cacheable,
966 &Interface->u.LockVideoMemory.address));
968 locked = gcvTRUE;
970 node = Interface->u.LockVideoMemory.node;
971 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
973 /* Map video memory address into user space. */
974 #ifdef __QNXNTO__
975 if (node->VidMem.logical == gcvNULL)
977 gcmkONERROR(
978 gckKERNEL_MapVideoMemory(Kernel,
979 FromUser,
980 Interface->u.LockVideoMemory.address,
981 processID,
982 node->VidMem.bytes,
983 &node->VidMem.logical));
985 gcmkASSERT(node->VidMem.logical != gcvNULL);
987 Interface->u.LockVideoMemory.memory = node->VidMem.logical;
988 #else
989 gcmkONERROR(
990 gckKERNEL_MapVideoMemory(Kernel,
991 FromUser,
992 Interface->u.LockVideoMemory.address,
993 &Interface->u.LockVideoMemory.memory));
994 gckOS_ZeroMemory(Interface->u.LockVideoMemory.memory, node->VidMem.bytes);
995 #endif
997 else
999 Interface->u.LockVideoMemory.memory = node->Virtual.logical;
1001 /* Success. */
1002 status = gcvSTATUS_OK;
1005 #if gcdSECURE_USER
1006 /* Return logical address as physical address. */
1007 Interface->u.LockVideoMemory.address =
1008 gcmPTR2INT(Interface->u.LockVideoMemory.memory);
1009 #endif
1010 gcmkONERROR(
1011 gckKERNEL_AddProcessDB(Kernel,
1012 processID, gcvDB_VIDEO_MEMORY_LOCKED,
1013 Interface->u.LockVideoMemory.node,
1014 gcvNULL,
1015 0));
1017 break;
1019 case gcvHAL_UNLOCK_VIDEO_MEMORY:
1020 /* Unlock video memory. */
1021 node = Interface->u.UnlockVideoMemory.node;
1023 #if gcdSECURE_USER
1024 /* Save node information before it disappears. */
1025 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1027 logical = gcvNULL;
1028 bytes = 0;
1030 else
1032 logical = node->Virtual.logical;
1033 bytes = node->Virtual.bytes;
1035 #endif
1037 /* Unlock video memory. */
1038 gcmkONERROR(
1039 gckVIDMEM_Unlock(Kernel,
1040 node,
1041 Interface->u.UnlockVideoMemory.type,
1042 &Interface->u.UnlockVideoMemory.asynchroneous));
1044 #if gcdSECURE_USER
1045 /* Flush the translation cache for virtual surfaces. */
1046 if (logical != gcvNULL)
1048 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
1049 cache,
1050 logical,
1051 bytes));
1053 #endif
1054 if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
1056 /* There isn't a event to unlock this node, remove record now */
1057 gcmkONERROR(
1058 gckKERNEL_RemoveProcessDB(Kernel,
1059 processID, gcvDB_VIDEO_MEMORY_LOCKED,
1060 Interface->u.UnlockVideoMemory.node));
1063 break;
1065 case gcvHAL_EVENT_COMMIT:
1066 /* Commit an event queue. */
1067 gcmkONERROR(
1068 gckEVENT_Commit(Kernel->eventObj,
1069 Interface->u.Event.queue));
1070 break;
1072 case gcvHAL_COMMIT:
1073 /* Commit a command and context buffer. */
1074 gcmkONERROR(
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,
1080 processID));
1081 break;
1083 case gcvHAL_STALL:
1084 /* Stall the command queue. */
1085 gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
1086 break;
1088 case gcvHAL_MAP_USER_MEMORY:
1089 /* Map user memory to DMA. */
1090 gcmkONERROR(
1091 gckOS_MapUserMemoryEx(Kernel->os,
1092 Kernel->core,
1093 Interface->u.MapUserMemory.memory,
1094 Interface->u.MapUserMemory.size,
1095 &Interface->u.MapUserMemory.info,
1096 &Interface->u.MapUserMemory.address));
1097 gcmkVERIFY_OK(
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));
1103 break;
1105 case gcvHAL_UNMAP_USER_MEMORY:
1106 address = Interface->u.MapUserMemory.address;
1108 /* Unmap user memory. */
1109 gcmkONERROR(
1110 gckOS_UnmapUserMemoryEx(Kernel->os,
1111 Kernel->core,
1112 Interface->u.UnmapUserMemory.memory,
1113 Interface->u.UnmapUserMemory.size,
1114 Interface->u.UnmapUserMemory.info,
1115 address));
1117 #if gcdSECURE_USER
1118 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
1119 Kernel,
1120 cache,
1121 Interface->u.UnmapUserMemory.memory,
1122 Interface->u.UnmapUserMemory.size));
1123 #endif
1124 gcmkVERIFY_OK(
1125 gckKERNEL_RemoveProcessDB(Kernel,
1126 processID, gcvDB_MAP_USER_MEMORY,
1127 Interface->u.UnmapUserMemory.memory));
1128 break;
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. */
1137 gcmkONERROR(
1138 gckOS_CreateUserSignal(Kernel->os,
1139 Interface->u.UserSignal.manualReset,
1140 &Interface->u.UserSignal.id));
1142 gcmkVERIFY_OK(
1143 gckKERNEL_AddProcessDB(Kernel,
1144 processID, gcvDB_SIGNAL,
1145 gcmINT2PTR(Interface->u.UserSignal.id),
1146 gcvNULL,
1147 0));
1148 break;
1150 case gcvUSER_SIGNAL_DESTROY:
1151 /* Destroy the signal. */
1152 gcmkONERROR(
1153 gckOS_DestroyUserSignal(Kernel->os,
1154 Interface->u.UserSignal.id));
1156 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
1157 Kernel,
1158 processID, gcvDB_SIGNAL,
1159 gcmINT2PTR(Interface->u.UserSignal.id)));
1160 break;
1162 case gcvUSER_SIGNAL_SIGNAL:
1163 /* Signal the signal. */
1164 gcmkONERROR(
1165 gckOS_SignalUserSignal(Kernel->os,
1166 Interface->u.UserSignal.id,
1167 Interface->u.UserSignal.state));
1168 break;
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);
1175 break;
1177 case gcvUSER_SIGNAL_MAP:
1178 gcmkONERROR(
1179 gckOS_MapSignal(Kernel->os,
1180 (gctSIGNAL)Interface->u.UserSignal.id,
1181 (gctHANDLE)processID,
1182 &signal));
1184 gcmkVERIFY_OK(
1185 gckKERNEL_AddProcessDB(Kernel,
1186 processID, gcvDB_SIGNAL,
1187 gcmINT2PTR(Interface->u.UserSignal.id),
1188 gcvNULL,
1189 0));
1190 break;
1192 case gcvUSER_SIGNAL_UNMAP:
1193 /* Destroy the signal. */
1194 gcmkONERROR(
1195 gckOS_DestroyUserSignal(Kernel->os,
1196 Interface->u.UserSignal.id));
1198 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
1199 Kernel,
1200 processID, gcvDB_SIGNAL,
1201 gcmINT2PTR(Interface->u.UserSignal.id)));
1202 break;
1204 default:
1205 /* Invalid user signal command. */
1206 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1208 break;
1209 #endif
1211 case gcvHAL_SET_POWER_MANAGEMENT_STATE:
1212 /* Set the power management state. */
1213 gcmkONERROR(
1214 gckHARDWARE_SetPowerManagementState(
1215 Kernel->hardware,
1216 Interface->u.SetPowerManagement.state));
1217 break;
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(
1225 Kernel->hardware,
1226 &Interface->u.QueryPowerManagement.state));
1228 /* Query the idle state. */
1229 gcmkONERROR(
1230 gckHARDWARE_QueryIdle(Kernel->hardware,
1231 &Interface->u.QueryPowerManagement.isIdle));
1232 break;
1234 case gcvHAL_READ_REGISTER:
1235 #if gcdREGISTER_ACCESS_FROM_USER
1237 gceCHIPPOWERSTATE power;
1238 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
1239 &power));
1241 if (power == gcvPOWER_ON)
1243 /* Read a register. */
1244 gcmkONERROR(gckOS_ReadRegisterEx(
1245 Kernel->os,
1246 Kernel->core,
1247 Interface->u.ReadRegisterData.address,
1248 &Interface->u.ReadRegisterData.data));
1250 else
1252 /* Chip is in power-state. */
1253 Interface->u.ReadRegisterData.data = 0;
1254 status = gcvSTATUS_CHIP_NOT_READY;
1257 #else
1258 /* No access from user land to read registers. */
1259 Interface->u.ReadRegisterData.data = 0;
1260 status = gcvSTATUS_NOT_SUPPORTED;
1261 #endif
1262 break;
1264 case gcvHAL_WRITE_REGISTER:
1265 #if gcdREGISTER_ACCESS_FROM_USER
1266 /* Write a register. */
1267 gcmkONERROR(
1268 gckOS_WriteRegisterEx(Kernel->os,
1269 Kernel->core,
1270 Interface->u.WriteRegisterData.address,
1271 Interface->u.WriteRegisterData.data));
1272 #else
1273 /* No access from user land to write registers. */
1274 status = gcvSTATUS_NOT_SUPPORTED;
1275 #endif
1276 break;
1278 case gcvHAL_READ_ALL_PROFILE_REGISTERS:
1279 #if VIVANTE_PROFILER
1280 /* Read all 3D profile registers. */
1281 gcmkONERROR(
1282 gckHARDWARE_QueryProfileRegisters(
1283 Kernel->hardware,
1284 &Interface->u.RegisterProfileData.counters));
1285 #else
1286 status = gcvSTATUS_OK;
1287 #endif
1288 break;
1290 case gcvHAL_PROFILE_REGISTERS_2D:
1291 #if VIVANTE_PROFILER
1292 /* Read all 2D profile registers. */
1293 gcmkONERROR(
1294 gckHARDWARE_ProfileEngine2D(
1295 Kernel->hardware,
1296 Interface->u.RegisterProfileData2D.hwProfile2D));
1297 #else
1298 status = gcvSTATUS_OK;
1299 #endif
1300 break;
1302 case gcvHAL_GET_PROFILE_SETTING:
1303 #if VIVANTE_PROFILER
1304 /* Get profile setting */
1305 Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
1307 gcmkVERIFY_OK(
1308 gckOS_MemCopy(Interface->u.GetProfileSetting.fileName,
1309 Kernel->profileFileName,
1310 gcdMAX_PROFILE_FILE_NAME));
1311 #endif
1313 status = gcvSTATUS_OK;
1314 break;
1316 case gcvHAL_SET_PROFILE_SETTING:
1317 #if VIVANTE_PROFILER
1318 /* Set profile setting */
1319 Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
1321 gcmkVERIFY_OK(
1322 gckOS_MemCopy(Kernel->profileFileName,
1323 Interface->u.SetProfileSetting.fileName,
1324 gcdMAX_PROFILE_FILE_NAME));
1325 #endif
1327 status = gcvSTATUS_OK;
1328 break;
1330 case gcvHAL_QUERY_KERNEL_SETTINGS:
1331 /* Get kernel settings. */
1332 gcmkONERROR(
1333 gckKERNEL_QuerySettings(Kernel,
1334 &Interface->u.QueryKernelSettings.settings));
1335 break;
1337 case gcvHAL_RESET:
1338 /* Reset the hardware. */
1339 gcmkONERROR(
1340 gckHARDWARE_Reset(Kernel->hardware));
1341 break;
1343 case gcvHAL_DEBUG:
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);
1359 else
1361 gckOS_DumpBuffer(Kernel->os,
1362 Interface->u.Debug.message,
1363 Interface->u.Debug.messageSize,
1364 gceDUMP_BUFFER_FROM_USER,
1365 gcvTRUE);
1368 status = gcvSTATUS_OK;
1369 break;
1371 case gcvHAL_CACHE:
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;
1377 break;
1379 else if (Interface->u.Cache.node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1381 /* Video memory has no physical handles. */
1382 physical = gcvNULL;
1384 else
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,
1395 processID,
1396 physical,
1397 paddr,
1398 Interface->u.Cache.logical,
1399 Interface->u.Cache.bytes);
1400 break;
1401 case gcvCACHE_CLEAN:
1402 /* Clean the cache. */
1403 status = gckOS_CacheClean(Kernel->os,
1404 processID,
1405 physical,
1406 paddr,
1407 Interface->u.Cache.logical,
1408 Interface->u.Cache.bytes);
1409 break;
1410 case gcvCACHE_INVALIDATE:
1411 /* Invalidate the cache. */
1412 status = gckOS_CacheInvalidate(Kernel->os,
1413 processID,
1414 physical,
1415 paddr,
1416 Interface->u.Cache.logical,
1417 Interface->u.Cache.bytes);
1418 break;
1419 default:
1420 status = gcvSTATUS_INVALID_ARGUMENT;
1421 break;
1423 break;
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*/
1450 if (timeDelta>>31)
1452 Interface->u.TimeStamp.timeDelta = 0;
1453 gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
1456 status = gcvSTATUS_OK;
1458 break;
1460 case gcvHAL_DATABASE:
1461 /* Query video memory. */
1462 gcmkONERROR(
1463 gckKERNEL_QueryProcessDB(Kernel,
1464 Interface->u.Database.processID,
1465 !Interface->u.Database.validProcessID,
1466 gcvDB_VIDEO_MEMORY,
1467 &Interface->u.Database.vidMem));
1469 /* Query non-paged memory. */
1470 gcmkONERROR(
1471 gckKERNEL_QueryProcessDB(Kernel,
1472 Interface->u.Database.processID,
1473 !Interface->u.Database.validProcessID,
1474 gcvDB_NON_PAGED,
1475 &Interface->u.Database.nonPaged));
1477 /* Query contiguous memory. */
1478 gcmkONERROR(
1479 gckKERNEL_QueryProcessDB(Kernel,
1480 Interface->u.Database.processID,
1481 !Interface->u.Database.validProcessID,
1482 gcvDB_CONTIGUOUS,
1483 &Interface->u.Database.contiguous));
1485 /* Query GPU idle time. */
1486 gcmkONERROR(
1487 gckKERNEL_QueryProcessDB(Kernel,
1488 Interface->u.Database.processID,
1489 !Interface->u.Database.validProcessID,
1490 gcvDB_IDLE,
1491 &Interface->u.Database.gpuIdle));
1492 break;
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);
1504 #endif
1505 break;
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;
1511 break;
1513 case gcvHAL_ATTACH:
1514 /* Attach user process. */
1515 gcmkONERROR(
1516 gckCOMMAND_Attach(Kernel->command,
1517 &Interface->u.Attach.context,
1518 &Interface->u.Attach.stateCount,
1519 processID));
1521 gcmkVERIFY_OK(
1522 gckKERNEL_AddProcessDB(Kernel,
1523 processID, gcvDB_CONTEXT,
1524 Interface->u.Attach.context,
1525 gcvNULL,
1526 0));
1527 break;
1529 case gcvHAL_DETACH:
1530 /* Detach user process. */
1531 gcmkONERROR(
1532 gckCOMMAND_Detach(Kernel->command,
1533 Interface->u.Detach.context));
1535 gcmkVERIFY_OK(
1536 gckKERNEL_RemoveProcessDB(Kernel,
1537 processID, gcvDB_CONTEXT,
1538 Interface->u.Detach.context));
1539 break;
1541 case gcvHAL_COMPOSE:
1542 /* Start composition. */
1543 gcmkONERROR(
1544 gckEVENT_Compose(Kernel->eventObj,
1545 &Interface->u.Compose));
1546 break;
1548 case gcvHAL_SET_TIMEOUT:
1549 /* set timeOut value from user */
1550 gckKERNEL_SetTimeOut(Kernel, Interface->u.SetTimeOut.timeOut);
1551 break;
1553 #if gcdFRAME_DB
1554 case gcvHAL_GET_FRAME_INFO:
1555 gcmkONERROR(gckHARDWARE_GetFrameInfo(
1556 Kernel->hardware,
1557 Interface->u.GetFrameInfo.frameInfo));
1558 break;
1559 #endif
1561 case gcvHAL_GET_SHARED_INFO:
1562 if (Interface->u.GetSharedInfo.dataId != 0)
1564 gcmkONERROR(gckKERNEL_FindProcessDB(Kernel,
1565 Interface->u.GetSharedInfo.pid,
1567 gcvDB_SHARED_INFO,
1568 gcmINT2PTR(Interface->u.GetSharedInfo.dataId),
1569 &record));
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);
1578 /* fetch data */
1579 gcmkONERROR(gckOS_CopyToUserData(
1580 Kernel->os,
1581 record.physical,
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;
1594 else
1596 data = &node->Virtual.sharedInfo;
1599 gcmkONERROR(gckOS_CopyToUserData(
1600 Kernel->os,
1601 data,
1602 Interface->u.GetSharedInfo.nodeData,
1603 sizeof(gcsVIDMEM_NODE_SHARED_INFO)
1607 break;
1609 case gcvHAL_SET_SHARED_INFO:
1610 if (Interface->u.SetSharedInfo.dataId != 0)
1612 status = gckKERNEL_FindProcessDB(Kernel, processID, 0,
1613 gcvDB_SHARED_INFO,
1614 gcmINT2PTR(Interface->u.SetSharedInfo.dataId),
1615 &record);
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(
1622 Kernel->os,
1623 Interface->u.SetSharedInfo.size,
1624 &data
1627 gcmkONERROR(
1628 gckKERNEL_AddProcessDB(Kernel, processID,
1629 gcvDB_SHARED_INFO,
1630 gcmINT2PTR(Interface->u.SetSharedInfo.dataId),
1631 data,
1632 Interface->u.SetSharedInfo.size
1635 else
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(
1652 Kernel->os,
1653 data,
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;
1665 else
1667 data = &node->Virtual.sharedInfo;
1670 gcmkONERROR(gckOS_CopyFromUserData(
1671 Kernel->os,
1672 data,
1673 Interface->u.SetSharedInfo.nodeData,
1674 sizeof(gcsVIDMEM_NODE_SHARED_INFO)
1678 break;
1680 default:
1681 /* Invalid command. */
1682 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1685 OnError:
1686 /* Save status. */
1687 Interface->status = status;
1689 if (gcmIS_ERROR(status))
1691 if (locked)
1693 /* Roll back the lock. */
1694 gcmkVERIFY_OK(
1695 gckVIDMEM_Unlock(Kernel,
1696 Interface->u.LockVideoMemory.node,
1697 gcvSURF_TYPE_UNKNOWN,
1698 &asynchronous));
1700 if (gcvTRUE == asynchronous)
1702 /* Bottom Half */
1703 gcmkVERIFY_OK(
1704 gckVIDMEM_Unlock(Kernel,
1705 Interface->u.LockVideoMemory.node,
1706 gcvSURF_TYPE_UNKNOWN,
1707 gcvNULL));
1712 #if QNX_SINGLE_THREADED_DEBUGGING
1713 gckOS_ReleaseMutex(Kernel->os, Kernel->debugMutex);
1714 #endif
1716 /* Return the status. */
1717 gcmkFOOTER();
1718 return status;
1721 /*******************************************************************************
1722 ** gckKERNEL_AttachProcess
1724 ** Attach or detach a process.
1726 ** INPUT:
1728 ** gckKERNEL Kernel
1729 ** Pointer to an gckKERNEL object.
1731 ** gctBOOL Attach
1732 ** gcvTRUE if a new process gets attached or gcFALSE when a process
1733 ** gets detatched.
1735 ** OUTPUT:
1737 ** Nothing.
1739 gceSTATUS
1740 gckKERNEL_AttachProcess(
1741 IN gckKERNEL Kernel,
1742 IN gctBOOL Attach
1745 gceSTATUS status;
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));
1758 /* Success. */
1759 gcmkFOOTER_NO();
1760 return gcvSTATUS_OK;
1762 OnError:
1763 /* Return the status. */
1764 gcmkFOOTER();
1765 return 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.
1774 ** INPUT:
1776 ** gckKERNEL Kernel
1777 ** Pointer to an gckKERNEL object.
1779 ** gctBOOL Attach
1780 ** gcvTRUE if a new process gets attached or gcFALSE when a process
1781 ** gets detatched.
1783 ** gctUINT32 PID
1784 ** PID of the process to attach or detach.
1786 ** OUTPUT:
1788 ** Nothing.
1790 gceSTATUS
1791 gckKERNEL_AttachProcessEx(
1792 IN gckKERNEL Kernel,
1793 IN gctBOOL Attach,
1794 IN gctUINT32 PID
1797 gceSTATUS status;
1798 gctINT32 old;
1800 gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel, Attach, PID);
1802 /* Verify the arguments. */
1803 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1805 if (Attach)
1807 /* Increment the number of clients attached. */
1808 gcmkONERROR(
1809 gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
1811 if (old == 0)
1813 #if gcdENABLE_VG
1814 if (Kernel->vg == gcvNULL)
1815 #endif
1817 gcmkONERROR(gckOS_Broadcast(Kernel->os,
1818 Kernel->hardware,
1819 gcvBROADCAST_FIRST_PROCESS));
1823 if (Kernel->dbCreated)
1825 /* Create the process database. */
1826 gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
1829 else
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. */
1841 gcmkONERROR(
1842 gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
1844 if (old == 1)
1846 #if gcdENABLE_VG
1847 if (Kernel->vg == gcvNULL)
1848 #endif
1850 /* Last client detached, switch to SUSPEND power state. */
1851 gcmkONERROR(gckOS_Broadcast(Kernel->os,
1852 Kernel->hardware,
1853 gcvBROADCAST_LAST_PROCESS));
1856 /* Flush the debug cache. */
1857 gcmkDEBUGFLUSH(~0U);
1861 /* Success. */
1862 gcmkFOOTER_NO();
1863 return gcvSTATUS_OK;
1865 OnError:
1866 /* Return the status. */
1867 gcmkFOOTER();
1868 return status;
1871 #if gcdSECURE_USER
1872 gceSTATUS
1873 gckKERNEL_MapLogicalToPhysical(
1874 IN gckKERNEL Kernel,
1875 IN gcskSECURE_CACHE_PTR Cache,
1876 IN OUT gctPOINTER * Data
1879 gceSTATUS status;
1880 static gctBOOL baseAddressValid = gcvFALSE;
1881 static gctUINT32 baseAddress;
1882 gctBOOL needBase;
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],
1902 &needBase));
1904 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
1906 gcskLOGICAL_CACHE_PTR next;
1907 gctINT i;
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)
1917 /* Bail out. */
1918 next = slot;
1919 break;
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. */
1933 gcmkONERROR(
1934 gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
1937 /* Move slot to head of list. */
1938 if (slot != Cache->cache[0].next)
1940 /* Unlink. */
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
1953 gctINT i;
1954 gcskLOGICAL_CACHE_PTR next = gcvNULL;
1955 gcskLOGICAL_CACHE_PTR oldestSlot = gcvNULL;
1956 slot = 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)
1967 /* Bail out. */
1968 next = slot;
1969 break;
1972 /* Determine age of this slot. */
1973 if ((oldestSlot == gcvNULL)
1974 || (oldestSlot->stamp > slot->stamp)
1977 oldestSlot = slot;
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)
1990 /* Bail out. */
1991 next = slot;
1992 break;
1995 /* Determine age of this slot. */
1996 if ((oldestSlot == gcvNULL)
1997 || (oldestSlot->stamp > slot->stamp)
2000 oldestSlot = slot;
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;
2020 else
2022 /* Use the oldest cache slot. */
2023 gcmkASSERT(oldestSlot != gcvNULL);
2024 slot = oldestSlot;
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. */
2041 gcmkONERROR(
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
2053 gctINT i;
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))
2072 break;
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. */
2095 gcmkONERROR(
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",
2102 *Data, key);
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)
2118 /* Unlink. */
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. */
2143 gcmkONERROR(
2144 gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
2147 #endif
2149 /* Return DMA address. */
2150 *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
2152 /* Success. */
2153 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2154 return gcvSTATUS_OK;
2156 OnError:
2157 /* Return the status. */
2158 gcmkFOOTER();
2159 return status;
2162 gceSTATUS
2163 gckKERNEL_FlushTranslationCache(
2164 IN gckKERNEL Kernel,
2165 IN gcskSECURE_CACHE_PTR Cache,
2166 IN gctPOINTER Logical,
2167 IN gctSIZE_T Bytes
2170 gctINT i;
2171 gcskLOGICAL_CACHE_PTR slot;
2172 gctUINT8_PTR ptr;
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;
2188 #endif
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;
2197 #endif
2199 /* Reset the cache functionality. */
2200 Cache->cacheIndex = gcvNULL;
2201 Cache->cacheFree = 1;
2202 Cache->cacheStamp = 0;
2205 else
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);
2216 ++i, slot = next
2219 /* Save pointer to next slot. */
2220 next = slot->next;
2222 /* Test if this slot falls within the range to flush. */
2223 ptr = (gctUINT8_PTR) slot->logical;
2224 if ((ptr >= low) && (ptr < high))
2226 /* Unlink slot. */
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);
2246 ++i, slot = next)
2248 /* Save pointer to next slot. */
2249 next = slot->next;
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)
2260 ? slot->next
2261 : (slot->prev->logical != gcvNULL)
2262 ? slot->prev
2263 : 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;
2278 slot->stamp = 0;
2282 #elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
2283 gctINT j;
2284 gcskLOGICAL_CACHE_PTR hash, next;
2286 /* Walk all hash tables. */
2287 for (i = 0, hash = Cache->hash;
2288 i < gcmCOUNTOF(Cache->hash);
2289 ++i, ++hash)
2291 /* Walk all slots in the hash. */
2292 for (j = 0, slot = hash->nextHash;
2293 (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
2294 ++j, slot = next)
2296 /* Save pointer to next slot. */
2297 next = slot->next;
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;
2308 else
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
2337 gctUINT32 index;
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;
2354 /* Next block. */
2355 low += gcdSECURE_CACHE_SLOTS;
2357 #endif
2360 /* Success. */
2361 gcmkFOOTER_NO();
2362 return gcvSTATUS_OK;
2364 #endif
2366 /*******************************************************************************
2368 ** gckKERNEL_Recovery
2370 ** Try to recover the GPU from a fatal error.
2372 ** INPUT:
2374 ** gckKERNEL Kernel
2375 ** Pointer to an gckKERNEL object.
2377 ** OUTPUT:
2379 ** Nothing.
2381 gceSTATUS
2382 gckKERNEL_Recovery(
2383 IN gckKERNEL Kernel
2386 #if gcdENABLE_RECOVERY
2387 gceSTATUS status;
2388 gckEVENT eventObj;
2389 gckHARDWARE hardware;
2390 #if gcdSECURE_USER
2391 gctUINT32 processID;
2392 gcskSECURE_CACHE_PTR cache;
2393 #endif
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));
2416 #if gcdSECURE_USER
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));
2421 #endif
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
2428 ** state. */
2429 gcmkONERROR(
2430 gckHARDWARE_SetPowerManagementState(hardware,
2431 gcvPOWER_OFF_RECOVERY));
2433 else
2435 /* Bail out on reset error. */
2436 gcmkONERROR(status);
2439 /* Success. */
2440 gcmkFOOTER_NO();
2441 return gcvSTATUS_OK;
2443 OnError:
2444 /* Return the status. */
2445 gcmkFOOTER();
2446 return status;
2447 #else
2448 return gcvSTATUS_OK;
2449 #endif
2452 /*******************************************************************************
2454 ** gckKERNEL_OpenUserData
2456 ** Get access to the user data.
2458 ** INPUT:
2460 ** gckKERNEL Kernel
2461 ** Pointer to an gckKERNEL object.
2463 ** gctBOOL NeedCopy
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.
2473 ** gctSIZE_T Size
2474 ** Size of the data.
2476 ** OUTPUT:
2478 ** gctPOINTER * KernelPointer
2479 ** Pointer to the kernel pointer that will be pointing to the data.
2481 gceSTATUS
2482 gckKERNEL_OpenUserData(
2483 IN gckKERNEL Kernel,
2484 IN gctBOOL NeedCopy,
2485 IN gctPOINTER StaticStorage,
2486 IN gctPOINTER UserPointer,
2487 IN gctSIZE_T Size,
2488 OUT gctPOINTER * KernelPointer
2491 gceSTATUS status;
2493 gcmkHEADER_ARG(
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);
2506 if (NeedCopy)
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;
2516 else
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;
2529 OnError:
2530 /* Return the status. */
2531 gcmkFOOTER();
2532 return status;
2535 /*******************************************************************************
2537 ** gckKERNEL_CloseUserData
2539 ** Release resources associated with the user data connection opened by
2540 ** gckKERNEL_OpenUserData.
2542 ** INPUT:
2544 ** gckKERNEL Kernel
2545 ** Pointer to an gckKERNEL object.
2547 ** gctBOOL NeedCopy
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.
2556 ** gctSIZE_T Size
2557 ** Size of the data.
2559 ** OUTPUT:
2561 ** gctPOINTER * KernelPointer
2562 ** Kernel pointer to the data.
2564 gceSTATUS
2565 gckKERNEL_CloseUserData(
2566 IN gckKERNEL Kernel,
2567 IN gctBOOL NeedCopy,
2568 IN gctBOOL FlushData,
2569 IN gctPOINTER UserPointer,
2570 IN gctSIZE_T Size,
2571 OUT gctPOINTER * KernelPointer
2574 gceSTATUS status = gcvSTATUS_OK;
2575 gctPOINTER pointer;
2577 gcmkHEADER_ARG(
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)
2594 if (NeedCopy)
2596 if (FlushData)
2598 gcmkONERROR(gckOS_CopyToUserData(
2599 Kernel->os, * KernelPointer, UserPointer, Size
2603 else
2605 /* Unmap record from kernel memory. */
2606 gcmkONERROR(gckOS_UnmapUserPointer(
2607 Kernel->os,
2608 UserPointer,
2609 Size,
2610 * KernelPointer
2614 /* Reset the kernel pointer. */
2615 * KernelPointer = gcvNULL;
2618 OnError:
2619 /* Return the status. */
2620 gcmkFOOTER();
2621 return status;
2624 void
2625 gckKERNEL_SetTimeOut(
2626 IN gckKERNEL Kernel,
2627 IN gctUINT32 timeOut
2630 gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
2631 #if gcdGPU_TIMEOUT
2632 Kernel->timeOut = timeOut;
2633 #endif
2634 gcmkFOOTER_NO();
2639 /*******************************************************************************
2640 ***** Test Code ****************************************************************
2641 *******************************************************************************/