/*******************************************************************************
**
**  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;
}
Пример #2
0
/*******************************************************************************
**
**  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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
/*******************************************************************************
**
**  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;
}
Пример #7
0
/*******************************************************************************
**
**  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;
}
Пример #8
0
/*******************************************************************************
**
**  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;
}
Пример #9
0
/*******************************************************************************
**
**  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;
}
Пример #10
0
/*******************************************************************************
**
**  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;
}
Пример #11
0
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;
}
Пример #12
0
/*******************************************************************************
**
**  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;
}
Пример #13
0
/*******************************************************************************
**
**  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;
}
Пример #14
0
/*******************************************************************************
**
**  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;
}
Пример #15
0
/*******************************************************************************
**
**  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;
}
Пример #16
0
/*******************************************************************************
**
**  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;
}
Пример #17
0
/*******************************************************************************
**
**  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;
}
Пример #18
0
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;
}