/*******************************************************************************
**
**	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;
}
/* echo xx > /proc/driver/gc set ... */
static ssize_t gc_proc_write(struct file *file,
		const char *buff, size_t len, loff_t *off)
{
    char messages[256];

	if(len > 256)
		len = 256;

	if(copy_from_user(messages, buff, len))
		return -EFAULT;

    printk("\n");
    if(strncmp(messages, "printPID", 8) == 0)
    {
        galDevice->printPID = galDevice->printPID ? gcvFALSE : gcvTRUE;
        printk("==>Change printPID to %s\n", galDevice->printPID ? "gcvTRUE" : "gcvFALSE");
    }
    else if(strncmp(messages, "profile", 7) == 0)
    {
        gctUINT32 idleTime, timeSlice;
        gctUINT32 start,end;
        timeSlice = 10000;
        start = gckOS_GetTicks();
        gckOS_IdleProfile(galDevice->os, &timeSlice, &idleTime);
        end = gckOS_GetTicks();

        printk("idle:total [%d, %d]\n", idleTime, timeSlice);
        printk("profile cost %d\n", end - start);
    }
    else if(strncmp(messages, "hang", 4) == 0)
    {
		galDevice->kernel->hardware->hang = galDevice->kernel->hardware->hang ? gcvFALSE : gcvTRUE;
    }
    else if(strncmp(messages, "reset", 5) == 0)
    {
        galDevice->reset = galDevice->reset ? gcvFALSE : gcvTRUE;
    }
#ifdef CONFIG_PXA_DVFM
    else if(strncmp(messages, "d2debug", 7) == 0)
    {
        galDevice->needD2DebugInfo = galDevice->needD2DebugInfo ? gcvFALSE : gcvTRUE;
    }
    else if(strncmp(messages, "D1", 2) == 0)
    {
        galDevice->enableD1 = galDevice->enableD1 ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "D2", 2) == 0)
    {
        galDevice->enableD2 = galDevice->enableD2 ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "D0", 2) == 0)
    {
        galDevice->enableD0CS= galDevice->enableD0CS ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "CG", 2) == 0)
    {
        galDevice->enableCG= galDevice->enableCG ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "needreset", 9) == 0)
    {
        galDevice->needResetAfterD2 = galDevice->needResetAfterD2 ? gcvFALSE : gcvTRUE;
    }
#endif
    else if(strncmp(messages, "su", 2) == 0)
    {
        gceSTATUS status;

        if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_OFF)
        {
            status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
            if (gcmIS_ERROR(status))
            {
                return -1;
            }

            gckOS_SuspendInterrupt(galDevice->os);
            gckOS_ClockOff();
        }
    }
    else if(strncmp(messages, "re", 2) == 0)
    {
        gceSTATUS status;

        if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_ON)
        {
            gckOS_ClockOn(0);
            gckOS_ResumeInterrupt(galDevice->os);

            status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}
        }
    }
    else if(strncmp(messages, "stress", 6) == 0)
    {
        int i;
         /* struct vmalloc_info vmi; */

     /* {get_vmalloc_info(&vmi);printk("%s,%d,VmallocUsed: %8lu kB\n",__func__,__LINE__,vmi.used >> 10); } */

#ifdef _DEBUG
	gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
	gckOS_SetDebugZone(1023);
#endif

        for(i=0;i<20000;i++)
        {
            gceSTATUS status;
            static int count = 0;

            printk("count:%d\n",count++);
            printk("!!!\t");
            if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_OFF)
            {
                status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}

                gckOS_SuspendInterrupt(galDevice->os);
                gckOS_ClockOff();

            }
            printk("@@@\t");
            if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_ON)
            {
                gckOS_ClockOn(0);
                gckOS_ResumeInterrupt(galDevice->os);

                status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}
            }
            printk("###\n");
        }

    }
    else if(strncmp(messages, "debug", 5) == 0)
    {
#ifdef _DEBUG
        static int count = 0;

        if(count%2 == 0)
        {
		gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
		gckOS_SetDebugZone(1023);
        }
        else
        {
            gckOS_SetDebugLevel(gcvLEVEL_NONE);
		gckOS_SetDebugZone(0);
        }
        count++;
#endif
    }
    else if(strncmp(messages, "16", 2) == 0)
    {
		printk("frequency change to 1/16\n");
        /* frequency change to 1/16 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x210));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x010));

    }
    else if(strncmp(messages, "32", 2) == 0)
    {
		printk("frequency change to 1/32\n");
        /* frequency change to 1/32*/
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x208));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x008));

    }
	else if(strncmp(messages, "64", 2) == 0)
    {
		printk("frequency change to 1/64\n");
        /* frequency change to 1/64 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x204));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x004));

    }
    else if('1' == messages[0])
    {
        printk("frequency change to full speed\n");
        /* frequency change to full speed */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x300));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x100));

    }
    else if('2' == messages[0])
    {
        printk("frequency change to 1/2\n");
        /* frequency change to 1/2 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x280));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x080));

    }
    else if('4' == messages[0])
    {
        printk("frequency change to 1/4\n");
        /* frequency change to 1/4 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x240));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x040));

    }
    else if('8' == messages[0])
    {
        printk("frequency change to 1/8\n");
        /* frequency change to 1/8 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x220));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x020));

    }
    else
    {
        printk("unknown echo\n");
    }

    return len;
}