/**************************************************************************** * * Copyright (C) 2005 - 2011 by Vivante Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the license, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *****************************************************************************/ #include "gc_hal_kernel_linux.h" #define _GC_OBJ_ZONE gcvZONE_KERNEL /******************************************************************************\ ******************************* gckKERNEL API Code ****************************** \******************************************************************************/ /******************************************************************************* ** ** gckKERNEL_QueryVideoMemory ** ** Query the amount of video memory. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** OUTPUT: ** ** gcsHAL_INTERFACE * Interface ** Pointer to an gcsHAL_INTERFACE structure that will be filled in with ** the memory information. */ gceSTATUS gckKERNEL_QueryVideoMemory( IN gckKERNEL Kernel, OUT gcsHAL_INTERFACE * Interface ) { gckGALDEVICE device; gcmkHEADER_ARG("Kernel=%p", Kernel); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Interface != NULL); /* Extract the pointer to the gckGALDEVICE class. */ device = (gckGALDEVICE) Kernel->context; /* Get internal memory size and physical address. */ Interface->u.QueryVideoMemory.internalSize = device->internalSize; Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysical; /* Get external memory size and physical address. */ Interface->u.QueryVideoMemory.externalSize = device->externalSize; Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysical; /* Get contiguous memory size and physical address. */ Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize; Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysical; /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; } /******************************************************************************* ** ** gckKERNEL_GetVideoMemoryPool ** ** Get the gckVIDMEM object belonging to the specified pool. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gcePOOL Pool ** Pool to query gckVIDMEM object for. ** ** OUTPUT: ** ** gckVIDMEM * VideoMemory ** Pointer to a variable that will hold the pointer to the gckVIDMEM ** object belonging to the requested pool. */ gceSTATUS gckKERNEL_GetVideoMemoryPool( IN gckKERNEL Kernel, IN gcePOOL Pool, OUT gckVIDMEM * VideoMemory ) { gckGALDEVICE device; gckVIDMEM videoMemory; gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(VideoMemory != NULL); /* Extract the pointer to the gckGALDEVICE class. */ device = (gckGALDEVICE) Kernel->context; /* Dispatch on pool. */ switch (Pool) { case gcvPOOL_LOCAL_INTERNAL: /* Internal memory. */ videoMemory = device->internalVidMem; break; case gcvPOOL_LOCAL_EXTERNAL: /* External memory. */ videoMemory = device->externalVidMem; break; case gcvPOOL_SYSTEM: /* System memory. */ videoMemory = device->contiguousVidMem; break; default: /* Unknown pool. */ videoMemory = NULL; } /* Return pointer to the gckVIDMEM object. */ *VideoMemory = videoMemory; /* Return status. */ gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory); return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK; } /******************************************************************************* ** ** gckKERNEL_MapMemory ** ** Map video memory into the current process space. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gctPHYS_ADDR Physical ** Physical address of video memory to map. ** ** gctSIZE_T Bytes ** Number of bytes to map. ** ** OUTPUT: ** ** gctPOINTER * Logical ** Pointer to a variable that will hold the base address of the mapped ** memory region. */ gceSTATUS gckKERNEL_MapMemory( IN gckKERNEL Kernel, IN gctPHYS_ADDR Physical, IN gctSIZE_T Bytes, OUT gctPOINTER * Logical ) { return gckOS_MapMemory(Kernel->os, Physical, Bytes, Logical); } /******************************************************************************* ** ** gckKERNEL_UnmapMemory ** ** Unmap video memory from the current process space. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gctPHYS_ADDR Physical ** Physical address of video memory to map. ** ** gctSIZE_T Bytes ** Number of bytes to map. ** ** gctPOINTER Logical ** Base address of the mapped memory region. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckKERNEL_UnmapMemory( IN gckKERNEL Kernel, IN gctPHYS_ADDR Physical, IN gctSIZE_T Bytes, IN gctPOINTER Logical ) { return gckOS_UnmapMemory(Kernel->os, Physical, Bytes, Logical); } /******************************************************************************* ** ** 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_MapVideoMemoryEx( IN gckKERNEL Kernel, IN gceCORE Core, IN gctBOOL InUserSpace, IN gctUINT32 Address, OUT gctPOINTER * Logical ) { gckGALDEVICE device; PLINUX_MDL mdl; PLINUX_MDL_MAP mdlMap; gcePOOL pool; gctUINT32 offset, base; gceSTATUS status; gctPOINTER logical; gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x", Kernel, InUserSpace, Address); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Logical != NULL); /* Extract the pointer to the gckGALDEVICE class. */ device = (gckGALDEVICE) Kernel->context; #if gcdENABLE_VG if (Core == gcvCORE_VG) { /* Split the memory address into a pool type and offset. */ gcmkONERROR( gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, Address, &pool, &offset)); } else #endif { /* Split the memory address into a pool type and offset. */ gcmkONERROR( gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset)); } /* Dispatch on pool. */ switch (pool) { case gcvPOOL_LOCAL_INTERNAL: /* Internal memory. */ logical = device->internalLogical; break; case gcvPOOL_LOCAL_EXTERNAL: /* External memory. */ logical = device->externalLogical; break; case gcvPOOL_SYSTEM: /* System memory. */ if (device->contiguousMapped) { logical = device->contiguousBase; } else { gctINT processID; gckOS_GetProcessID(&processID); mdl = (PLINUX_MDL) device->contiguousPhysical; mdlMap = FindMdlMap(mdl, processID); gcmkASSERT(mdlMap); logical = (gctPOINTER) mdlMap->vmaAddr; } #if gcdENABLE_VG if (Core == gcvCORE_VG) { gcmkVERIFY_OK( gckVGHARDWARE_SplitMemory(Kernel->vg->hardware, device->contiguousVidMem->baseAddress, &pool, &base)); } else #endif { gcmkVERIFY_OK( gckHARDWARE_SplitMemory(Kernel->hardware, device->contiguousVidMem->baseAddress, &pool, &base)); } offset -= base; break; default: /* Invalid memory pool. */ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT); } /* Build logical address of specified address. */ *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset); /* Success. */ gcmkFOOTER_ARG("*Logical=%p", *Logical); return gcvSTATUS_OK; OnError: /* Retunn the status. */ gcmkFOOTER(); return status; } /******************************************************************************* ** ** 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_Notify ** ** This function iscalled by clients to notify the gckKERNRL object of an event. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** gceNOTIFY Notification ** Notification event. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckKERNEL_Notify( IN gckKERNEL Kernel, IN gceNOTIFY Notification, IN gctBOOL Data ) { gceSTATUS status; gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d", Kernel, Notification, Data); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); /* Dispatch on notifcation. */ switch (Notification) { case gcvNOTIFY_INTERRUPT: /* Process the interrupt. */ #if COMMAND_PROCESSOR_VERSION > 1 status = gckINTERRUPT_Notify(Kernel->interrupt, Data); #else status = gckHARDWARE_Interrupt(Kernel->hardware, Data); #endif break; default: status = gcvSTATUS_OK; break; } /* Success. */ gcmkFOOTER(); return status; } gceSTATUS gckKERNEL_QuerySettings( IN gckKERNEL Kernel, OUT gcsKERNEL_SETTINGS * Settings ) { gckGALDEVICE device; gcmkHEADER_ARG("Kernel=%p", Kernel); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); gcmkVERIFY_ARGUMENT(Settings != gcvNULL); /* Extract the pointer to the gckGALDEVICE class. */ device = (gckGALDEVICE) Kernel->context; /* Fill in signal. */ Settings->signal = device->signal; /* Success. */ gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal); return gcvSTATUS_OK; }