Пример #1
0
/*******************************************************************************
**
**  gckGALDEVICE_Construct
**
**  Constructor.
**
**  INPUT:
**
**  OUTPUT:
**
**      gckGALDEVICE * Device
**          Pointer to a variable receiving the gckGALDEVICE object pointer on
**          success.
*/
gceSTATUS
gckGALDEVICE_Construct(
    IN gctINT IrqLine,
    IN gctUINT32 RegisterMemBase,
    IN gctSIZE_T RegisterMemSize,
    IN gctINT IrqLine2D,
    IN gctUINT32 RegisterMemBase2D,
    IN gctSIZE_T RegisterMemSize2D,
    IN gctINT IrqLineVG,
    IN gctUINT32 RegisterMemBaseVG,
    IN gctSIZE_T RegisterMemSizeVG,
    IN gctUINT32 ContiguousBase,
    IN gctSIZE_T ContiguousSize,
    IN gctSIZE_T BankSize,
    IN gctINT FastClear,
    IN gctINT Compression,
    IN gctUINT32 PhysBaseAddr,
    IN gctUINT32 PhysSize,
    IN gctINT Signal,
    IN gctUINT LogFileSize,
    IN struct device *pdev,
    IN gctINT PowerManagement,
    OUT gckGALDEVICE *Device
    )
{
    gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
    gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
    gctUINT32 horizontalTileSize, verticalTileSize;
    struct resource* mem_region;
    gctUINT32 physAddr;
    gctUINT32 physical;
    gckGALDEVICE device;
    gceSTATUS status;
    gctINT32 i;
    gceHARDWARE_TYPE type;
    gckDB sharedDB = gcvNULL;
    gckKERNEL kernel = gcvNULL;

    gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
                   "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
                   "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
                   "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
                   "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
                   IrqLine, RegisterMemBase, RegisterMemSize,
                   IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
                   IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
                   ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
                   PhysBaseAddr, PhysSize, Signal);

    /* Allocate device structure. */
    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);

    if (!device)
    {
        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
    }

    memset(device, 0, sizeof(struct _gckGALDEVICE));

   device->dbgnode = gcvNULL;
   if(LogFileSize != 0)
   {
	if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
	{
		gcmkTRACE_ZONE(
		gcvLEVEL_ERROR, gcvZONE_DRIVER,
		"%s(%d): Failed to create  the debug file system  %s/%s \n",
		__FUNCTION__, __LINE__,
		PARENT_FILE, DEBUG_FILE
		);
	}
	else
	{
		/*Everything is OK*/
	 	gckDebugFileSystemSetCurrentNode(device->dbgnode);
	}
    }
#ifdef CONFIG_PM
    /*Init runtime pm for gpu*/
    pm_runtime_enable(pdev);
    device->pmdev = pdev;
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
    /*get gpu regulator*/
    device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
    if (IS_ERR(device->gpu_regulator)) {
	gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
		"%s(%d): Failed to get gpu regulator  %s/%s \n",
		__FUNCTION__, __LINE__,
		PARENT_FILE, DEBUG_FILE);
	gcmkONERROR(gcvSTATUS_NOT_FOUND);
    }
#endif
    /*Initialize the clock structure*/
    if (IrqLine != -1) {
        device->clk_3d_core = clk_get(pdev, "gpu3d_clk");
        if (!IS_ERR(device->clk_3d_core)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
            if (cpu_is_mx6q()) {
	            device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
	            if (IS_ERR(device->clk_3d_shader)) {
	                IrqLine = -1;
	                clk_put(device->clk_3d_core);
	                device->clk_3d_core = NULL;
	                device->clk_3d_shader = NULL;
	                gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
	            }
	          }
#else
	            device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
	            device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
	            if (IS_ERR(device->clk_3d_shader)) {
	                IrqLine = -1;
	                clk_put(device->clk_3d_core);
	                device->clk_3d_core = NULL;
	                device->clk_3d_shader = NULL;
	                gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
	            }
#endif
        } else {
            IrqLine = -1;
            device->clk_3d_core = NULL;
            gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
        }
    }
    if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
        device->clk_2d_core = clk_get(pdev, "gpu2d_clk");
        if (IS_ERR(device->clk_2d_core)) {
            IrqLine2D = -1;
            IrqLineVG = -1;
            device->clk_2d_core = NULL;
            gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
        } else {
	    if (IrqLine2D != -1) {
                device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
                if (IS_ERR(device->clk_2d_axi)) {
                    device->clk_2d_axi = NULL;
                    IrqLine2D = -1;
                    gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
                }
            }
            if (IrqLineVG != -1) {
                device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
                if (IS_ERR(device->clk_vg_axi)) {
                    IrqLineVG = -1;
	                device->clk_vg_axi = NULL;
	                gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
                }
            }
        }
    }

    if (IrqLine != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
        device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
    }

    if (IrqLine2D != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
        device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
    }

    if (IrqLineVG != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
        device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
    }

    device->requestedContiguousBase  = 0;
    device->requestedContiguousSize  = 0;


    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        physical = device->requestedRegisterMemBases[i];

        /* Set up register memory region. */
        if (physical != 0)
        {
            mem_region = request_mem_region(
                physical, device->requestedRegisterMemSizes[i], "galcore register region"
                );

            if (mem_region == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->registerBases[i] = (gctPOINTER) ioremap_nocache(
                physical, device->requestedRegisterMemSizes[i]);

            if (device->registerBases[i] == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            physical += device->requestedRegisterMemSizes[i];
        }
        else
        {
            device->registerBases[i] = gcvNULL;
        }
    }

    /* Set the base address */
    device->baseAddress = PhysBaseAddr;

    /* Construct the gckOS object. */
    gcmkONERROR(gckOS_Construct(device, &device->os));

    if (IrqLine != -1)
    {
        /* Construct the gckKERNEL object. */
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_MAJOR, device,
            gcvNULL, &device->kernels[gcvCORE_MAJOR]));

        sharedDB = device->kernels[gcvCORE_MAJOR]->db;

        /* Initialize core mapping */
        for (i = 0; i < 8; i++)
        {
            device->coreMapping[i] = gcvCORE_MAJOR;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_MAJOR]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
            device
            ));

        gcmkONERROR(gckHARDWARE_SetFastClear(
            device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
            ));

        gcmkONERROR(gckHARDWARE_SetPowerManagement(
            device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
            ));

#if COMMAND_PROCESSOR_VERSION == 1
        /* Start the command queue. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_MAJOR] = gcvNULL;
    }

    if (IrqLine2D != -1)
    {
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_2D, device,
            sharedDB, &device->kernels[gcvCORE_2D]));

        if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;

        /* Verify the hardware type */
        gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));

        if (type != gcvHARDWARE_2D)
        {
            gcmkTRACE_ZONE(
                gcvLEVEL_ERROR, gcvZONE_DRIVER,
                "%s(%d): Unexpected hardware type: %d\n",
                __FUNCTION__, __LINE__,
                type
                );

            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
        }

        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_2D;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_2D]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
            device
            ));

        gcmkONERROR(gckHARDWARE_SetPowerManagement(
            device->kernels[gcvCORE_2D]->hardware, PowerManagement
            ));

#if COMMAND_PROCESSOR_VERSION == 1
        /* Start the command queue. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_2D] = gcvNULL;
    }

    if (IrqLineVG != -1)
    {
#if gcdENABLE_VG
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_VG, device,
            sharedDB, &device->kernels[gcvCORE_VG]));
        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL
            && device->kernels[gcvCORE_2D] == gcvNULL
            )
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_VG;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
        }


        gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
            device->kernels[gcvCORE_VG]->vg->hardware,
            PowerManagement
            ));
#endif
    }
    else
    {
        device->kernels[gcvCORE_VG] = gcvNULL;
    }

    /* Initialize the ISR. */
    device->irqLines[gcvCORE_MAJOR] = IrqLine;
    device->irqLines[gcvCORE_2D]    = IrqLine2D;
    device->irqLines[gcvCORE_VG]    = IrqLineVG;

    /* Initialize the kernel thread semaphores. */
    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
    }

    device->signal = Signal;

    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->kernels[i] != gcvNULL) break;
    }

    if (i == gcdMAX_GPU_COUNT)
	{
		gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
	}

#if gcdENABLE_VG
    if (i == gcvCORE_VG)
    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
                device->kernels[i]->vg->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));
            /* query the amount of video memory */
        gcmkONERROR(gckVGHARDWARE_QueryMemory(
            device->kernels[i]->vg->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }
    else
#endif
    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckHARDWARE_QuerySystemMemory(
                device->kernels[i]->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));

            /* query the amount of video memory */
        gcmkONERROR(gckHARDWARE_QueryMemory(
            device->kernels[i]->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }


    /* Grab the first availiable kernel */
    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->irqLines[i] != -1)
        {
            kernel = device->kernels[i];
            break;
        }
    }

    /* Set up the internal memory region. */
    if (device->internalSize > 0)
    {
        status = gckVIDMEM_Construct(
            device->os,
            internalBaseAddress, device->internalSize, internalAlignment,
            0, &device->internalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->internalSize = 0;
        }
        else
        {
            /* Map internal memory. */
            device->internalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->internalSize);

            if (device->internalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
            device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
            physical += device->internalSize;
        }
    }

    if (device->externalSize > 0)
    {
        /* create the external memory heap */
        status = gckVIDMEM_Construct(
            device->os,
            externalBaseAddress, device->externalSize, externalAlignment,
            0, &device->externalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->externalSize = 0;
        }
        else
        {
            /* Map external memory. */
            device->externalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->externalSize);

            if (device->externalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
            device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
            physical += device->externalSize;
        }
    }

    /* set up the contiguous memory */
    device->contiguousSize = ContiguousSize;

    if (ContiguousSize > 0)
    {
        if (ContiguousBase == 0)
        {
            while (device->contiguousSize > 0)
            {
                /* Allocate contiguous memory. */
                status = _AllocateMemory(
                    device,
                    device->contiguousSize,
                    &device->contiguousBase,
                    &device->contiguousPhysical,
                    &physAddr
                    );

                if (gcmIS_SUCCESS(status))
                {
                    device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
                    status = gckVIDMEM_Construct(
                        device->os,
                        physAddr | device->systemMemoryBaseAddress,
                        device->contiguousSize,
                        64,
                        BankSize,
                        &device->contiguousVidMem
                        );

                    if (gcmIS_SUCCESS(status))
                    {
                        break;
                    }

                    gcmkONERROR(_FreeMemory(
                        device,
                        device->contiguousBase,
                        device->contiguousPhysical
                        ));

                    gcmRELEASE_NAME(device->contiguousPhysicalName);
                    device->contiguousBase     = gcvNULL;
                    device->contiguousPhysical = gcvNULL;
                }

                if (device->contiguousSize <= (4 << 20))
                {
                    device->contiguousSize = 0;
                }
                else
                {
                    device->contiguousSize -= (4 << 20);
                }
            }
        }
        else
        {
            /* Create the contiguous memory heap. */
            status = gckVIDMEM_Construct(
                device->os,
                ContiguousBase | device->systemMemoryBaseAddress,
                ContiguousSize,
                64, BankSize,
                &device->contiguousVidMem
                );

            if (gcmIS_ERROR(status))
            {
                /* Error, disable contiguous memory pool. */
                device->contiguousVidMem = gcvNULL;
                device->contiguousSize   = 0;
            }
            else
            {
                mem_region = request_mem_region(
                    ContiguousBase, ContiguousSize, "galcore managed memory"
                    );

                if (mem_region == gcvNULL)
                {
                    gcmkTRACE_ZONE(
                        gcvLEVEL_ERROR, gcvZONE_DRIVER,
                        "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
                        __FUNCTION__, __LINE__,
                        ContiguousSize, ContiguousBase
                        );

                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                }

                device->requestedContiguousBase  = ContiguousBase;
                device->requestedContiguousSize  = ContiguousSize;

#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
                if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
                {
                    device->contiguousBase
#if gcdPAGED_MEMORY_CACHEABLE
                        = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
#else
                        = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
#endif
                    if (device->contiguousBase == gcvNULL)
                    {
                        device->contiguousVidMem = gcvNULL;
                        device->contiguousSize = 0;

                        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                    }
                }
#endif

                device->contiguousPhysical = gcvNULL;
                device->contiguousPhysicalName = 0;
                device->contiguousSize     = ContiguousSize;
                device->contiguousMapped   = gcvTRUE;
            }
        }
    }
Пример #2
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;
    gckKERNEL kernel = Kernel;
    gctPOINTER info = gcvNULL;
    gctPHYS_ADDR physical = gcvNULL;
    gctPOINTER logical = gcvNULL;
    gctSIZE_T bytes = 0;

    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:
        bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
        /* Allocate non-paged memory. */
        gcmkERR_BREAK(gckOS_AllocateContiguous(
                          Kernel->os,
                          gcvTRUE,
                          &bytes,
                          &physical,
                          &logical
                      ));

        kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
        kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
        kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
        break;

    case gcvHAL_FREE_NON_PAGED_MEMORY:
        physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);

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

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

        gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
        break;

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

        kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
        kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
        kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
        break;

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

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

        gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
        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,
                          &node
                      ));

        kernelInterface->u.AllocateVideoMemory.node = gcmPTR_TO_UINT64(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,
                          &node
                      ));

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

        kernelInterface->u.AllocateLinearVideoMemory.node = gcmPTR_TO_UINT64(node);
        break;

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

        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(
                          node
                      ));

        gcmkERR_BREAK(gckKERNEL_RemoveProcessDB(
                          Kernel,
                          processID, gcvDB_VIDEO_MEMORY,
                          node
                      ));

        break;

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

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

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

        kernelInterface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
        break;

    case gcvHAL_UNMAP_USER_MEMORY:
        /* Unmap user memory. */
        gcmkERR_BREAK(gckOS_UnmapUserMemory(
                          Kernel->os,
                          gcvCORE_VG,
                          gcmUINT64_TO_PTR(kernelInterface->u.UnmapUserMemory.memory),
                          (gctSIZE_T) kernelInterface->u.UnmapUserMemory.size,
                          gcmNAME_TO_PTR(kernelInterface->u.UnmapUserMemory.info),
                          kernelInterface->u.UnmapUserMemory.address
                      ));
        break;
    case gcvHAL_LOCK_VIDEO_MEMORY:
        node = gcmUINT64_TO_PTR(Interface->u.LockVideoMemory.node);

        /* Lock video memory. */
        gcmkERR_BREAK(
            gckVIDMEM_Lock(Kernel,
                           node,
                           gcvFALSE,
                           &Interface->u.LockVideoMemory.address));

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

            /* Success. */
            status = gcvSTATUS_OK;
        }

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

    case gcvHAL_UNLOCK_VIDEO_MEMORY:
        /* Unlock video memory. */
        node = gcmUINT64_TO_PTR(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));

#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,
                                          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,
                          gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context),
                          gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue),
                          kernelInterface->u.VGCommit.entryCount,
                          gcmUINT64_TO_PTR(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;
}
/*******************************************************************************
**
**  gckGALDEVICE_Destroy
**
**  Class destructor.
**
**  INPUT:
**
**      Nothing.
**
**  OUTPUT:
**
**      Nothing.
**
**  RETURNS:
**
**      Nothing.
*/
gceSTATUS
gckGALDEVICE_Destroy(
    gckGALDEVICE Device)
{
    gctINT i;
    gceSTATUS status = gcvSTATUS_OK;
    gckKERNEL kernel = gcvNULL;

    gcmkHEADER_ARG("Device=0x%x", Device);

    if (Device != gcvNULL)
    {
        /* Grab the first availiable kernel */
        for (i = 0; i < gcdMAX_GPU_COUNT; i++)
        {
            if (Device->irqLines[i] != -1)
            {
                kernel = Device->kernels[i];
                break;
            }
        }
        if (Device->internalPhysicalName != 0)
        {
            gcmRELEASE_NAME(Device->internalPhysicalName);
            Device->internalPhysicalName = 0;
        }
        if (Device->externalPhysicalName != 0)
        {
            gcmRELEASE_NAME(Device->externalPhysicalName);
            Device->externalPhysicalName = 0;
        }
        if (Device->contiguousPhysicalName != 0)
        {
            gcmRELEASE_NAME(Device->contiguousPhysicalName);
            Device->contiguousPhysicalName = 0;
        }


        for (i = 0; i < gcdMAX_GPU_COUNT; i++)
        {
            if (Device->kernels[i] != gcvNULL)
            {
                /* Destroy the gckKERNEL object. */
                gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
                Device->kernels[i] = gcvNULL;
            }
        }

        {
            if (Device->internalLogical != gcvNULL)
            {
                /* Unmap the internal memory. */
                iounmap(Device->internalLogical);
                Device->internalLogical = gcvNULL;
            }

            if (Device->internalVidMem != gcvNULL)
            {
                /* Destroy the internal heap. */
                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
                Device->internalVidMem = gcvNULL;
            }
        }

        {
            if (Device->externalLogical != gcvNULL)
            {
                /* Unmap the external memory. */
                iounmap(Device->externalLogical);
                Device->externalLogical = gcvNULL;
            }

            if (Device->externalVidMem != gcvNULL)
            {
                /* destroy the external heap */
                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
                Device->externalVidMem = gcvNULL;
            }
        }

        {
            if (Device->contiguousBase != gcvNULL)
            {
                if (Device->contiguousMapped)
                {
                }
                else
                {
                    gcmkONERROR(_FreeMemory(
                        Device,
                        Device->contiguousBase,
                        Device->contiguousPhysical
                        ));
                }

                Device->contiguousBase     = gcvNULL;
                Device->contiguousPhysical = gcvNULL;
            }

            if (Device->requestedContiguousBase != 0)
            {
                release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
                Device->requestedContiguousBase = 0;
                Device->requestedContiguousSize = 0;
            }

            if (Device->contiguousVidMem != gcvNULL)
            {
                /* Destroy the contiguous heap. */
                gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
                Device->contiguousVidMem = gcvNULL;
            }
        }

	{
	    if(gckDebugFileSystemIsEnabled())
	    {
		 gckDebugFileSystemFreeNode(Device->dbgnode);
		 kfree(Device->dbgnode);
		 Device->dbgnode = gcvNULL;
	    }
	}

        for (i = 0; i < gcdMAX_GPU_COUNT; i++)
        {
            if (Device->registerBases[i] != gcvNULL)
            {
                /* Unmap register memory. */
                iounmap(Device->registerBases[i]);
			    if (Device->requestedRegisterMemBases[i] != 0)
			    {
				    release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
			    }

                Device->registerBases[i] = gcvNULL;
                Device->requestedRegisterMemBases[i] = 0;
                Device->requestedRegisterMemSizes[i] = 0;
            }
        }

        /* Destroy the gckOS object. */
        if (Device->os != gcvNULL)
        {
            gcmkVERIFY_OK(gckOS_Destroy(Device->os));
            Device->os = gcvNULL;
        }

        /* Free the device. */
        kfree(Device);
    }

    gcmkFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    gcmkFOOTER();
    return status;
}
/*******************************************************************************
**  gckKERNEL_DestroyProcessDB
**
**  Destroy a process database.  If the database contains any records, the data
**  inside those records will be deleted as well.  This aids in the cleanup if
**  a process has died unexpectedly or has memory leaks.
**
**  INPUT:
**
**      gckKERNEL Kernel
**          Pointer to a gckKERNEL object.
**
**      gctUINT32 ProcessID
**          Process ID used to identify the database.
**
**  OUTPUT:
**
**      Nothing.
*/
gceSTATUS
gckKERNEL_DestroyProcessDB(
    IN gckKERNEL Kernel,
    IN gctUINT32 ProcessID
    )
{
    gceSTATUS status;
    gcsDATABASE_PTR database;
    gcsDATABASE_RECORD_PTR record, next;
    gctBOOL asynchronous;
    gctPHYS_ADDR physical;
    gcuVIDMEM_NODE_PTR node;
    gckKERNEL kernel = Kernel;
    gctUINT32 i;

    gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);

    /* Find the database. */
    gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));

    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
                   "DB(%d): VidMem: total=%lu max=%lu",
                   ProcessID, database->vidMem.totalBytes,
                   database->vidMem.maxBytes);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
                   "DB(%d): NonPaged: total=%lu max=%lu",
                   ProcessID, database->nonPaged.totalBytes,
                   database->nonPaged.maxBytes);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
                   "DB(%d): Contiguous: total=%lu max=%lu",
                   ProcessID, database->contiguous.totalBytes,
                   database->contiguous.maxBytes);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
                   "DB(%d): Idle time=%llu",
                   ProcessID, Kernel->db->idleTime);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
                   "DB(%d): Map: total=%lu max=%lu",
                   ProcessID, database->mapMemory.totalBytes,
                   database->mapMemory.maxBytes);
    gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
                   "DB(%d): Map: total=%lu max=%lu",
                   ProcessID, database->mapUserMemory.totalBytes,
                   database->mapUserMemory.maxBytes);

    if (database->list != gcvNULL)
    {
        gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                       "Process %d has entries in its database:",
                       ProcessID);
    }

    for(i = 0; i < gcmCOUNTOF(database->list); i++)
    {

    /* Walk all records. */
    for (record = database->list[i]; record != gcvNULL; record = next)
    {
        /* Next next record. */
        next = record->next;

        /* Dispatch on record type. */
        switch (record->type)
        {
        case gcvDB_VIDEO_MEMORY:
            /* Free the video memory. */
            status = gckVIDMEM_Free(gcmUINT64_TO_PTR(record->data));

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: VIDEO_MEMORY 0x%x (status=%d)",
                           record->data, status);
            break;

        case gcvDB_NON_PAGED:
            physical = gcmNAME_TO_PTR(record->physical);
            /* Unmap user logical memory first. */
            status = gckOS_UnmapUserLogical(Kernel->os,
                                            physical,
                                            record->bytes,
                                            record->data);

            /* Free the non paged memory. */
            status = gckOS_FreeNonPagedMemory(Kernel->os,
                                              record->bytes,
                                              physical,
                                              record->data);
            gcmRELEASE_NAME(record->physical);

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
                           record->data, record->bytes, status);
            break;

#if gcdVIRTUAL_COMMAND_BUFFER
        case gcvDB_COMMAND_BUFFER:
            /* Free the command buffer. */
            status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
                                                          record->bytes,
                                                          gcmNAME_TO_PTR(record->physical),
                                                          record->data,
                                                          gcvKERNEL_PIXEL);
            gcmRELEASE_NAME(record->physical);

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
                           record->data, record->bytes, status);
            break;
#endif

        case gcvDB_CONTIGUOUS:
            physical = gcmNAME_TO_PTR(record->physical);
            /* Unmap user logical memory first. */
            status = gckOS_UnmapUserLogical(Kernel->os,
                                            physical,
                                            record->bytes,
                                            record->data);

            /* Free the contiguous memory. */
            status = gckEVENT_FreeContiguousMemory(Kernel->eventObj,
                                                   record->bytes,
                                                   physical,
                                                   record->data,
                                                   gcvKERNEL_PIXEL);
            gcmRELEASE_NAME(record->physical);

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
                           record->data, record->bytes, status);
            break;

        case gcvDB_SIGNAL:
#if USE_NEW_LINUX_SIGNAL
            status = gcvSTATUS_NOT_SUPPORTED;
#else
            /* Free the user signal. */
            status = gckOS_DestroyUserSignal(Kernel->os,
                                             gcmPTR2INT(record->data));
#endif /* USE_NEW_LINUX_SIGNAL */

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: SIGNAL %d (status=%d)",
                           (gctINT)(gctUINTPTR_T)record->data, status);
            break;

        case gcvDB_VIDEO_MEMORY_LOCKED:
            node = gcmUINT64_TO_PTR(record->data);
            /* Unlock what we still locked */
            status = gckVIDMEM_Unlock(record->kernel,
                                      node,
                                      gcvSURF_TYPE_UNKNOWN,
                                      &asynchronous);

            if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
            {
                /* TODO: we maybe need to schedule a event here */
                status = gckVIDMEM_Unlock(record->kernel,
                                          node,
                                          gcvSURF_TYPE_UNKNOWN,
                                          gcvNULL);
            }

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
                           node, status);
            break;

        case gcvDB_CONTEXT:
            /* TODO: Free the context */
            status = gckCOMMAND_Detach(Kernel->command, gcmNAME_TO_PTR(record->data));
            gcmRELEASE_NAME(record->data);

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: CONTEXT 0x%x (status=%d)",
                           record->data, status);
            break;

        case gcvDB_MAP_MEMORY:
            /* Unmap memory. */
            status = gckKERNEL_UnmapMemory(Kernel,
                                           record->physical,
                                           record->bytes,
                                           record->data);

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: MAP MEMORY %d (status=%d)",
                           gcmPTR2INT(record->data), status);
            break;

        case gcvDB_MAP_USER_MEMORY:
            /* TODO: Unmap user memory. */
            status = gckOS_UnmapUserMemory(Kernel->os,
                                           Kernel->core,
                                           record->physical,
                                           record->bytes,
                                           gcmNAME_TO_PTR(record->data),
                                           0);
            gcmRELEASE_NAME(record->data);

            gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
                           "DB: MAP USER MEMORY %d (status=%d)",
                           gcmPTR2INT(record->data), status);
            break;

        case gcvDB_SHARED_INFO:
            status = gckOS_FreeMemory(Kernel->os, record->physical);
            break;

        default:
            gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
                           "DB: Correcupted record=0x%08x type=%d",
                           record, record->type);
            break;
        }

        /* Delete the record. */
        gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
                                           database,
                                           record->type,
                                           record->data,
                                           gcvNULL));
    }

    }

    /* Delete the database. */
    gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));

    /* Success. */
    gcmkFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Return the status. */
    gcmkFOOTER();
    return status;
}
/*******************************************************************************
**
**  gckGALDEVICE_Construct
**
**  Constructor.
**
**  INPUT:
**
**  OUTPUT:
**
**      gckGALDEVICE * Device
**          Pointer to a variable receiving the gckGALDEVICE object pointer on
**          success.
*/
gceSTATUS
gckGALDEVICE_Construct(
    IN gctINT IrqLine,
    IN gctUINT32 RegisterMemBase,
    IN gctSIZE_T RegisterMemSize,
    IN gctINT IrqLine2D,
    IN gctUINT32 RegisterMemBase2D,
    IN gctSIZE_T RegisterMemSize2D,
    IN gctINT IrqLineVG,
    IN gctUINT32 RegisterMemBaseVG,
    IN gctSIZE_T RegisterMemSizeVG,
    IN gctUINT32 ContiguousBase,
    IN gctSIZE_T ContiguousSize,
    IN gctSIZE_T BankSize,
    IN gctINT FastClear,
    IN gctINT Compression,
    IN gctUINT32 PhysBaseAddr,
    IN gctUINT32 PhysSize,
    IN gctINT Signal,
    IN gctUINT LogFileSize,
    OUT gckGALDEVICE *Device
    )
{
    gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
    gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
    gctUINT32 horizontalTileSize, verticalTileSize;
    struct resource* mem_region;
    gctUINT32 physAddr;
    gctUINT32 physical;
    gckGALDEVICE device;
    gceSTATUS status;
    gctINT32 i;
    gceHARDWARE_TYPE type;
    gckDB sharedDB = gcvNULL;
    gckKERNEL kernel = gcvNULL;

    gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
                   "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
                   "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
                   "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
                   "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
                   IrqLine, RegisterMemBase, RegisterMemSize,
                   IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
                   IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
                   ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
                   PhysBaseAddr, PhysSize, Signal);

    /* Allocate device structure. */
    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);

    if (!device)
    {
        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
    }

    memset(device, 0, sizeof(struct _gckGALDEVICE));

   device->dbgnode = gcvNULL;
   if(LogFileSize != 0)
   {
	if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
	{
		gcmkTRACE_ZONE(
		gcvLEVEL_ERROR, gcvZONE_DRIVER,
		"%s(%d): Failed to create  the debug file system  %s/%s \n",
		__FUNCTION__, __LINE__,
		PARENT_FILE, DEBUG_FILE
		);
	}
	else
	{
		/*Everything is OK*/
	 	gckDebugFileSystemSetCurrentNode(device->dbgnode);
	}
    }

    if (IrqLine != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
        device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
    }

    if (IrqLine2D != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
        device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
    }

    if (IrqLineVG != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
        device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
    }

    device->requestedContiguousBase  = 0;
    device->requestedContiguousSize  = 0;


    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        physical = device->requestedRegisterMemBases[i];

        /* Set up register memory region. */
        if (physical != 0)
        {
            mem_region = request_mem_region(
                physical, device->requestedRegisterMemSizes[i], "galcore register region"
                );

            if (mem_region == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->registerBases[i] = (gctPOINTER) ioremap_nocache(
                physical, device->requestedRegisterMemSizes[i]);

            if (device->registerBases[i] == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            physical += device->requestedRegisterMemSizes[i];
        }
        else
        {
            device->registerBases[i] = gcvNULL;
        }
    }

    /* Set the base address */
    device->baseAddress = PhysBaseAddr;

    /* Construct the gckOS object. */
    gcmkONERROR(gckOS_Construct(device, &device->os));

    if (IrqLine != -1)
    {
        /* Construct the gckKERNEL object. */
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_MAJOR, device,
            gcvNULL, &device->kernels[gcvCORE_MAJOR]));

        sharedDB = device->kernels[gcvCORE_MAJOR]->db;

        /* Initialize core mapping */
        for (i = 0; i < 8; i++)
        {
            device->coreMapping[i] = gcvCORE_MAJOR;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_MAJOR]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
            device
            ));

        gcmkONERROR(gckHARDWARE_SetFastClear(
            device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
            ));


#if COMMAND_PROCESSOR_VERSION == 1
        /* Start the command queue. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_MAJOR] = gcvNULL;
    }

    if (IrqLine2D != -1)
    {
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_2D, device,
            sharedDB, &device->kernels[gcvCORE_2D]));

        if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;

        /* Verify the hardware type */
        gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));

        if (type != gcvHARDWARE_2D)
        {
            gcmkTRACE_ZONE(
                gcvLEVEL_ERROR, gcvZONE_DRIVER,
                "%s(%d): Unexpected hardware type: %d\n",
                __FUNCTION__, __LINE__,
                type
                );

            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
        }

        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_2D;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_2D]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
            device
            ));

#if COMMAND_PROCESSOR_VERSION == 1
        /* Start the command queue. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_2D] = gcvNULL;
    }

    if (IrqLineVG != -1)
    {
    }
    else
    {
        device->kernels[gcvCORE_VG] = gcvNULL;
    }

    /* Initialize the ISR. */
    device->irqLines[gcvCORE_MAJOR] = IrqLine;
    device->irqLines[gcvCORE_2D]    = IrqLine2D;
    device->irqLines[gcvCORE_VG]    = IrqLineVG;

    /* Initialize the kernel thread semaphores. */
    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
    }

    device->signal = Signal;

    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->kernels[i] != gcvNULL) break;
    }

    if (i == gcdMAX_GPU_COUNT)
	{
		gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
	}

    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckHARDWARE_QuerySystemMemory(
                device->kernels[i]->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));

            /* query the amount of video memory */
        gcmkONERROR(gckHARDWARE_QueryMemory(
            device->kernels[i]->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }


    /* Grab the first availiable kernel */
    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->irqLines[i] != -1)
        {
            kernel = device->kernels[i];
            break;
        }
    }

    /* Set up the internal memory region. */
    if (device->internalSize > 0)
    {
        status = gckVIDMEM_Construct(
            device->os,
            internalBaseAddress, device->internalSize, internalAlignment,
            0, &device->internalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->internalSize = 0;
        }
        else
        {
            /* Map internal memory. */
            device->internalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->internalSize);

            if (device->internalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
            device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
            physical += device->internalSize;
        }
    }

    if (device->externalSize > 0)
    {
        /* create the external memory heap */
        status = gckVIDMEM_Construct(
            device->os,
            externalBaseAddress, device->externalSize, externalAlignment,
            0, &device->externalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->externalSize = 0;
        }
        else
        {
            /* Map external memory. */
            device->externalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->externalSize);

            if (device->externalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
            device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
            physical += device->externalSize;
        }
    }

    /* set up the contiguous memory */
    device->contiguousSize = ContiguousSize;

    if (ContiguousSize > 0)
    {
        if (ContiguousBase == 0)
        {
            while (device->contiguousSize > 0)
            {
                /* Allocate contiguous memory. */
                status = _AllocateMemory(
                    device,
                    device->contiguousSize,
                    &device->contiguousBase,
                    &device->contiguousPhysical,
                    &physAddr
                    );

                if (gcmIS_SUCCESS(status))
                {
                    device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
                    status = gckVIDMEM_Construct(
                        device->os,
                        physAddr | device->systemMemoryBaseAddress,
                        device->contiguousSize,
                        64,
                        BankSize,
                        &device->contiguousVidMem
                        );

                    if (gcmIS_SUCCESS(status))
                    {
                        break;
                    }

                    gcmkONERROR(_FreeMemory(
                        device,
                        device->contiguousBase,
                        device->contiguousPhysical
                        ));

                    gcmRELEASE_NAME(device->contiguousPhysicalName);
                    device->contiguousBase     = gcvNULL;
                    device->contiguousPhysical = gcvNULL;
                }

                if (device->contiguousSize <= (4 << 20))
                {
                    device->contiguousSize = 0;
                }
                else
                {
                    device->contiguousSize -= (4 << 20);
                }
            }
        }
        else
        {
            /* Create the contiguous memory heap. */
            status = gckVIDMEM_Construct(
                device->os,
                ContiguousBase | device->systemMemoryBaseAddress,
                ContiguousSize,
                64, BankSize,
                &device->contiguousVidMem
                );

            if (gcmIS_ERROR(status))
            {
                /* Error, disable contiguous memory pool. */
                device->contiguousVidMem = gcvNULL;
                device->contiguousSize   = 0;
            }
            else
            {
                mem_region = request_mem_region(
                    ContiguousBase, ContiguousSize, "galcore managed memory"
                    );

                if (mem_region == gcvNULL)
                {
                    gcmkTRACE_ZONE(
                        gcvLEVEL_ERROR, gcvZONE_DRIVER,
                        "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
                        __FUNCTION__, __LINE__,
                        ContiguousSize, ContiguousBase
                        );

                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                }

                device->requestedContiguousBase  = ContiguousBase;
                device->requestedContiguousSize  = ContiguousSize;


                device->contiguousPhysical = gcvNULL;
                device->contiguousPhysicalName = 0;
                device->contiguousSize     = ContiguousSize;
                device->contiguousMapped   = gcvTRUE;
            }
        }
    }

    /* Return pointer to the device. */
    * Device = device;

    gcmkFOOTER_ARG("*Device=0x%x", * Device);
    return gcvSTATUS_OK;

OnError:
    /* Roll back. */
    gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));

    gcmkFOOTER();
    return status;
}