コード例 #1
0
Bool ReUseSurface(GALINFOPTR galInfo, PixmapPtr pPixmap, Viv2DPixmapPtr toBeUpdatedpPix)
{

	GenericSurfacePtr surf = gcvNULL;
	gctUINT alignedWidth, alignedHeight;
	gctUINT bytesPerPixel;
	alignedWidth = gcmALIGN(pPixmap->drawable.width, WIDTH_ALIGNMENT);
	alignedHeight = gcmALIGN(pPixmap->drawable.height, HEIGHT_ALIGNMENT);
	bytesPerPixel = BITSTOBYTES(pPixmap->drawable.bitsPerPixel);

	/* The same as CreatSurface */
	if (bytesPerPixel < 2) {
		bytesPerPixel = 2;
	}

	surf = (GenericSurfacePtr)toBeUpdatedpPix->mVidMemInfo;
	if ( surf && surf->mVideoNode.mSizeInBytes >= (alignedWidth * alignedHeight * bytesPerPixel))
	{
		surf->mTiling = gcvLINEAR;
		surf->mAlignedWidth = alignedWidth;
		surf->mAlignedHeight = alignedHeight;
		surf->mStride = alignedWidth * bytesPerPixel;
		surf->mRotation = gcvSURF_0_DEGREE;
		surf->mLogicalAddr = surf->mVideoNode.mLogicalAddr;
		surf->mIsWrapped = gcvFALSE;

		if ( surf->mData )
			pixman_image_unref( (pixman_image_t *)surf->mData );

		surf->mData = gcvNULL;
    TRACE_EXIT(TRUE);
}

	TRACE_EXIT(FALSE);
}
コード例 #2
0
/*Creating and Destroying Functions*/
Bool CreateSurface(GALINFOPTR galInfo, PixmapPtr pPixmap, Viv2DPixmapPtr pPix) {
    GenericSurfacePtr surf = gcvNULL;
    VIVGPUPtr gpuctx = (VIVGPUPtr) galInfo->mGpu;
    gctUINT alignedWidth, alignedHeight;
    gctUINT bytesPerPixel;
    alignedWidth = gcmALIGN(pPixmap->drawable.width, WIDTH_ALIGNMENT);
    alignedHeight = gcmALIGN(pPixmap->drawable.height, HEIGHT_ALIGNMENT);
    bytesPerPixel = BITSTOBYTES(pPixmap->drawable.bitsPerPixel);

    /*QUICK FIX*/
    if (bytesPerPixel < 2) {
        bytesPerPixel = 2;
    }

    if (!VIV2DGPUSurfaceAlloc(gpuctx, alignedWidth, alignedHeight, bytesPerPixel, &surf)) {
        TRACE_ERROR("Surface Creation Error\n");
        TRACE_EXIT(FALSE);
    }

    pPix->mVidMemInfo = surf;
    TRACE_EXIT(TRUE);
}
コード例 #3
0
Bool WrapSurface(PixmapPtr pPixmap, void * logical, unsigned int physical, Viv2DPixmapPtr pPix) {
    gceSTATUS status = gcvSTATUS_OK;
    gctUINT alignedWidth, alignedHeight;
    gctUINT bytesPerPixel;
    GenericSurfacePtr surf = gcvNULL;
    gctPOINTER mHandle = gcvNULL;
    status = gcoOS_Allocate(gcvNULL, sizeof (GenericSurface), &mHandle);
    if (status != gcvSTATUS_OK) {
        TRACE_ERROR("Unable to allocate generic surface\n");
        TRACE_EXIT(FALSE);
    }
    memset(mHandle, 0, sizeof (GenericSurface));
    surf = (GenericSurfacePtr) mHandle;

    alignedWidth = gcmALIGN(pPixmap->drawable.width, WIDTH_ALIGNMENT);
    alignedHeight = gcmALIGN(pPixmap->drawable.height, HEIGHT_ALIGNMENT);
    bytesPerPixel = BITSTOBYTES(pPixmap->drawable.bitsPerPixel);

    surf->mVideoNode.mSizeInBytes = alignedWidth * bytesPerPixel * alignedHeight;
    surf->mVideoNode.mPool = gcvPOOL_USER;

    surf->mVideoNode.mPhysicalAddr = physical;
    surf->mVideoNode.mLogicalAddr = (gctPOINTER) logical;

    surf->mBytesPerPixel = bytesPerPixel;
    surf->mTiling = gcvLINEAR;
    surf->mAlignedWidth = alignedWidth;
    surf->mAlignedHeight = alignedHeight;
    surf->mStride = alignedWidth * bytesPerPixel;
    surf->mRotation = gcvSURF_0_DEGREE;
    surf->mLogicalAddr = surf->mVideoNode.mLogicalAddr;
    surf->mIsWrapped = gcvTRUE;

    pPix->mVidMemInfo = surf;
    TRACE_EXIT(TRUE);
}
コード例 #4
0
gceSTATUS
gcfDumpData(
    IN gcoOS Os,
    IN gctSTRING Tag,
    IN gctPOINTER Logical,
    IN gctSIZE_T Bytes
    )
{
    gctUINT32_PTR ptr = (gctUINT32_PTR) Logical;
    gctSIZE_T bytes   = gcmALIGN(Bytes, 4);

    if (!setDumpFlag)
        return gcvSTATUS_OK;


    while (bytes >= 16)
    {
        gcmDUMP(Os,
                "  0x%08X 0x%08X 0x%08X 0x%08X",
                ptr[0], ptr[1], ptr[2], ptr[3]);

        ptr   += 4;
        bytes -= 16;
    }

    switch (bytes)
    {
    case 12:
        gcmDUMP(Os, "  0x%08X 0x%08X 0x%08X", ptr[0], ptr[1], ptr[2]);
        break;

    case 8:
        gcmDUMP(Os, "  0x%08X 0x%08X", ptr[0], ptr[1]);
        break;

    case 4:
        gcmDUMP(Os, "  0x%08X", ptr[0]);
        break;
    }

    gcmDUMP(Os, "] -- %s", Tag);

    return gcvSTATUS_OK;
}
コード例 #5
0
/*******************************************************************************
**
**  gckHEAP_Allocate
**
**  Allocate data from the heap.
**
**  INPUT:
**
**      gckHEAP Heap
**          Pointer to a gckHEAP object.
**
**      IN gctSIZE_T Bytes
**          Number of byte to allocate.
**
**  OUTPUT:
**
**      gctPOINTER * Memory
**          Pointer to a variable that will hold the address of the allocated
**          memory.
*/
gceSTATUS
gckHEAP_Allocate(
    IN gckHEAP Heap,
    IN gctSIZE_T Bytes,
    OUT gctPOINTER * Memory
    )
{
    gctBOOL acquired = gcvFALSE;
    gcskHEAP_PTR heap;
    gceSTATUS status;
    gctSIZE_T bytes;
    gcskNODE_PTR node, used, prevFree = gcvNULL;
    gctPOINTER memory = gcvNULL;

    gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
    gcmkVERIFY_ARGUMENT(Bytes > 0);
    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);

    /* Determine number of bytes required for a node. */
    bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);

    /* Acquire the mutex. */
    gcmkONERROR(
        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));

    acquired = gcvTRUE;

    /* Check if this allocation is bigger than the default allocation size. */
    if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
    {
        /* Adjust allocation size. */
        Heap->allocationSize = bytes * 2;
    }

    else if (Heap->heap != gcvNULL)
    {
        gctINT i;

        /* 2 retries, since we might need to compact. */
        for (i = 0; i < 2; ++i)
        {
            /* Walk all the heaps. */
            for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
            {
                /* Check if this heap has enough bytes to hold the request. */
                if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
                {
                    prevFree = gcvNULL;

                    /* Walk the chain of free nodes. */
                    for (node = heap->freeList;
                         node != gcvNULL;
                         node = node->next
                    )
                    {
                        gcmkASSERT(node->next != gcdIN_USE);

                        /* Check if this free node has enough bytes. */
                        if (node->bytes >= bytes)
                        {
                            /* Use the node. */
                            goto UseNode;
                        }

                        /* Save current free node for linked list management. */
                        prevFree = node;
                    }
                }
            }

            if (i == 0)
            {
                /* Compact the heap. */
                gcmkVERIFY_OK(_CompactKernelHeap(Heap));

#if gcmIS_DEBUG(gcdDEBUG_CODE)
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "===== KERNEL HEAP =====");
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Number of allocations           : %12u",
                               Heap->allocCount);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Number of bytes allocated       : %12llu",
                               Heap->allocBytes);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Maximum allocation size         : %12llu",
                               Heap->allocBytesMax);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Total number of bytes allocated : %12llu",
                               Heap->allocBytesTotal);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Number of heaps                 : %12u",
                               Heap->heapCount);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Heap memory in bytes            : %12llu",
                               Heap->heapMemory);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Maximum number of heaps         : %12u",
                               Heap->heapCountMax);
                gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
                               "Maximum heap memory in bytes    : %12llu",
                               Heap->heapMemoryMax);
#endif
            }
        }
    }

    /* Release the mutex. */
    gcmkONERROR(
        gckOS_ReleaseMutex(Heap->os, Heap->mutex));

    acquired = gcvFALSE;

    /* Allocate a new heap. */
    gcmkONERROR(
        gckOS_AllocateMemory(Heap->os,
                             Heap->allocationSize,
                             &memory));

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
                   "Allocated heap 0x%x (%lu bytes)",
                   memory, Heap->allocationSize);

    /* Acquire the mutex. */
    gcmkONERROR(
        gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));

    acquired = gcvTRUE;

    /* Use the allocated memory as the heap. */
    heap = (gcskHEAP_PTR) memory;

    /* Insert this heap to the head of the chain. */
    heap->next = Heap->heap;
    heap->prev = gcvNULL;
    heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);

    if (heap->next != gcvNULL)
    {
        heap->next->prev = heap;
    }
    Heap->heap = heap;

    /* Mark the end of the heap. */
    node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
                          + Heap->allocationSize
                          - gcmSIZEOF(gcskNODE)
                          );
    node->bytes = 0;
    node->next  = gcvNULL;

    /* Create a free list. */
    node           = (gcskNODE_PTR) (heap + 1);
    heap->freeList = node;

    /* Initialize the free list. */
    node->bytes = heap->size - gcmSIZEOF(gcskNODE);
    node->next  = gcvNULL;

    /* No previous free. */
    prevFree = gcvNULL;

#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
    /* Update profiling. */
    Heap->heapCount  += 1;
    Heap->heapMemory += Heap->allocationSize;

    if (Heap->heapCount > Heap->heapCountMax)
    {
        Heap->heapCountMax = Heap->heapCount;
    }
    if (Heap->heapMemory > Heap->heapMemoryMax)
    {
        Heap->heapMemoryMax = Heap->heapMemory;
    }
#endif

UseNode:
    /* Verify some stuff. */
    gcmkASSERT(heap != gcvNULL);
    gcmkASSERT(node != gcvNULL);
    gcmkASSERT(node->bytes >= bytes);

    if (heap->prev != gcvNULL)
    {
        /* Unlink the heap from the linked list. */
        heap->prev->next = heap->next;
        if (heap->next != gcvNULL)
        {
            heap->next->prev = heap->prev;
        }

        /* Move the heap to the front of the list. */
        heap->next       = Heap->heap;
        heap->prev       = gcvNULL;
        Heap->heap       = heap;
        heap->next->prev = heap;
    }

    /* Check if there is enough free space left after usage for another free
    ** node. */
    if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
    {
        /* Allocated used space from the back of the free list. */
        used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);

        /* Adjust the number of free bytes. */
        node->bytes -= bytes;
        gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
    }
    else
    {
        /* Remove this free list from the chain. */
        if (prevFree == gcvNULL)
        {
            heap->freeList = node->next;
        }
        else
        {
            prevFree->next = node->next;
        }

        /* Consume the entire free node. */
        used  = (gcskNODE_PTR) node;
        bytes = node->bytes;
    }

    /* Mark node as used. */
    used->bytes     = bytes;
    used->next      = gcdIN_USE;
#if gcmIS_DEBUG(gcdDEBUG_CODE)
    used->timeStamp = ++Heap->timeStamp;
#endif

#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
    /* Update profile counters. */
    Heap->allocCount      += 1;
    Heap->allocBytes      += bytes;
    Heap->allocBytesMax    = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
    Heap->allocBytesTotal += bytes;
#endif

    /* Release the mutex. */
    gcmkVERIFY_OK(
        gckOS_ReleaseMutex(Heap->os, Heap->mutex));

    /* Return pointer to memory. */
    *Memory = used + 1;

    /* Success. */
    gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
    return gcvSTATUS_OK;

OnError:
    if (acquired)
    {
        /* Release the mutex. */
        gcmkVERIFY_OK(
            gckOS_ReleaseMutex(Heap->os, Heap->mutex));
    }

    if (memory != gcvNULL)
    {
        /* Free the heap memory. */
        gckOS_FreeMemory(Heap->os, memory);
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #6
0
static gctSIZE_T
_MeasureState(
    IN gcoVGHARDWARE Hardware,
    IN gcsVGCONTEXT_INIT_PTR InitInfo,
    IN gctSIZE_T BufferIndex,
    IN gctUINT32 StateIndex,
    IN gctUINT32 ResetValue,
    IN gctSIZE_T ValueCount
    )
{
    gctSIZE_T result;
    gctSIZE_T mapLast;

    /* End of buffer alignement? */
    if (ValueCount == 0)
    {
        /* Save information for this LoadState. */
        InitInfo->bufferIndex = gcmALIGN(BufferIndex, 2);

        /* Return end of buffer. */
        result = 0;
    }
    else
    {
        /* See if we can append this state to the previous one. */
        if (StateIndex == InitInfo->stateIndex)
        {
            /* Update the state index. */
            InitInfo->stateIndex += ValueCount;

            /* Return number of slots required. */
            result = ValueCount;
        }
        else
        {
            /* Determine if we need alignment. */
            gctSIZE_T align = BufferIndex & 1;

            /* Save information for this LoadState. */
            InitInfo->bufferIndex = BufferIndex + align;
            InitInfo->stateIndex  = StateIndex  + ValueCount;

            /* Return number of slots required. */
            result = align + 1 + ValueCount;
        }

        /* Determine the new map size. */
        mapLast = StateIndex + ValueCount - 1;

        /* Update the map dimensions as necessary. */
#ifndef __QNXNTO__
        if (mapLast > Hardware->context.mapLast)
        {
            Hardware->context.mapLast = mapLast;
        }

        if (StateIndex < Hardware->context.mapFirst)
        {
            Hardware->context.mapFirst = StateIndex;
        }
#else
        if (mapLast > Hardware->pContext->mapLast)
        {
            Hardware->pContext->mapLast = mapLast;
        }

        if (StateIndex < Hardware->pContext->mapFirst)
        {
            Hardware->pContext->mapFirst = StateIndex;
        }
#endif
    }

    /* Return size for load state. */
    return result;
}
コード例 #7
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;
}
コード例 #8
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;
}
コード例 #9
0
/*******************************************************************************
**
**  gckVIDMEM_Construct
**
**  Construct a new gckVIDMEM object.
**
**  INPUT:
**
**      gckOS Os
**          Pointer to an gckOS object.
**
**      gctUINT32 BaseAddress
**          Base address for the video memory heap.
**
**      gctSIZE_T Bytes
**          Number of bytes in the video memory heap.
**
**      gctSIZE_T Threshold
**          Minimum number of bytes beyond am allocation before the node is
**          split.  Can be used as a minimum alignment requirement.
**
**      gctSIZE_T BankSize
**          Number of bytes per physical memory bank.  Used by bank
**          optimization.
**
**  OUTPUT:
**
**      gckVIDMEM * Memory
**          Pointer to a variable that will hold the pointer to the gckVIDMEM
**          object.
*/
gceSTATUS
gckVIDMEM_Construct(
    IN gckOS Os,
    IN gctUINT32 BaseAddress,
    IN gctSIZE_T Bytes,
    IN gctSIZE_T Threshold,
    IN gctSIZE_T BankSize,
    OUT gckVIDMEM * Memory
    )
{
    gckVIDMEM memory = gcvNULL;
    gceSTATUS status;
    gcuVIDMEM_NODE_PTR node;
    gctINT i, banks = 0;

    gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
                   "BankSize=%lu",
                   Os, BaseAddress, Bytes, Threshold, BankSize);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
    gcmkVERIFY_ARGUMENT(Bytes > 0);
    gcmkVERIFY_ARGUMENT(Memory != gcvNULL);

    /* Allocate the gckVIDMEM object. */
    gcmkONERROR(
        gckOS_Allocate(Os,
                       gcmSIZEOF(struct _gckVIDMEM),
                       (gctPOINTER *) &memory));

    /* Initialize the gckVIDMEM object. */
    memory->object.type = gcvOBJ_VIDMEM;
    memory->os          = Os;

    /* Set video memory heap information. */
    memory->baseAddress = BaseAddress;
    memory->bytes       = Bytes;
    memory->freeBytes   = Bytes;
    memory->threshold   = Threshold;
    memory->mutex       = gcvNULL;

    BaseAddress = 0;

    /* Walk all possible banks. */
    for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
    {
        gctSIZE_T bytes;

        if (BankSize == 0)
        {
            /* Use all bytes for the first bank. */
            bytes = Bytes;
        }
        else
        {
            /* Compute number of bytes for this bank. */
            bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;

            if (bytes > Bytes)
            {
                /* Make sure we don't exceed the total number of bytes. */
                bytes = Bytes;
            }
        }

        if (bytes == 0)
        {
            /* Mark heap is not used. */
            memory->sentinel[i].VidMem.next     =
            memory->sentinel[i].VidMem.prev     =
            memory->sentinel[i].VidMem.nextFree =
            memory->sentinel[i].VidMem.prevFree = gcvNULL;
            continue;
        }

        /* Allocate one gcuVIDMEM_NODE union. */
        gcmkONERROR(
            gckOS_Allocate(Os,
                           gcmSIZEOF(gcuVIDMEM_NODE),
                           (gctPOINTER *) &node));

        /* Initialize gcuVIDMEM_NODE union. */
        node->VidMem.memory    = memory;

        node->VidMem.next      =
        node->VidMem.prev      =
        node->VidMem.nextFree  =
        node->VidMem.prevFree  = &memory->sentinel[i];

        node->VidMem.offset    = BaseAddress;
        node->VidMem.bytes     = bytes;
        node->VidMem.alignment = 0;
        node->VidMem.physical  = 0;
        node->VidMem.pool      = gcvPOOL_UNKNOWN;

        node->VidMem.locked    = 0;

#ifdef __QNXNTO__
        node->VidMem.logical   = gcvNULL;
        node->VidMem.handle    = 0;
#endif

        /* Initialize the linked list of nodes. */
        memory->sentinel[i].VidMem.next     =
        memory->sentinel[i].VidMem.prev     =
        memory->sentinel[i].VidMem.nextFree =
        memory->sentinel[i].VidMem.prevFree = node;

        /* Mark sentinel. */
        memory->sentinel[i].VidMem.bytes = 0;

        /* Adjust address for next bank. */
        BaseAddress += bytes;
        Bytes       -= bytes;
        banks       ++;
    }

    /* Assign all the bank mappings. */
    memory->mapping[gcvSURF_RENDER_TARGET]      = banks - 1;
    memory->mapping[gcvSURF_BITMAP]             = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_DEPTH]              = banks - 1;
    memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_TEXTURE]            = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_VERTEX]             = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_INDEX]              = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_TILE_STATUS]        = banks - 1;
    if (banks > 1) --banks;
    memory->mapping[gcvSURF_TYPE_UNKNOWN]       = 0;

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] INDEX:         bank %d",
                  memory->mapping[gcvSURF_INDEX]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] VERTEX:        bank %d",
                  memory->mapping[gcvSURF_VERTEX]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] TEXTURE:       bank %d",
                  memory->mapping[gcvSURF_TEXTURE]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] RENDER_TARGET: bank %d",
                  memory->mapping[gcvSURF_RENDER_TARGET]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] DEPTH:         bank %d",
                  memory->mapping[gcvSURF_DEPTH]);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
                  "[GALCORE] TILE_STATUS:   bank %d",
                  memory->mapping[gcvSURF_TILE_STATUS]);

    /* Allocate the mutex. */
    gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));

    /* Return pointer to the gckVIDMEM object. */
    *Memory = memory;

    /* Success. */
    gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
    return gcvSTATUS_OK;

OnError:
    /* Roll back. */
    if (memory != gcvNULL)
    {
        if (memory->mutex != gcvNULL)
        {
            /* Delete the mutex. */
            gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
        }

        for (i = 0; i < banks; ++i)
        {
            /* Free the heap. */
            gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
            gcmkVERIFY_OK(gckOS_Free(Os, memory->sentinel[i].VidMem.next));
        }

        /* Free the object. */
        gcmkVERIFY_OK(gckOS_Free(Os, memory));
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}
コード例 #10
0
/*******************************************************************************
**
**  gckKERNEL_Dispatch
**
**  Dispatch a command received from the user HAL layer.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to an gckKERNEL object.
**
**      gcsHAL_INTERFACE * Interface
**          Pointer to a gcsHAL_INTERFACE structure that defines the command to
**          be dispatched.
**
**  OUTPUT:
**
**      gcsHAL_INTERFACE * Interface
**          Pointer to a gcsHAL_INTERFACE structure that receives any data to be
**          returned.
*/
gceSTATUS gckVGKERNEL_Dispatch(
    IN gckKERNEL Kernel,
    IN gctBOOL FromUser,
    IN OUT gcsHAL_INTERFACE * Interface
    )
{
    gceSTATUS status;
    gcsHAL_INTERFACE * kernelInterface = Interface;
    gcuVIDMEM_NODE_PTR node;
    gctUINT32 processID;

    gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
    gcmkVERIFY_ARGUMENT(Interface != gcvNULL);

    gcmkONERROR(gckOS_GetProcessID(&processID));

    /* Dispatch on command. */
    switch (Interface->command)
    {
    case gcvHAL_QUERY_VIDEO_MEMORY:
        /* Query video memory size. */
        gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
            Kernel, kernelInterface
            ));
        break;

    case gcvHAL_QUERY_CHIP_IDENTITY:
        /* Query chip identity. */
        gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
            Kernel->vg->hardware,
            &kernelInterface->u.QueryChipIdentity.chipModel,
            &kernelInterface->u.QueryChipIdentity.chipRevision,
            &kernelInterface->u.QueryChipIdentity.chipFeatures,
            &kernelInterface->u.QueryChipIdentity.chipMinorFeatures,
            &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2
            ));
        break;

    case gcvHAL_QUERY_COMMAND_BUFFER:
        /* Query command buffer information. */
        gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
            Kernel,
            &kernelInterface->u.QueryCommandBuffer.information
            ));
        break;
    case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
        /* Allocate non-paged memory. */
        gcmkERR_BREAK(gckOS_AllocateContiguous(
            Kernel->os,
            gcvTRUE,
            &kernelInterface->u.AllocateNonPagedMemory.bytes,
            &kernelInterface->u.AllocateNonPagedMemory.physical,
            &kernelInterface->u.AllocateNonPagedMemory.logical
            ));
        break;

    case gcvHAL_FREE_NON_PAGED_MEMORY:
        /* Unmap user logical out of physical memory first. */
        gcmkERR_BREAK(gckOS_UnmapUserLogical(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.bytes,
            kernelInterface->u.AllocateNonPagedMemory.logical
            ));

        /* Free non-paged memory. */
        gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.bytes,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.logical
            ));
        break;

    case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
        /* Allocate contiguous memory. */
        gcmkERR_BREAK(gckOS_AllocateContiguous(
            Kernel->os,
            gcvTRUE,
            &kernelInterface->u.AllocateNonPagedMemory.bytes,
            &kernelInterface->u.AllocateNonPagedMemory.physical,
            &kernelInterface->u.AllocateNonPagedMemory.logical
            ));
        break;

    case gcvHAL_FREE_CONTIGUOUS_MEMORY:
        /* Unmap user logical out of physical memory first. */
        gcmkERR_BREAK(gckOS_UnmapUserLogical(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.bytes,
            kernelInterface->u.AllocateNonPagedMemory.logical
            ));

        /* Free contiguous memory. */
        gcmkERR_BREAK(gckOS_FreeContiguous(
            Kernel->os,
            kernelInterface->u.AllocateNonPagedMemory.physical,
            kernelInterface->u.AllocateNonPagedMemory.logical,
            kernelInterface->u.AllocateNonPagedMemory.bytes
            ));
        break;

    case gcvHAL_ALLOCATE_VIDEO_MEMORY:
        {
            gctSIZE_T bytes;
            gctUINT32 bitsPerPixel;
            gctUINT32 bits;

            /* Align width and height to tiles. */
            gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
                Kernel->vg->hardware,
                kernelInterface->u.AllocateVideoMemory.type,
                &kernelInterface->u.AllocateVideoMemory.width,
                &kernelInterface->u.AllocateVideoMemory.height
                ));

            /* Convert format into bytes per pixel and bytes per tile. */
            gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
                Kernel->vg->hardware,
                kernelInterface->u.AllocateVideoMemory.format,
                &bitsPerPixel,
                gcvNULL
                ));

            /* Compute number of bits for the allocation. */
            bits
                = kernelInterface->u.AllocateVideoMemory.width
                * kernelInterface->u.AllocateVideoMemory.height
                * kernelInterface->u.AllocateVideoMemory.depth
                * bitsPerPixel;

            /* Compute number of bytes for the allocation. */
            bytes = gcmALIGN(bits, 8) / 8;

            /* Allocate memory. */
            gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
                Kernel,
                &kernelInterface->u.AllocateVideoMemory.pool,
                bytes,
                64,
                kernelInterface->u.AllocateVideoMemory.type,
                &kernelInterface->u.AllocateVideoMemory.node
                ));
        }
        break;

    case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
        /* Allocate memory. */
        gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
            Kernel,
            &kernelInterface->u.AllocateLinearVideoMemory.pool,
            kernelInterface->u.AllocateLinearVideoMemory.bytes,
            kernelInterface->u.AllocateLinearVideoMemory.alignment,
            kernelInterface->u.AllocateLinearVideoMemory.type,
            &kernelInterface->u.AllocateLinearVideoMemory.node
            ));

        gcmkERR_BREAK(gckKERNEL_AddProcessDB(Kernel,
           processID, gcvDB_VIDEO_MEMORY,
           Interface->u.AllocateLinearVideoMemory.node,
           gcvNULL,
           kernelInterface->u.AllocateLinearVideoMemory.bytes
           ));

        break;

    case gcvHAL_FREE_VIDEO_MEMORY:
#ifdef __QNXNTO__
        /* Unmap the video memory */
        node = Interface->u.FreeVideoMemory.node;

        if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM) &&
            (node->VidMem.logical != gcvNULL))
        {
            gckKERNEL_UnmapVideoMemory(Kernel,
                                       node->VidMem.logical,
                                       processID,
                                       node->VidMem.bytes);
            node->VidMem.logical = gcvNULL;
        }
#endif /* __QNXNTO__ */

        /* Free video memory. */
        gcmkERR_BREAK(gckVIDMEM_Free(
            Interface->u.FreeVideoMemory.node
            ));

        gcmkERR_BREAK(gckKERNEL_RemoveProcessDB(
            Kernel,
            processID, gcvDB_VIDEO_MEMORY,
            Interface->u.FreeVideoMemory.node
            ));

        break;

    case gcvHAL_MAP_MEMORY:
        /* Map memory. */
        gcmkERR_BREAK(gckKERNEL_MapMemory(
            Kernel,
            kernelInterface->u.MapMemory.physical,
            kernelInterface->u.MapMemory.bytes,
            &kernelInterface->u.MapMemory.logical
            ));
        break;

    case gcvHAL_UNMAP_MEMORY:
        /* Unmap memory. */
        gcmkERR_BREAK(gckKERNEL_UnmapMemory(
            Kernel,
            kernelInterface->u.MapMemory.physical,
            kernelInterface->u.MapMemory.bytes,
            kernelInterface->u.MapMemory.logical
            ));
        break;

    case gcvHAL_MAP_USER_MEMORY:
        /* Map user memory to DMA. */
        gcmkERR_BREAK(gckOS_MapUserMemory(
            Kernel->os,
            gcvCORE_VG,
            kernelInterface->u.MapUserMemory.memory,
            kernelInterface->u.MapUserMemory.physical,
            kernelInterface->u.MapUserMemory.size,
            &kernelInterface->u.MapUserMemory.info,
            &kernelInterface->u.MapUserMemory.address
            ));
        break;

    case gcvHAL_UNMAP_USER_MEMORY:
        /* Unmap user memory. */
        gcmkERR_BREAK(gckOS_UnmapUserMemory(
            Kernel->os,
            gcvCORE_VG,
            kernelInterface->u.UnmapUserMemory.memory,
            kernelInterface->u.UnmapUserMemory.size,
            kernelInterface->u.UnmapUserMemory.info,
            kernelInterface->u.UnmapUserMemory.address
            ));
        break;
    case gcvHAL_LOCK_VIDEO_MEMORY:
        /* Lock video memory. */
        gcmkERR_BREAK(
            gckVIDMEM_Lock(Kernel,
                           Interface->u.LockVideoMemory.node,
                           gcvFALSE,
                           &Interface->u.LockVideoMemory.address));

        node = Interface->u.LockVideoMemory.node;
        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
        {
            /* Map video memory address into user space. */
#ifdef __QNXNTO__
        if (node->VidMem.logical == gcvNULL)
        {
            gcmkONERROR(
                gckKERNEL_MapVideoMemory(Kernel,
                                         FromUser,
                                         Interface->u.LockVideoMemory.address,
                                         processID,
                                         node->VidMem.bytes,
                                         &node->VidMem.logical));
        }

        Interface->u.LockVideoMemory.memory = node->VidMem.logical;
#else
            gcmkERR_BREAK(
                gckKERNEL_MapVideoMemoryEx(Kernel,
                                         gcvCORE_VG,
                                         FromUser,
                                         Interface->u.LockVideoMemory.address,
                                         &Interface->u.LockVideoMemory.memory));
#endif
        }
        else
        {
            Interface->u.LockVideoMemory.memory = node->Virtual.logical;

            /* Success. */
            status = gcvSTATUS_OK;
        }

#if gcdSECURE_USER
        /* Return logical address as physical address. */
        Interface->u.LockVideoMemory.address =
            gcmPTR2INT(Interface->u.LockVideoMemory.memory);
#endif
        gcmkERR_BREAK(
            gckKERNEL_AddProcessDB(Kernel,
                                   processID, gcvDB_VIDEO_MEMORY_LOCKED,
                                   Interface->u.LockVideoMemory.node,
                                   gcvNULL,
                                   0));
        break;

    case gcvHAL_UNLOCK_VIDEO_MEMORY:
        /* Unlock video memory. */
        node = Interface->u.UnlockVideoMemory.node;

#if gcdSECURE_USER
        /* Save node information before it disappears. */
        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
        {
            logical = gcvNULL;
            bytes   = 0;
        }
        else
        {
            logical = node->Virtual.logical;
            bytes   = node->Virtual.bytes;
        }
#endif

        /* Unlock video memory. */
        gcmkERR_BREAK(
            gckVIDMEM_Unlock(Kernel,
                             node,
                             Interface->u.UnlockVideoMemory.type,
                             &Interface->u.UnlockVideoMemory.asynchroneous,
                             gcvFALSE));

#if gcdSECURE_USER
        /* Flush the translation cache for virtual surfaces. */
        if (logical != gcvNULL)
        {
            gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
                                                          cache,
                                                          logical,
                                                          bytes));
        }
#endif

        if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE)
        {
            /* There isn't a event to unlock this node, remove record now */
            gcmkERR_BREAK(
                    gckKERNEL_RemoveProcessDB(Kernel,
                        processID, gcvDB_VIDEO_MEMORY_LOCKED,
                        Interface->u.UnlockVideoMemory.node));
        }

        break;
    case gcvHAL_USER_SIGNAL:
#if !USE_NEW_LINUX_SIGNAL
        /* Dispatch depends on the user signal subcommands. */
        switch(Interface->u.UserSignal.command)
        {
        case gcvUSER_SIGNAL_CREATE:
            /* Create a signal used in the user space. */
            gcmkERR_BREAK(
                gckOS_CreateUserSignal(Kernel->os,
                                       Interface->u.UserSignal.manualReset,
                                       &Interface->u.UserSignal.id));

            gcmkVERIFY_OK(
                gckKERNEL_AddProcessDB(Kernel,
                                       processID, gcvDB_SIGNAL,
                                       gcmINT2PTR(Interface->u.UserSignal.id),
                                       gcvNULL,
                                       0));
            break;

        case gcvUSER_SIGNAL_DESTROY:
            /* Destroy the signal. */
            gcmkERR_BREAK(
                gckOS_DestroyUserSignal(Kernel->os,
                                        Interface->u.UserSignal.id));

            gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
                Kernel,
                processID, gcvDB_SIGNAL,
                gcmINT2PTR(Interface->u.UserSignal.id)));
            break;

        case gcvUSER_SIGNAL_SIGNAL:
            /* Signal the signal. */
            gcmkERR_BREAK(
                gckOS_SignalUserSignal(Kernel->os,
                                       Interface->u.UserSignal.id,
                                       Interface->u.UserSignal.state));
            break;

        case gcvUSER_SIGNAL_WAIT:
            /* Wait on the signal. */
            status = gckOS_WaitUserSignal(Kernel->os,
                                          Interface->u.UserSignal.id,
                                          Interface->u.UserSignal.wait);
            break;

        default:
            /* Invalid user signal command. */
            gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
        }
#endif
        break;

    case gcvHAL_COMMIT:
        /* Commit a command and context buffer. */
        gcmkERR_BREAK(gckVGCOMMAND_Commit(
            Kernel->vg->command,
            kernelInterface->u.VGCommit.context,
            kernelInterface->u.VGCommit.queue,
            kernelInterface->u.VGCommit.entryCount,
            kernelInterface->u.VGCommit.taskTable
            ));
        break;
    case gcvHAL_VERSION:
        kernelInterface->u.Version.major = gcvVERSION_MAJOR;
        kernelInterface->u.Version.minor = gcvVERSION_MINOR;
        kernelInterface->u.Version.patch = gcvVERSION_PATCH;
        kernelInterface->u.Version.build = gcvVERSION_BUILD;
        status = gcvSTATUS_OK;
        break;

    case gcvHAL_GET_BASE_ADDRESS:
        /* Get base address. */
        gcmkERR_BREAK(
            gckOS_GetBaseAddress(Kernel->os,
                                 &kernelInterface->u.GetBaseAddress.baseAddress));
        break;
    default:
        /* Invalid command. */
        status = gcvSTATUS_INVALID_ARGUMENT;
    }

OnError:
    /* Save status. */
    kernelInterface->status = status;

    gcmkFOOTER();

    /* Return the status. */
    return status;
}
コード例 #11
0
    return gcvSTATUS_OK;
}

gceSTATUS
gcfDumpBuffer(
    IN gcoOS Os,
    IN gctSTRING Tag,
    IN gctUINT32 Physical,
    IN gctPOINTER Logical,
    IN gctUINT32 Offset,
    IN gctSIZE_T Bytes
    )
{

    gctUINT32_PTR ptr = (gctUINT32_PTR) Logical + (Offset >> 2);
    gctSIZE_T bytes   = gcmALIGN(Bytes + (Offset & 3), 4);

    if (!setDumpFlag)
        return gcvSTATUS_OK;

#if gcdDUMP_COMMAND
    static gctPOINTER   dumpLock;

    if (dumpLock == gcvNULL)
    {
        /* TODO: Delete this mutex somehow. */
        gcmVERIFY_OK(gcoOS_CreateMutex(Os, &dumpLock));
    }

    /* Acquire mutex to avoid multiple threads dumping data
       at the same time. */
コード例 #12
0
gceSTATUS glfCreateNamedObject(
	IN glsCONTEXT_PTR Context,
	IN glsNAMEDOBJECTLIST_PTR List,
	IN gctUINT32 Name,
	IN glfNAMEDOBJECTDESTRUCTOR ObjectDestructor,
	OUT glsNAMEDOBJECT_PTR * ObjectWrapper
	)
{
    gceSTATUS status = gcvSTATUS_OK;
    gcmHEADER_ARG("Context=0x%x List=0x%x Name=%u ObjectDestructor=0x%x ObjectWrapper=0x%x",
                    Context, List, Name, ObjectDestructor, ObjectWrapper);

	do
	{
		glsNAMEDOBJECT_PTR wrapper;
		glsNAMEDOBJECT_PTR* entry;
		gctUINT32 index;

		/* Are there available wrappers in the free list? */
		wrapper = List->freeList;
		if ((Name == 0) && (wrapper != gcvNULL))
		{
			/* Remove the first wrapper from the list. */
			List->freeList = wrapper->next;
		}

		/* Create a new wrapper. */
		else
		{
			/* Create a new wrapper. */
			wrapper = gcvNULL;

			/* Generate a name if not specified. */
			if (Name == 0)
			{
				if (List->nextName == 0)
				{
					/* No more names. */
					status = gcvSTATUS_OUT_OF_RESOURCES;
					break;
				}

				Name = List->nextName++;
			}
			else if (Name > List->nextName)
			{
				/* Name for the object has been explicitly specified by
				   the application and it is greater then the next automatic
				   would-be name. Update the next name with the value from
				   the application; this creates a hole in the name range. */
				List->nextName = Name + 1;
			}
			else if (List->freeList != gcvNULL)
			{
				/* Name for the object has been explicitly specified by
				   the application and it is less then or equal to the next
				   automatic would-be name.  This means the name most likely
				   lives inside the free list. */
				if (List->freeList->name == Name)
				{
					wrapper        = List->freeList;
					List->freeList = wrapper->next;
				}
				else
				{
					glsNAMEDOBJECT_PTR previous = List->freeList;

					for (wrapper = List->freeList;
						 wrapper != gcvNULL;
						 wrapper = wrapper->next)
					{
						if (wrapper->name == Name)
						{
							previous->next = wrapper->next;
							break;
						}

						previous = wrapper;
					}
				}
			}

			if (wrapper == gcvNULL)
			{
				/* Allocate wrapper and the user object. */
				gcmERR_BREAK(gcoOS_Allocate(
					gcvNULL,
					gcmALIGN(sizeof(glsNAMEDOBJECT), 4) + List->objectSize,
					(gctPOINTER) &wrapper
					));

				/* Set the objects's name. */
				wrapper->name = Name;

				/* Set the object pointer. */
				wrapper->object
					= ((gctUINT8_PTR) wrapper)
					+ gcmALIGN(sizeof(glsNAMEDOBJECT), 4);

                wrapper->referenceCount = 0;

                wrapper->listBelonged = List;
			}
		}

		/* Set the destructor. */
		wrapper->deleteObject = ObjectDestructor;

		/* Determine the hash table index. */
		index = wrapper->name % glvNAMEDOBJECT_HASHTABLE_SIZE;

		/* Shortcut to the table entry. */
		entry = &List->hashTable[index];

		/* Insert into the chain. */
		wrapper->next = *entry;
		*entry = wrapper;

        glfReferenceNamedObject(wrapper);

		/* Set the result. */
		*ObjectWrapper = wrapper;
	}
	while (gcvFALSE);

    gcmFOOTER();

	return status;
}
コード例 #13
0
/*******************************************************************************
**
**	gckCOMMAND_Reserve
**
**	Reserve space in the command queue.  Also acquire the command queue mutex.
**
**	INPUT:
**
**		gckCOMMAND Command
**			Pointer to an gckCOMMAND object.
**
**		gctSIZE_T RequestedBytes
**			Number of bytes previously reserved.
**
**	OUTPUT:
**
**		gctPOINTER * Buffer
**          Pointer to a variable that will receive the address of the reserved
**          space.
**
**      gctSIZE_T * BufferSize
**          Pointer to a variable that will receive the number of bytes
**          available in the command queue.
*/
gceSTATUS
gckCOMMAND_Reserve(
    IN gckCOMMAND Command,
    IN gctSIZE_T RequestedBytes,
	IN gctBOOL Locking,
    OUT gctPOINTER * Buffer,
    OUT gctSIZE_T * BufferSize
    )
{
    gceSTATUS status;
    gctSIZE_T requiredBytes, bytes;
    gctBOOL acquired = gcvFALSE;

    gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu Locking=%d",
					Command, RequestedBytes, Locking);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);

	if (!Locking)
	{
	    /* Grab the conmmand queue mutex. */
    	gcmkONERROR(
        	gckOS_AcquireMutex(Command->os,
            	               Command->mutexQueue,
                	           gcvINFINITE));
	    acquired = gcvTRUE;
	}

	/* Compute number of bytes required for WAIT/LINK. */
	gcmkONERROR(
		gckHARDWARE_WaitLink(Command->kernel->hardware,
							 gcvNULL,
							 Command->offset + gcmALIGN(RequestedBytes,
														Command->alignment),
							 &requiredBytes,
							 gcvNULL,
							 gcvNULL));

	/* Compute total number of bytes required. */
	requiredBytes += gcmALIGN(RequestedBytes, Command->alignment);

	/* Compute number of bytes available in command queue. */
	bytes = Command->pageSize - Command->offset;

	if (bytes < requiredBytes)
	{
        /* Create a new command queue. */
        gcmkONERROR(_NewQueue(Command, gcvTRUE));

		/* Recompute number of bytes available in command queue. */
		bytes = Command->pageSize - Command->offset;

		if (bytes < requiredBytes)
		{
			/* Rare case, not enough room in command queue. */
			gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
		}
	}

	/* Return pointer to empty slot command queue. */
	*Buffer = (gctUINT8 *) Command->logical + Command->offset;

	/* Return number of bytes left in command queue. */
	*BufferSize = bytes;

	/* Success. */
	gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
	return gcvSTATUS_OK;

OnError:
    if (acquired)
    {
        /* Release command queue mutex on error. */
        gcmkVERIFY_OK(
        	gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
    }

    /* Return status. */
    gcmkFOOTER();
    return status;
}