/**************************************************************************** * * Copyright (C) 2005 - 2013 by Vivante Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the license, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************************************/ #include "gc_hal_kernel_precomp.h" #include /******************************************************************************\ ******************************** Debug Variables ******************************* \******************************************************************************/ static gceSTATUS _lastError = gcvSTATUS_OK; static gctUINT32 _debugLevel = gcvLEVEL_ERROR; /* _debugZones config value Please Reference define in gc_hal_base.h */ static gctUINT32 _debugZones = gcvZONE_NONE; /******************************************************************************\ ********************************* Debug Switches ******************************* \******************************************************************************/ /* gcdBUFFERED_OUTPUT When set to non-zero, all output is collected into a buffer with the specified size. Once the buffer gets full, the debug buffer will be printed to the console. gcdBUFFERED_SIZE determines the size of the buffer. */ #define gcdBUFFERED_OUTPUT 0 /* gcdBUFFERED_SIZE When set to non-zero, all output is collected into a buffer with the specified size. Once the buffer gets full, the debug buffer will be printed to the console. */ #define gcdBUFFERED_SIZE (1024 * 1024 * 2) /* gcdDMA_BUFFER_COUNT If greater then zero, the debugger will attempt to find the command buffer where DMA is currently executing and then print this buffer and (gcdDMA_BUFFER_COUNT - 1) buffers before the current one. If set to zero or the current buffer is not found, all buffers are printed. */ #define gcdDMA_BUFFER_COUNT 0 /* gcdTHREAD_BUFFERS When greater then one, will accumulate messages from the specified number of threads in separate output buffers. */ #define gcdTHREAD_BUFFERS 1 /* gcdENABLE_OVERFLOW When set to non-zero, and the output buffer gets full, instead of being printed, it will be allowed to overflow removing the oldest messages. */ #define gcdENABLE_OVERFLOW 1 /* gcdSHOW_LINE_NUMBER When enabledm each print statement will be preceeded with the current line number. */ #define gcdSHOW_LINE_NUMBER 0 /* gcdSHOW_PROCESS_ID When enabledm each print statement will be preceeded with the current process ID. */ #define gcdSHOW_PROCESS_ID 0 /* gcdSHOW_THREAD_ID When enabledm each print statement will be preceeded with the current thread ID. */ #define gcdSHOW_THREAD_ID 0 /* gcdSHOW_TIME When enabled each print statement will be preceeded with the current high-resolution time. */ #define gcdSHOW_TIME 0 /******************************************************************************\ ****************************** Miscellaneous Macros **************************** \******************************************************************************/ #if gcmIS_DEBUG(gcdDEBUG_TRACE) # define gcmDBGASSERT(Expression, Format, Value) \ if (!(Expression)) \ { \ _DirectPrint( \ "*** gcmDBGASSERT ***************************\n" \ " function : %s\n" \ " line : %d\n" \ " expression : " #Expression "\n" \ " actual value : " Format "\n", \ __FUNCTION__, __LINE__, Value \ ); \ } #else # define gcmDBGASSERT(Expression, Format, Value) #endif #define gcmPTRALIGNMENT(Pointer, Alignemnt) \ ( \ gcmALIGN(gcmPTR2INT(Pointer), Alignemnt) - gcmPTR2INT(Pointer) \ ) #if gcdALIGNBYSIZE # define gcmISALIGNED(Offset, Alignment) \ (((Offset) & ((Alignment) - 1)) == 0) # define gcmkALIGNPTR(Type, Pointer, Alignment) \ Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT(Pointer), Alignment)) #else # define gcmISALIGNED(Offset, Alignment) \ gcvTRUE # define gcmkALIGNPTR(Type, Pointer, Alignment) #endif #define gcmALIGNSIZE(Offset, Size) \ ((Size - Offset) + Size) #define gcdHAVEPREFIX \ ( \ gcdSHOW_TIME \ || gcdSHOW_LINE_NUMBER \ || gcdSHOW_PROCESS_ID \ || gcdSHOW_THREAD_ID \ ) #if gcdHAVEPREFIX # define gcdOFFSET 0 #if gcdSHOW_TIME #if gcmISALIGNED(gcdOFFSET, 8) # define gcdTIMESIZE gcmSIZEOF(gctUINT64) # elif gcdOFFSET == 4 # define gcdTIMESIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64)) # else # error "Unexpected offset value." # endif # undef gcdOFFSET # define gcdOFFSET 8 #if !defined(gcdPREFIX_LEADER) # define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64) # define gcdTIMEFORMAT "0x%016llX" # else # define gcdTIMEFORMAT ", 0x%016llX" # endif # else # define gcdTIMESIZE 0 # define gcdTIMEFORMAT # endif #if gcdSHOW_LINE_NUMBER #if gcmISALIGNED(gcdOFFSET, 8) # define gcdNUMSIZE gcmSIZEOF(gctUINT64) # elif gcdOFFSET == 4 # define gcdNUMSIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64)) # else # error "Unexpected offset value." # endif # undef gcdOFFSET # define gcdOFFSET 8 #if !defined(gcdPREFIX_LEADER) # define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64) # define gcdNUMFORMAT "%8llu" # else # define gcdNUMFORMAT ", %8llu" # endif # else # define gcdNUMSIZE 0 # define gcdNUMFORMAT # endif #if gcdSHOW_PROCESS_ID #if gcmISALIGNED(gcdOFFSET, 4) # define gcdPIDSIZE gcmSIZEOF(gctUINT32) # else # error "Unexpected offset value." # endif # undef gcdOFFSET # define gcdOFFSET 4 #if !defined(gcdPREFIX_LEADER) # define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32) # define gcdPIDFORMAT "pid=%5d" # else # define gcdPIDFORMAT ", pid=%5d" # endif # else # define gcdPIDSIZE 0 # define gcdPIDFORMAT # endif #if gcdSHOW_THREAD_ID #if gcmISALIGNED(gcdOFFSET, 4) # define gcdTIDSIZE gcmSIZEOF(gctUINT32) # else # error "Unexpected offset value." # endif # undef gcdOFFSET # define gcdOFFSET 4 #if !defined(gcdPREFIX_LEADER) # define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32) # define gcdTIDFORMAT "tid=%5d" # else # define gcdTIDFORMAT ", tid=%5d" # endif # else # define gcdTIDSIZE 0 # define gcdTIDFORMAT # endif # define gcdPREFIX_SIZE \ ( \ gcdTIMESIZE \ + gcdNUMSIZE \ + gcdPIDSIZE \ + gcdTIDSIZE \ ) static const char * _prefixFormat = "[" gcdTIMEFORMAT gcdNUMFORMAT gcdPIDFORMAT gcdTIDFORMAT "] "; #else # define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32) # define gcdPREFIX_SIZE 0 #endif /* Assumed largest variable argument leader size. */ #define gcdVARARG_LEADER gcmSIZEOF(gctUINT64) /* Alignnments. */ #if gcdALIGNBYSIZE # define gcdPREFIX_ALIGNMENT gcdPREFIX_LEADER # define gcdVARARG_ALIGNMENT gcdVARARG_LEADER #else # define gcdPREFIX_ALIGNMENT 0 # define gcdVARARG_ALIGNMENT 0 #endif #if gcdBUFFERED_OUTPUT # define gcdOUTPUTPREFIX _AppendPrefix # define gcdOUTPUTSTRING _AppendString # define gcdOUTPUTCOPY _AppendCopy # define gcdOUTPUTBUFFER _AppendBuffer #else # define gcdOUTPUTPREFIX _PrintPrefix # define gcdOUTPUTSTRING _PrintString # define gcdOUTPUTCOPY _PrintString # define gcdOUTPUTBUFFER _PrintBuffer #endif /******************************************************************************\ ****************************** Private Structures ****************************** \******************************************************************************/ typedef enum _gceBUFITEM { gceBUFITEM_NONE, gcvBUFITEM_PREFIX, gcvBUFITEM_STRING, gcvBUFITEM_COPY, gcvBUFITEM_BUFFER } gceBUFITEM; /* Common item head/buffer terminator. */ typedef struct _gcsBUFITEM_HEAD * gcsBUFITEM_HEAD_PTR; typedef struct _gcsBUFITEM_HEAD { gceBUFITEM type; } gcsBUFITEM_HEAD; /* String prefix (for ex. [ 1,tid=0x019A]) */ typedef struct _gcsBUFITEM_PREFIX * gcsBUFITEM_PREFIX_PTR; typedef struct _gcsBUFITEM_PREFIX { gceBUFITEM type; #if gcdHAVEPREFIX gctPOINTER prefixData; #endif } gcsBUFITEM_PREFIX; /* Buffered string. */ typedef struct _gcsBUFITEM_STRING * gcsBUFITEM_STRING_PTR; typedef struct _gcsBUFITEM_STRING { gceBUFITEM type; gctINT indent; gctCONST_STRING message; gctPOINTER messageData; gctUINT messageDataSize; } gcsBUFITEM_STRING; /* Buffered string (copy of the string is included with the record). */ typedef struct _gcsBUFITEM_COPY * gcsBUFITEM_COPY_PTR; typedef struct _gcsBUFITEM_COPY { gceBUFITEM type; gctINT indent; gctPOINTER messageData; gctUINT messageDataSize; } gcsBUFITEM_COPY; /* Memory buffer. */ typedef struct _gcsBUFITEM_BUFFER * gcsBUFITEM_BUFFER_PTR; typedef struct _gcsBUFITEM_BUFFER { gceBUFITEM type; gctINT indent; gceDUMP_BUFFER bufferType; #if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1) gctUINT32 dmaAddress; #endif gctUINT dataSize; gctUINT32 address; #if gcdHAVEPREFIX gctPOINTER prefixData; #endif } gcsBUFITEM_BUFFER; typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR; typedef struct _gcsBUFFERED_OUTPUT { #if gcdTHREAD_BUFFERS > 1 gctUINT32 threadID; #endif #if gcdSHOW_LINE_NUMBER gctUINT64 lineNumber; #endif gctINT indent; #if gcdBUFFERED_OUTPUT gctINT start; gctINT index; gctINT count; gctUINT8 buffer[gcdBUFFERED_SIZE]; #endif gcsBUFFERED_OUTPUT_PTR prev; gcsBUFFERED_OUTPUT_PTR next; } gcsBUFFERED_OUTPUT; typedef gctUINT (* gcfPRINTSTRING) ( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gcsBUFITEM_HEAD_PTR Item ); typedef gctINT (* gcfGETITEMSIZE) ( IN gcsBUFITEM_HEAD_PTR Item ); /******************************************************************************\ ******************************* Private Variables ****************************** \******************************************************************************/ static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS]; static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL; static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL; /******************************************************************************\ ****************************** Item Size Functions ***************************** \******************************************************************************/ #if gcdBUFFERED_OUTPUT static gctINT _GetTerminatorItemSize( IN gcsBUFITEM_HEAD_PTR Item ) { return gcmSIZEOF(gcsBUFITEM_HEAD); } static gctINT _GetPrefixItemSize( IN gcsBUFITEM_HEAD_PTR Item ) { #if gcdHAVEPREFIX gcsBUFITEM_PREFIX_PTR item = (gcsBUFITEM_PREFIX_PTR) Item; gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item); return vlen + gcdPREFIX_SIZE; #else return gcmSIZEOF(gcsBUFITEM_PREFIX); #endif } static gctINT _GetStringItemSize( IN gcsBUFITEM_HEAD_PTR Item ) { gcsBUFITEM_STRING_PTR item = (gcsBUFITEM_STRING_PTR) Item; gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item); return vlen + item->messageDataSize; } static gctINT _GetCopyItemSize( IN gcsBUFITEM_HEAD_PTR Item ) { gcsBUFITEM_COPY_PTR item = (gcsBUFITEM_COPY_PTR) Item; gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item); return vlen + item->messageDataSize; } static gctINT _GetBufferItemSize( IN gcsBUFITEM_HEAD_PTR Item ) { #if gcdHAVEPREFIX gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item; gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item); return vlen + gcdPREFIX_SIZE + item->dataSize; #else gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item; return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize; #endif } static gcfGETITEMSIZE _itemSize[] = { _GetTerminatorItemSize, _GetPrefixItemSize, _GetStringItemSize, _GetCopyItemSize, _GetBufferItemSize }; #endif /******************************************************************************\ ******************************* Printing Functions ***************************** \******************************************************************************/ #if gcdDEBUG || gcdBUFFERED_OUTPUT static void _DirectPrint( gctCONST_STRING Message, ... ) { gctINT len; char buffer[768]; gctARGUMENTS arguments; gcmkARGUMENTS_START(arguments, Message); len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, arguments); gcmkARGUMENTS_END(arguments); buffer[len] = '\0'; gcmkOUTPUT_STRING(buffer); } #endif static int _AppendIndent( IN gctINT Indent, IN char * Buffer, IN int BufferSize ) { gctINT i; gctINT len = 0; gctINT indent = Indent % 40; for (i = 0; i < indent; i += 1) { Buffer[len++] = ' '; } if (indent != Indent) { len += gcmkSPRINTF( Buffer + len, BufferSize - len, " <%d> ", Indent ); Buffer[len] = '\0'; } return len; } #if gcdHAVEPREFIX static void _PrintPrefix( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctPOINTER Data ) { char buffer[768]; gctINT len; /* Format the string. */ len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, Data); buffer[len] = '\0'; /* Print the string. */ gcmkOUTPUT_STRING(buffer); } #endif static void _PrintString( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctINT Indent, IN gctCONST_STRING Message, IN gctUINT ArgumentSize, IN gctPOINTER Data ) { char buffer[768]; gctINT len; /* Append the indent string. */ len = _AppendIndent(Indent, buffer, gcmSIZEOF(buffer)); /* Format the string. */ len += gcmkVSPRINTF(buffer + len, gcmSIZEOF(buffer) - len, Message, Data); buffer[len] = '\0'; /* Add end-of-line if missing. */ if (buffer[len - 1] != '\n') { buffer[len++] = '\n'; buffer[len] = '\0'; } /* Print the string. */ gcmkOUTPUT_STRING(buffer); } static void _PrintBuffer( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctINT Indent, IN gctPOINTER PrefixData, IN gctPOINTER Data, IN gctUINT Address, IN gctUINT DataSize, IN gceDUMP_BUFFER Type, IN gctUINT32 DmaAddress ) { static gctCONST_STRING _titleString[] = { "CONTEXT BUFFER", "USER COMMAND BUFFER", "KERNEL COMMAND BUFFER", "LINK BUFFER", "WAIT LINK BUFFER", "" }; static const gctINT COLUMN_COUNT = 8; gctUINT i, count, column, address; gctUINT32_PTR data; gctCHAR buffer[768]; gctUINT indent, len; gctBOOL command; /* Append space for the prefix. */ #if gcdHAVEPREFIX indent = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, PrefixData); buffer[indent] = '\0'; #else indent = 0; #endif /* Append the indent string. */ indent += _AppendIndent( Indent, buffer + indent, gcmSIZEOF(buffer) - indent ); switch (Type) { case gceDUMP_BUFFER_CONTEXT: case gceDUMP_BUFFER_USER: case gceDUMP_BUFFER_KERNEL: case gceDUMP_BUFFER_LINK: case gceDUMP_BUFFER_WAITLINK: /* Form and print the title string. */ gcmkSPRINTF2( buffer + indent, gcmSIZEOF(buffer) - indent, "%s%s\n", _titleString[Type], ((DmaAddress >= Address) && (DmaAddress < Address + DataSize)) ? " (CURRENT)" : "" ); gcmkOUTPUT_STRING(buffer); /* Terminate the string. */ buffer[indent] = '\0'; /* This is a command buffer. */ command = gcvTRUE; break; case gceDUMP_BUFFER_FROM_USER: /* This is not a command buffer. */ command = gcvFALSE; /* No title. */ break; default: gcmDBGASSERT(gcvFALSE, "%s", "invalid buffer type"); /* This is not a command buffer. */ command = gcvFALSE; } /* Overwrite the prefix with spaces. */ for (i = 0; i < indent; i += 1) { buffer[i] = ' '; } /* Form and print the opening string. */ if (command) { gcmkSPRINTF2( buffer + indent, gcmSIZEOF(buffer) - indent, "@[kernel.command %08X %08X\n", Address, DataSize ); gcmkOUTPUT_STRING(buffer); /* Terminate the string. */ buffer[indent] = '\0'; } /* Get initial address. */ address = Address; /* Cast the data pointer. */ data = (gctUINT32_PTR) Data; /* Compute the number of double words. */ count = DataSize / gcmSIZEOF(gctUINT32); /* Print the buffer. */ for (i = 0, len = indent, column = 0; i < count; i += 1) { /* Append the address. */ if (column == 0) { len += gcmkSPRINTF( buffer + len, gcmSIZEOF(buffer) - len, "0x%08X:", address ); } /* Append the data value. */ len += gcmkSPRINTF2( buffer + len, gcmSIZEOF(buffer) - len, "%c%08X", (address == DmaAddress)? '>' : ' ', data[i] ); buffer[len] = '\0'; /* Update the address. */ address += gcmSIZEOF(gctUINT32); /* Advance column count. */ column += 1; /* End of line? */ if ((column % COLUMN_COUNT) == 0) { /* Append EOL. */ gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n"); /* Print the string. */ gcmkOUTPUT_STRING(buffer); /* Reset. */ len = indent; column = 0; } } /* Print the last partial string. */ if (column != 0) { /* Append EOL. */ gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n"); /* Print the string. */ gcmkOUTPUT_STRING(buffer); } /* Form and print the opening string. */ if (command) { buffer[indent] = '\0'; gcmkSTRCAT(buffer, gcmSIZEOF(buffer), "] -- command\n"); gcmkOUTPUT_STRING(buffer); } } #if gcdBUFFERED_OUTPUT static gctUINT _PrintNone( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gcsBUFITEM_HEAD_PTR Item ) { /* Return the size of the node. */ return gcmSIZEOF(gcsBUFITEM_HEAD); } static gctUINT _PrintPrefixWrapper( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gcsBUFITEM_HEAD_PTR Item ) { #if gcdHAVEPREFIX gcsBUFITEM_PREFIX_PTR item; gctUINT vlen; /* Get access to the data. */ item = (gcsBUFITEM_PREFIX_PTR) Item; /* Print the message. */ _PrintPrefix(OutputBuffer, item->prefixData); /* Compute the size of the variable portion of the structure. */ vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item); /* Return the size of the node. */ return vlen + gcdPREFIX_SIZE; #else return gcmSIZEOF(gcsBUFITEM_PREFIX); #endif } static gctUINT _PrintStringWrapper( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gcsBUFITEM_HEAD_PTR Item ) { gcsBUFITEM_STRING_PTR item; gctUINT vlen; /* Get access to the data. */ item = (gcsBUFITEM_STRING_PTR) Item; /* Print the message. */ _PrintString( OutputBuffer, item->indent, item->message, item->messageDataSize, item->messageData ); /* Compute the size of the variable portion of the structure. */ vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item); /* Return the size of the node. */ return vlen + item->messageDataSize; } static gctUINT _PrintCopyWrapper( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gcsBUFITEM_HEAD_PTR Item ) { gcsBUFITEM_COPY_PTR item; gctCONST_STRING message; gctUINT vlen; /* Get access to the data. */ item = (gcsBUFITEM_COPY_PTR) Item; /* Determine the string pointer. */ message = (gctCONST_STRING) (item + 1); /* Print the message. */ _PrintString( OutputBuffer, item->indent, message, item->messageDataSize, item->messageData ); /* Compute the size of the variable portion of the structure. */ vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item); /* Return the size of the node. */ return vlen + item->messageDataSize; } static gctUINT _PrintBufferWrapper( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gcsBUFITEM_HEAD_PTR Item ) { #if gcdHAVEPREFIX gctUINT32 dmaAddress; gcsBUFITEM_BUFFER_PTR item; gctPOINTER data; gctUINT vlen; /* Get access to the data. */ item = (gcsBUFITEM_BUFFER_PTR) Item; #if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1) dmaAddress = item->dmaAddress; #else dmaAddress = 0xFFFFFFFF; #endif if (dmaAddress != 0) { /* Compute the data address. */ data = ((gctUINT8_PTR) item->prefixData) + gcdPREFIX_SIZE; /* Print buffer. */ _PrintBuffer( OutputBuffer, item->indent, item->prefixData, data, item->address, item->dataSize, item->bufferType, dmaAddress ); } /* Compute the size of the variable portion of the structure. */ vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item); /* Return the size of the node. */ return vlen + gcdPREFIX_SIZE + item->dataSize; #else gctUINT32 dmaAddress; gcsBUFITEM_BUFFER_PTR item; /* Get access to the data. */ item = (gcsBUFITEM_BUFFER_PTR) Item; #if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1) dmaAddress = item->dmaAddress; #else dmaAddress = 0xFFFFFFFF; #endif if (dmaAddress != 0) { /* Print buffer. */ _PrintBuffer( OutputBuffer, item->indent, gcvNULL, item + 1, item->address, item->dataSize, item->bufferType, dmaAddress ); } /* Return the size of the node. */ return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize; #endif } static gcfPRINTSTRING _printArray[] = { _PrintNone, _PrintPrefixWrapper, _PrintStringWrapper, _PrintCopyWrapper, _PrintBufferWrapper }; #endif /******************************************************************************\ ******************************* Private Functions ****************************** \******************************************************************************/ #if gcdBUFFERED_OUTPUT #if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1) static gcsBUFITEM_BUFFER_PTR _FindCurrentDMABuffer( gctUINT32 DmaAddress ) { gctINT i, skip; gcsBUFITEM_HEAD_PTR item; gcsBUFITEM_BUFFER_PTR dmaCurrent; /* Reset the current buffer. */ dmaCurrent = gcvNULL; /* Get the first stored item. */ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start]; /* Run through all items. */ for (i = 0; i < _outputBufferHead->count; i += 1) { /* Buffer item? */ if (item->type == gcvBUFITEM_BUFFER) { gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item; if ((DmaAddress >= buffer->address) && (DmaAddress < buffer->address + buffer->dataSize)) { dmaCurrent = buffer; } } /* Get the item size and skip it. */ skip = (* _itemSize[item->type]) (item); item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip); /* End of the buffer? Wrap around. */ if (item->type == gceBUFITEM_NONE) { item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer; } } /* Return result. */ return dmaCurrent; } static void _EnableAllDMABuffers( void ) { gctINT i, skip; gcsBUFITEM_HEAD_PTR item; /* Get the first stored item. */ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start]; /* Run through all items. */ for (i = 0; i < _outputBufferHead->count; i += 1) { /* Buffer item? */ if (item->type == gcvBUFITEM_BUFFER) { gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item; /* Enable the buffer. */ buffer->dmaAddress = ~0U; } /* Get the item size and skip it. */ skip = (* _itemSize[item->type]) (item); item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip); /* End of the buffer? Wrap around. */ if (item->type == gceBUFITEM_NONE) { item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer; } } } static void _EnableDMABuffers( gctUINT32 DmaAddress, gcsBUFITEM_BUFFER_PTR CurrentDMABuffer ) { gctINT i, skip, index; gcsBUFITEM_HEAD_PTR item; gcsBUFITEM_BUFFER_PTR buffers[gcdDMA_BUFFER_COUNT]; /* Reset buffer pointers. */ gckOS_ZeroMemory(buffers, gcmSIZEOF(buffers)); /* Set the current buffer index. */ index = -1; /* Get the first stored item. */ item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start]; /* Run through all items until the current DMA buffer is found. */ for (i = 0; i < _outputBufferHead->count; i += 1) { /* Buffer item? */ if (item->type == gcvBUFITEM_BUFFER) { /* Advance the index. */ index = (index + 1) % gcdDMA_BUFFER_COUNT; /* Add to the buffer array. */ buffers[index] = (gcsBUFITEM_BUFFER_PTR) item; /* Stop if this is the current DMA buffer. */ if ((gcsBUFITEM_BUFFER_PTR) item == CurrentDMABuffer) { break; } } /* Get the item size and skip it. */ skip = (* _itemSize[item->type]) (item); item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip); /* End of the buffer? Wrap around. */ if (item->type == gceBUFITEM_NONE) { item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer; } } /* Enable the found buffers. */ gcmDBGASSERT(index != -1, "%d", index); for (i = 0; i < gcdDMA_BUFFER_COUNT; i += 1) { if (buffers[index] == gcvNULL) { break; } buffers[index]->dmaAddress = DmaAddress; index -= 1; if (index == -1) { index = gcdDMA_BUFFER_COUNT - 1; } } } #endif static void _Flush( gctUINT32 DmaAddress ) { gctINT i, skip; gcsBUFITEM_HEAD_PTR item; gcsBUFFERED_OUTPUT_PTR outputBuffer = _outputBufferHead; #if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1) if ((outputBuffer != gcvNULL) && (outputBuffer->count != 0)) { /* Find the current DMA buffer. */ gcsBUFITEM_BUFFER_PTR dmaCurrent = _FindCurrentDMABuffer(DmaAddress); /* Was the current buffer found? */ if (dmaCurrent == gcvNULL) { /* No, print all buffers. */ _EnableAllDMABuffers(); } else { /* Yes, enable only specified number of buffers. */ _EnableDMABuffers(DmaAddress, dmaCurrent); } } #endif while (outputBuffer != gcvNULL) { if (outputBuffer->count != 0) { _DirectPrint("********************************************************************************\n"); _DirectPrint("FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", outputBuffer->count); _DirectPrint("********************************************************************************\n"); item = (gcsBUFITEM_HEAD_PTR) &outputBuffer->buffer[outputBuffer->start]; for (i = 0; i < outputBuffer->count; i += 1) { skip = (* _printArray[item->type]) (outputBuffer, item); item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip); if (item->type == gceBUFITEM_NONE) { item = (gcsBUFITEM_HEAD_PTR) outputBuffer->buffer; } } outputBuffer->start = 0; outputBuffer->index = 0; outputBuffer->count = 0; } outputBuffer = outputBuffer->next; } } static gcsBUFITEM_HEAD_PTR _AllocateItem( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctINT Size ) { gctINT skip; gcsBUFITEM_HEAD_PTR item, next; #if gcdENABLE_OVERFLOW if ( (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD)) || ( (OutputBuffer->index < OutputBuffer->start) && (OutputBuffer->index + Size >= OutputBuffer->start) ) ) { if (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD)) { if (OutputBuffer->index < OutputBuffer->start) { item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start]; while (item->type != gceBUFITEM_NONE) { skip = (* _itemSize[item->type]) (item); OutputBuffer->start += skip; OutputBuffer->count -= 1; item->type = gceBUFITEM_NONE; item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip); } OutputBuffer->start = 0; } OutputBuffer->index = 0; } item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start]; while (OutputBuffer->start - OutputBuffer->index <= Size) { skip = (* _itemSize[item->type]) (item); OutputBuffer->start += skip; OutputBuffer->count -= 1; item->type = gceBUFITEM_NONE; item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip); if (item->type == gceBUFITEM_NONE) { OutputBuffer->start = 0; break; } } } #else if (OutputBuffer->index + Size > gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD)) { _DirectPrint("\nMessage buffer full; forcing message flush.\n\n"); _Flush(~0U); } #endif item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->index]; OutputBuffer->index += Size; OutputBuffer->count += 1; next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + Size); next->type = gceBUFITEM_NONE; return item; } #if gcdALIGNBYSIZE static void _FreeExtraSpace( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctPOINTER Item, IN gctINT ItemSize, IN gctINT FreeSize ) { gcsBUFITEM_HEAD_PTR next; OutputBuffer->index -= FreeSize; next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) Item + ItemSize); next->type = gceBUFITEM_NONE; } #endif #if gcdHAVEPREFIX static void _AppendPrefix( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctPOINTER Data ) { gctUINT8_PTR prefixData; gcsBUFITEM_PREFIX_PTR item; gctINT allocSize; #if gcdALIGNBYSIZE gctUINT alignment; gctINT size, freeSize; #endif gcmDBGASSERT(Data != gcvNULL, "%p", Data); /* Determine the maximum item size. */ allocSize = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT; /* Allocate prefix item. */ item = (gcsBUFITEM_PREFIX_PTR) _AllocateItem(OutputBuffer, allocSize); /* Compute the initial prefix data pointer. */ prefixData = (gctUINT8_PTR) (item + 1); /* Align the data pointer as necessary. */ #if gcdALIGNBYSIZE alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT); prefixData += alignment; #endif /* Set item data. */ item->type = gcvBUFITEM_PREFIX; item->prefixData = prefixData; /* Copy argument value. */ memcpy(prefixData, Data, gcdPREFIX_SIZE); #if gcdALIGNBYSIZE /* Compute the actual node size. */ size = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + alignment; /* Free extra memory if any. */ freeSize = allocSize - size; if (freeSize != 0) { _FreeExtraSpace(OutputBuffer, item, size, freeSize); } #endif } #endif static void _AppendString( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctINT Indent, IN gctCONST_STRING Message, IN gctUINT ArgumentSize, IN gctPOINTER Data ) { gctUINT8_PTR messageData; gcsBUFITEM_STRING_PTR item; gctINT allocSize; #if gcdALIGNBYSIZE gctUINT alignment; gctINT size, freeSize; #endif /* Determine the maximum item size. */ allocSize = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + gcdVARARG_ALIGNMENT; /* Allocate prefix item. */ item = (gcsBUFITEM_STRING_PTR) _AllocateItem(OutputBuffer, allocSize); /* Compute the initial message data pointer. */ messageData = (gctUINT8_PTR) (item + 1); /* Align the data pointer as necessary. */ #if gcdALIGNBYSIZE alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT); messageData += alignment; #endif /* Set item data. */ item->type = gcvBUFITEM_STRING; item->indent = Indent; item->message = Message; item->messageData = messageData; item->messageDataSize = ArgumentSize; /* Copy argument value. */ if (ArgumentSize != 0) { memcpy(messageData, Data, ArgumentSize); } #if gcdALIGNBYSIZE /* Compute the actual node size. */ size = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + alignment; /* Free extra memory if any. */ freeSize = allocSize - size; if (freeSize != 0) { _FreeExtraSpace(OutputBuffer, item, size, freeSize); } #endif } static void _AppendCopy( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctINT Indent, IN gctCONST_STRING Message, IN gctUINT ArgumentSize, IN gctPOINTER Data ) { gctUINT8_PTR messageData; gcsBUFITEM_COPY_PTR item; gctINT allocSize; gctINT messageLength; gctCONST_STRING message; #if gcdALIGNBYSIZE gctUINT alignment; gctINT size, freeSize; #endif /* Get the length of the string. */ messageLength = strlen(Message) + 1; /* Determine the maximum item size. */ allocSize = gcmSIZEOF(gcsBUFITEM_COPY) + messageLength + ArgumentSize + gcdVARARG_ALIGNMENT; /* Allocate prefix item. */ item = (gcsBUFITEM_COPY_PTR) _AllocateItem(OutputBuffer, allocSize); /* Determine the message placement. */ message = (gctCONST_STRING) (item + 1); /* Compute the initial message data pointer. */ messageData = (gctUINT8_PTR) message + messageLength; /* Align the data pointer as necessary. */ #if gcdALIGNBYSIZE if (ArgumentSize == 0) { alignment = 0; } else { alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT); messageData += alignment; } #endif /* Set item data. */ item->type = gcvBUFITEM_COPY; item->indent = Indent; item->messageData = messageData; item->messageDataSize = ArgumentSize; /* Copy the message. */ memcpy((gctPOINTER) message, Message, messageLength); /* Copy argument value. */ if (ArgumentSize != 0) { memcpy(messageData, Data, ArgumentSize); } #if gcdALIGNBYSIZE /* Compute the actual node size. */ size = gcmSIZEOF(gcsBUFITEM_COPY) + messageLength + ArgumentSize + alignment; /* Free extra memory if any. */ freeSize = allocSize - size; if (freeSize != 0) { _FreeExtraSpace(OutputBuffer, item, size, freeSize); } #endif } static void _AppendBuffer( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctINT Indent, IN gctPOINTER PrefixData, IN gctPOINTER Data, IN gctUINT Address, IN gctUINT DataSize, IN gceDUMP_BUFFER Type, IN gctUINT32 DmaAddress ) { #if gcdHAVEPREFIX gctUINT8_PTR prefixData; gcsBUFITEM_BUFFER_PTR item; gctINT allocSize; gctPOINTER data; #if gcdALIGNBYSIZE gctUINT alignment; gctINT size, freeSize; #endif gcmDBGASSERT(DataSize != 0, "%d", DataSize); gcmDBGASSERT(Data != gcvNULL, "%p", Data); /* Determine the maximum item size. */ allocSize = gcmSIZEOF(gcsBUFITEM_BUFFER) + gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT + DataSize; /* Allocate prefix item. */ item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, allocSize); /* Compute the initial prefix data pointer. */ prefixData = (gctUINT8_PTR) (item + 1); #if gcdALIGNBYSIZE /* Align the data pointer as necessary. */ alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT); prefixData += alignment; #endif /* Set item data. */ item->type = gcvBUFITEM_BUFFER; item->indent = Indent; item->bufferType = Type; item->dataSize = DataSize; item->address = Address; item->prefixData = prefixData; #if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1) item->dmaAddress = DmaAddress; #endif /* Copy prefix data. */ memcpy(prefixData, PrefixData, gcdPREFIX_SIZE); /* Compute the data pointer. */ data = prefixData + gcdPREFIX_SIZE; /* Copy argument value. */ memcpy(data, Data, DataSize); #if gcdALIGNBYSIZE /* Compute the actual node size. */ size = gcmSIZEOF(gcsBUFITEM_BUFFER) + gcdPREFIX_SIZE + alignment + DataSize; /* Free extra memory if any. */ freeSize = allocSize - size; if (freeSize != 0) { _FreeExtraSpace(OutputBuffer, item, size, freeSize); } #endif #else gcsBUFITEM_BUFFER_PTR item; gctINT size; gcmDBGASSERT(DataSize != 0, "%d", DataSize); gcmDBGASSERT(Data != gcvNULL, "%p", Data); /* Determine the maximum item size. */ size = gcmSIZEOF(gcsBUFITEM_BUFFER) + DataSize; /* Allocate prefix item. */ item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, size); /* Set item data. */ item->type = gcvBUFITEM_BUFFER; item->indent = Indent; item->dataSize = DataSize; item->address = Address; /* Copy argument value. */ memcpy(item + 1, Data, DataSize); #endif } #endif static gcmINLINE void _InitBuffers( void ) { int i; if (_outputBufferHead == gcvNULL) { for (i = 0; i < gcdTHREAD_BUFFERS; i += 1) { if (_outputBufferTail == gcvNULL) { _outputBufferHead = &_outputBuffer[i]; } else { _outputBufferTail->next = &_outputBuffer[i]; } #if gcdTHREAD_BUFFERS > 1 _outputBuffer[i].threadID = ~0U; #endif _outputBuffer[i].prev = _outputBufferTail; _outputBuffer[i].next = gcvNULL; _outputBufferTail = &_outputBuffer[i]; } } } static gcmINLINE gcsBUFFERED_OUTPUT_PTR _GetOutputBuffer( void ) { gcsBUFFERED_OUTPUT_PTR outputBuffer; #if gcdTHREAD_BUFFERS > 1 /* Get the current thread ID. */ gctUINT32 ThreadID = gcmkGETTHREADID(); /* Locate the output buffer for the thread. */ outputBuffer = _outputBufferHead; while (outputBuffer != gcvNULL) { if (outputBuffer->threadID == ThreadID) { break; } outputBuffer = outputBuffer->next; } /* No matching buffer found? */ if (outputBuffer == gcvNULL) { /* Get the tail for the buffer. */ outputBuffer = _outputBufferTail; /* Move it to the head. */ _outputBufferTail = _outputBufferTail->prev; _outputBufferTail->next = gcvNULL; outputBuffer->prev = gcvNULL; outputBuffer->next = _outputBufferHead; _outputBufferHead->prev = outputBuffer; _outputBufferHead = outputBuffer; /* Reset the buffer. */ outputBuffer->threadID = ThreadID; #if gcdBUFFERED_OUTPUT outputBuffer->start = 0; outputBuffer->index = 0; outputBuffer->count = 0; #endif #if gcdSHOW_LINE_NUMBER outputBuffer->lineNumber = 0; #endif } #else outputBuffer = _outputBufferHead; #endif return outputBuffer; } static gcmINLINE int _GetArgumentSize( IN gctCONST_STRING Message ) { int i, count; gcmDBGASSERT(Message != gcvNULL, "%p", Message); for (i = 0, count = 0; Message[i]; i += 1) { if (Message[i] == '%') { count += 1; } } return count * gcmSIZEOF(gctUINT32); } #if gcdHAVEPREFIX static void _InitPrefixData( IN gcsBUFFERED_OUTPUT_PTR OutputBuffer, IN gctPOINTER Data ) { gctUINT8_PTR data = (gctUINT8_PTR) Data; #if gcdSHOW_TIME { gctUINT64 time; gckOS_GetProfileTick(&time); gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64)); * ((gctUINT64_PTR) data) = time; data += gcmSIZEOF(gctUINT64); } #endif #if gcdSHOW_LINE_NUMBER { gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64)); * ((gctUINT64_PTR) data) = OutputBuffer->lineNumber; data += gcmSIZEOF(gctUINT64); } #endif #if gcdSHOW_PROCESS_ID { gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32)); * ((gctUINT32_PTR) data) = gcmkGETPROCESSID(); data += gcmSIZEOF(gctUINT32); } #endif #if gcdSHOW_THREAD_ID { gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32)); * ((gctUINT32_PTR) data) = gcmkGETTHREADID(); } #endif } #endif static void _Print( IN gctUINT ArgumentSize, IN gctBOOL CopyMessage, IN gctCONST_STRING Message, IN gctARGUMENTS Arguments ) { gcsBUFFERED_OUTPUT_PTR outputBuffer; gcmkDECLARE_LOCK(lockHandle); gcmkLOCKSECTION(lockHandle); /* Initialize output buffer list. */ _InitBuffers(); /* Locate the proper output buffer. */ outputBuffer = _GetOutputBuffer(); /* Update the line number. */ #if gcdSHOW_LINE_NUMBER outputBuffer->lineNumber += 1; #endif /* Print prefix. */ #if gcdHAVEPREFIX { gctUINT8_PTR alignedPrefixData; gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT]; /* Compute aligned pointer. */ alignedPrefixData = prefixData; gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT); /* Initialize the prefix data. */ _InitPrefixData(outputBuffer, alignedPrefixData); /* Print the prefix. */ gcdOUTPUTPREFIX(outputBuffer, alignedPrefixData); } #endif /* Form the indent string. */ if (strncmp(Message, "--", 2) == 0) { outputBuffer->indent -= 2; } /* Print the message. */ if (CopyMessage) { gcdOUTPUTCOPY( outputBuffer, outputBuffer->indent, Message, ArgumentSize, * (gctPOINTER *) &Arguments ); } else { gcdOUTPUTSTRING( outputBuffer, outputBuffer->indent, Message, ArgumentSize, * (gctPOINTER *) &Arguments ); } /* Check increasing indent. */ if (strncmp(Message, "++", 2) == 0) { outputBuffer->indent += 2; } gcmkUNLOCKSECTION(lockHandle); } /******************************************************************************\ ********************************* Debug Macros ********************************* \******************************************************************************/ #ifdef __QNXNTO__ extern volatile unsigned g_nQnxInIsrs; #define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \ { \ if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \ { \ gctARGUMENTS __arguments__; \ gcmkARGUMENTS_START(__arguments__, Message); \ _Print(ArgumentSize, CopyMessage, Message, __arguments__); \ gcmkARGUMENTS_END(__arguments__); \ } \ atomic_sub(&g_nQnxInIsrs, 1); \ } #else #define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \ { \ gctARGUMENTS __arguments__; \ gcmkARGUMENTS_START(__arguments__, Message); \ _Print(ArgumentSize, CopyMessage, Message, __arguments__); \ gcmkARGUMENTS_END(__arguments__); \ } #endif /******************************************************************************\ ********************************** Debug Code ********************************** \******************************************************************************/ /******************************************************************************* ** ** gckOS_Print ** ** Send a message to the debugger. ** ** INPUT: ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_Print( IN gctCONST_STRING Message, ... ) { gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message); } /******************************************************************************* ** ** gckOS_PrintN ** ** Send a message to the debugger. ** ** INPUT: ** ** gctUINT ArgumentSize ** The size of the optional arguments in bytes. ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_PrintN( IN gctUINT ArgumentSize, IN gctCONST_STRING Message, ... ) { gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message); } /******************************************************************************* ** ** gckOS_CopyPrint ** ** Send a message to the debugger. If in buffered output mode, the entire ** message will be copied into the buffer instead of using the pointer to ** the string. ** ** INPUT: ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_CopyPrint( IN gctCONST_STRING Message, ... ) { gcmDEBUGPRINT(_GetArgumentSize(Message), gcvTRUE, Message); } /******************************************************************************* ** ** gckOS_DumpBuffer ** ** Print the contents of the specified buffer. ** ** INPUT: ** ** gckOS Os ** Pointer to gckOS object. ** ** gctPOINTER Buffer ** Pointer to the buffer to print. ** ** gctUINT Size ** Size of the buffer. ** ** gceDUMP_BUFFER Type ** Buffer type. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DumpBuffer( IN gckOS Os, IN gctPOINTER Buffer, IN gctUINT Size, IN gceDUMP_BUFFER Type, IN gctBOOL CopyMessage ) { gctUINT32 address; gcsBUFFERED_OUTPUT_PTR outputBuffer; static gctBOOL userLocked; gctCHAR *buffer = (gctCHAR*)Buffer; gcmkDECLARE_LOCK(lockHandle); /* Request lock when not coming from user, or coming from user and not yet locked and message is starting with @[. */ if (Type == gceDUMP_BUFFER_FROM_USER) { if ((Size > 2) && (buffer[0] == '@') && (buffer[1] == '[')) { /* Beginning of a user dump. */ gcmkLOCKSECTION(lockHandle); userLocked = gcvTRUE; } /* Else, let it pass through. */ } else { gcmkLOCKSECTION(lockHandle); userLocked = gcvFALSE; } if (Buffer != gcvNULL) { /* Initialize output buffer list. */ _InitBuffers(); /* Locate the proper output buffer. */ outputBuffer = _GetOutputBuffer(); /* Update the line number. */ #if gcdSHOW_LINE_NUMBER outputBuffer->lineNumber += 1; #endif /* Get the physical address of the buffer. */ if (Type != gceDUMP_BUFFER_FROM_USER) { gcmkVERIFY_OK(gckOS_GetPhysicalAddress(Os, Buffer, &address)); } else { address = 0; } #if gcdHAVEPREFIX { gctUINT8_PTR alignedPrefixData; gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT]; /* Compute aligned pointer. */ alignedPrefixData = prefixData; gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT); /* Initialize the prefix data. */ _InitPrefixData(outputBuffer, alignedPrefixData); /* Print/schedule the buffer. */ gcdOUTPUTBUFFER( outputBuffer, outputBuffer->indent, alignedPrefixData, Buffer, address, Size, Type, 0 ); } #else /* Print/schedule the buffer. */ if (Type == gceDUMP_BUFFER_FROM_USER) { gcdOUTPUTSTRING( outputBuffer, outputBuffer->indent, Buffer, 0, gcvNULL ); } else { gcdOUTPUTBUFFER( outputBuffer, outputBuffer->indent, gcvNULL, Buffer, address, Size, Type, 0 ); } #endif } /* Unlock when not coming from user, or coming from user and not yet locked. */ if (userLocked) { if ((Size > 4) && (buffer[0] == ']') && (buffer[1] == ' ') && (buffer[2] == '-') && (buffer[3] == '-')) { /* End of a user dump. */ gcmkUNLOCKSECTION(lockHandle); userLocked = gcvFALSE; } /* Else, let it pass through, don't unlock. */ } else { gcmkUNLOCKSECTION(lockHandle); } } /******************************************************************************* ** ** gckOS_DebugTrace ** ** Send a leveled message to the debugger. ** ** INPUT: ** ** gctUINT32 Level ** Debug level of message. ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugTrace( IN gctUINT32 Level, IN gctCONST_STRING Message, ... ) { if (Level > _debugLevel) { return; } gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message); } /******************************************************************************* ** ** gckOS_DebugTraceN ** ** Send a leveled message to the debugger. ** ** INPUT: ** ** gctUINT32 Level ** Debug level of message. ** ** gctUINT ArgumentSize ** The size of the optional arguments in bytes. ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugTraceN( IN gctUINT32 Level, IN gctUINT ArgumentSize, IN gctCONST_STRING Message, ... ) { if (Level > _debugLevel) { return; } gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message); } /******************************************************************************* ** ** gckOS_DebugTraceZone ** ** Send a leveled and zoned message to the debugger. ** ** INPUT: ** ** gctUINT32 Level ** Debug level for message. ** ** gctUINT32 Zone ** Debug zone for message. ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugTraceZone( IN gctUINT32 Level, IN gctUINT32 Zone, IN gctCONST_STRING Message, ... ) { if ((Level > _debugLevel) || !(Zone & _debugZones)) { return; } gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message); } /******************************************************************************* ** ** gckOS_DebugTraceZoneN ** ** Send a leveled and zoned message to the debugger. ** ** INPUT: ** ** gctUINT32 Level ** Debug level for message. ** ** gctUINT32 Zone ** Debug zone for message. ** ** gctUINT ArgumentSize ** The size of the optional arguments in bytes. ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugTraceZoneN( IN gctUINT32 Level, IN gctUINT32 Zone, IN gctUINT ArgumentSize, IN gctCONST_STRING Message, ... ) { if ((Level > _debugLevel) || !(Zone & _debugZones)) { return; } gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message); } /******************************************************************************* ** ** gckOS_DebugBreak ** ** Break into the debugger. ** ** INPUT: ** ** Nothing. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugBreak( void ) { gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__); } /******************************************************************************* ** ** gckOS_DebugFatal ** ** Send a message to the debugger and break into the debugger. ** ** INPUT: ** ** gctCONST_STRING Message ** Pointer to message. ** ** ... ** Optional arguments. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugFatal( IN gctCONST_STRING Message, ... ) { gcmkPRINT_VERSION(); gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message); /* Break into the debugger. */ gckOS_DebugBreak(); } /******************************************************************************* ** ** gckOS_SetDebugLevel ** ** Set the debug level. ** ** INPUT: ** ** gctUINT32 Level ** New debug level. ** ** OUTPUT: ** ** Nothing. */ void gckOS_SetDebugLevel( IN gctUINT32 Level ) { _debugLevel = Level; } /******************************************************************************* ** ** gckOS_SetDebugZone ** ** Set the debug zone. ** ** INPUT: ** ** gctUINT32 Zone ** New debug zone. ** ** OUTPUT: ** ** Nothing. */ void gckOS_SetDebugZone( IN gctUINT32 Zone ) { _debugZones = Zone; } /******************************************************************************* ** ** gckOS_SetDebugLevelZone ** ** Set the debug level and zone. ** ** INPUT: ** ** gctUINT32 Level ** New debug level. ** ** gctUINT32 Zone ** New debug zone. ** ** OUTPUT: ** ** Nothing. */ void gckOS_SetDebugLevelZone( IN gctUINT32 Level, IN gctUINT32 Zone ) { _debugLevel = Level; _debugZones = Zone; } /******************************************************************************* ** ** gckOS_SetDebugZones ** ** Enable or disable debug zones. ** ** INPUT: ** ** gctUINT32 Zones ** Debug zones to enable or disable. ** ** gctBOOL Enable ** Set to gcvTRUE to enable the zones (or the Zones with the current ** zones) or gcvFALSE to disable the specified Zones. ** ** OUTPUT: ** ** Nothing. */ void gckOS_SetDebugZones( IN gctUINT32 Zones, IN gctBOOL Enable ) { if (Enable) { /* Enable the zones. */ _debugZones |= Zones; } else { /* Disable the zones. */ _debugZones &= ~Zones; } } /******************************************************************************* ** ** gckOS_Verify ** ** Called to verify the result of a function call. ** ** INPUT: ** ** gceSTATUS Status ** Function call result. ** ** OUTPUT: ** ** Nothing. */ void gckOS_Verify( IN gceSTATUS status ) { _lastError = status; } /******************************************************************************* ** ** gckOS_DebugFlush ** ** Force messages to be flushed out. ** ** INPUT: ** ** gctCONST_STRING CallerName ** Name of the caller function. ** ** gctUINT LineNumber ** Line number of the caller. ** ** gctUINT32 DmaAddress ** The current DMA address or ~0U to ignore. ** ** OUTPUT: ** ** Nothing. */ void gckOS_DebugFlush( gctCONST_STRING CallerName, gctUINT LineNumber, gctUINT32 DmaAddress ) { #if gcdBUFFERED_OUTPUT _DirectPrint("\nFlush requested by %s(%d).\n\n", CallerName, LineNumber); _Flush(DmaAddress); #endif } gctCONST_STRING gckOS_DebugStatus2Name( gceSTATUS status ) { switch (status) { case gcvSTATUS_OK: return "gcvSTATUS_OK"; case gcvSTATUS_TRUE: return "gcvSTATUS_TRUE"; case gcvSTATUS_NO_MORE_DATA: return "gcvSTATUS_NO_MORE_DATA"; case gcvSTATUS_CACHED: return "gcvSTATUS_CACHED"; case gcvSTATUS_MIPMAP_TOO_LARGE: return "gcvSTATUS_MIPMAP_TOO_LARGE"; case gcvSTATUS_NAME_NOT_FOUND: return "gcvSTATUS_NAME_NOT_FOUND"; case gcvSTATUS_NOT_OUR_INTERRUPT: return "gcvSTATUS_NOT_OUR_INTERRUPT"; case gcvSTATUS_MISMATCH: return "gcvSTATUS_MISMATCH"; case gcvSTATUS_MIPMAP_TOO_SMALL: return "gcvSTATUS_MIPMAP_TOO_SMALL"; case gcvSTATUS_LARGER: return "gcvSTATUS_LARGER"; case gcvSTATUS_SMALLER: return "gcvSTATUS_SMALLER"; case gcvSTATUS_CHIP_NOT_READY: return "gcvSTATUS_CHIP_NOT_READY"; case gcvSTATUS_NEED_CONVERSION: return "gcvSTATUS_NEED_CONVERSION"; case gcvSTATUS_SKIP: return "gcvSTATUS_SKIP"; case gcvSTATUS_DATA_TOO_LARGE: return "gcvSTATUS_DATA_TOO_LARGE"; case gcvSTATUS_INVALID_CONFIG: return "gcvSTATUS_INVALID_CONFIG"; case gcvSTATUS_CHANGED: return "gcvSTATUS_CHANGED"; case gcvSTATUS_NOT_SUPPORT_DITHER: return "gcvSTATUS_NOT_SUPPORT_DITHER"; case gcvSTATUS_INVALID_ARGUMENT: return "gcvSTATUS_INVALID_ARGUMENT"; case gcvSTATUS_INVALID_OBJECT: return "gcvSTATUS_INVALID_OBJECT"; case gcvSTATUS_OUT_OF_MEMORY: return "gcvSTATUS_OUT_OF_MEMORY"; case gcvSTATUS_MEMORY_LOCKED: return "gcvSTATUS_MEMORY_LOCKED"; case gcvSTATUS_MEMORY_UNLOCKED: return "gcvSTATUS_MEMORY_UNLOCKED"; case gcvSTATUS_HEAP_CORRUPTED: return "gcvSTATUS_HEAP_CORRUPTED"; case gcvSTATUS_GENERIC_IO: return "gcvSTATUS_GENERIC_IO"; case gcvSTATUS_INVALID_ADDRESS: return "gcvSTATUS_INVALID_ADDRESS"; case gcvSTATUS_CONTEXT_LOSSED: return "gcvSTATUS_CONTEXT_LOSSED"; case gcvSTATUS_TOO_COMPLEX: return "gcvSTATUS_TOO_COMPLEX"; case gcvSTATUS_BUFFER_TOO_SMALL: return "gcvSTATUS_BUFFER_TOO_SMALL"; case gcvSTATUS_INTERFACE_ERROR: return "gcvSTATUS_INTERFACE_ERROR"; case gcvSTATUS_NOT_SUPPORTED: return "gcvSTATUS_NOT_SUPPORTED"; case gcvSTATUS_MORE_DATA: return "gcvSTATUS_MORE_DATA"; case gcvSTATUS_TIMEOUT: return "gcvSTATUS_TIMEOUT"; case gcvSTATUS_OUT_OF_RESOURCES: return "gcvSTATUS_OUT_OF_RESOURCES"; case gcvSTATUS_INVALID_DATA: return "gcvSTATUS_INVALID_DATA"; case gcvSTATUS_INVALID_MIPMAP: return "gcvSTATUS_INVALID_MIPMAP"; case gcvSTATUS_NOT_FOUND: return "gcvSTATUS_NOT_FOUND"; case gcvSTATUS_NOT_ALIGNED: return "gcvSTATUS_NOT_ALIGNED"; case gcvSTATUS_INVALID_REQUEST: return "gcvSTATUS_INVALID_REQUEST"; case gcvSTATUS_GPU_NOT_RESPONDING: return "gcvSTATUS_GPU_NOT_RESPONDING"; case gcvSTATUS_TIMER_OVERFLOW: return "gcvSTATUS_TIMER_OVERFLOW"; case gcvSTATUS_VERSION_MISMATCH: return "gcvSTATUS_VERSION_MISMATCH"; case gcvSTATUS_LOCKED: return "gcvSTATUS_LOCKED"; /* Linker errors. */ case gcvSTATUS_GLOBAL_TYPE_MISMATCH: return "gcvSTATUS_GLOBAL_TYPE_MISMATCH"; case gcvSTATUS_TOO_MANY_ATTRIBUTES: return "gcvSTATUS_TOO_MANY_ATTRIBUTES"; case gcvSTATUS_TOO_MANY_UNIFORMS: return "gcvSTATUS_TOO_MANY_UNIFORMS"; case gcvSTATUS_TOO_MANY_VARYINGS: return "gcvSTATUS_TOO_MANY_VARYINGS"; case gcvSTATUS_UNDECLARED_VARYING: return "gcvSTATUS_UNDECLARED_VARYING"; case gcvSTATUS_VARYING_TYPE_MISMATCH: return "gcvSTATUS_VARYING_TYPE_MISMATCH"; case gcvSTATUS_MISSING_MAIN: return "gcvSTATUS_MISSING_MAIN"; case gcvSTATUS_NAME_MISMATCH: return "gcvSTATUS_NAME_MISMATCH"; case gcvSTATUS_INVALID_INDEX: return "gcvSTATUS_INVALID_INDEX"; default: return "nil"; } }