/******************************************************************************* ** ** gckKERNEL_Dispatch ** ** Dispatch a command received from the user HAL layer. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gcsHAL_INTERFACE * Interface ** Pointer to a gcsHAL_INTERFACE structure that defines the command to ** be dispatched. ** ** OUTPUT: ** ** gcsHAL_INTERFACE * Interface ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be ** returned. */ gceSTATUS gckVGKERNEL_Dispatch( IN gckKERNEL Kernel, IN gctBOOL FromUser, IN OUT gcsHAL_INTERFACE * Interface ) { gceSTATUS status; gcsHAL_INTERFACE * kernelInterface = Interface; gcuVIDMEM_NODE_PTR node; gctUINT32 processID; gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Interface != gcvNULL); gcmkONERROR(gckOS_GetProcessID(&processID)); /* Dispatch on command. */ switch (Interface->command) { case gcvHAL_QUERY_VIDEO_MEMORY: /* Query video memory size. */ gcmkERR_BREAK(gckKERNEL_QueryVideoMemory( Kernel, kernelInterface )); break; case gcvHAL_QUERY_CHIP_IDENTITY: /* Query chip identity. */ gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity( Kernel->vg->hardware, &kernelInterface->u.QueryChipIdentity.chipModel, &kernelInterface->u.QueryChipIdentity.chipRevision, &kernelInterface->u.QueryChipIdentity.chipFeatures, &kernelInterface->u.QueryChipIdentity.chipMinorFeatures, &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2 )); break; case gcvHAL_QUERY_COMMAND_BUFFER: /* Query command buffer information. */ gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer( Kernel, &kernelInterface->u.QueryCommandBuffer.information )); break; case gcvHAL_ALLOCATE_NON_PAGED_MEMORY: /* Allocate non-paged memory. */ gcmkERR_BREAK(gckOS_AllocateContiguous( Kernel->os, gcvTRUE, &kernelInterface->u.AllocateNonPagedMemory.bytes, &kernelInterface->u.AllocateNonPagedMemory.physical, &kernelInterface->u.AllocateNonPagedMemory.logical )); break; case gcvHAL_FREE_NON_PAGED_MEMORY: /* Unmap user logical out of physical memory first. */ gcmkERR_BREAK(gckOS_UnmapUserLogical( Kernel->os, kernelInterface->u.AllocateNonPagedMemory.physical, kernelInterface->u.AllocateNonPagedMemory.bytes, kernelInterface->u.AllocateNonPagedMemory.logical )); /* Free non-paged memory. */ gcmkERR_BREAK(gckOS_FreeNonPagedMemory( Kernel->os, kernelInterface->u.AllocateNonPagedMemory.bytes, kernelInterface->u.AllocateNonPagedMemory.physical, kernelInterface->u.AllocateNonPagedMemory.logical )); break; case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY: /* Allocate contiguous memory. */ gcmkERR_BREAK(gckOS_AllocateContiguous( Kernel->os, gcvTRUE, &kernelInterface->u.AllocateNonPagedMemory.bytes, &kernelInterface->u.AllocateNonPagedMemory.physical, &kernelInterface->u.AllocateNonPagedMemory.logical )); break; case gcvHAL_FREE_CONTIGUOUS_MEMORY: /* Unmap user logical out of physical memory first. */ gcmkERR_BREAK(gckOS_UnmapUserLogical( Kernel->os, kernelInterface->u.AllocateNonPagedMemory.physical, kernelInterface->u.AllocateNonPagedMemory.bytes, kernelInterface->u.AllocateNonPagedMemory.logical )); /* Free contiguous memory. */ gcmkERR_BREAK(gckOS_FreeContiguous( Kernel->os, kernelInterface->u.AllocateNonPagedMemory.physical, kernelInterface->u.AllocateNonPagedMemory.logical, kernelInterface->u.AllocateNonPagedMemory.bytes )); break; case gcvHAL_ALLOCATE_VIDEO_MEMORY: { gctSIZE_T bytes; gctUINT32 bitsPerPixel; gctUINT32 bits; /* Align width and height to tiles. */ gcmkERR_BREAK(gckVGHARDWARE_AlignToTile( Kernel->vg->hardware, kernelInterface->u.AllocateVideoMemory.type, &kernelInterface->u.AllocateVideoMemory.width, &kernelInterface->u.AllocateVideoMemory.height )); /* Convert format into bytes per pixel and bytes per tile. */ gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat( Kernel->vg->hardware, kernelInterface->u.AllocateVideoMemory.format, &bitsPerPixel, gcvNULL )); /* Compute number of bits for the allocation. */ bits = kernelInterface->u.AllocateVideoMemory.width * kernelInterface->u.AllocateVideoMemory.height * kernelInterface->u.AllocateVideoMemory.depth * bitsPerPixel; /* Compute number of bytes for the allocation. */ bytes = gcmALIGN(bits, 8) / 8; /* Allocate memory. */ gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory( Kernel, &kernelInterface->u.AllocateVideoMemory.pool, bytes, 64, kernelInterface->u.AllocateVideoMemory.type, &kernelInterface->u.AllocateVideoMemory.node )); } break; case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY: /* Allocate memory. */ gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory( Kernel, &kernelInterface->u.AllocateLinearVideoMemory.pool, kernelInterface->u.AllocateLinearVideoMemory.bytes, kernelInterface->u.AllocateLinearVideoMemory.alignment, kernelInterface->u.AllocateLinearVideoMemory.type, &kernelInterface->u.AllocateLinearVideoMemory.node )); gcmkERR_BREAK(gckKERNEL_AddProcessDB(Kernel, processID, gcvDB_VIDEO_MEMORY, Interface->u.AllocateLinearVideoMemory.node, gcvNULL, kernelInterface->u.AllocateLinearVideoMemory.bytes )); break; case gcvHAL_FREE_VIDEO_MEMORY: #ifdef __QNXNTO__ /* Unmap the video memory */ node = Interface->u.FreeVideoMemory.node; if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM) && (node->VidMem.logical != gcvNULL)) { gckKERNEL_UnmapVideoMemory(Kernel, node->VidMem.logical, processID, node->VidMem.bytes); node->VidMem.logical = gcvNULL; } #endif /* __QNXNTO__ */ /* Free video memory. */ gcmkERR_BREAK(gckVIDMEM_Free( Interface->u.FreeVideoMemory.node )); gcmkERR_BREAK(gckKERNEL_RemoveProcessDB( Kernel, processID, gcvDB_VIDEO_MEMORY, Interface->u.FreeVideoMemory.node )); break; case gcvHAL_MAP_MEMORY: /* Map memory. */ gcmkERR_BREAK(gckKERNEL_MapMemory( Kernel, kernelInterface->u.MapMemory.physical, kernelInterface->u.MapMemory.bytes, &kernelInterface->u.MapMemory.logical )); break; case gcvHAL_UNMAP_MEMORY: /* Unmap memory. */ gcmkERR_BREAK(gckKERNEL_UnmapMemory( Kernel, kernelInterface->u.MapMemory.physical, kernelInterface->u.MapMemory.bytes, kernelInterface->u.MapMemory.logical )); break; case gcvHAL_MAP_USER_MEMORY: /* Map user memory to DMA. */ gcmkERR_BREAK(gckOS_MapUserMemory( Kernel->os, gcvCORE_VG, kernelInterface->u.MapUserMemory.memory, kernelInterface->u.MapUserMemory.physical, kernelInterface->u.MapUserMemory.size, &kernelInterface->u.MapUserMemory.info, &kernelInterface->u.MapUserMemory.address )); break; case gcvHAL_UNMAP_USER_MEMORY: /* Unmap user memory. */ gcmkERR_BREAK(gckOS_UnmapUserMemory( Kernel->os, gcvCORE_VG, kernelInterface->u.UnmapUserMemory.memory, kernelInterface->u.UnmapUserMemory.size, kernelInterface->u.UnmapUserMemory.info, kernelInterface->u.UnmapUserMemory.address )); break; case gcvHAL_LOCK_VIDEO_MEMORY: /* Lock video memory. */ gcmkERR_BREAK( gckVIDMEM_Lock(Kernel, Interface->u.LockVideoMemory.node, gcvFALSE, &Interface->u.LockVideoMemory.address)); node = Interface->u.LockVideoMemory.node; if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) { /* Map video memory address into user space. */ #ifdef __QNXNTO__ if (node->VidMem.logical == gcvNULL) { gcmkONERROR( gckKERNEL_MapVideoMemory(Kernel, FromUser, Interface->u.LockVideoMemory.address, processID, node->VidMem.bytes, &node->VidMem.logical)); } Interface->u.LockVideoMemory.memory = node->VidMem.logical; #else gcmkERR_BREAK( gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_VG, FromUser, Interface->u.LockVideoMemory.address, &Interface->u.LockVideoMemory.memory)); #endif } else { Interface->u.LockVideoMemory.memory = node->Virtual.logical; /* Success. */ status = gcvSTATUS_OK; } #if gcdSECURE_USER /* Return logical address as physical address. */ Interface->u.LockVideoMemory.address = gcmPTR2INT(Interface->u.LockVideoMemory.memory); #endif gcmkERR_BREAK( gckKERNEL_AddProcessDB(Kernel, processID, gcvDB_VIDEO_MEMORY_LOCKED, Interface->u.LockVideoMemory.node, gcvNULL, 0)); break; case gcvHAL_UNLOCK_VIDEO_MEMORY: /* Unlock video memory. */ node = Interface->u.UnlockVideoMemory.node; #if gcdSECURE_USER /* Save node information before it disappears. */ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM) { logical = gcvNULL; bytes = 0; } else { logical = node->Virtual.logical; bytes = node->Virtual.bytes; } #endif /* Unlock video memory. */ gcmkERR_BREAK( gckVIDMEM_Unlock(Kernel, node, Interface->u.UnlockVideoMemory.type, &Interface->u.UnlockVideoMemory.asynchroneous, gcvFALSE)); #if gcdSECURE_USER /* Flush the translation cache for virtual surfaces. */ if (logical != gcvNULL) { gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel, cache, logical, bytes)); } #endif if (Interface->u.UnlockVideoMemory.asynchroneous == gcvFALSE) { /* There isn't a event to unlock this node, remove record now */ gcmkERR_BREAK( gckKERNEL_RemoveProcessDB(Kernel, processID, gcvDB_VIDEO_MEMORY_LOCKED, Interface->u.UnlockVideoMemory.node)); } break; case gcvHAL_USER_SIGNAL: #if !USE_NEW_LINUX_SIGNAL /* Dispatch depends on the user signal subcommands. */ switch(Interface->u.UserSignal.command) { case gcvUSER_SIGNAL_CREATE: /* Create a signal used in the user space. */ gcmkERR_BREAK( gckOS_CreateUserSignal(Kernel->os, Interface->u.UserSignal.manualReset, &Interface->u.UserSignal.id)); gcmkVERIFY_OK( gckKERNEL_AddProcessDB(Kernel, processID, gcvDB_SIGNAL, gcmINT2PTR(Interface->u.UserSignal.id), gcvNULL, 0)); break; case gcvUSER_SIGNAL_DESTROY: /* Destroy the signal. */ gcmkERR_BREAK( gckOS_DestroyUserSignal(Kernel->os, Interface->u.UserSignal.id)); gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB( Kernel, processID, gcvDB_SIGNAL, gcmINT2PTR(Interface->u.UserSignal.id))); break; case gcvUSER_SIGNAL_SIGNAL: /* Signal the signal. */ gcmkERR_BREAK( gckOS_SignalUserSignal(Kernel->os, Interface->u.UserSignal.id, Interface->u.UserSignal.state)); break; case gcvUSER_SIGNAL_WAIT: /* Wait on the signal. */ status = gckOS_WaitUserSignal(Kernel->os, Interface->u.UserSignal.id, Interface->u.UserSignal.wait); break; default: /* Invalid user signal command. */ gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT); } #endif break; case gcvHAL_COMMIT: /* Commit a command and context buffer. */ gcmkERR_BREAK(gckVGCOMMAND_Commit( Kernel->vg->command, kernelInterface->u.VGCommit.context, kernelInterface->u.VGCommit.queue, kernelInterface->u.VGCommit.entryCount, kernelInterface->u.VGCommit.taskTable )); break; case gcvHAL_VERSION: kernelInterface->u.Version.major = gcvVERSION_MAJOR; kernelInterface->u.Version.minor = gcvVERSION_MINOR; kernelInterface->u.Version.patch = gcvVERSION_PATCH; kernelInterface->u.Version.build = gcvVERSION_BUILD; status = gcvSTATUS_OK; break; case gcvHAL_GET_BASE_ADDRESS: /* Get base address. */ gcmkERR_BREAK( gckOS_GetBaseAddress(Kernel->os, &kernelInterface->u.GetBaseAddress.baseAddress)); break; default: /* Invalid command. */ status = gcvSTATUS_INVALID_ARGUMENT; } OnError: /* Save status. */ kernelInterface->status = status; gcmkFOOTER(); /* Return the status. */ return status; }
int drv_release( struct inode* inode, struct file* filp ) { gceSTATUS status = gcvSTATUS_OK; gcsHAL_PRIVATE_DATA_PTR data = gcvNULL; gckGALDEVICE device; gctINT i; gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp); if (filp == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): filp is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } data = filp->private_data; if (data == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): private_data is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } device = data->device; if (device == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): device is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } if (!device->contiguousMapped) { if (data->contiguousLogical != gcvNULL) { gcmkONERROR(gckOS_UnmapMemoryEx( galDevice->os, galDevice->contiguousPhysical, galDevice->contiguousSize, data->contiguousLogical, data->pidOpen )); for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { gcmkVERIFY_OK( gckKERNEL_RemoveProcessDB(galDevice->kernels[i], data->pidOpen, gcvDB_MAP_MEMORY, data->contiguousLogical)); } } data->contiguousLogical = gcvNULL; } } /* A process gets detached. */ gcmkPRINT("Process %d released (%s)\n", data->pidOpen, _GC_VERSION_STRING_); for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { /*gcmkONERROR(gckKERNEL_ShowProcessMemUsage(galDevice->kernels[i], data->pidOpen));*/ gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen)); } } kfree(data); filp->private_data = gcvNULL; /* Print memory information _gc_gather_infomation(buf, &len); printk("%s", buf);*/ /* Success. */ gcmkFOOTER_NO(); return 0; OnError: if(data!=gcvNULL) { kfree(data); filp->private_data = gcvNULL; } gcmkFOOTER(); return -ENOTTY; }
int drv_release( struct inode* inode, struct file* filp ) { gceSTATUS status; gcsHAL_PRIVATE_DATA_PTR data; gckGALDEVICE device; gctINT i; gctUINT32 processID; gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp); if (filp == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): filp is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } data = filp->private_data; if (data == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): private_data is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } device = data->device; if (device == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): device is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } if (!device->contiguousMapped) { if (data->contiguousLogical != gcvNULL) { gcmkVERIFY_OK(gckOS_GetProcessID(&processID)); gcmkONERROR(gckOS_UnmapMemoryEx( galDevice->os, galDevice->contiguousPhysical, galDevice->contiguousSize, data->contiguousLogical, data->pidOpen )); for (i = 0; i < gcdCORE_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { gcmkVERIFY_OK( gckKERNEL_RemoveProcessDB(galDevice->kernels[i], processID, gcvDB_MAP_MEMORY, data->contiguousLogical)); } } data->contiguousLogical = gcvNULL; } } /* Clean user signals if exit unnormally. */ gcmkVERIFY_OK(gckOS_GetProcessID(&processID)); gcmkVERIFY_OK(gckOS_CleanProcessSignal(galDevice->os, (gctHANDLE)processID)); /* A process gets detached. */ for (i = 0; i < gcdCORE_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen)); } } kfree(data); filp->private_data = NULL; /* Success. */ gcmkFOOTER_NO(); return 0; OnError: gcmkFOOTER(); return -ENOTTY; }
int drv_open( struct inode* inode, struct file* filp ) { gceSTATUS status = gcvSTATUS_OK; gctBOOL attached = gcvFALSE; gcsHAL_PRIVATE_DATA_PTR data = gcvNULL; gctINT i; gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp); if (filp == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): filp is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN); if (data == gcvNULL) { gcmkTRACE_ZONE( gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): private_data is NULL\n", __FUNCTION__, __LINE__ ); gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY); } data->device = galDevice; data->mappedMemory = gcvNULL; data->contiguousLogical = gcvNULL; gcmkONERROR(gckOS_GetProcessID(&data->pidOpen)); /* Attached the process. */ for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE)); } } attached = gcvTRUE; if (!galDevice->contiguousMapped) { gcmkONERROR(gckOS_MapMemory( galDevice->os, galDevice->contiguousPhysical, galDevice->contiguousSize, &data->contiguousLogical )); for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { gcmkVERIFY_OK(gckKERNEL_AddProcessDB( galDevice->kernels[i], data->pidOpen, gcvDB_MAP_MEMORY, data->contiguousLogical, galDevice->contiguousPhysical, galDevice->contiguousSize)); } } } filp->private_data = data; /* Success. */ gcmkFOOTER_NO(); return 0; OnError: if (data != gcvNULL) { if (data->contiguousLogical != gcvNULL) { gcmkVERIFY_OK(gckOS_UnmapMemory( galDevice->os, galDevice->contiguousPhysical, galDevice->contiguousSize, data->contiguousLogical )); for(i = 0; i < gcdMAX_GPU_COUNT; i++) { gcmkVERIFY_OK( gckKERNEL_RemoveProcessDB(galDevice->kernels[i], data->pidOpen, gcvDB_MAP_MEMORY, data->contiguousLogical)); } } kfree(data); data = gcvNULL; } if (attached) { for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (galDevice->kernels[i] != gcvNULL) { gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE)); } } } gcmkFOOTER(); return -ENOTTY; }