/*************************************************************************/ /*!
@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
@License        Dual MIT/GPLv2

The contents of this file are subject to the MIT license as set out below.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 2 ("GPL") in which case the provisions
of GPL are applicable instead of those above.

If you wish to allow use of your version of this file only under the terms of
GPL, and not to allow others to use your version of this file under the terms
of the MIT license, indicate your decision by deleting the provisions above
and replace them with the notice and other provisions required by GPL as set
out in the file called "GPL-COPYING" included in this distribution. If you do
not delete the provisions above, a recipient may use your version of this file
under the terms of either the MIT license or GPL.

This License is also included in this distribution in the file called
"MIT-COPYING".

EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/

#if !defined(__DC_OSFUNCS_H__)
#define __DC_OSFUNCS_H__

#include "img_types.h"
#include "physheap.h"
#include "kerneldisplay.h"
#include "pvrsrv.h"

#if defined(DEBUG)
#define DC_ASSERT(EXPR)							\
	do								\
	{								\
		if (!(EXPR))						\
		{							\
			DC_OSAbort(__FILE__, __LINE__);			\
		}							\
	} while (0)
#else
#define DC_ASSERT(EXPR) (void)(EXPR) /* Null implementation of ASSERT (does nothing) */
#endif

#define DC_ALIGN(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment) - 1))


/*******************************************************************************
 * DC OS functions
 ******************************************************************************/

/* Services display class function pointers */
typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DEVICE)(DC_DEVICE_FUNCTIONS *psFuncTable, IMG_UINT32 ui32MaxConfigsInFlight, IMG_HANDLE hDeviceData, IMG_HANDLE *phSrvHandle);
typedef void (*PFN_DC_UNREGISTER_DEVICE)(IMG_HANDLE hSrvHandle);
typedef void (*PFN_DC_DISPLAY_CONFIGURATION_RETIRED)(IMG_HANDLE hConfigData);
typedef PVRSRV_ERROR (*PFN_DC_IMPORT_BUFFER_ACQUIRE)(IMG_HANDLE hImport, IMG_DEVMEM_LOG2ALIGN_T uiLog2PageSize, IMG_UINT32 *pui32PageCount, IMG_DEV_PHYADDR **ppasDevPAddr);
typedef void (*PFN_DC_IMPORT_BUFFER_RELEASE)(IMG_HANDLE hImport, IMG_DEV_PHYADDR *pasDevPAddr);

/* Services physical heap function pointers */
typedef PVRSRV_ERROR (*PFN_PHYS_HEAP_ACQUIRE)(IMG_UINT32 ui32PhysHeapID, PHYS_HEAP **ppsPhysHeap);
typedef void (*PFN_PHYS_HEAP_RELEASE)(PHYS_HEAP *psPhysHeap);
typedef PHYS_HEAP_TYPE (*PFN_PHYS_HEAP_GET_TYPE)(PHYS_HEAP *psPhysHeap);
typedef PVRSRV_ERROR (*PFN_PHYS_HEAP_GET_SIZE)(PHYS_HEAP *psPhysHeap, IMG_UINT32 ui32RegionId, IMG_UINT64 *puiSize);
typedef PVRSRV_ERROR (*PFN_PHYS_HEAP_GET_ADDRESS)(PHYS_HEAP *psPhysHeap, IMG_UINT32 ui32RegionId, IMG_CPU_PHYADDR *psCpuPAddr);
typedef void (*PFN_PHYS_HEAP_CPU_PADDR_TO_DEV_PADDR)(PHYS_HEAP *psPhysHeap, IMG_UINT32 ui32NumOfAddr, IMG_DEV_PHYADDR *psDevPAddr, IMG_CPU_PHYADDR *psCpuPAddr);

/* Services system functions */
typedef PVRSRV_ERROR (*PFN_SYS_INSTALL_DEVICE_LISR)(void *pvOSDevice, IMG_UINT32 ui32IRQ, const IMG_CHAR *pszName, PFN_LISR pfnLISR, void *pvData, IMG_HANDLE *phLISRData);
typedef PVRSRV_ERROR (*PFN_SYS_UNINSTALL_DEVICE_LISR)(IMG_HANDLE hLISRData);

/* Other service related functions */
typedef void (*PFN_CHECK_STATUS)(void *hCmdCompCallerHandle);
typedef const IMG_CHAR *(*PFN_GET_ERROR_STRING)(PVRSRV_ERROR eError);

#define DC_OS_BYTES_TO_PAGES(range)	(((range) + (DC_OSGetPageSize() - 1)) >> DC_OSGetPageShift())

typedef struct DC_SERVICES_FUNCS_TAG
{
	/* Display class functions */
	PFN_DC_REGISTER_DEVICE			pfnDCRegisterDevice;
	PFN_DC_UNREGISTER_DEVICE		pfnDCUnregisterDevice;
	PFN_DC_DISPLAY_CONFIGURATION_RETIRED	pfnDCDisplayConfigurationRetired;
	PFN_DC_IMPORT_BUFFER_ACQUIRE		pfnDCImportBufferAcquire;
	PFN_DC_IMPORT_BUFFER_RELEASE		pfnDCImportBufferRelease;

	/* Physical heap functions */
	PFN_PHYS_HEAP_ACQUIRE			pfnPhysHeapAcquire;
	PFN_PHYS_HEAP_RELEASE			pfnPhysHeapRelease;
	PFN_PHYS_HEAP_GET_TYPE			pfnPhysHeapGetType;
	PFN_PHYS_HEAP_GET_SIZE			pfnPhysHeapRegionGetSize;
	PFN_PHYS_HEAP_GET_ADDRESS		pfnPhysHeapRegionGetCpuPAddr;
	PFN_PHYS_HEAP_CPU_PADDR_TO_DEV_PADDR	pfnPhysHeapCpuPAddrToDevPAddr;

	/* System functions */
	PFN_SYS_INSTALL_DEVICE_LISR		pfnSysInstallDeviceLISR;
	PFN_SYS_UNINSTALL_DEVICE_LISR		pfnSysUninstallDeviceLISR;

	/* Other service related functions */
	PFN_CHECK_STATUS		        pfnCheckStatus;
	PFN_GET_ERROR_STRING			pfnGetErrorString;

} DC_SERVICES_FUNCS;

typedef enum
{
	DBGLVL_FATAL = 0,
	DBGLVL_ALERT,
	DBGLVL_ERROR,
	DBGLVL_WARNING,
	DBGLVL_NOTICE,
	DBGLVL_INFO,
	DBGLVL_DEBUG,
} DC_OS_DEBUG_LEVEL;

/* Logging & other misc stuff */
void DC_OSSetDrvName(const IMG_CHAR *pszDrvName);
void DC_OSAbort(const IMG_CHAR *pszFile, IMG_UINT32 ui32Line);

void DC_OSDebugPrintf(DC_OS_DEBUG_LEVEL eDebugLevel, const IMG_CHAR *pszFormat, ...);

IMG_CHAR *DC_OSStringNCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uiLength);

IMG_INT64 DC_OSClockns(void);

/* Memory management */
IMG_UINT32 DC_OSGetPageSize(void);
IMG_UINT32 DC_OSGetPageShift(void);
IMG_UINT32 DC_OSGetPageMask(void);

void *DC_OSAllocMem(size_t uiSize);
void *DC_OSCallocMem(size_t uiSize);
void DC_OSFreeMem(void *pvMem);
void DC_OSMemSet(void *pvDest, IMG_UINT8 ui8Value, size_t uiSize);

IMG_UINT32 DC_OSAddrRangeStart(void *pvDevice, IMG_UINT8 ui8BaseNum);
void *DC_OSRequestAddrRegion(IMG_CPU_PHYADDR sCpuPAddr, IMG_UINT32 ui32Size, IMG_CHAR *pszRequestorName);
void DC_OSReleaseAddrRegion(IMG_CPU_PHYADDR sCpuPAddr, IMG_UINT32 ui32Size);

IMG_CPU_VIRTADDR DC_OSMapPhysAddr(IMG_CPU_PHYADDR sCpuPAddr, IMG_UINT32 ui32Size);
void DC_OSUnmapPhysAddr(IMG_CPU_VIRTADDR pvCpuVAddr, IMG_UINT32 ui32Size);

/* Register access */
IMG_UINT32 DC_OSReadReg32(IMG_CPU_VIRTADDR pvRegCpuVBase, IMG_UINT32 ui32Offset);
void DC_OSWriteReg32(IMG_CPU_VIRTADDR pvRegCpuVBase, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);

/* Floating-point support */
IMG_UINT32 DC_OSDiv64(IMG_UINT64 ui64Numerator, IMG_UINT32 ui32Denominator);
void DC_OSFloatingPointBegin(void);
void DC_OSFloatingPointEnd(void);

/* Inter-thread synchronisation */
PVRSRV_ERROR DC_OSMutexCreate(void **ppvMutex);
void DC_OSMutexDestroy(void *pvMutex);
void DC_OSMutexLock(void *pvMutex);
void DC_OSMutexUnlock(void *pvMutex);

/* Locks that can be held in interrupt handlers */
#if defined(LINUX)
#include <linux/spinlock.h>
typedef spinlock_t DC_SPINLOCK;
# define DC_OSSpinLockCreate(psLock) spin_lock_init(psLock)
# define DC_OSSpinLockDestroy(psLock) /* no need to destroy a spinlock */
/* used outside hardirqs */
# define DC_OSSpinLockIRQSave(psLock, ulIRQFlags) spin_lock_irqsave(psLock, ulIRQFlags)
# define DC_OSSpinUnlockIRQRestore(psLock, ulIRQFlags) spin_unlock_irqrestore(psLock, ulIRQFlags)
/* used inside hardirqs */
# define DC_OSSpinLock(psLock) spin_lock(psLock)
# define DC_OSSpinUnlock(psLock) spin_unlock(psLock)

#elif defined(__QNXNTO__)
#include <pthread.h>
typedef pthread_spinlock_t DC_SPINLOCK;
# define DC_OSSpinLockCreate(psLock) pthread_spin_init(psLock, PTHREAD_PROCESS_PRIVATE)
# define DC_OSSpinLockDestroy(psLock) pthread_spin_destroy(psLock)
# define DC_OSSpinLockIRQSave(psLock, ulIRQFlags) PVR_UNREFERENCED_PARAMETER(ulIRQFlags); pthread_spin_lock(psLock)
# define DC_OSSpinUnlockIRQRestore(psLock, ulIRQFlags) PVR_UNREFERENCED_PARAMETER(ulIRQFlags); pthread_spin_unlock(psLock) 

# define DC_OSSpinLock(psLock) pthread_spin_lock(psLock)
# define DC_OSSpinUnlock(psLock) pthread_spin_unlock(psLock)

#elif defined(INTEGRITY_OS)
typedef struct DC_SPINLOCK_TAG
{
	IMG_UINT64 ui64Lock;
} DC_SPINLOCK;
IMG_BOOL DC_OSSpinLockCreate(void **pplMutex);
IMG_BOOL DC_OSSpinLockDestroy(void *plMutex);
IMG_BOOL DC_OSSpinLock(void *plMutex);
IMG_BOOL DC_OSSpinUnlock(void *plMutex);
#define DC_OSSpinLockIRQSave(plMutex) DC_OSSpinLock(plMutex)
#define DC_OSSpinUnlockIRQRestore(plMutex) DC_OSSpinUnlock(plMutex)
#else
#error "define an OS"
#endif

void DC_OSDelayus(IMG_UINT32 ui32Timeus);

/* Services access */
PVRSRV_ERROR DC_OSPVRServicesConnectionOpen(IMG_HANDLE *phPVRServicesConnection);
void DC_OSPVRServicesConnectionClose(IMG_HANDLE hPVRServicesConnection);
PVRSRV_ERROR DC_OSPVRServicesSetupFuncs(IMG_HANDLE hPVRServicesConnection, DC_SERVICES_FUNCS *psServicesFuncs);

/* Workqueue functionality */
/* OS work queue interface function pointer */
typedef PVRSRV_ERROR (*PFN_WORK_PROCESSOR)(void *pvData);

PVRSRV_ERROR DC_OSWorkQueueCreate(IMG_HANDLE *phQueue, IMG_UINT32 ui32Length);
PVRSRV_ERROR DC_OSWorkQueueDestroy(IMG_HANDLE hQueue);
PVRSRV_ERROR DC_OSWorkQueueFlush(IMG_HANDLE hQueue);

PVRSRV_ERROR DC_OSWorkQueueCreateWorkItem(IMG_HANDLE *phWorkItem, PFN_WORK_PROCESSOR pfnProcessor, void *pvProcessorData);

PVRSRV_ERROR DC_OSWorkQueueDestroyWorkItem(IMG_HANDLE phWorkItem);
PVRSRV_ERROR DC_OSWorkQueueAddWorkItem(IMG_HANDLE hQueue, IMG_HANDLE hWorkItem);

/* Atomic ops */

#if defined(LINUX)

#include <asm/atomic.h>

#define DC_OSAtomicRead(pCounter) atomic_read(pCounter)
#define DC_OSAtomicWrite(pCounter, i) atomic_set(pCounter, i)
#define DC_OSAtomicIncrement(pCounter) atomic_inc_return(pCounter)
#define DC_OSAtomicDecrement(pCounter) atomic_dec_return(pCounter)

#else

IMG_INT DC_OSAtomicRead(const ATOMIC_T *pCounter);
void DC_OSAtomicWrite(ATOMIC_T *pCounter, IMG_INT v);
IMG_INT DC_OSAtomicIncrement(ATOMIC_T *pCounter);
IMG_INT DC_OSAtomicDecrement(ATOMIC_T *pCounter);

#endif

#endif /* !defined(__DC_OSFUNCS_H__) */

