/******************************************************************************* ** ** gckKERNEL_MapVideoMemory ** ** Get the logical address for a hardware specific memory address for the ** current process. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gctBOOL InUserSpace ** gcvTRUE to map the memory into the user space. ** ** gctUINT32 Address ** Hardware specific memory address. ** ** OUTPUT: ** ** gctPOINTER * Logical ** Pointer to a variable that will hold the logical address of the ** specified memory address. */ gceSTATUS gckKERNEL_MapVideoMemory( IN gckKERNEL Kernel, IN gctBOOL InUserSpace, IN gctUINT32 Address, OUT gctPOINTER * Logical ) { return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, Logical); }
/******************************************************************************* ** ** 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; }