gceSTATUS _power_off_gc(gckGALDEVICE device, gctBOOL early_suspend) { /* turn off gc */ if (device->kernel->hardware->chipPowerState != gcvPOWER_OFF) { gceSTATUS status; gckCOMMAND command; command = device->kernel->command; printk("[%s]\t@%d\tC:0x%p\tQ:0x%p\n", __func__, __LINE__, command->mutexContext, command->mutexQueue); // stall { /* Acquire the context switching mutex so nothing else can be committed. */ #if MUTEX_CONTEXT gcmkONERROR( gckOS_AcquireMutex(device->kernel->hardware->os, command->mutexContext, gcvINFINITE)); #endif if (gcvTRUE == early_suspend) { gcmkONERROR( gckCOMMAND_Stall(command)); } } // stop { /* Stop the command parser. */ gcmkONERROR( gckCOMMAND_Stop(command)); #if MUTEX_QUEUE /* Grab the command queue mutex so nothing can get access to the command queue. */ gcmkONERROR( gckOS_AcquireMutex(device->kernel->hardware->os, command->mutexQueue, gcvINFINITE)); #endif } // disable irq and clock { gckOS_SuspendInterrupt(device->os); gckOS_ClockOff(); } galDevice->kernel->hardware->chipPowerState = gcvPOWER_OFF; } return gcvSTATUS_OK; OnError: printk("ERROR: %s has error \n",__func__); return gcvSTATUS_OK; }
/******************************************************************************* ** ** gckKERNEL_Dispatch ** ** Dispatch a command received from the user HAL layer. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gctBOOL FromUser ** whether the call is from the user space. ** ** 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 gckKERNEL_Dispatch( IN gckKERNEL Kernel, IN gctBOOL FromUser, IN OUT gcsHAL_INTERFACE * Interface ) { gceSTATUS status; gctUINT32 bitsPerPixel; gctSIZE_T bytes; gcuVIDMEM_NODE_PTR node; gctBOOL locked = gcvFALSE; gctPHYS_ADDR physical; gctUINT32 address; gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x", Kernel, FromUser, Interface); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Interface != gcvNULL); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL, "Dispatching command %d", Interface->command); /* Dispatch on command. */ switch (Interface->command) { case gcvHAL_GET_BASE_ADDRESS: /* Get base address. */ gcmkONERROR( gckOS_GetBaseAddress(Kernel->os, &Interface->u.GetBaseAddress.baseAddress)); break; case gcvHAL_QUERY_VIDEO_MEMORY: /* Query video memory size. */ gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface)); break; case gcvHAL_QUERY_CHIP_IDENTITY: /* Query chip identity. */ gcmkONERROR( gckHARDWARE_QueryChipIdentity( Kernel->hardware, &Interface->u.QueryChipIdentity.chipModel, &Interface->u.QueryChipIdentity.chipRevision, &Interface->u.QueryChipIdentity.chipFeatures, &Interface->u.QueryChipIdentity.chipMinorFeatures, &Interface->u.QueryChipIdentity.chipMinorFeatures1)); /* Query chip specifications. */ gcmkONERROR( gckHARDWARE_QueryChipSpecs( Kernel->hardware, &Interface->u.QueryChipIdentity.streamCount, &Interface->u.QueryChipIdentity.registerMax, &Interface->u.QueryChipIdentity.threadCount, &Interface->u.QueryChipIdentity.shaderCoreCount, &Interface->u.QueryChipIdentity.vertexCacheSize, &Interface->u.QueryChipIdentity.vertexOutputBufferSize)); break; case gcvHAL_MAP_MEMORY: physical = Interface->u.MapMemory.physical; /* Map memory. */ gcmkONERROR( gckKERNEL_MapMemory(Kernel, physical, Interface->u.MapMemory.bytes, &Interface->u.MapMemory.logical)); break; case gcvHAL_UNMAP_MEMORY: physical = Interface->u.UnmapMemory.physical; /* Unmap memory. */ gcmkONERROR( gckKERNEL_UnmapMemory(Kernel, physical, Interface->u.UnmapMemory.bytes, Interface->u.UnmapMemory.logical)); break; case gcvHAL_ALLOCATE_NON_PAGED_MEMORY: /* Allocate non-paged memory. */ #ifdef __QNXNTO__ if (FromUser) { gcmkONERROR( gckOS_AllocateNonPagedMemoryShmPool( Kernel->os, FromUser, Interface->pid, Interface->handle, &Interface->u.AllocateNonPagedMemory.bytes, &Interface->u.AllocateNonPagedMemory.physical, &Interface->u.AllocateNonPagedMemory.logical)); break; } #endif gcmkONERROR( gckOS_AllocateNonPagedMemory( Kernel->os, FromUser, &Interface->u.AllocateNonPagedMemory.bytes, &Interface->u.AllocateNonPagedMemory.physical, &Interface->u.AllocateNonPagedMemory.logical)); break; case gcvHAL_FREE_NON_PAGED_MEMORY: physical = Interface->u.FreeNonPagedMemory.physical; /* Free non-paged memory. */ gcmkONERROR( gckOS_FreeNonPagedMemory(Kernel->os, Interface->u.FreeNonPagedMemory.bytes, physical, Interface->u.FreeNonPagedMemory.logical)); break; case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY: /* Allocate contiguous memory. */ #ifdef __QNXNTO__ if (FromUser) { gcmkONERROR( gckOS_AllocateNonPagedMemoryShmPool( Kernel->os, FromUser, Interface->pid, Interface->handle, &Interface->u.AllocateNonPagedMemory.bytes, &Interface->u.AllocateNonPagedMemory.physical, &Interface->u.AllocateNonPagedMemory.logical)); break; } #endif gcmkONERROR( gckOS_AllocateContiguous( Kernel->os, FromUser, &Interface->u.AllocateContiguousMemory.bytes, &Interface->u.AllocateContiguousMemory.physical, &Interface->u.AllocateContiguousMemory.logical)); break; case gcvHAL_FREE_CONTIGUOUS_MEMORY: physical = Interface->u.FreeContiguousMemory.physical; /* Free contiguous memory. */ gcmkONERROR( gckOS_FreeContiguous(Kernel->os, physical, Interface->u.FreeContiguousMemory.logical, Interface->u.FreeContiguousMemory.bytes)); break; case gcvHAL_ALLOCATE_VIDEO_MEMORY: /* Align width and height to tiles. */ gcmkONERROR( gckHARDWARE_AlignToTile(Kernel->hardware, Interface->u.AllocateVideoMemory.type, &Interface->u.AllocateVideoMemory.width, &Interface->u.AllocateVideoMemory.height, gcvNULL)); /* Convert format into bytes per pixel and bytes per tile. */ gcmkONERROR( gckHARDWARE_ConvertFormat(Kernel->hardware, Interface->u.AllocateVideoMemory.format, &bitsPerPixel, gcvNULL)); /* Compute number of bytes for the allocation. */ bytes = Interface->u.AllocateVideoMemory.width * bitsPerPixel * Interface->u.AllocateVideoMemory.height * Interface->u.AllocateVideoMemory.depth / 8; /* Allocate memory. */ #ifdef __QNXNTO__ gcmkONERROR( _AllocateMemory(Kernel, &Interface->u.AllocateVideoMemory.pool, bytes, 64, Interface->u.AllocateVideoMemory.type, Interface->handle, &Interface->u.AllocateVideoMemory.node)); #else gcmkONERROR( _AllocateMemory(Kernel, &Interface->u.AllocateVideoMemory.pool, bytes, 64, Interface->u.AllocateVideoMemory.type, &Interface->u.AllocateVideoMemory.node)); #endif break; case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY: /* Allocate memory. */ #ifdef __QNXNTO__ gcmkONERROR( _AllocateMemory(Kernel, &Interface->u.AllocateLinearVideoMemory.pool, Interface->u.AllocateLinearVideoMemory.bytes, Interface->u.AllocateLinearVideoMemory.alignment, Interface->u.AllocateLinearVideoMemory.type, Interface->handle, &Interface->u.AllocateLinearVideoMemory.node)); /* Set the current user pid in the node, * which is used while locking memory. */ gcmkVERIFY_OK(gckVIDMEM_SetPID( Interface->u.AllocateLinearVideoMemory.node, Interface->pid)); #else gcmkONERROR( _AllocateMemory(Kernel, &Interface->u.AllocateLinearVideoMemory.pool, Interface->u.AllocateLinearVideoMemory.bytes, Interface->u.AllocateLinearVideoMemory.alignment, Interface->u.AllocateLinearVideoMemory.type, &Interface->u.AllocateLinearVideoMemory.node)); #endif break; case gcvHAL_FREE_VIDEO_MEMORY: #ifdef __QNXNTO__ node = Interface->u.FreeVideoMemory.node; if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM && node->VidMem.logical != gcvNULL) { gcmkONERROR( gckKERNEL_UnmapVideoMemory(Kernel, node->VidMem.logical, Interface->pid, node->VidMem.bytes)); node->VidMem.logical = gcvNULL; } #endif /* Free video memory. */ gcmkONERROR( gckVIDMEM_Free(Interface->u.FreeVideoMemory.node)); break; case gcvHAL_LOCK_VIDEO_MEMORY: /* Lock video memory. */ gcmkONERROR( gckVIDMEM_Lock(Interface->u.LockVideoMemory.node, &Interface->u.LockVideoMemory.address)); locked = gcvTRUE; 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, Interface->pid, node->VidMem.bytes, &node->VidMem.logical)); } Interface->u.LockVideoMemory.memory = node->VidMem.logical; #else gcmkONERROR( gckKERNEL_MapVideoMemory(Kernel, FromUser, Interface->u.LockVideoMemory.address, &Interface->u.LockVideoMemory.memory)); #endif #ifdef __QNXNTO__ /* Add more information to node, which is used while unmapping. */ gcmkVERIFY_OK(gckVIDMEM_SetPID( Interface->u.LockVideoMemory.node, Interface->pid)); #endif } else { /* Copy logical memory for virtual memory. */ 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 break; case gcvHAL_UNLOCK_VIDEO_MEMORY: /* Unlock video memory. */ node = Interface->u.UnlockVideoMemory.node; /* Unlock video memory. */ gcmkONERROR( gckVIDMEM_Unlock(node, Interface->u.UnlockVideoMemory.type, &Interface->u.UnlockVideoMemory.asynchroneous)); break; case gcvHAL_EVENT_COMMIT: /* Commit an event queue. */ gcmkONERROR( gckEVENT_Commit(Kernel->event, Interface->u.Event.queue)); break; case gcvHAL_COMMIT: /* Commit a command and context buffer. */ gcmkONERROR( gckCOMMAND_Commit(Kernel->command, Interface->u.Commit.commandBuffer, Interface->u.Commit.contextBuffer, Interface->u.Commit.process)); break; case gcvHAL_STALL: /* Stall the command queue. */ gcmkONERROR(gckCOMMAND_Stall(Kernel->command)); break; case gcvHAL_MAP_USER_MEMORY: /* Map user memory to DMA. */ gcmkONERROR( gckOS_MapUserMemory(Kernel->os, Interface->u.MapUserMemory.memory, Interface->u.MapUserMemory.size, &Interface->u.MapUserMemory.info, &Interface->u.MapUserMemory.address)); break; case gcvHAL_UNMAP_USER_MEMORY: address = Interface->u.MapUserMemory.address; /* Unmap user memory. */ gcmkONERROR( gckOS_UnmapUserMemory(Kernel->os, Interface->u.UnmapUserMemory.memory, Interface->u.UnmapUserMemory.size, Interface->u.UnmapUserMemory.info, address)); break; #if !USE_NEW_LINUX_SIGNAL case gcvHAL_USER_SIGNAL: gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL, "Dispatching gcvHAL_USER_SIGNAL %d", Interface->u.UserSignal.command); /* Dispatch depends on the user signal subcommands. */ switch(Interface->u.UserSignal.command) { case gcvUSER_SIGNAL_CREATE: /* Create a signal used in the user space. */ gcmkONERROR( gckOS_CreateUserSignal(Kernel->os, Interface->u.UserSignal.manualReset, Interface->u.UserSignal.signalType, &Interface->u.UserSignal.id)); break; case gcvUSER_SIGNAL_DESTROY: /* Destroy the signal. */ gcmkONERROR( gckOS_DestroyUserSignal(Kernel->os, Interface->u.UserSignal.id)); break; case gcvUSER_SIGNAL_SIGNAL: /* Signal the signal. */ gcmkONERROR( 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. */ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } break; #endif case gcvHAL_SET_POWER_MANAGEMENT_STATE: /* Set the power management state. */ gcmkONERROR( gckHARDWARE_SetPowerManagementState( Kernel->hardware, Interface->u.SetPowerManagement.state)); break; case gcvHAL_QUERY_POWER_MANAGEMENT_STATE: /* Chip is not idle. */ Interface->u.QueryPowerManagement.isIdle = gcvFALSE; /* Query the power management state. */ gcmkONERROR(gckHARDWARE_QueryPowerManagementState( Kernel->hardware, &Interface->u.QueryPowerManagement.state)); /* Query the idle state. */ gcmkONERROR( gckHARDWARE_QueryIdle(Kernel->hardware, &Interface->u.QueryPowerManagement.isIdle)); break; case gcvHAL_READ_REGISTER: #if gcdREGISTER_ACCESS_FROM_USER /* Read a register. */ gcmkONERROR( gckOS_ReadRegister(Kernel->os, Interface->u.ReadRegisterData.address, &Interface->u.ReadRegisterData.data)); #else /* No access from user land to read registers. */ Interface->u.ReadRegisterData.data = 0; status = gcvSTATUS_NOT_SUPPORTED; #endif break; case gcvHAL_WRITE_REGISTER: #if gcdREGISTER_ACCESS_FROM_USER /* Write a register. */ gcmkONERROR( gckOS_WriteRegister(Kernel->os, Interface->u.WriteRegisterData.address, Interface->u.WriteRegisterData.data)); #else /* No access from user land to write registers. */ status = gcvSTATUS_NOT_SUPPORTED; #endif break; case gcvHAL_READ_ALL_PROFILE_REGISTERS: #if VIVANTE_PROFILER /* Read all 3D profile registers. */ gcmkONERROR( gckHARDWARE_QueryProfileRegisters( Kernel->hardware, &Interface->u.RegisterProfileData.counters)); #else status = gcvSTATUS_OK; #endif break; case gcvHAL_PROFILE_REGISTERS_2D: #if VIVANTE_PROFILER /* Read all 2D profile registers. */ gcmkONERROR( gckHARDWARE_ProfileEngine2D( Kernel->hardware, Interface->u.RegisterProfileData2D.hwProfile2D)); #else status = gcvSTATUS_OK; #endif break; case gcvHAL_GET_PROFILE_SETTING: #if VIVANTE_PROFILER /* Get profile setting */ Interface->u.GetProfileSetting.enable = Kernel->profileEnable; gcmkVERIFY_OK( gckOS_MemCopy(Interface->u.GetProfileSetting.fileName, Kernel->profileFileName, gcdMAX_PROFILE_FILE_NAME)); #endif status = gcvSTATUS_OK; break; case gcvHAL_SET_PROFILE_SETTING: #if VIVANTE_PROFILER /* Set profile setting */ Kernel->profileEnable = Interface->u.SetProfileSetting.enable; gcmkVERIFY_OK( gckOS_MemCopy(Kernel->profileFileName, Interface->u.SetProfileSetting.fileName, gcdMAX_PROFILE_FILE_NAME)); #endif status = gcvSTATUS_OK; break; case gcvHAL_QUERY_KERNEL_SETTINGS: /* Get kernel settings. */ gcmkONERROR( gckKERNEL_QuerySettings(Kernel, &Interface->u.QueryKernelSettings.settings)); break; case gcvHAL_RESET: /* Reset the hardware. */ gcmkONERROR( gckHARDWARE_Reset(Kernel->hardware)); break; case gcvHAL_DEBUG: /* Set debug level and zones. */ if (Interface->u.Debug.set) { gckOS_SetDebugLevel(Interface->u.Debug.level); gckOS_SetDebugZones(Interface->u.Debug.zones, Interface->u.Debug.enable); } if (Interface->u.Debug.message[0] != '\0') { /* Print a message to the debugger. */ gcmkPRINT(Interface->u.Debug.message); } status = gcvSTATUS_OK; break; case gcvHAL_CACHE: if (Interface->u.Cache.invalidate) { /* Flush and invalidate the cache. */ status = gckOS_CacheInvalidate(Kernel->os, Interface->u.Cache.process, Interface->u.Cache.logical, Interface->u.Cache.bytes); } else { /* Flush the cache. */ status = gckOS_CacheFlush(Kernel->os, Interface->u.Cache.process, Interface->u.Cache.logical, Interface->u.Cache.bytes); } break; default: /* Invalid command. */ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } OnError: /* Save status. */ Interface->status = status; if (gcmIS_ERROR(status)) { if (locked) { /* Roll back the lock. */ gcmkVERIFY_OK( gckVIDMEM_Unlock(Interface->u.LockVideoMemory.node, gcvSURF_TYPE_UNKNOWN, gcvNULL)); } } /* Return the status. */ gcmkFOOTER(); return status; }