/******************************************************************************* ** ** gcoBUFFER_Destroy ** ** Destroy an gcoBUFFER object. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to an gcoBUFFER object to delete. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoBUFFER_Destroy( IN gcoBUFFER Buffer ) { gceSTATUS status; gcmHEADER_ARG("Buffer=0x%x", Buffer); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); /* Commit buffer before destroying it. */ if (Buffer->size != 0) { /* Commit the command buffers. */ gcmONERROR(gcoHARDWARE_Commit()); /* Stall the hardware. */ gcmONERROR(gcoHARDWARE_Stall()); } /* Free all associated objects. */ gcmONERROR(gcoBUFFER_FreeObjects(Buffer)); OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_Destroy ** ** Destroy a gcoDUMP object created by gcDUMP_COnstruct. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_Destroy( IN gcoDUMP Dump ) { gcmHEADER_ARG("Dump=0x%x", Dump); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if (Dump->file != gcvNULL) { if (Dump->frameStart != 0) { gcoDUMP_FrameEnd(Dump); } /* Close any open file. */ gcmVERIFY_OK(gcoDUMP_Control(Dump, gcvNULL)); } if (gcPLS.hal->dump == Dump) { /* Remove current gcoDUMP object. */ gcPLS.hal->dump = gcvNULL; } /* Free the gcoDUMP structure. */ gcmVERIFY_OK(gcmOS_SAFE_FREE(gcvNULL, Dump)); /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; }
/******************************************************************************* ** ** gcoBUFFER_Write ** ** Copy a number of bytes into the buffer. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to an gcoBUFFER object. ** ** gctCONST_POINTER Data ** Pointer to a buffer that contains the data to be copied. ** ** IN gctSIZE_T Bytes ** Number of bytes to copy. ** ** IN gctBOOL Aligned ** gcvTRUE if the data needs to be aligned to 64-bit. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoBUFFER_Write( IN gcoBUFFER Buffer, IN gctCONST_POINTER Data, IN gctSIZE_T Bytes, IN gctBOOL Aligned ) { gceSTATUS status; gcoCMDBUF reserve; gcmHEADER_ARG("Buffer=0x%x Data=0x%x Bytes=%lu Aligned=%d", Buffer, Data, Bytes, Aligned); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); gcmDEBUG_VERIFY_ARGUMENT(Data != gcvNULL); gcmDEBUG_VERIFY_ARGUMENT(Bytes > 0); /* Reserve data in the buffer. */ gcmONERROR(gcoBUFFER_Reserve(Buffer, Bytes, Aligned, &reserve)); /* Write data into the buffer. */ gcmONERROR(gcoOS_MemCopy(reserve->lastReserve, Data, Bytes)); /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return status. */ gcmFOOTER(); return status; }
gceSTATUS gcoQUEUE_Free( IN gcoQUEUE Queue ) { gcmHEADER_ARG("Queue=0x%x", Queue); /* Verify the arguments. */ gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE); /* Free any records in the queue. */ #ifdef __QNXNTO__ Queue->head = gcvNULL; #else while (Queue->head != gcvNULL) { gcsQUEUE_PTR record; /* Unlink the first record from the queue. */ record = Queue->head; Queue->head = record->next; /* Put record on free list. */ record->next = Queue->freeList; Queue->freeList = record; } #endif /* Update count */ Queue->recordCount = 0; /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; }
gceSTATUS gcoQUEUE_Destroy( IN gcoQUEUE Queue ) { gceSTATUS status; gcmHEADER_ARG("Queue=0x%x", Queue); /* Verify the arguments. */ gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE); #ifndef __QNXNTO__ /* Free any records in the queue. */ while (Queue->head != gcvNULL) { gcsQUEUE_PTR record; /* Unlink the first record from the queue. */ record = Queue->head; Queue->head = record->next; gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, record)); } /* Free any records in the free list. */ while (Queue->freeList != gcvNULL) { gcsQUEUE_PTR record; /* Unlink the first record from the queue. */ record = Queue->freeList; Queue->freeList = record->next; gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, record)); } #else /* Free any records in the queue. */ if ( Queue->records ) { gcmVERIFY_OK(gcoOS_FreeNonPagedMemory(gcvNULL, BUFFER_SIZE, gcvNULL, Queue->records)); } #endif /* Free the queue. */ gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, Queue)); /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_AddSurface ** ** Allocate a surface. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctINT32 Width, Height ** Width and height of the surface. ** ** gceSURF_FORMAT PixelFormat ** Pixel format for the surface. ** ** gctUINT32 Address ** Physical address to be used as a handle for the surface. ** ** gctSIZE_T ByteCount ** Number of bytes inside the surface. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_AddSurface( IN gcoDUMP Dump, IN gctINT32 Width, IN gctINT32 Height, IN gceSURF_FORMAT PixelFormat, IN gctUINT32 Address, IN gctSIZE_T ByteCount ) { gceSTATUS status; gcsDUMP_SURFACE surface; gcmHEADER_ARG("Dump=0x%x Width=%d Height=%d PixelFormat=%d Address=%x " "ByteCount=%d", Dump, Width, Height, PixelFormat, Address, ByteCount); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); gcmVERIFY_ARGUMENT(ByteCount > 0); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Write the data record. */ surface.type = gcvTAG_SURFACE; surface.address = Address; surface.width = (gctINT16) Width; surface.height = (gctINT16) Height; surface.format = PixelFormat; surface.length = ByteCount; gcmERR_BREAK( gcoOS_Write(gcvNULL, Dump->file, sizeof(surface), &surface)); /* Update the frame length. */ Dump->frameLength += sizeof(surface); /* Update the file length. */ Dump->length += sizeof(surface); } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_DumpData ** ** Dump data the file. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gceDUMP_TAG Type ** Type of data. ** ** gctUINT32 Address ** Physical address to be used as a handle for the data. ** ** gctSIZE_T ByteCount ** Number of bytes to write. ** ** gctCONST_POINTER Data ** Pointer to the data to write. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_DumpData( IN gcoDUMP Dump, IN gceDUMP_TAG Type, IN gctUINT32 Address, IN gctSIZE_T ByteCount, IN gctCONST_POINTER Data ) { gceSTATUS status; gcsDUMP_DATA header; gcmHEADER_ARG("Dump=0x%x Type=%d Address=%x ByteCount=%d Data=0x%x", Dump, Type, Address, ByteCount, Data); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); gcmVERIFY_ARGUMENT(ByteCount > 0); gcmVERIFY_ARGUMENT(Data != gcvNULL); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Write the data record. */ header.type = Type; header.length = ByteCount; header.address = Address; gcmERR_BREAK( gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Write the data. */ gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, ByteCount, Data)); /* Update the frame length. */ Dump->frameLength += sizeof(header) + ByteCount; /* Update the file length. */ Dump->length += sizeof(header) + ByteCount; } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_FrameEnd ** ** Mark the end of a frame. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_FrameEnd( IN gcoDUMP Dump ) { gceSTATUS status; gcsDUMP_DATA header; gctUINT32 pos; gcmHEADER_ARG("Dump=0x%x", Dump); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos)); /* Seek to the beginning of the frame. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, Dump->frameStart)); /* Make sure we got the right byte count. */ gcmASSERT(pos - Dump->frameStart == Dump->frameLength + sizeof(header)); /* Update the frame header. */ header.type = gcvTAG_FRAME; header.length = Dump->frameLength; header.address = ++ Dump->frameCount; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Seek to the end of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos)); /* Mark the frame as ended. */ Dump->frameStart = 0; } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_Delete ** ** Mark an address as deleted. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctUINT32 Address ** Physical address to delete. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_Delete( IN gcoDUMP Dump, IN gctUINT32 Address ) { gceSTATUS status; gcsDUMP_DATA header; gcmHEADER_ARG("Dump=0x%x Address=%x", Dump, Address); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if (Dump->file == gcvNULL) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Write the delete record. */ header.type = gcvTAG_DELETE; header.length = 0; header.address = Address; gcmERR_BREAK( gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Update the frame length. */ Dump->frameLength += sizeof(header); /* Update the file length. */ Dump->length += sizeof(header); } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_IsEnabled ** ** Test whether dumping is enabeld or not. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** OUTPUT: ** ** gctBOOL * Enabled ** Pointer to a variable receiving the dump status. */ gceSTATUS gcoDUMP_IsEnabled( IN gcoDUMP Dump, OUT gctBOOL * Enabled ) { gcmHEADER_ARG("Dump=0x%x Enabled=0x%x", Dump, Enabled); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); gcmVERIFY_ARGUMENT(Enabled != gcvNULL); /* Return dump status. */ *Enabled = (Dump->file != gcvNULL); /* Success. */ gcmFOOTER_ARG("*Enabled=%d", *Enabled); return gcvSTATUS_OK; }
gceSTATUS gcoQUEUE_Commit( IN gcoQUEUE Queue ) { gceSTATUS status = gcvSTATUS_OK; gcsHAL_INTERFACE iface; gcmHEADER_ARG("Queue=0x%x", Queue); /* Verify the arguments. */ gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE); if (Queue->head != gcvNULL) { /* Initialize event commit command. */ iface.command = gcvHAL_EVENT_COMMIT; iface.u.Event.queue = Queue->head; /* Send command to kernel. */ gcmONERROR( gcoOS_DeviceControl(gcvNULL, IOCTL_GCHAL_INTERFACE, &iface, gcmSIZEOF(iface), &iface, gcmSIZEOF(iface))); /* Test for error. */ gcmONERROR(iface.status); /* Free any records in the queue. */ gcmONERROR(gcoQUEUE_Free(Queue)); } /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_FrameBegin ** ** Mark the beginning of a frame. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_FrameBegin( IN gcoDUMP Dump ) { gceSTATUS status; gcsDUMP_DATA header; gcmHEADER_ARG("Dump=0x%x", Dump); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); if ( (Dump->file == gcvNULL) || (Dump->frameStart != 0) ) { /* There is no open dump file. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } do { /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &Dump->frameStart)); /* Write the frame header. */ header.type = gcvTAG_FRAME; header.length = Dump->frameLength = 0; header.address = 0; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Update the file length. */ Dump->length += sizeof(header); } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoBUFFER_Commit ** ** Commit the command buffer to the hardware. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to a gcoBUFFER object. ** ** gcePIPE_SELECT CurrentPipe ** Current graphics pipe. ** ** gcsSTATE_DELTA_PTR StateDelta ** Pointer to the state delta. ** ** gcoQUEUE Queue ** Pointer to a gcoQUEUE object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoBUFFER_Commit( IN gcoBUFFER Buffer, IN gcePIPE_SELECT CurrentPipe, IN gcsSTATE_DELTA_PTR StateDelta, IN gcoQUEUE Queue ) { gcsHAL_INTERFACE iface; gceSTATUS status; gcoCMDBUF current; gcmHEADER_ARG("Buffer=0x%x Queue=0x%x", Buffer, Queue); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE); /* Grab current command buffer. */ current = Buffer->currentCommandBuffer; if (current == gcvNULL) { /* No command buffer, done. */ gcmFOOTER_NO(); return gcvSTATUS_OK; } if (current->offset - current->startOffset <= Buffer->info.reservedHead) { /* Commit the event queue. */ status = gcoQUEUE_Commit(Queue); gcmFOOTER(); return status; } /* Make sure the tail got aligned properly. */ current->offset = gcmALIGN(current->offset, Buffer->info.alignment); if (gcPLS.hal->dump != gcvNULL) { /* Dump the command buffer. */ gcmVERIFY_OK( gcoDUMP_DumpData(gcPLS.hal->dump, gcvTAG_COMMAND, 0, current->offset - current->startOffset - Buffer->info.reservedHead, (gctUINT8_PTR) current->logical + current->startOffset + Buffer->info.reservedHead)); } /* The current pipe becomes the exit pipe for the current command buffer. */ current->exitPipe = CurrentPipe; /* Send command and context buffer to hardware. */ iface.command = gcvHAL_COMMIT; iface.u.Commit.context = #ifndef VIVANTE_NO_3D (current->using2D && !current->using3D) ? gcvNULL : Buffer->context; #else gcvNULL; #endif iface.u.Commit.commandBuffer = current; iface.u.Commit.delta = StateDelta; iface.u.Commit.queue = Queue->head; /* Call kernel service. */ gcmONERROR( gcoOS_DeviceControl(gcvNULL, IOCTL_GCHAL_INTERFACE, &iface, gcmSIZEOF(iface), &iface, gcmSIZEOF(iface))); gcmONERROR(iface.status); /* Free the event queue. */ gcmONERROR(gcoQUEUE_Free(Queue)); /* Advance the offset for next commit. */ current->startOffset = current->offset + Buffer->info.reservedTail; if (current->bytes - current->startOffset > Buffer->totalReserved) { /* Adjust buffer offset and size. */ current->offset = current->startOffset + Buffer->info.reservedHead; current->free = current->bytes - current->offset - Buffer->info.alignment - Buffer->info.reservedTail; } else { /* Buffer is full. */ current->startOffset = current->bytes; current->offset = current->bytes; current->free = 0; } /* The exit pipe becomes the entry pipe for the next command buffer. */ current->entryPipe = current->exitPipe; #if gcdSECURE_USER /* Reset the state array tail. */ current->hintArrayTail = current->hintArray; #endif /* Reset usage flags. */ current->using2D = gcvFALSE; current->using3D = gcvFALSE; current->usingFilterBlit = gcvFALSE; current->usingPalette = gcvFALSE; /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoBUFFER_Reserve ** ** Reserve a number of bytes in the buffer. ** ** INPUT: ** ** gcoBUFFER Buffer ** Pointer to an gcoBUFFER object. ** ** gctSIZE_T Bytes ** Number of bytes to reserve. ** ** gctBOOL Aligned ** gcvTRUE if the data needs to be aligned to 64-bit. ** ** OUTPUT: ** ** gctUINT32_PTR ** AddressHints ** Pointer to a variable that receives the current position in the ** state hint array. gcvNULL is allowed. ** ** gctPOINTER * Memory ** Pointer to a variable that will hold the address of location in the ** buffer that has been reserved. */ gceSTATUS gcoBUFFER_Reserve( IN gcoBUFFER Buffer, IN gctSIZE_T Bytes, IN gctBOOL Aligned, OUT gcoCMDBUF * Reserve ) { gceSTATUS status = gcvSTATUS_OK; gcoCMDBUF current; gctSIZE_T alignBytes, bytes; gctUINT offset; gcmHEADER_ARG("Buffer=0x%x Bytes=%lu Aligned=%d Reserve=0x%x", Buffer, Bytes, Aligned, Reserve); /* Verify the arguments. */ gcmVERIFY_OBJECT(Buffer, gcvOBJ_BUFFER); gcmDEBUG_VERIFY_ARGUMENT(Reserve != gcvNULL); /* Get the current command buffer. */ current = Buffer->currentCommandBuffer; /* Compute the number of aligned bytes. */ alignBytes = Aligned ? ( gcmALIGN(current->offset, Buffer->info.alignment) - current->offset ) : 0; /* Compute the number of required bytes. */ bytes = Bytes + alignBytes; if (bytes > current->free) { gcsHAL_INTERFACE iface; if (bytes > Buffer->maxSize - Buffer->totalReserved) { /* This just won't fit! */ gcmFATAL("FATAL: Command of %lu bytes is too big!", Bytes); gcmONERROR(gcvSTATUS_OUT_OF_MEMORY); } /* Sent event to signal when command buffer completes. */ iface.command = gcvHAL_SIGNAL; iface.u.Signal.signal = Buffer->signal [Buffer->currentCommandBufferIndex]; iface.u.Signal.auxSignal = gcvNULL; iface.u.Signal.process = gcoOS_GetCurrentProcessID(); iface.u.Signal.fromWhere = gcvKERNEL_COMMAND; /* Send event. */ gcmONERROR( gcoHARDWARE_CallEvent(&iface)); /* Commit current command buffer. */ gcmONERROR( gcoHARDWARE_Commit()); /* Grab a new command buffer. */ gcmONERROR( gcoBUFFER_GetCMDBUF(Buffer)); /* Get the pointer. */ current = Buffer->currentCommandBuffer; /* Calculate total bytes again. */ alignBytes = 0; bytes = Bytes; } gcmASSERT(current != gcvNULL); gcmASSERT(bytes <= current->free); /* Determine the data offset. */ offset = current->offset + alignBytes; /* Update the last reserved location. */ current->lastReserve = (gctUINT8_PTR) current->logical + offset; current->lastOffset = offset; /* Adjust command buffer size. */ current->offset += bytes; current->free -= bytes; /* Set the result. */ * Reserve = current; /* Success. */ gcmFOOTER(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoDUMP_Control ** ** Control dumping. ** ** INPUT: ** ** gcoDUMP Dump ** Pointer to a gcoDUMP object. ** ** gctSTRING FileName ** If 'FileName' is not gcvNULL, it points to the filename to be used for ** capturing all data. If 'FileName' is gcvNULL, turn off any current ** capturing. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gcoDUMP_Control( IN gcoDUMP Dump, IN gctSTRING FileName ) { gceSTATUS status = gcvSTATUS_OK; gcsDUMP_FILE header; gctUINT32 pos; gcmHEADER_ARG("Dump=0x%x FileName=0x%x", Dump, FileName); /* Verify the arguments. */ gcmVERIFY_OBJECT(Dump, gcvOBJ_DUMP); do { if (FileName != gcvNULL) { /* Need to create a new dump file. */ if (Dump->file == gcvNULL) { /* Create the dump file. */ gcmERR_BREAK(gcoOS_Open(gcvNULL, FileName, gcvFILE_CREATE, &Dump->file)); /* Write the file header. */ header.signature = gcvDUMP_FILE_SIGNATURE; header.length = Dump->length = 0; header.frames = Dump->frameCount = 0; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Frame is not yet started. */ Dump->frameStart = 0; } } else { /* Need to close any current dump file. */ if (Dump->file != gcvNULL) { /* Close any open frame. */ if (Dump->frameStart != 0) { gcoDUMP_FrameEnd(Dump); gcoDUMP_FrameBegin(Dump); } /* Get the current position. */ gcmERR_BREAK(gcoOS_GetPos(gcvNULL, Dump->file, &pos)); /* Seek to the beginnnig of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, 0)); /* Make sure we have the correct size. */ gcmASSERT(pos == Dump->length + sizeof(header)); /* Update the file header. */ header.signature = gcvDUMP_FILE_SIGNATURE; header.length = Dump->length; header.frames = Dump->frameCount; gcmERR_BREAK(gcoOS_Write(gcvNULL, Dump->file, sizeof(header), &header)); /* Seek to the end of the file. */ gcmERR_BREAK(gcoOS_SetPos(gcvNULL, Dump->file, pos)); /* Close the file. */ gcmERR_BREAK(gcoOS_Close(gcvNULL, Dump->file)); /* Mark the file as closed. */ Dump->file = gcvNULL; } } } while (gcvFALSE); /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoBUFFER_Construct ** ** Construct a new gcoBUFFER object. ** ** INPUT: ** ** gcoHAL Hal ** Pointer to a gcoHAL object. ** ** gcoHARDWARE Hardware ** Pointer to a gcoHARDWARE object. ** ** gckCONTEXT Context ** Pointer to a gckCONTEXT object. ** ** gctSIZE_T MaxSize ** Maximum size of buffer. ** ** OUTPUT: ** ** gcoBUFFER * Buffer ** Pointer to a variable that will hold the the gcoBUFFER object ** pointer. */ gceSTATUS gcoBUFFER_Construct( IN gcoHAL Hal, IN gcoHARDWARE Hardware, IN gckCONTEXT Context, IN gctSIZE_T MaxSize, OUT gcoBUFFER * Buffer ) { gceSTATUS status; gcoBUFFER buffer = gcvNULL; gctUINT i = 0; gctPOINTER pointer = gcvNULL; gcmHEADER_ARG("Hal=0x%x Hardware=0x%x Context=0x%x MaxSize=%lu", Hal, Hardware, Context, MaxSize); /* Verify the arguments. */ gcmVERIFY_OBJECT(Hal, gcvOBJ_HAL); gcmVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE); gcmDEBUG_VERIFY_ARGUMENT(Buffer != gcvNULL); /*************************************************************************** ** Allocate and reset the gcoBUFFER object. */ gcmONERROR(gcoOS_Allocate( gcvNULL, gcmSIZEOF(struct _gcoBUFFER), &pointer )); buffer = pointer; /* Initialize the gcoBUFFER object. */ buffer->object.type = gcvOBJ_BUFFER; buffer->hal = Hal; buffer->context = Context; /* Maximum size of buffer. */ buffer->size = 0; buffer->maxSize = MaxSize; /* Zero the command buffers. */ for (i = 0; i < gcmCOUNTOF(buffer->commandBuffers); ++i) { buffer->commandBuffers[i] = gcvNULL; buffer->signal[i] = gcvNULL; } /*************************************************************************** ** Query alignment. */ gcmONERROR(gcoHARDWARE_QueryCommandBuffer( &buffer->info.alignment, &buffer->info.reservedHead, &buffer->info.reservedTail )); buffer->totalReserved = buffer->info.reservedHead + buffer->info.reservedTail + buffer->info.alignment; /*************************************************************************** ** Initialize the command buffers. */ for (i = 0; i < gcdCMD_BUFFERS; ++i) { /* Construct a command buffer. */ gcmONERROR(gcoCMDBUF_Construct( gcvNULL, gcvNULL, buffer->maxSize, &buffer->info, &buffer->commandBuffers[i] )); /* Create the signal. */ gcmONERROR(gcoOS_CreateSignal( gcvNULL, gcvFALSE, &buffer->signal[i] )); gcmTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_SIGNAL, "%s(%d): buffer %d signal created 0x%08X", __FUNCTION__, __LINE__, i, buffer->signal[i] ); /* Mark the buffer as available. */ gcmONERROR(gcoOS_Signal( gcvNULL, buffer->signal[i], gcvTRUE\ )); } /* Number of buffers initialized. */ buffer->count = gcdCMD_BUFFERS; /* Grab the first command buffer. */ buffer->currentCommandBuffer = gcvNULL; gcmONERROR(gcoBUFFER_GetCMDBUF(buffer)); /* Return pointer to the gcoBUFFER object. */ *Buffer = buffer; /* Success. */ gcmFOOTER_ARG("*Buffer=0x%x", *Buffer); return gcvSTATUS_OK; OnError: if (buffer != gcvNULL) { gcmVERIFY_OK(gcoBUFFER_FreeObjects(buffer)); } /* Return the status. */ gcmFOOTER(); return status; }
/******************************************************************************* ** ** gcoCMDBUF_Destroy ** ** Destroy a gcoCMDBUF object. ** ** INPUT: ** ** gcoCMDBUF CommandBuffer ** Pointer to an gcoCMDBUF object. ** ** OUTPUT: ** ** None. */ gceSTATUS gcoCMDBUF_Destroy( IN gcoCMDBUF CommandBuffer ) { gceSTATUS status; gcsHAL_INTERFACE iface; gcmHEADER_ARG("CommandBuffer=0x%x", CommandBuffer); /* Verify the object. */ gcmVERIFY_OBJECT(CommandBuffer, gcvOBJ_COMMANDBUFFER); if (CommandBuffer->logical != gcvNULL) { /* Use events to free the buffer. */ iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY; iface.u.FreeContiguousMemory.bytes = CommandBuffer->bytes; iface.u.FreeContiguousMemory.physical = CommandBuffer->physical; iface.u.FreeContiguousMemory.logical = CommandBuffer->logical; /* Send event. */ gcmONERROR(gcoHARDWARE_CallEvent(&iface)); /* Reset the buffer pointer. */ CommandBuffer->logical = gcvNULL; } #if gcdSECURE_USER if (CommandBuffer->hintArray != gcvNULL) { #ifdef __QNXNTO__ gcmONERROR(gcoOS_FreeNonPagedMemory( gcvNULL, CommandBuffer->hintArraySize, gcvNULL, CommandBuffer->hintArray )); #else gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, CommandBuffer->hintArray)); #endif CommandBuffer->hintArray = CommandBuffer->hintArrayTail = gcvNULL; } #endif /* Free the gcoCMDBUF object. */ #ifdef __QNXNTO__ gcmONERROR(gcoOS_FreeNonPagedMemory( gcvNULL, gcmSIZEOF(struct _gcoCMDBUF), gcvNULL, CommandBuffer )); #else gcmONERROR(gcmOS_SAFE_FREE(gcvNULL, CommandBuffer)); #endif /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmFOOTER(); return status; }
gceSTATUS gcoQUEUE_AppendEvent( IN gcoQUEUE Queue, IN gcsHAL_INTERFACE * Interface ) { gceSTATUS status; gcsQUEUE_PTR record = gcvNULL; #ifdef __QNXNTO__ gctSIZE_T allocationSize; gctPHYS_ADDR physAddr; #else gctPOINTER pointer = gcvNULL; #endif gcmHEADER_ARG("Queue=0x%x Interface=0x%x", Queue, Interface); /* Verify the arguments. */ gcmVERIFY_OBJECT(Queue, gcvOBJ_QUEUE); gcmVERIFY_ARGUMENT(Interface != gcvNULL); /* Allocate record. */ #ifdef __QNXNTO__ allocationSize = gcmSIZEOF(gcsQUEUE); if (Queue->freeBytes < allocationSize) { gctSIZE_T recordsSize = BUFFER_SIZE; gcsQUEUE_PTR prevRecords = Queue->records; gcsHAL_INTERFACE iface; /* Allocate new set of records. */ gcmONERROR( gcoOS_AllocateNonPagedMemory(gcvNULL, gcvTRUE, &recordsSize, &physAddr, (gctPOINTER *) &Queue->records)); Queue->freeBytes = recordsSize; Queue->offset = 0; if ( Queue->freeBytes < allocationSize ) { gcmFOOTER_ARG("status=%d", gcvSTATUS_DATA_TOO_LARGE); return gcvSTATUS_DATA_TOO_LARGE; } /* Schedule to free Queue->records, * hence not unmapping currently scheduled events immediately. */ iface.command = gcvHAL_FREE_NON_PAGED_MEMORY; iface.u.FreeNonPagedMemory.bytes = BUFFER_SIZE; iface.u.FreeNonPagedMemory.physical = 0; iface.u.FreeNonPagedMemory.logical = prevRecords; gcmONERROR( gcoQUEUE_AppendEvent(Queue, &iface)); } record = (gcsQUEUE_PTR)((gctUINT32)Queue->records + Queue->offset); Queue->offset += allocationSize; Queue->freeBytes -= allocationSize; #else /* Check if we have records on the free list. */ if (Queue->freeList != gcvNULL) { /* Allocate from hte free list. */ record = Queue->freeList; Queue->freeList = record->next; } else { gcmONERROR(gcoOS_Allocate(gcvNULL, gcmSIZEOF(gcsQUEUE), &pointer)); record = pointer; } #endif /* Initialize record. */ record->next = gcvNULL; gcoOS_MemCopy(&record->iface, Interface, gcmSIZEOF(record->iface)); if (Queue->head == gcvNULL) { /* Initialize queue. */ Queue->head = record; } else { /* Append record to end of queue. */ Queue->tail->next = record; } /* Mark end of queue. */ Queue->tail = record; /* update count */ Queue->recordCount++; /* Success. */ gcmFOOTER_NO(); return gcvSTATUS_OK; OnError: #ifndef __QNXNTO__ if (pointer != gcvNULL) { /* Put record on free list. */ record->next = Queue->freeList; Queue->freeList = record; } #endif /* Return the status. */ gcmFOOTER(); return status; }