static gctBOOL ReadSource( IN gcoOS Os, IN gctCONST_STRING FileName, OUT gctSIZE_T * SourceSize, OUT gctSTRING * Source ) { gceSTATUS status; gctFILE file; gctUINT32 count; gctSIZE_T byteRead; gctSTRING source; gcmASSERT(FileName); status = gcoOS_Open(Os, FileName, gcvFILE_READ, &file); if (gcmIS_ERROR(status)) { printf("*ERROR* Failed to open input file: %s\n", FileName); return gcvFALSE; } gcmVERIFY_OK(gcoOS_Seek(Os, file, 0, gcvFILE_SEEK_END)); gcmVERIFY_OK(gcoOS_GetPos(Os, file, &count)); status = gcoOS_Allocate(Os, count + 1, (gctPOINTER *) &source); if (!gcmIS_SUCCESS(status)) { printf("*ERROR* Not enough memory\n"); gcmVERIFY_OK(gcoOS_Close(Os, file)); return gcvFALSE; } gcmVERIFY_OK(gcoOS_SetPos(Os, file, 0)); status = gcoOS_Read(Os, file, count, source, &byteRead); if (!gcmIS_SUCCESS(status) || byteRead != count) { printf("*ERROR* Failed to open input file: %s\n", FileName); gcmVERIFY_OK(gcoOS_Close(Os, file)); return gcvFALSE; } source[count] = '\0'; gcmVERIFY_OK(gcoOS_Close(Os, file)); *SourceSize = count; *Source = source; return gcvTRUE; }
static gctINT _SearchKeyword( IN gctCONST_STRING Symbol ) { gctINT low, mid, high; gceSTATUS result; low = 0; high = KeywordCount - 1; while (low <= high) { mid = (low + high) / 2; result = gcoOS_StrCmp(Symbol, KeywordTable[mid].symbol); if (result == gcvSTATUS_SMALLER) { high = mid - 1; } else if (result == gcvSTATUS_LARGER) { low = mid + 1; } else { gcmASSERT(gcmIS_SUCCESS(result)); return KeywordTable[mid].token; } } return T_NOT_KEYWORD; }
static int __disable_gpufreq(gckGALDEVICE device) { gctUINT32 clockRate = 0; gceSTATUS status = gcvSTATUS_OK; int i; for(i = 0; i < gcdMAX_GPU_COUNT; i++) { if(device->kernels[i] != gcvNULL) { gckHARDWARE hardware = device->kernels[i]->hardware; if(!hardware->devObj.kobj) continue; gckOS_GPUFreqNotifierCallChain( device->os, GPUFREQ_GPU_EVENT_DESTORY, (gctPOINTER) &hardware->devObj); } } status = gckOS_QueryClkRate(device->os, gcvCORE_MAJOR, &clockRate); if(gcmIS_SUCCESS(status) && clockRate != 0) { gpufreq_exit(device->os); printk("[galcore] gpufreq exited\n"); } return 0; }
static gctINT GetShaderType( IN gctCONST_STRING FileName ) { gctCONST_STRING ext; gcmASSERT(FileName); ext = strrchr(FileName, '.'); if (ext != gcvNULL) { if (gcmIS_SUCCESS(gcoOS_StrNCmp(ext, ".frag", 4))) return gcSHADER_TYPE_FRAGMENT; if (gcmIS_SUCCESS(gcoOS_StrNCmp(ext, ".vert", 4))) return gcSHADER_TYPE_VERTEX; } return gcSHADER_TYPE_FRAGMENT; }
gceSTATUS vgsMEMORYMANAGER_Destroy( IN vgsMEMORYMANAGER_PTR Manager ) { gceSTATUS status; vgsMEMORYITEM_PTR current; vgsMEMORYITEM_PTR next; gcmHEADER_ARG("Manager=0x%x", Manager); /* Verify arguments. */ gcmVERIFY_ARGUMENT(Manager != gcvNULL); /* Assume success. */ status = gcvSTATUS_OK; /* Everything has to be freed. */ #if vgvVALIDATE_MEMORY_MANAGER gcmASSERT(Manager->allocatedCount == 0); #endif /* Destroy all allocated buffers. */ while (Manager->firstAllocated) { /* Get the current buffer. */ current = Manager->firstAllocated; /* Get the next buffer. */ next = current->next; /* Free the current. */ gcmERR_BREAK(gcoOS_Free(Manager->os, current)); /* Advance to the next one. */ Manager->firstAllocated = next; } /* Success? */ if (gcmIS_SUCCESS(status)) { status = gcoOS_Free(Manager->os, Manager); } gcmFOOTER(); /* Return status. */ return status; }
static gctBOOL OutputShaderData( IN gcoOS Os, IN gctCONST_STRING FileName, IN gctSIZE_T Size, IN gctCONST_STRING Data ) { gceSTATUS status; gctSTRING dataFileName; gctSIZE_T length; gctFILE file; gcmASSERT(FileName); gcmVERIFY_OK(gcoOS_StrLen(FileName, &length)); length += 6; gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName)); gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName)); gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".gcSL")); status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATE, &file); if (gcmIS_ERROR(status)) { gcoOS_Free(Os, dataFileName); printf("*ERROR* Failed to open the data file: %s\n", dataFileName); return gcvFALSE; } gcoOS_Free(Os, dataFileName); gcmASSERT(file); status = gcoOS_Write(Os, file, Size, Data); if (!gcmIS_SUCCESS(status)) { printf("*ERROR* Failed to write the data file: %s\n", dataFileName); goto ErrorExit; } gcmVERIFY_OK(gcoOS_Close(Os, file)); return gcvTRUE; ErrorExit: gcmVERIFY_OK(gcoOS_Close(Os, file)); return gcvFALSE; }
static irqreturn_t isrRoutine2D(int irq, void *ctxt) { gceSTATUS status; gckGALDEVICE device; device = (gckGALDEVICE) ctxt; /* Call kernel interrupt notification. */ status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE); if (gcmIS_SUCCESS(status)) { device->dataReadys[gcvCORE_2D] = gcvTRUE; up(&device->semas[gcvCORE_2D]); return IRQ_HANDLED; } return IRQ_NONE; }
glmENTER2(glmARGINT, Count, glmARGPTR, Buffers) { GLsizei i; glsNAMEDOBJECT_PTR wrapper; glmPROFILE(context, GLES1_GENBUFFERS, 0); /* Validate count. */ if (Count < 0) { glmERROR(GL_INVALID_VALUE); break; } /* Don't do anything if Buffers is NULL. */ if (Buffers == gcvNULL) { break; } /* Generate buffers. */ for (i = 0; i < Count; i++) { /* Create a new wrapper. */ if (gcmIS_SUCCESS(_CreateBuffer(context, 0, &wrapper))) { Buffers[i] = wrapper->name; } else { Buffers[i] = 0; } } gcmDUMP_API("${ES11 glGenBuffers 0x%08X (0x%08X)", Count, Buffers); gcmDUMP_API_ARRAY(Buffers, Count); gcmDUMP_API("$}"); }
int main( int argc, char * argv[] ) { gctBOOL dumpLog = gcvFALSE; gctSTRING fileName[2] = { gcvNULL, gcvNULL }; gcSHADER shaders[2] = { gcvNULL, gcvNULL }; gctINT i; gcoOS os = gcvNULL; gcoHAL hal = gcvNULL; gceSTATUS result; gctUINT option = 1; /* no optimization */ char outFile[128] = { '\0' }; char logVSFile[128] = { '\0' }; char logFSFile[128] = { '\0' }; printf("vCompile version 0.8, Copyright (c) 2005-2011, Vivante Corporation\n\n"); #ifdef _WIN32 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) /*| _CRTDBG_CHECK_ALWAYS_DF*/ | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); /* _CrtSetBreakAlloc(79); */ #endif #if gcdDEBUG gcoOS_SetDebugLevel(gcvLEVEL_VERBOSE); gcoOS_SetDebugZone(gcvZONE_COMPILER); #endif for (i = 1; i < argc; i++) { if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-l"))) { dumpLog = gcvTRUE; } else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O0"))) { /* Currently, optimization level is either FULL or NONE */ option = 0; /* no optimization */ } else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O"))) { option = 1; /* full optimization */ } else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-OT"))) { /* For optimization unit test */ if (i++ == argc) { printf("*ERROR* Optimization testing pattern not provided.\n"); return 1; } else { gctINT testPattern; gcmVERIFY_OK(gcoOS_StrToInt(argv[i], (gctINT *)&testPattern)); if (testPattern < 0) { printf("*ERROR* Unknown optimization testing pattern.\n"); return 1; } option = testPattern; } } else { if (fileName[0] == gcvNULL) fileName[0] = argv[i]; else if (fileName[1] == gcvNULL) fileName[1] = argv[i]; else { printf("*ERROR* Too many shaders.\n"); return 1; } } } if (fileName[0] == gcvNULL) { printf("Usage: %s [-l] [-O0] shaderFileName [shaderFileName]\n", argv[0]); printf(" -l Generate log file.\n" " -O0 Disable optimizations.\n" "\n" "If only one shader is specified, that shader will be compiled into a .gcSL\n" "file. If two shaders are specified, those shaders will be compiled and\n" "linked into a .gcPGM file. With two shaders, the vertex shader file needs\n" "to be the first.\n"); return 0; } result = gcoOS_Construct(gcvNULL, &os); if (result != gcvSTATUS_OK) { printf("*ERROR* Failed to construct a new gcoOS object\n"); return 1; } result = gcoHAL_Construct(gcvNULL, os, &hal); if (result != gcvSTATUS_OK) { printf("*ERROR* Failed to construct a new gcoHAL object\n"); goto ErrorExit; } /* Dump compile log only when one shader is present */ shaders[0] = CompileFile(os, fileName[0], hal, option, dumpLog && (fileName[1] == gcvNULL), fileName[1] == gcvNULL ); if (shaders[0] == gcvNULL) { goto ErrorExit; } if (fileName[1] != gcvNULL) { gctSIZE_T programBufferSize = 0; gctPOINTER programBuffer = gcvNULL; gcsHINT_PTR hints = gcvNULL; gceSTATUS status; gctPOINTER binary = gcvNULL; gctSIZE_T binarySize = 0; FILE * f; gctSTRING p; gcoOS_StrCopySafe(outFile, gcmSIZEOF(outFile), fileName[0]); p = strrchr(outFile, '.'); gcoOS_StrCopySafe(p, gcmSIZEOF(outFile) - (p - outFile), ".gcPGM"); gcoOS_StrCopySafe(logVSFile, gcmSIZEOF(logVSFile), fileName[0]); gcoOS_StrCatSafe(logVSFile, gcmSIZEOF(logVSFile), ".log"); gcoOS_StrCopySafe(logFSFile, gcmSIZEOF(logFSFile), fileName[1]); gcoOS_StrCatSafe(logFSFile, gcmSIZEOF(logFSFile), ".log"); shaders[1] = CompileFile(os, fileName[1], hal, option, gcvFALSE, gcvFALSE); if (shaders[1] == gcvNULL) { goto ErrorExit; } if ( dumpLog) { gcoOS_SetDebugShaderFiles(logVSFile, logFSFile); } status = gcLinkShaders(shaders[0], shaders[1], gcvSHADER_DEAD_CODE | gcvSHADER_RESOURCE_USAGE | gcvSHADER_OPTIMIZER | gcvSHADER_USE_GL_Z | gcvSHADER_USE_GL_POSITION | gcvSHADER_USE_GL_FACE, &programBufferSize, &programBuffer, &hints); if ( dumpLog) { gcoOS_SetDebugShaderFiles(gcvNULL, gcvNULL); } if (gcmIS_ERROR(status)) { printf("*ERROR* gcLinkShaders returned errror %d\n", status); } else { int ret; status = gcSaveProgram(shaders[0], shaders[1], programBufferSize, programBuffer, hints, &binary, &binarySize); if (gcmIS_ERROR(status)) { printf("*ERROR* gcSaveShaders returned errror %d\n", status); } f = fopen(outFile, "wb"); ret = fwrite(binary, binarySize, 1, f); if (ret); fclose(f); } if (programBuffer != gcvNULL) gcoOS_Free(os, programBuffer); if (hints != gcvNULL) gcoOS_Free(os, hints); if (binary != gcvNULL) gcoOS_Free(os, binary); } gcSHADER_Destroy(shaders[0]); if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]); gcoHAL_Destroy(hal); gcoOS_Destroy(os); return 0; ErrorExit: if (shaders[0] != gcvNULL) gcSHADER_Destroy(shaders[0]); if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]); if (gcvNULL != hal) gcoHAL_Destroy(hal); if (gcvNULL != os) gcoOS_Destroy(os); return 1; }
static gcSHADER CompileFile( IN gcoOS Os, IN gctCONST_STRING FileName, IN gcoHAL Hal, IN gctUINT Option, IN gctBOOL DumpLog, IN gctBOOL DumpCompiledShader ) { gceSTATUS status; gctINT shaderType; gctSIZE_T sourceSize; gctSTRING source = gcvNULL; gcSHADER binary; gctSTRING log = gcvNULL; gctSIZE_T bufferSize; gctSTRING buffer; gctSTRING dataFileName = gcvNULL; gctSIZE_T length; gctFILE logFile = gcvNULL; gcmASSERT(FileName); shaderType = GetShaderType(FileName); if (!ReadSource(Os, FileName, &sourceSize, &source)) return gcvNULL; status = gcCompileShader(Hal, shaderType, sourceSize, source, &binary, &log); if (log != gcvNULL) { printf("<LOG>\n"); printf("%s", log); printf("</LOG>\n"); } if (gcmIS_ERROR(status)) { gcmASSERT(binary == gcvNULL); binary = gcvNULL; printf("*ERROR* Failed to compile %s (error: %d)\n", FileName, status); goto Exit; } gcmASSERT(binary != gcvNULL); if (DumpLog) { gcmVERIFY_OK(gcoOS_StrLen(FileName, &length)); length += 5; gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName)); gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName)); gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".log")); status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATETEXT, &logFile); if (gcmIS_ERROR(status)) { logFile = gcvNULL; printf("*ERROR* Failed to open the log file: %s\n", dataFileName); } gcoOS_Free(Os, dataFileName); } gcmVERIFY_OK(gcSHADER_SetOptimizationOption(binary, Option)); status = gcOptimizeShader(binary, logFile); if (!gcmIS_SUCCESS(status)) { printf("*ERROR* Failed to optimize %s (error: %d)\n", FileName, status); } if (logFile != gcvNULL) { gcmVERIFY_OK(gcoOS_Close(Os, logFile)); } if (DumpCompiledShader) { status = gcSHADER_Save(binary, gcvNULL, &bufferSize); if (gcmIS_ERROR(status)) { printf("*ERROR* Failed to get the buffer size of the shader\n"); goto Exit; } status = gcoOS_Allocate(Os, bufferSize, (gctPOINTER *) &buffer); if (!gcmIS_SUCCESS(status)) { printf("*ERROR* Not enough memory\n"); goto Exit; } status = gcSHADER_Save(binary, buffer, &bufferSize); if (status != gcvSTATUS_OK) { printf("*ERROR* Failed to get the buffer size of the shader\n"); gcoOS_Free(Os, buffer); goto Exit; } OutputShaderData(Os, FileName, bufferSize, buffer); gcoOS_Free(Os, buffer); } Exit: if (DumpLog && log != gcvNULL) { printf("**************** Compile Log ****************"); printf("%s", log); printf("*********************************************"); } if (log != gcvNULL) gcoOS_Free(Os, log); if (source != gcvNULL) gcoOS_Free(Os, source); return binary; }
/******************************************************************************* ** ** gckCOMMAND_Commit ** ** Commit a command buffer to the command queue. ** ** INPUT: ** ** gckCOMMAND Command ** Pointer to an gckCOMMAND object. ** ** gcoCMDBUF CommandBuffer ** Pointer to an gcoCMDBUF object. ** ** gcoCONTEXT Context ** Pointer to an gcoCONTEXT object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckCOMMAND_Commit( IN gckCOMMAND Command, IN gcoCMDBUF CommandBuffer, IN gcoCONTEXT Context, IN gctHANDLE Process ) { gcoCMDBUF commandBuffer; gcoCONTEXT context; gckHARDWARE hardware; gceSTATUS status; gctPOINTER initialLink, link; gctSIZE_T bytes, initialSize, lastRun; gcoCMDBUF buffer; gctPOINTER wait; gctSIZE_T waitSize; gctUINT32 offset; gctPOINTER fetchAddress; gctSIZE_T fetchSize; gctUINT8_PTR logical; gcsMAPPED_PTR stack = gcvNULL; gctINT acquired = 0; #if gcdSECURE_USER gctUINT32_PTR hint; #endif #if gcdDUMP_COMMAND gctPOINTER dataPointer; gctSIZE_T dataBytes; #endif gctPOINTER flushPointer; gctSIZE_T flushSize; gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x Context=0x%x", Command, CommandBuffer, Context); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND); #if gcdNULL_DRIVER == 2 /* Do nothing with infinite hardware. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; #endif gcmkONERROR( _AddMap(Command->os, CommandBuffer, gcmSIZEOF(struct _gcoCMDBUF), (gctPOINTER *) &commandBuffer, &stack)); gcmkVERIFY_OBJECT(commandBuffer, gcvOBJ_COMMANDBUFFER); gcmkONERROR( _AddMap(Command->os, Context, gcmSIZEOF(struct _gcoCONTEXT), (gctPOINTER *) &context, &stack)); gcmkVERIFY_OBJECT(context, gcvOBJ_CONTEXT); /* Extract the gckHARDWARE and gckEVENT objects. */ hardware = Command->kernel->hardware; gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE); /* Acquire the context switching mutex. */ gcmkONERROR( gckOS_AcquireMutex(Command->os, Command->mutexContext, gcvINFINITE)); ++acquired; /* Reserved slot in the context or command buffer. */ gcmkONERROR( gckHARDWARE_PipeSelect(hardware, gcvNULL, 0, &bytes)); /* Test if we need to switch to this context. */ if ((context->id != 0) && (context->id != Command->currentContext) ) { /* Map the context buffer.*/ gcmkONERROR( _AddMap(Command->os, context->logical, context->bufferSize, (gctPOINTER *) &logical, &stack)); #if gcdSECURE_USER /* Map the hint array.*/ gcmkONERROR( _AddMap(Command->os, context->hintArray, context->hintCount * gcmSIZEOF(gctUINT32), (gctPOINTER *) &hint, &stack)); /* Loop while we have valid hints. */ while (*hint != 0) { /* Map handle into physical address. */ gcmkONERROR( gckKERNEL_MapLogicalToPhysical( Command->kernel, Process, (gctPOINTER *) (logical + *hint))); /* Next hint. */ ++hint; } #endif /* See if we have to check pipes. */ if (context->pipe2DIndex != 0) { /* See if we are in the correct pipe. */ if (context->initialPipe == Command->pipeSelect) { gctUINT32 reserved = bytes; gctUINT8_PTR nop = logical; /* Already in the correct pipe, fill context buffer with NOP. */ while (reserved > 0) { bytes = reserved; gcmkONERROR( gckHARDWARE_Nop(hardware, nop, &bytes)); gcmkASSERT(reserved >= bytes); reserved -= bytes; nop += bytes; } } else { /* Switch to the correct pipe. */ gcmkONERROR( gckHARDWARE_PipeSelect(hardware, logical, context->initialPipe, &bytes)); } } /* Save initial link pointer. */ initialLink = logical; initialSize = context->bufferSize; #if MRVL_PRINT_CMD_BUFFER _AddCmdBuffer( Command, initialLink, initialSize, gcvTRUE, gcvFALSE ); #endif /* Save initial buffer to flush. */ flushPointer = initialLink; flushSize = initialSize; /* Save pointer to next link. */ gcmkONERROR( _AddMap(Command->os, context->link, 8, &link, &stack)); /* Start parsing CommandBuffer. */ buffer = commandBuffer; /* Mark context buffer as used. */ if (context->inUse != gcvNULL) { gctBOOL_PTR inUse; gcmkONERROR( _AddMap(Command->os, (gctPOINTER) context->inUse, gcmSIZEOF(gctBOOL), (gctPOINTER *) &inUse, &stack)); *inUse = gcvTRUE; } } else { /* Test if this is a new context. */ if (context->id == 0) { /* Generate unique ID for the context buffer. */ context->id = ++ Command->contextCounter; if (context->id == 0) { /* Context counter overflow (wow!) */ gcmkONERROR(gcvSTATUS_TOO_COMPLEX); } } /* Map the command buffer. */ gcmkONERROR( _AddMap(Command->os, commandBuffer->logical, commandBuffer->offset, (gctPOINTER *) &logical, &stack)); #if gcdSECURE_USER /* Map the hint table. */ gcmkONERROR( _AddMap(Command->os, commandBuffer->hintCommit, commandBuffer->offset - commandBuffer->startOffset, (gctPOINTER *) &hint, &stack)); /* Walk while we have valid hints. */ while (*hint != 0) { /* Map the handle to a physical address. */ gcmkONERROR( gckKERNEL_MapLogicalToPhysical( Command->kernel, Process, (gctPOINTER *) (logical + *hint))); /* Next hint. */ ++hint; } #endif if (context->entryPipe == Command->pipeSelect) { gctUINT32 reserved = Command->reservedHead; gctUINT8_PTR nop = logical + commandBuffer->startOffset; /* Already in the correct pipe, fill context buffer with NOP. */ while (reserved > 0) { bytes = reserved; gcmkONERROR( gckHARDWARE_Nop(hardware, nop, &bytes)); gcmkASSERT(reserved >= bytes); reserved -= bytes; nop += bytes; } } else { /* Switch to the correct pipe. */ gcmkONERROR( gckHARDWARE_PipeSelect(hardware, logical + commandBuffer->startOffset, context->entryPipe, &bytes)); } /* Save initial link pointer. */ initialLink = logical + commandBuffer->startOffset; initialSize = commandBuffer->offset - commandBuffer->startOffset + Command->reservedTail; #if MRVL_PRINT_CMD_BUFFER _AddCmdBuffer( Command, initialLink, initialSize, gcvFALSE, gcvFALSE ); #endif /* Save initial buffer to flush. */ flushPointer = initialLink; flushSize = initialSize; /* Save pointer to next link. */ link = logical + commandBuffer->offset; /* No more data. */ buffer = gcvNULL; } #if MRVL_PRINT_CMD_BUFFER _AddLink(Command, Command->wait, initialLink); #endif #if gcdDUMP_COMMAND dataPointer = initialLink; dataBytes = initialSize; #endif /* Loop through all remaining command buffers. */ if (buffer != gcvNULL) { /* Map the command buffer. */ gcmkONERROR( _AddMap(Command->os, buffer->logical, buffer->offset + Command->reservedTail, (gctPOINTER *) &logical, &stack)); #if MRVL_PRINT_CMD_BUFFER _AddCmdBuffer( Command, (gctUINT32_PTR)logical, buffer->offset + Command->reservedTail, gcvFALSE, gcvFALSE ); #endif #if gcdSECURE_USER /* Map the hint table. */ gcmkONERROR( _AddMap(Command->os, buffer->hintCommit, buffer->offset - buffer->startOffset, (gctPOINTER *) &hint, &stack)); /* Walk while we have valid hints. */ while (*hint != 0) { /* Map the handle to a physical address. */ gcmkONERROR( gckKERNEL_MapLogicalToPhysical( Command->kernel, Process, (gctPOINTER *) (logical + *hint))); /* Next hint. */ ++hint; } #endif /* First slot becomes a NOP. */ { gctUINT32 reserved = Command->reservedHead; gctUINT8_PTR nop = logical + buffer->startOffset; /* Already in the correct pipe, fill context buffer with NOP. */ while (reserved > 0) { bytes = reserved; gcmkONERROR( gckHARDWARE_Nop(hardware, nop, &bytes)); gcmkASSERT(reserved >= bytes); reserved -= bytes; nop += bytes; } } /* Generate the LINK to this command buffer. */ gcmkONERROR( gckHARDWARE_Link(hardware, link, logical + buffer->startOffset, buffer->offset - buffer->startOffset + Command->reservedTail, &bytes)); #if MRVL_PRINT_CMD_BUFFER _AddLink(Command, link, (gctUINT32_PTR)logical); #endif /* Flush the initial buffer. */ gcmkONERROR(gckOS_CacheFlush(Command->os, Process, flushPointer, flushSize)); /* Save new flush pointer. */ flushPointer = logical + buffer->startOffset; flushSize = buffer->offset - buffer->startOffset + Command->reservedTail; #if gcdDUMP_COMMAND _DumpCommand(Command, dataPointer, dataBytes); dataPointer = logical + buffer->startOffset; dataBytes = buffer->offset - buffer->startOffset + Command->reservedTail; #endif /* Save pointer to next link. */ link = logical + buffer->offset; } /* Compute number of bytes required for WAIT/LINK. */ gcmkONERROR( gckHARDWARE_WaitLink(hardware, gcvNULL, Command->offset, &bytes, gcvNULL, gcvNULL)); lastRun = bytes; /* Grab the command queue mutex. */ gcmkONERROR( gckOS_AcquireMutex(Command->os, Command->mutexQueue, gcvINFINITE)); ++acquired; if (Command->kernel->notifyIdle) { /* Increase the commit stamp */ Command->commitStamp++; /* Set busy if idle */ if (Command->idle) { Command->idle = gcvFALSE; gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE)); } } /* Compute number of bytes left in current command queue. */ bytes = Command->pageSize - Command->offset; if (bytes < lastRun) { /* Create a new command queue. */ gcmkONERROR(_NewQueue(Command, gcvTRUE)); /* Adjust run size with any extra commands inserted. */ lastRun += Command->offset; } /* Get current offset. */ offset = Command->offset; /* Append WAIT/LINK in command queue. */ bytes = Command->pageSize - offset; gcmkONERROR( gckHARDWARE_WaitLink(hardware, (gctUINT8 *) Command->logical + offset, offset, &bytes, &wait, &waitSize)); /* Flush the cache for the wait/link. */ gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, (gctUINT8 *) Command->logical + offset, bytes)); #if gcdDUMP_COMMAND _DumpCommand(Command, (gctUINT8 *) Command->logical + offset, bytes); #endif /* Adjust offset. */ offset += bytes; if (Command->newQueue) { /* Compute fetch location and size for a new command queue. */ fetchAddress = Command->logical; fetchSize = offset; } else { /* Compute fetch location and size for an existing command queue. */ fetchAddress = (gctUINT8 *) Command->logical + Command->offset; fetchSize = offset - Command->offset; } bytes = 8; /* Link in WAIT/LINK. */ gcmkONERROR( gckHARDWARE_Link(hardware, link, fetchAddress, fetchSize, &bytes)); #if MRVL_PRINT_CMD_BUFFER _AddLink(Command, link, fetchAddress); #endif /* Flush the cache for the command buffer. */ gcmkONERROR(gckOS_CacheFlush(Command->os, Process, flushPointer, flushSize)); #if gcdDUMP_COMMAND _DumpCommand(Command, dataPointer, dataBytes); #endif /* Execute the entire sequence. */ gcmkONERROR( gckHARDWARE_Link(hardware, Command->wait, initialLink, initialSize, &Command->waitSize)); /* Flush the cache for the link. */ gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, Command->wait, Command->waitSize)); #if gcdDUMP_COMMAND _DumpCommand(Command, Command->wait, Command->waitSize); #endif /* Update command queue offset. */ Command->offset = offset; Command->newQueue = gcvFALSE; /* Update address of last WAIT. */ Command->wait = wait; Command->waitSize = waitSize; /* Update context and pipe select. */ Command->currentContext = context->id; Command->pipeSelect = context->currentPipe; /* Update queue tail pointer. */ gcmkONERROR( gckHARDWARE_UpdateQueueTail(hardware, Command->logical, Command->offset)); #if gcdDUMP_COMMAND gcmkPRINT("@[kernel.commit]"); #endif /* Release the command queue mutex. */ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue)); --acquired; /* Release the context switching mutex. */ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext)); --acquired; /* Submit events if asked for. */ if (Command->submit) { /* Submit events. */ status = gckEVENT_Submit(Command->kernel->event, gcvFALSE, gcvFALSE); if (gcmIS_SUCCESS(status)) { /* Success. */ Command->submit = gcvFALSE; } else { gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND, "gckEVENT_Submit returned %d", status); } } /* Success. */ status = gcvSTATUS_OK; OnError: if (acquired > 1) { /* Release the command queue mutex. */ gcmkVERIFY_OK( gckOS_ReleaseMutex(Command->os, Command->mutexQueue)); } if (acquired > 0) { /* Release the context switching mutex. */ gcmkVERIFY_OK( gckOS_ReleaseMutex(Command->os, Command->mutexContext)); } /* Unmap all mapped pointers. */ while (stack != gcvNULL) { gcsMAPPED_PTR map = stack; stack = map->next; gcmkVERIFY_OK( gckOS_UnmapUserPointer(Command->os, map->pointer, map->bytes, map->kernelPointer)); gcmkVERIFY_OK( gckOS_Free(Command->os, map)); } /* Return status. */ gcmkFOOTER(); return status; }
/******************************************************************************* ** ** gckKERNEL_AllocateLinearMemory ** ** Function walks all required memory pools and allocates the requested ** amount of video memory. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gcePOOL * Pool ** Pointer the desired memory pool. ** ** gctSIZE_T Bytes ** Number of bytes to allocate. ** ** gctSIZE_T Alignment ** Required buffer alignment. ** ** gceSURF_TYPE Type ** Surface type. ** ** OUTPUT: ** ** gcePOOL * Pool ** Pointer to the actual pool where the memory was allocated. ** ** gcuVIDMEM_NODE_PTR * Node ** Allocated node. */ gceSTATUS gckKERNEL_AllocateLinearMemory( IN gckKERNEL Kernel, IN OUT gcePOOL * Pool, IN gctSIZE_T Bytes, IN gctSIZE_T Alignment, IN gceSURF_TYPE Type, OUT gcuVIDMEM_NODE_PTR * Node ) { gcePOOL pool; gceSTATUS status; gckVIDMEM videoMemory; /* Get initial pool. */ switch (pool = *Pool) { case gcvPOOL_DEFAULT: case gcvPOOL_LOCAL: pool = gcvPOOL_LOCAL_INTERNAL; break; case gcvPOOL_UNIFIED: pool = gcvPOOL_SYSTEM; break; default: break; } do { /* Verify the number of bytes to allocate. */ if (Bytes == 0) { status = gcvSTATUS_INVALID_ARGUMENT; break; } if (pool == gcvPOOL_VIRTUAL) { /* Create a gcuVIDMEM_NODE for virtual memory. */ gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node)); /* Success. */ break; } else { /* Get pointer to gckVIDMEM object for pool. */ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory); if (status == gcvSTATUS_OK) { /* Allocate memory. */ status = gckVIDMEM_AllocateLinear(Kernel, videoMemory, Bytes, Alignment, Type, Node); if (status == gcvSTATUS_OK) { /* Memory allocated. */ break; } } } if (pool == gcvPOOL_LOCAL_INTERNAL) { /* Advance to external memory. */ pool = gcvPOOL_LOCAL_EXTERNAL; } else if (pool == gcvPOOL_LOCAL_EXTERNAL) { /* Advance to contiguous system memory. */ pool = gcvPOOL_SYSTEM; } else if (pool == gcvPOOL_SYSTEM) { /* Advance to virtual memory. */ pool = gcvPOOL_VIRTUAL; } else { /* Out of pools. */ break; } } /* Loop only for multiple selection pools. */ while ((*Pool == gcvPOOL_DEFAULT) || (*Pool == gcvPOOL_LOCAL) || (*Pool == gcvPOOL_UNIFIED) ); if (gcmIS_SUCCESS(status)) { /* Return pool used for allocation. */ *Pool = pool; } /* Return status. */ return status; }
/******************************************************************************* ** ** _AllocateMemory ** ** Private function to walk all required memory pools to allocate the requested ** amount of video memory. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gcsHAL_INTERFACE * Interface ** Pointer to a gcsHAL_INTERFACE structure that defines the command to ** be dispatched. ** ** OUTPUT: ** ** gcsHAL_INTERFACE * Interface ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be ** returned. */ static gceSTATUS _AllocateMemory( IN gckKERNEL Kernel, IN OUT gcePOOL * Pool, IN gctSIZE_T Bytes, IN gctSIZE_T Alignment, IN gceSURF_TYPE Type, #ifdef __QNXNTO__ IN gctHANDLE Handle, #endif OUT gcuVIDMEM_NODE_PTR * Node ) { gcePOOL pool; gceSTATUS status; gckVIDMEM videoMemory; gcmkVERIFY_ARGUMENT(Pool != gcvNULL); /* Get initial pool. */ switch (pool = *Pool) { case gcvPOOL_DEFAULT: case gcvPOOL_LOCAL: pool = gcvPOOL_LOCAL_INTERNAL; break; case gcvPOOL_UNIFIED: pool = gcvPOOL_SYSTEM; break; default: break; } do { /* Verify the number of bytes to allocate. */ if (Bytes == 0) { gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT); } if (pool == gcvPOOL_VIRTUAL) { /* Create a gcuVIDMEM_NODE for virtual memory. */ #ifdef __QNXNTO__ gcmkERR_BREAK( gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Handle, Node)); #else gcmkERR_BREAK( gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node)); #endif /* Success. */ break; } else if (pool == gcvPOOL_CONTIGUOUS) { /* Create a gcuVIDMEM_NODE for contiguous memory. */ #ifdef __QNXNTO__ status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Handle, Node); #else status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Node); #endif if (gcmIS_SUCCESS(status)) { /* Memory allocated. */ break; } } else { /* Get pointer to gckVIDMEM object for pool. */ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory); if (gcmIS_SUCCESS(status)) { /* Allocate memory. */ status = gckVIDMEM_AllocateLinear(videoMemory, Bytes, Alignment, Type, #ifdef __QNXNTO__ Handle, #endif Node); if (gcmIS_SUCCESS(status)) { /* Memory allocated. */ (*Node)->VidMem.pool = pool; break; } } } if (pool == gcvPOOL_LOCAL_INTERNAL) { /* Advance to external memory. */ pool = gcvPOOL_LOCAL_EXTERNAL; } else if (pool == gcvPOOL_LOCAL_EXTERNAL) { /* Advance to contiguous system memory. */ pool = gcvPOOL_SYSTEM; } else if (pool == gcvPOOL_SYSTEM) { /* Advance to contiguous memory. */ pool = gcvPOOL_CONTIGUOUS; } else if ((pool == gcvPOOL_CONTIGUOUS) && (Type != gcvSURF_TILE_STATUS) ) { static int count= 1; /* Advance to virtual memory. */ if (count == 1) { gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL, "Try to allocate virtual memory!\n"); count = 0; } pool = gcvPOOL_VIRTUAL; } else { /* Out of pools. */ break; } } /* Loop only for multiple selection pools. */ while ((*Pool == gcvPOOL_DEFAULT) || (*Pool == gcvPOOL_LOCAL) || (*Pool == gcvPOOL_UNIFIED) ); if (gcmIS_SUCCESS(status)) { /* Return pool used for allocation. */ *Pool = pool; } /* Return status. */ return status; }
/******************************************************************************* ** ** gckGALDEVICE_Construct ** ** Constructor. ** ** INPUT: ** ** OUTPUT: ** ** gckGALDEVICE * Device ** Pointer to a variable receiving the gckGALDEVICE object pointer on ** success. */ gceSTATUS gckGALDEVICE_Construct( IN gctINT IrqLine, IN gctUINT32 RegisterMemBase, IN gctSIZE_T RegisterMemSize, IN gctINT IrqLine2D, IN gctUINT32 RegisterMemBase2D, IN gctSIZE_T RegisterMemSize2D, IN gctINT IrqLineVG, IN gctUINT32 RegisterMemBaseVG, IN gctSIZE_T RegisterMemSizeVG, IN gctUINT32 ContiguousBase, IN gctSIZE_T ContiguousSize, IN gctSIZE_T BankSize, IN gctINT FastClear, IN gctINT Compression, IN gctUINT32 PhysBaseAddr, IN gctUINT32 PhysSize, IN gctINT Signal, OUT gckGALDEVICE *Device ) { gctUINT32 internalBaseAddress = 0, internalAlignment = 0; gctUINT32 externalBaseAddress = 0, externalAlignment = 0; gctUINT32 horizontalTileSize, verticalTileSize; struct resource* mem_region; gctUINT32 physAddr; gctUINT32 physical; gckGALDEVICE device; gceSTATUS status; gctINT32 i; gceHARDWARE_TYPE type; gckDB sharedDB = gcvNULL; gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u " "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u " "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u " "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu " "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d", IrqLine, RegisterMemBase, RegisterMemSize, IrqLine2D, RegisterMemBase2D, RegisterMemSize2D, IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG, ContiguousBase, ContiguousSize, BankSize, FastClear, Compression, PhysBaseAddr, PhysSize, Signal); /* Allocate device structure. */ device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN); if (!device) { gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); } memset(device, 0, sizeof(struct _gckGALDEVICE)); if (IrqLine != -1) { device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase; device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize; } if (IrqLine2D != -1) { device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D; device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D; } if (IrqLineVG != -1) { device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG; device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG; } device->requestedContiguousBase = 0; device->requestedContiguousSize = 0; for (i = 0; i < gcdCORE_COUNT; i++) { physical = device->requestedRegisterMemBases[i]; /* Set up register memory region. */ if (physical != 0) { mem_region = request_mem_region( physical, device->requestedRegisterMemSizes[i], "galcore register region" ); #if 0 if (mem_region == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to claim %lu bytes @ 0x%08X\n", __FUNCTION__, __LINE__, physical, device->requestedRegisterMemSizes[i] ); gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } #endif device->registerBases[i] = (gctPOINTER) ioremap_nocache( physical, device->requestedRegisterMemSizes[i]); if (device->registerBases[i] == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Unable to map %ld bytes @ 0x%08X\n", __FUNCTION__, __LINE__, physical, device->requestedRegisterMemSizes[i] ); gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } physical += device->requestedRegisterMemSizes[i]; } else { device->registerBases[i] = gcvNULL; } } /* Set the base address */ device->baseAddress = PhysBaseAddr; /* Construct the gckOS object. */ gcmkONERROR(gckOS_Construct(device, &device->os)); if (IrqLine != -1) { /* Construct the gckKERNEL object. */ gcmkONERROR(gckKERNEL_Construct( device->os, gcvCORE_MAJOR, device, gcvNULL, &device->kernels[gcvCORE_MAJOR])); sharedDB = device->kernels[gcvCORE_MAJOR]->db; /* Initialize core mapping */ for (i = 0; i < 8; i++) { device->coreMapping[i] = gcvCORE_MAJOR; } /* Setup the ISR manager. */ gcmkONERROR(gckHARDWARE_SetIsrManager( device->kernels[gcvCORE_MAJOR]->hardware, (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR, (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR, device )); gcmkONERROR(gckHARDWARE_SetFastClear( device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression )); #if COMMAND_PROCESSOR_VERSION == 1 /* Start the command queue. */ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command)); #endif } else { device->kernels[gcvCORE_MAJOR] = gcvNULL; } if (IrqLine2D != -1) { gcmkONERROR(gckKERNEL_Construct( device->os, gcvCORE_2D, device, sharedDB, &device->kernels[gcvCORE_2D])); if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db; /* Verify the hardware type */ gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type)); if (type != gcvHARDWARE_2D) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Unexpected hardware type: %d\n", __FUNCTION__, __LINE__, type ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } /* Initialize core mapping */ if (device->kernels[gcvCORE_MAJOR] == gcvNULL) { for (i = 0; i < 8; i++) { device->coreMapping[i] = gcvCORE_2D; } } else { device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D; } /* Setup the ISR manager. */ gcmkONERROR(gckHARDWARE_SetIsrManager( device->kernels[gcvCORE_2D]->hardware, (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D, (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D, device )); #if COMMAND_PROCESSOR_VERSION == 1 /* Start the command queue. */ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command)); #endif } else { device->kernels[gcvCORE_2D] = gcvNULL; } if (IrqLineVG != -1) { #if gcdENABLE_VG gcmkONERROR(gckKERNEL_Construct( device->os, gcvCORE_VG, device, sharedDB, &device->kernels[gcvCORE_VG])); /* Initialize core mapping */ if (device->kernels[gcvCORE_MAJOR] == gcvNULL && device->kernels[gcvCORE_2D] == gcvNULL ) { for (i = 0; i < 8; i++) { device->coreMapping[i] = gcvCORE_VG; } } else { device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG; } #endif } else { device->kernels[gcvCORE_VG] = gcvNULL; } /* Initialize the ISR. */ device->irqLines[gcvCORE_MAJOR] = IrqLine; device->irqLines[gcvCORE_2D] = IrqLine2D; device->irqLines[gcvCORE_VG] = IrqLineVG; /* Initialize the kernel thread semaphores. */ for (i = 0; i < gcdCORE_COUNT; i++) { if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0); } device->signal = Signal; for (i = 0; i < gcdCORE_COUNT; i++) { if (device->kernels[i] != gcvNULL) break; } if (i == gcdCORE_COUNT) gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); #if gcdENABLE_VG if (i == gcvCORE_VG) { /* Query the ceiling of the system memory. */ gcmkONERROR(gckVGHARDWARE_QuerySystemMemory( device->kernels[i]->vg->hardware, &device->systemMemorySize, &device->systemMemoryBaseAddress )); /* query the amount of video memory */ gcmkONERROR(gckVGHARDWARE_QueryMemory( device->kernels[i]->vg->hardware, &device->internalSize, &internalBaseAddress, &internalAlignment, &device->externalSize, &externalBaseAddress, &externalAlignment, &horizontalTileSize, &verticalTileSize )); } else #endif { /* Query the ceiling of the system memory. */ gcmkONERROR(gckHARDWARE_QuerySystemMemory( device->kernels[i]->hardware, &device->systemMemorySize, &device->systemMemoryBaseAddress )); /* query the amount of video memory */ gcmkONERROR(gckHARDWARE_QueryMemory( device->kernels[i]->hardware, &device->internalSize, &internalBaseAddress, &internalAlignment, &device->externalSize, &externalBaseAddress, &externalAlignment, &horizontalTileSize, &verticalTileSize )); } /* Set up the internal memory region. */ if (device->internalSize > 0) { status = gckVIDMEM_Construct( device->os, internalBaseAddress, device->internalSize, internalAlignment, 0, &device->internalVidMem ); if (gcmIS_ERROR(status)) { /* Error, disable internal heap. */ device->internalSize = 0; } else { /* Map internal memory. */ device->internalLogical = (gctPOINTER) ioremap_nocache(physical, device->internalSize); if (device->internalLogical == gcvNULL) { gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } device->internalPhysical = (gctPHYS_ADDR) physical; physical += device->internalSize; } } if (device->externalSize > 0) { /* create the external memory heap */ status = gckVIDMEM_Construct( device->os, externalBaseAddress, device->externalSize, externalAlignment, 0, &device->externalVidMem ); if (gcmIS_ERROR(status)) { /* Error, disable internal heap. */ device->externalSize = 0; } else { /* Map external memory. */ device->externalLogical = (gctPOINTER) ioremap_nocache(physical, device->externalSize); if (device->externalLogical == gcvNULL) { gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } device->externalPhysical = (gctPHYS_ADDR) physical; physical += device->externalSize; } } /* set up the contiguous memory */ device->contiguousSize = ContiguousSize; if (ContiguousSize > 0) { if (ContiguousBase == 0) { while (device->contiguousSize > 0) { /* Allocate contiguous memory. */ status = _AllocateMemory( device, device->contiguousSize, &device->contiguousBase, &device->contiguousPhysical, &physAddr ); if (gcmIS_SUCCESS(status)) { status = gckVIDMEM_Construct( device->os, physAddr | device->systemMemoryBaseAddress, device->contiguousSize, 64, BankSize, &device->contiguousVidMem ); if (gcmIS_SUCCESS(status)) { break; } gcmkONERROR(_FreeMemory( device, device->contiguousBase, device->contiguousPhysical )); device->contiguousBase = gcvNULL; device->contiguousPhysical = gcvNULL; } if (device->contiguousSize <= (4 << 20)) { device->contiguousSize = 0; } else { device->contiguousSize -= (4 << 20); } } } else { /* Create the contiguous memory heap. */ status = gckVIDMEM_Construct( device->os, (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress, ContiguousSize, 64, BankSize, &device->contiguousVidMem ); if (gcmIS_ERROR(status)) { /* Error, disable contiguous memory pool. */ device->contiguousVidMem = gcvNULL; device->contiguousSize = 0; } else { mem_region = request_mem_region( ContiguousBase, ContiguousSize, "galcore managed memory" ); #if 0 if (mem_region == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to claim %ld bytes @ 0x%08X\n", __FUNCTION__, __LINE__, ContiguousSize, ContiguousBase ); gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } #endif device->requestedContiguousBase = ContiguousBase; device->requestedContiguousSize = ContiguousSize; #if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG if (gcmIS_CORE_PRESENT(device, gcvCORE_VG)) { device->contiguousBase #if gcdPAGED_MEMORY_CACHEABLE = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize); #else = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize); #endif if (device->contiguousBase == gcvNULL) { device->contiguousVidMem = gcvNULL; device->contiguousSize = 0; gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } } #endif device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase; device->contiguousSize = ContiguousSize; device->contiguousMapped = gcvTRUE; } } }
/******************************************************************************* ** gckKERNEL_DestroyProcessDB ** ** Destroy a process database. If the database contains any records, the data ** inside those records will be deleted as well. This aids in the cleanup if ** a process has died unexpectedly or has memory leaks. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to a gckKERNEL object. ** ** gctUINT32 ProcessID ** Process ID used to identify the database. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckKERNEL_DestroyProcessDB( IN gckKERNEL Kernel, IN gctUINT32 ProcessID ) { gceSTATUS status; gcsDATABASE_PTR database; gcsDATABASE_RECORD_PTR record, next; gctBOOL asynchronous; gctPHYS_ADDR physical; gcuVIDMEM_NODE_PTR node; gckKERNEL kernel = Kernel; gctUINT32 i; gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); /* Find the database. */ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database)); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE, "DB(%d): VidMem: total=%lu max=%lu", ProcessID, database->vidMem.totalBytes, database->vidMem.maxBytes); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE, "DB(%d): NonPaged: total=%lu max=%lu", ProcessID, database->nonPaged.totalBytes, database->nonPaged.maxBytes); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE, "DB(%d): Contiguous: total=%lu max=%lu", ProcessID, database->contiguous.totalBytes, database->contiguous.maxBytes); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE, "DB(%d): Idle time=%llu", ProcessID, Kernel->db->idleTime); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE, "DB(%d): Map: total=%lu max=%lu", ProcessID, database->mapMemory.totalBytes, database->mapMemory.maxBytes); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE, "DB(%d): Map: total=%lu max=%lu", ProcessID, database->mapUserMemory.totalBytes, database->mapUserMemory.maxBytes); if (database->list != gcvNULL) { gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "Process %d has entries in its database:", ProcessID); } for(i = 0; i < gcmCOUNTOF(database->list); i++) { /* Walk all records. */ for (record = database->list[i]; record != gcvNULL; record = next) { /* Next next record. */ next = record->next; /* Dispatch on record type. */ switch (record->type) { case gcvDB_VIDEO_MEMORY: /* Free the video memory. */ status = gckVIDMEM_Free(gcmUINT64_TO_PTR(record->data)); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: VIDEO_MEMORY 0x%x (status=%d)", record->data, status); break; case gcvDB_NON_PAGED: physical = gcmNAME_TO_PTR(record->physical); /* Unmap user logical memory first. */ status = gckOS_UnmapUserLogical(Kernel->os, physical, record->bytes, record->data); /* Free the non paged memory. */ status = gckOS_FreeNonPagedMemory(Kernel->os, record->bytes, physical, record->data); gcmRELEASE_NAME(record->physical); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)", record->data, record->bytes, status); break; #if gcdVIRTUAL_COMMAND_BUFFER case gcvDB_COMMAND_BUFFER: /* Free the command buffer. */ status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj, record->bytes, gcmNAME_TO_PTR(record->physical), record->data, gcvKERNEL_PIXEL); gcmRELEASE_NAME(record->physical); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)", record->data, record->bytes, status); break; #endif case gcvDB_CONTIGUOUS: physical = gcmNAME_TO_PTR(record->physical); /* Unmap user logical memory first. */ status = gckOS_UnmapUserLogical(Kernel->os, physical, record->bytes, record->data); /* Free the contiguous memory. */ status = gckEVENT_FreeContiguousMemory(Kernel->eventObj, record->bytes, physical, record->data, gcvKERNEL_PIXEL); gcmRELEASE_NAME(record->physical); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)", record->data, record->bytes, status); break; case gcvDB_SIGNAL: #if USE_NEW_LINUX_SIGNAL status = gcvSTATUS_NOT_SUPPORTED; #else /* Free the user signal. */ status = gckOS_DestroyUserSignal(Kernel->os, gcmPTR2INT(record->data)); #endif /* USE_NEW_LINUX_SIGNAL */ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: SIGNAL %d (status=%d)", (gctINT)(gctUINTPTR_T)record->data, status); break; case gcvDB_VIDEO_MEMORY_LOCKED: node = gcmUINT64_TO_PTR(record->data); /* Unlock what we still locked */ status = gckVIDMEM_Unlock(record->kernel, node, gcvSURF_TYPE_UNKNOWN, &asynchronous); if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous)) { /* TODO: we maybe need to schedule a event here */ status = gckVIDMEM_Unlock(record->kernel, node, gcvSURF_TYPE_UNKNOWN, gcvNULL); } gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)", node, status); break; case gcvDB_CONTEXT: /* TODO: Free the context */ status = gckCOMMAND_Detach(Kernel->command, gcmNAME_TO_PTR(record->data)); gcmRELEASE_NAME(record->data); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: CONTEXT 0x%x (status=%d)", record->data, status); break; case gcvDB_MAP_MEMORY: /* Unmap memory. */ status = gckKERNEL_UnmapMemory(Kernel, record->physical, record->bytes, record->data); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: MAP MEMORY %d (status=%d)", gcmPTR2INT(record->data), status); break; case gcvDB_MAP_USER_MEMORY: /* TODO: Unmap user memory. */ status = gckOS_UnmapUserMemory(Kernel->os, Kernel->core, record->physical, record->bytes, gcmNAME_TO_PTR(record->data), 0); gcmRELEASE_NAME(record->data); gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE, "DB: MAP USER MEMORY %d (status=%d)", gcmPTR2INT(record->data), status); break; case gcvDB_SHARED_INFO: status = gckOS_FreeMemory(Kernel->os, record->physical); break; default: gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE, "DB: Correcupted record=0x%08x type=%d", record, record->type); break; } /* Delete the record. */ gcmkONERROR(gckKERNEL_DeleteRecord(Kernel, database, record->type, record->data, gcvNULL)); } } /* Delete the database. */ gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database)); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmkFOOTER(); return status; }
gceSTATUS ppoPREPROCESSOR_MacroExpand_2_NoFormalArgs( ppoPREPROCESSOR PP, ppoINPUT_STREAM *IS, ppoTOKEN *Head, ppoTOKEN *End, gctBOOL *AnyExpanationHappened, gctBOOL *MatchCase, ppoTOKEN ID, ppoMACRO_SYMBOL MS) { gceSTATUS status = gcvSTATUS_INVALID_DATA; ppoTOKEN id = ID; ppoMACRO_SYMBOL ms = MS; ppoTOKEN replacement_list = gcvNULL; gcmHEADER_ARG("PP=0x%x IS=0x%x Head=0x%x End=0x%x AnyExpanationHappened=0x%x MatchCase=0x%x ID=0x%x MS=0x%x", PP, IS, Head, End, AnyExpanationHappened, MatchCase, ID, MS); gcmASSERT(ms != gcvNULL); if (ms->argc == 0) { gcmTRACE(gcvLEVEL_VERBOSE, "ME : macro %s has no arg(s).",id->poolString); if (ms->replacementList == gcvNULL) { gcmTRACE(gcvLEVEL_VERBOSE, "ME : macro %s, has no replacement-list.",id->poolString); *Head = gcvNULL; *End = gcvNULL; *AnyExpanationHappened = gcvTRUE; *MatchCase = gcvTRUE; status = ppoTOKEN_Destroy(PP,id); if (gcmIS_SUCCESS(status)) { gcmFOOTER_ARG("*Head=0x%x *End=0x%x *AnyExpanationHappened=%d *MatchCase=%d", *Head, *End, *AnyExpanationHappened, *MatchCase); return gcvSTATUS_OK; } else { gcmFOOTER(); return status; } } gcmTRACE(gcvLEVEL_VERBOSE, "ME : macro %s, has replacement-list.",id->poolString); gcmTRACE(gcvLEVEL_VERBOSE, "ME : macro %s, colon replacement-list.",id->poolString); gcmONERROR(ppoTOKEN_ColonTokenList( PP, ms->replacementList, __FILE__, __LINE__, "ME : colon replacementList", &replacement_list) ); *Head = replacement_list; gcmTRACE(gcvLEVEL_VERBOSE, "ME : macro %s, add hs.",id->poolString); while(replacement_list) { gcmASSERT(replacement_list->hideSet == gcvNULL); ppoHIDE_SET_LIST_Append( PP, replacement_list, id); ppoHIDE_SET_AddHS(PP, replacement_list, id->poolString); if((void*)replacement_list->inputStream.base.node.prev == gcvNULL) { *End = replacement_list; } replacement_list = (ppoTOKEN)replacement_list->inputStream.base.node.prev; } *AnyExpanationHappened = gcvTRUE; *MatchCase = gcvTRUE; status = ppoTOKEN_Destroy(PP,id); if (gcmIS_SUCCESS(status)) { gcmFOOTER_ARG("*Head=0x%x *End=0x%x *AnyExpanationHappened=%d *MatchCase=%d", *Head, *End, *AnyExpanationHappened, *MatchCase); return gcvSTATUS_OK; } else { gcmFOOTER(); return status; } } else/*if (ms->argc == 0)*/ { *Head = gcvNULL; *End = gcvNULL; *AnyExpanationHappened = gcvFALSE; *MatchCase = gcvFALSE; gcmFOOTER_ARG("*Head=0x%x *End=0x%x *AnyExpanationHappened=%d *MatchCase=%d", *Head, *End, *AnyExpanationHappened, *MatchCase); return gcvSTATUS_OK; } OnError: gcmFOOTER(); return status; }
/******************************************************************************* ** ** gckGALDEVICE_Construct ** ** Constructor. ** ** INPUT: ** ** OUTPUT: ** ** gckGALDEVICE * Device ** Pointer to a variable receiving the gckGALDEVICE object pointer on ** success. */ gceSTATUS gckGALDEVICE_Construct( IN gctINT IrqLine, IN gctUINT32 RegisterMemBase, IN gctSIZE_T RegisterMemSize, IN gctINT IrqLine2D, IN gctUINT32 RegisterMemBase2D, IN gctSIZE_T RegisterMemSize2D, IN gctINT IrqLineVG, IN gctUINT32 RegisterMemBaseVG, IN gctSIZE_T RegisterMemSizeVG, IN gctUINT32 ContiguousBase, IN gctSIZE_T ContiguousSize, IN gctSIZE_T BankSize, IN gctINT FastClear, IN gctINT Compression, IN gctUINT32 PhysBaseAddr, IN gctUINT32 PhysSize, IN gctINT Signal, IN gctUINT LogFileSize, IN struct device *pdev, IN gctINT PowerManagement, OUT gckGALDEVICE *Device ) { gctUINT32 internalBaseAddress = 0, internalAlignment = 0; gctUINT32 externalBaseAddress = 0, externalAlignment = 0; gctUINT32 horizontalTileSize, verticalTileSize; struct resource* mem_region; gctUINT32 physAddr; gctUINT32 physical; gckGALDEVICE device; gceSTATUS status; gctINT32 i; gceHARDWARE_TYPE type; gckDB sharedDB = gcvNULL; gckKERNEL kernel = gcvNULL; gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u " "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u " "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u " "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu " "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d", IrqLine, RegisterMemBase, RegisterMemSize, IrqLine2D, RegisterMemBase2D, RegisterMemSize2D, IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG, ContiguousBase, ContiguousSize, BankSize, FastClear, Compression, PhysBaseAddr, PhysSize, Signal); /* Allocate device structure. */ device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN); if (!device) { gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); } memset(device, 0, sizeof(struct _gckGALDEVICE)); device->dbgnode = gcvNULL; if(LogFileSize != 0) { if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to create the debug file system %s/%s \n", __FUNCTION__, __LINE__, PARENT_FILE, DEBUG_FILE ); } else { /*Everything is OK*/ gckDebugFileSystemSetCurrentNode(device->dbgnode); } } #ifdef CONFIG_PM /*Init runtime pm for gpu*/ pm_runtime_enable(pdev); device->pmdev = pdev; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) /*get gpu regulator*/ device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu"); if (IS_ERR(device->gpu_regulator)) { gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to get gpu regulator %s/%s \n", __FUNCTION__, __LINE__, PARENT_FILE, DEBUG_FILE); gcmkONERROR(gcvSTATUS_NOT_FOUND); } #endif /*Initialize the clock structure*/ if (IrqLine != -1) { device->clk_3d_core = clk_get(pdev, "gpu3d_clk"); if (!IS_ERR(device->clk_3d_core)) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) if (cpu_is_mx6q()) { device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk"); if (IS_ERR(device->clk_3d_shader)) { IrqLine = -1; clk_put(device->clk_3d_core); device->clk_3d_core = NULL; device->clk_3d_shader = NULL; gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n"); } } #else device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk"); device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk"); if (IS_ERR(device->clk_3d_shader)) { IrqLine = -1; clk_put(device->clk_3d_core); device->clk_3d_core = NULL; device->clk_3d_shader = NULL; gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n"); } #endif } else { IrqLine = -1; device->clk_3d_core = NULL; gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n"); } } if ((IrqLine2D != -1) || (IrqLineVG != -1)) { device->clk_2d_core = clk_get(pdev, "gpu2d_clk"); if (IS_ERR(device->clk_2d_core)) { IrqLine2D = -1; IrqLineVG = -1; device->clk_2d_core = NULL; gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n"); } else { if (IrqLine2D != -1) { device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk"); if (IS_ERR(device->clk_2d_axi)) { device->clk_2d_axi = NULL; IrqLine2D = -1; gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n"); } } if (IrqLineVG != -1) { device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk"); if (IS_ERR(device->clk_vg_axi)) { IrqLineVG = -1; device->clk_vg_axi = NULL; gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n"); } } } } if (IrqLine != -1) { device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase; device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize; } if (IrqLine2D != -1) { device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D; device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D; } if (IrqLineVG != -1) { device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG; device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG; } device->requestedContiguousBase = 0; device->requestedContiguousSize = 0; for (i = 0; i < gcdMAX_GPU_COUNT; i++) { physical = device->requestedRegisterMemBases[i]; /* Set up register memory region. */ if (physical != 0) { mem_region = request_mem_region( physical, device->requestedRegisterMemSizes[i], "galcore register region" ); if (mem_region == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to claim %lu bytes @ 0x%08X\n", __FUNCTION__, __LINE__, physical, device->requestedRegisterMemSizes[i] ); gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } device->registerBases[i] = (gctPOINTER) ioremap_nocache( physical, device->requestedRegisterMemSizes[i]); if (device->registerBases[i] == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Unable to map %ld bytes @ 0x%08X\n", __FUNCTION__, __LINE__, physical, device->requestedRegisterMemSizes[i] ); gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } physical += device->requestedRegisterMemSizes[i]; } else { device->registerBases[i] = gcvNULL; } } /* Set the base address */ device->baseAddress = PhysBaseAddr; /* Construct the gckOS object. */ gcmkONERROR(gckOS_Construct(device, &device->os)); if (IrqLine != -1) { /* Construct the gckKERNEL object. */ gcmkONERROR(gckKERNEL_Construct( device->os, gcvCORE_MAJOR, device, gcvNULL, &device->kernels[gcvCORE_MAJOR])); sharedDB = device->kernels[gcvCORE_MAJOR]->db; /* Initialize core mapping */ for (i = 0; i < 8; i++) { device->coreMapping[i] = gcvCORE_MAJOR; } /* Setup the ISR manager. */ gcmkONERROR(gckHARDWARE_SetIsrManager( device->kernels[gcvCORE_MAJOR]->hardware, (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR, (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR, device )); gcmkONERROR(gckHARDWARE_SetFastClear( device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression )); gcmkONERROR(gckHARDWARE_SetPowerManagement( device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement )); #if COMMAND_PROCESSOR_VERSION == 1 /* Start the command queue. */ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command)); #endif } else { device->kernels[gcvCORE_MAJOR] = gcvNULL; } if (IrqLine2D != -1) { gcmkONERROR(gckKERNEL_Construct( device->os, gcvCORE_2D, device, sharedDB, &device->kernels[gcvCORE_2D])); if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db; /* Verify the hardware type */ gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type)); if (type != gcvHARDWARE_2D) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Unexpected hardware type: %d\n", __FUNCTION__, __LINE__, type ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } /* Initialize core mapping */ if (device->kernels[gcvCORE_MAJOR] == gcvNULL) { for (i = 0; i < 8; i++) { device->coreMapping[i] = gcvCORE_2D; } } else { device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D; } /* Setup the ISR manager. */ gcmkONERROR(gckHARDWARE_SetIsrManager( device->kernels[gcvCORE_2D]->hardware, (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D, (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D, device )); gcmkONERROR(gckHARDWARE_SetPowerManagement( device->kernels[gcvCORE_2D]->hardware, PowerManagement )); #if COMMAND_PROCESSOR_VERSION == 1 /* Start the command queue. */ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command)); #endif } else { device->kernels[gcvCORE_2D] = gcvNULL; } if (IrqLineVG != -1) { #if gcdENABLE_VG gcmkONERROR(gckKERNEL_Construct( device->os, gcvCORE_VG, device, sharedDB, &device->kernels[gcvCORE_VG])); /* Initialize core mapping */ if (device->kernels[gcvCORE_MAJOR] == gcvNULL && device->kernels[gcvCORE_2D] == gcvNULL ) { for (i = 0; i < 8; i++) { device->coreMapping[i] = gcvCORE_VG; } } else { device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG; } gcmkONERROR(gckVGHARDWARE_SetPowerManagement( device->kernels[gcvCORE_VG]->vg->hardware, PowerManagement )); #endif } else { device->kernels[gcvCORE_VG] = gcvNULL; } /* Initialize the ISR. */ device->irqLines[gcvCORE_MAJOR] = IrqLine; device->irqLines[gcvCORE_2D] = IrqLine2D; device->irqLines[gcvCORE_VG] = IrqLineVG; /* Initialize the kernel thread semaphores. */ for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0); } device->signal = Signal; for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->kernels[i] != gcvNULL) break; } if (i == gcdMAX_GPU_COUNT) { gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } #if gcdENABLE_VG if (i == gcvCORE_VG) { /* Query the ceiling of the system memory. */ gcmkONERROR(gckVGHARDWARE_QuerySystemMemory( device->kernels[i]->vg->hardware, &device->systemMemorySize, &device->systemMemoryBaseAddress )); /* query the amount of video memory */ gcmkONERROR(gckVGHARDWARE_QueryMemory( device->kernels[i]->vg->hardware, &device->internalSize, &internalBaseAddress, &internalAlignment, &device->externalSize, &externalBaseAddress, &externalAlignment, &horizontalTileSize, &verticalTileSize )); } else #endif { /* Query the ceiling of the system memory. */ gcmkONERROR(gckHARDWARE_QuerySystemMemory( device->kernels[i]->hardware, &device->systemMemorySize, &device->systemMemoryBaseAddress )); /* query the amount of video memory */ gcmkONERROR(gckHARDWARE_QueryMemory( device->kernels[i]->hardware, &device->internalSize, &internalBaseAddress, &internalAlignment, &device->externalSize, &externalBaseAddress, &externalAlignment, &horizontalTileSize, &verticalTileSize )); } /* Grab the first availiable kernel */ for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->irqLines[i] != -1) { kernel = device->kernels[i]; break; } } /* Set up the internal memory region. */ if (device->internalSize > 0) { status = gckVIDMEM_Construct( device->os, internalBaseAddress, device->internalSize, internalAlignment, 0, &device->internalVidMem ); if (gcmIS_ERROR(status)) { /* Error, disable internal heap. */ device->internalSize = 0; } else { /* Map internal memory. */ device->internalLogical = (gctPOINTER) ioremap_nocache(physical, device->internalSize); if (device->internalLogical == gcvNULL) { gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical; device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical); physical += device->internalSize; } } if (device->externalSize > 0) { /* create the external memory heap */ status = gckVIDMEM_Construct( device->os, externalBaseAddress, device->externalSize, externalAlignment, 0, &device->externalVidMem ); if (gcmIS_ERROR(status)) { /* Error, disable internal heap. */ device->externalSize = 0; } else { /* Map external memory. */ device->externalLogical = (gctPOINTER) ioremap_nocache(physical, device->externalSize); if (device->externalLogical == gcvNULL) { gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical; device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical); physical += device->externalSize; } } /* set up the contiguous memory */ device->contiguousSize = ContiguousSize; if (ContiguousSize > 0) { if (ContiguousBase == 0) { while (device->contiguousSize > 0) { /* Allocate contiguous memory. */ status = _AllocateMemory( device, device->contiguousSize, &device->contiguousBase, &device->contiguousPhysical, &physAddr ); if (gcmIS_SUCCESS(status)) { device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical); status = gckVIDMEM_Construct( device->os, physAddr | device->systemMemoryBaseAddress, device->contiguousSize, 64, BankSize, &device->contiguousVidMem ); if (gcmIS_SUCCESS(status)) { break; } gcmkONERROR(_FreeMemory( device, device->contiguousBase, device->contiguousPhysical )); gcmRELEASE_NAME(device->contiguousPhysicalName); device->contiguousBase = gcvNULL; device->contiguousPhysical = gcvNULL; } if (device->contiguousSize <= (4 << 20)) { device->contiguousSize = 0; } else { device->contiguousSize -= (4 << 20); } } } else { /* Create the contiguous memory heap. */ status = gckVIDMEM_Construct( device->os, ContiguousBase | device->systemMemoryBaseAddress, ContiguousSize, 64, BankSize, &device->contiguousVidMem ); if (gcmIS_ERROR(status)) { /* Error, disable contiguous memory pool. */ device->contiguousVidMem = gcvNULL; device->contiguousSize = 0; } else { mem_region = request_mem_region( ContiguousBase, ContiguousSize, "galcore managed memory" ); if (mem_region == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to claim %ld bytes @ 0x%08X\n", __FUNCTION__, __LINE__, ContiguousSize, ContiguousBase ); gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } device->requestedContiguousBase = ContiguousBase; device->requestedContiguousSize = ContiguousSize; #if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG if (gcmIS_CORE_PRESENT(device, gcvCORE_VG)) { device->contiguousBase #if gcdPAGED_MEMORY_CACHEABLE = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize); #else = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize); #endif if (device->contiguousBase == gcvNULL) { device->contiguousVidMem = gcvNULL; device->contiguousSize = 0; gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES); } } #endif device->contiguousPhysical = gcvNULL; device->contiguousPhysicalName = 0; device->contiguousSize = ContiguousSize; device->contiguousMapped = gcvTRUE; } } }
/******************************************************************************* ** ** gckKERNEL_GetVideoMemoryPool ** ** Get the gckVIDMEM object belonging to the specified pool. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gcePOOL Pool ** Pool to query gckVIDMEM object for. ** ** OUTPUT: ** ** gckVIDMEM * VideoMemory ** Pointer to a variable that will hold the pointer to the gckVIDMEM ** object belonging to the requested pool. */ gceSTATUS gckKERNEL_GetVideoMemoryPool( IN gckKERNEL Kernel, IN gcePOOL Pool, OUT gckVIDMEM * VideoMemory ) { GCHAL * gchal; gckVIDMEM videoMemory; gceSTATUS status; gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "[ENTER] gckHARDWARE_GetVideoMemoryPool"); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL); /* Extract the pointer to the GCHAL class. */ gchal = (GCHAL *) Kernel->context; /* Dispatch on pool. */ switch (Pool) { case gcvPOOL_LOCAL_INTERNAL: /* Internal memory. */ videoMemory = gchal->GetInternalHeap(); break; case gcvPOOL_LOCAL_EXTERNAL: /* External memory. */ videoMemory = gchal->GetExternalHeap(); break; case gcvPOOL_SYSTEM: /* System memory. */ videoMemory = gchal->GetContiguousHeap(); break; default: /* Unknown pool. */ videoMemory = gcvNULL; gcmkFATAL("Unknown memory pool: %u", Pool); } /* Return pointer to the gckVIDMEM object. */ *VideoMemory = videoMemory; /* Determine the status. */ status = (videoMemory == gcvNULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK; if (gcmIS_SUCCESS(status)) { gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL, "gckHARDWARE_GetVideoMemoryPool: Pool %u starts at %p", Pool, videoMemory); } gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "[LEAVE] gckHARDWARE_GetVideoMemoryPool(%u)", status); /* Return the status. */ gcmkFOOTER_ARG("status=%d, *VideoMemory=%p", status, gcmOPT_VALUE(VideoMemory)); return status; }
long drv_ioctl( struct file* filp, unsigned int ioctlCode, unsigned long arg ) { gceSTATUS status; gcsHAL_INTERFACE iface; gctUINT32 copyLen; DRIVER_ARGS drvArgs; gckGALDEVICE device; gcsHAL_PRIVATE_DATA_PTR data; gctINT32 i, count; gckVIDMEM_NODE nodeObject; gcmkHEADER_ARG( "filp=0x%08X ioctlCode=0x%08X arg=0x%08X", filp, ioctlCode, arg ); if (filp == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): filp is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } data = filp->private_data; if (data == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): private_data is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } device = data->device; if (device == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): device is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } if ((ioctlCode != IOCTL_GCHAL_INTERFACE) && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE) ) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): unknown command %d\n", __FUNCTION__, __LINE__, ioctlCode ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } /* Get the drvArgs. */ copyLen = copy_from_user( &drvArgs, (void *) arg, sizeof(DRIVER_ARGS) ); if (copyLen != 0) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): error copying of the input arguments.\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } /* Now bring in the gcsHAL_INTERFACE structure. */ if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE)) || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE)) ) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): input or/and output structures are invalid.\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } copyLen = copy_from_user( &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE) ); if (copyLen != 0) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): error copying of input HAL interface.\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } if (iface.command == gcvHAL_CHIP_INFO) { count = 0; for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->kernels[i] != gcvNULL) { #if gcdENABLE_VG if (i == gcvCORE_VG) { iface.u.ChipInfo.types[count] = gcvHARDWARE_VG; } else #endif { gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware, &iface.u.ChipInfo.types[count])); } count++; } } iface.u.ChipInfo.count = count; iface.status = status = gcvSTATUS_OK; } else { if (iface.hardwareType > 7) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): unknown hardwareType %d\n", __FUNCTION__, __LINE__, iface.hardwareType ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } #if gcdENABLE_VG if (device->coreMapping[iface.hardwareType] == gcvCORE_VG) { status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG], (ioctlCode == IOCTL_GCHAL_INTERFACE), &iface); } else #endif { status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]], (ioctlCode == IOCTL_GCHAL_INTERFACE), &iface); } } /* Redo system call after pending signal is handled. */ if (status == gcvSTATUS_INTERRUPTED) { gcmkFOOTER(); return -ERESTARTSYS; } if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY)) { gcuVIDMEM_NODE_PTR node; gctUINT32 processID; gckOS_GetProcessID(&processID); gcmkONERROR(gckVIDMEM_HANDLE_Lookup(device->kernels[device->coreMapping[iface.hardwareType]], processID, (gctUINT32)iface.u.LockVideoMemory.node, &nodeObject)); node = nodeObject->node; /* Special case for mapped memory. */ if ((data->mappedMemory != gcvNULL) && (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) ) { /* Compute offset into mapped memory. */ gctUINT32 offset = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory) - (gctUINT8 *) device->contiguousBase; /* Compute offset into user-mapped region. */ iface.u.LockVideoMemory.memory = gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset); } } /* Copy data back to the user. */ copyLen = copy_to_user( gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE) ); if (copyLen != 0) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): error copying of output HAL interface.\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } /* Success. */ gcmkFOOTER_NO(); return 0; OnError: gcmkFOOTER(); return -ENOTTY; }
/******************************************************************************* ** ** gckKERNEL_MapVideoMemory ** ** Get the logical address for a hardware specific memory address for the ** current process. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gctBOOL InUserSpace ** gcvTRUE to map the memory into the user space. ** ** gctUINT32 Address ** Hardware specific memory address. ** ** OUTPUT: ** ** gctPOINTER * Logical ** Pointer to a variable that will hold the logical address of the ** specified memory address. */ gceSTATUS gckKERNEL_MapVideoMemoryEx( IN gckKERNEL Kernel, IN gceCORE Core, IN gctBOOL InUserSpace, IN gctUINT32 Address, OUT gctPOINTER * Logical ) { GCHAL * gchal; gcePOOL pool; gctUINT32 offset, base; gceSTATUS status; gctPOINTER logical; gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x", Kernel, InUserSpace, Address); gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "[ENTER] gckKERNEL_MapVideoMemory"); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Logical != gcvNULL); /* Extract the pointer to the GCHAL class. */ gchal = (GCHAL *) Kernel->context; do { #if gcdENABLE_VG if (Core == gcvCORE_VG) { /* Split the memory address into a pool type and offset. */ gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset)); } else #endif { /* Split the memory address into a pool type and offset. */ gcmkERR_BREAK(gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset)); } /* Dispatch on pool. */ switch (pool) { case gcvPOOL_LOCAL_INTERNAL: /* Internal memory. */ logical = gchal->GetInternalLogical(); break; case gcvPOOL_LOCAL_EXTERNAL: /* External memory. */ logical = gchal->GetExternalLogical(); break; case gcvPOOL_SYSTEM: /* System memory. */ #if UNDER_CE >= 600 if (InUserSpace) { logical = gchal->GetProcessContiguousLogical(); } else { logical = gchal->GetContiguousLogical(); } #else logical = gchal->GetContiguousLogical(); #endif #if gcdENABLE_VG if (Core == gcvCORE_VG) { gcmkVERIFY_OK(gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, gchal->GetContiguousHeap()->baseAddress, &pool, &base)); } else #endif { gcmkVERIFY_OK(gckHARDWARE_SplitMemory(Kernel->hardware, gchal->GetContiguousHeap()->baseAddress, &pool, &base)); } offset -= base; break; default: /* Invalid memory pool. */ gcmkFATAL("Unknown memory pool: %u", pool); return gcvSTATUS_INVALID_ARGUMENT; } /* Build logical address of specified address. */ *Logical = reinterpret_cast<gctPOINTER> (static_cast<gctUINT8 *>(logical) + offset); } while (gcvFALSE); if (gcmIS_SUCCESS(status)) { gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL, "gckKERNEL_MapVideoMemory: Address 0x%08X maps to %p", Address, *Logical); } gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "[LEAVE] gckKERNEL_MapVideoMemory(%u)", status); /* Return the status. */ gcmkFOOTER(); return status; }
gceSTATUS gcoPROFILER_Initialize( IN gcoHAL Hal ) { gceSTATUS status = gcvSTATUS_OK; char* fileName; char* filter = gcvNULL; gctSTRING portName; gctINT port; gcsHAL_INTERFACE iface; gcmHEADER(); /* Check if already initialized. */ if (gcPLS.hal->profiler.enable) { gcPLS.hal->profiler.enable++; gcmFOOTER(); return status; } /* Get profile setting. */ iface.command = gcvHAL_GET_PROFILE_SETTING; /* Call the kernel. */ status = gcoOS_DeviceControl(gcvNULL, IOCTL_GCHAL_INTERFACE, &iface, gcmSIZEOF(iface), &iface, gcmSIZEOF(iface)); if (gcmIS_ERROR(status) || !iface.u.GetProfileSetting.enable) { gcPLS.hal->profiler.enable = 0; status = gcvSTATUS_GENERIC_IO; gcmFOOTER(); return status; } gcmVERIFY_OK(gcoOS_ZeroMemory(&gcPLS.hal->profiler, gcmSIZEOF(gcPLS.hal->profiler))); gcoOS_GetEnv(gcvNULL, "VP_COUNTER_FILTER", &filter); /* Enable/Disable specific counters. */ if ((filter != gcvNULL)) { gctSIZE_T bitsLen; gcoOS_StrLen(filter, &bitsLen); if (bitsLen > 2) { gcPLS.hal->profiler.enableHal = (filter[2] == '1'); } else { gcPLS.hal->profiler.enableHal = gcvTRUE; } if (bitsLen > 3) { gcPLS.hal->profiler.enableHW = (filter[3] == '1'); } else { gcPLS.hal->profiler.enableHW = gcvTRUE; } if (bitsLen > 8) { gcPLS.hal->profiler.enableSH = (filter[8] == '1'); } else { gcPLS.hal->profiler.enableSH = gcvTRUE; } } else { gcPLS.hal->profiler.enableHal = gcvTRUE; gcPLS.hal->profiler.enableHW = gcvTRUE; gcPLS.hal->profiler.enableSH = gcvTRUE; } gcoOS_GetEnv(gcvNULL, "VPROFILER_OUTPUT", &fileName); gcPLS.hal->profiler.useSocket = gcvFALSE; if (fileName && *fileName != '\0' && *fileName != ' ') { /* Extract port info. */ gcoOS_StrFindReverse(fileName, ':', &portName); if (portName) { gcoOS_StrToInt(portName + 1, &port); if (port > 0) { /*status = gcoOS_Socket(gcvNULL, AF_INET, SOCK_STREAM, 0, &gcPLS.hal->profiler.sockFd);*/ status = gcoOS_Socket(gcvNULL, 2, 1, 0, &gcPLS.hal->profiler.sockFd); if (gcmIS_SUCCESS(status)) { *portName = '\0'; status = gcoOS_Connect(gcvNULL, gcPLS.hal->profiler.sockFd, fileName, port); *portName = ':'; if (gcmIS_SUCCESS(status)) { gcPLS.hal->profiler.useSocket = gcvTRUE; } } } } } else { fileName = iface.u.GetProfileSetting.fileName; } if (! gcPLS.hal->profiler.useSocket) { status = gcoOS_Open(gcvNULL, fileName, #ifdef gcdNEW_PROFILER_FILE gcvFILE_CREATE, #else gcvFILE_CREATETEXT, #endif &gcPLS.hal->profiler.file); } if (gcmIS_ERROR(status)) { gcPLS.hal->profiler.enable = 0; status = gcvSTATUS_GENERIC_IO; gcmFOOTER(); return status; } gcPLS.hal->profiler.enable = 1; gcoOS_GetTime(&gcPLS.hal->profiler.frameStart); gcPLS.hal->profiler.frameStartTimeusec = gcPLS.hal->profiler.frameStart; gcPLS.hal->profiler.prevVSInstCount = 0; gcPLS.hal->profiler.prevVSBranchInstCount = 0; gcPLS.hal->profiler.prevVSTexInstCount = 0; gcPLS.hal->profiler.prevVSVertexCount = 0; gcPLS.hal->profiler.prevPSInstCount = 0; gcPLS.hal->profiler.prevPSBranchInstCount = 0; gcPLS.hal->profiler.prevPSTexInstCount = 0; gcPLS.hal->profiler.prevPSPixelCount = 0; #if gcdNEW_PROFILER_FILE gcmWRITE_CONST(VPHEADER); gcmWRITE_BUFFER(4, "VP12"); #else gcmWRITE_STRING("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<VProfile>\n"); #endif /* Success. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gckCOMMAND_Execute ** ** Execute a previously reserved command queue by appending a WAIT/LINK command ** sequence after it and modifying the last WAIT into a LINK command. The ** command FIFO mutex will be released whether this function succeeds or not. ** ** INPUT: ** ** gckCOMMAND Command ** Pointer to an gckCOMMAND object. ** ** gctSIZE_T RequestedBytes ** Number of bytes previously reserved. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckCOMMAND_Execute( IN gckCOMMAND Command, IN gctSIZE_T RequestedBytes, IN gctBOOL Locking ) { gctUINT32 offset; gctPOINTER address; gctSIZE_T bytes; gceSTATUS status; gctPOINTER wait; gctSIZE_T waitBytes; gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu Locking=%d", Command, RequestedBytes, Locking); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND); if (Command->kernel->notifyIdle) { /* Increase the commit stamp */ Command->commitStamp++; /* Set busy if idle */ if (Command->idle) { Command->idle = gcvFALSE; gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE)); } } /* Compute offset for WAIT/LINK. */ offset = Command->offset + RequestedBytes; /* Compute number of byts left in command queue. */ bytes = Command->pageSize - offset; /* Append WAIT/LINK in command queue. */ gcmkONERROR( gckHARDWARE_WaitLink(Command->kernel->hardware, (gctUINT8 *) Command->logical + offset, offset, &bytes, &wait, &waitBytes)); if (Command->newQueue) { /* For a new command queue, point to the start of the command ** queue and include both the commands inserted at the head of it ** and the WAIT/LINK. */ address = Command->logical; bytes += offset; } else { /* For an existing command queue, point to the current offset and ** include the WAIT/LINK. */ address = (gctUINT8 *) Command->logical + Command->offset; bytes += RequestedBytes; } /* Flush the cache. */ gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, address, bytes)); #if gcdDUMP_COMMAND _DumpCommand(Command, address, bytes); #endif /* Convert the last WAIT into a LINK. */ gcmkONERROR(gckHARDWARE_Link(Command->kernel->hardware, Command->wait, address, bytes, &Command->waitSize)); #if MRVL_PRINT_CMD_BUFFER _AddLink(Command, Command->wait, address); #endif /* Flush the cache. */ gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, Command->wait, Command->waitSize)); #if gcdDUMP_COMMAND _DumpCommand(Command, Command->wait, 8); #endif /* Update the pointer to the last WAIT. */ Command->wait = wait; Command->waitSize = waitBytes; /* Update the command queue. */ Command->offset += bytes; Command->newQueue = gcvFALSE; /* Update queue tail pointer. */ gcmkONERROR( gckHARDWARE_UpdateQueueTail(Command->kernel->hardware, Command->logical, Command->offset)); #if gcdDUMP_COMMAND gcmkPRINT("@[kernel.execute]"); #endif if (!Locking) { /* Release the command queue mutex. */ gcmkONERROR( gckOS_ReleaseMutex(Command->os, Command->mutexQueue)); } /* Submit events if asked for. */ if (Command->submit) { /* Submit events. */ status = gckEVENT_Submit(Command->kernel->event, gcvFALSE, gcvFALSE); if (gcmIS_SUCCESS(status)) { /* Success. */ Command->submit = gcvFALSE; } else { gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND, "gckEVENT_Submit returned %d", status); } } /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Release the command queue mutex. */ gcmkVERIFY_OK( gckOS_ReleaseMutex(Command->os, Command->mutexQueue)); /* Return the status. */ gcmkFOOTER(); return status; }