/******************************************************************************* ** ** 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; } } }
/******************************************************************************* ** ** 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; }