/****************************************************************************
 *                                                                          *
 * Copyright 1999-2005 ATI Technologies Inc., Markham, Ontario, CANADA.     *
 * All Rights Reserved.                                                     *
 *                                                                          *
 * Your use and or redistribution of this software in source and \ or       *
 * binary form, with or without modification, is subject to: (i) your       *
 * ongoing acceptance of and compliance with the terms and conditions of    *
 * the ATI Technologies Inc. software End User License Agreement; and (ii)  *
 * your inclusion of this notice in any version of this software that you   *
 * use or redistribute.  A copy of the ATI Technologies Inc. software End   *
 * User License Agreement is included with this software and is also        *
 * available by contacting ATI Technologies Inc. at http://www.ati.com      *
 *                                                                          *
 ****************************************************************************/

#ifndef _FIREGL_PUBLIC_H_
#define _FIREGL_PUBLIC_H_

#include <stdarg.h>
#include "kcl_pci.h"
#include "kcl_io.h"

#define FIREGL_USWC_SUPPORT     1

#define FGL_DEVICE_SIGNATURE    0x10020000

#if defined(__i386__) || defined(__x86_64__)
#define LITTLEENDIAN_CPU 1
#endif

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)

#define REMAP_PAGE_RANGE_FN remap_pfn_range
#define REMAP_PAGE_RANGE_STR "remap_pfn_range"
#define REMAP_PAGE_RANGE_OFF(offset) ((offset) >> PAGE_SHIFT)

#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9) */

#define REMAP_PAGE_RANGE_FN remap_page_range
#define REMAP_PAGE_RANGE_STR "remap_page_range"
#define REMAP_PAGE_RANGE_OFF(offset) (offset)

#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) */

#define REMAP_PAGE_RANGE(vma,offset) \
    REMAP_PAGE_RANGE_FN(FGL_VMA_API_PASS \
                        (vma)->vm_start,	\
                        REMAP_PAGE_RANGE_OFF(offset), \
                        (vma)->vm_end - (vma)->vm_start, \
                        (vma)->vm_page_prot)


/* Page table macros */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
#define PAGING_FAULT_SIGBUS_INT (unsigned long)NOPAGE_SIGBUS
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) */
#define PAGING_FAULT_SIGBUS_INT VM_FAULT_SIGBUS
#endif

#define PGD_OFFSET(mm, pgd_p, pte_linear)	\
do { \
    pgd_p = pgd_offset(mm, pte_linear); \
} while(0)

#define PGD_PRESENT(pgd_p) \
do { \
    if (!pgd_present(*(pgd_p)))	\
    { \
        return PAGING_FAULT_SIGBUS_INT;   /* Something bad happened; generate SIGBUS */ \
        /* alternatively we could generate a NOPAGE_OOM "out of memory" */ \
    } \
} while(0)

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)

#define PMD_OFFSET(pmd_p, pgd_p, pte_linear) \
do { \
    pud_t *pud_p = pud_offset(pgd_p, pte_linear); \
    if (!pud_present(*(pud_p)))	\
    { \
        return PAGING_FAULT_SIGBUS_INT;   /* Something bad happened; generate SIGBUS */ \
        /* alternatively we could generate a NOPAGE_OOM "out of memory" */ \
    } \
    pmd_p = pmd_offset(pud_p, pte_linear); \
} while(0)

#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) */

#define PMD_OFFSET(pmd_p, pgd_p, pte_linear)	\
do { \
    pmd_p = pmd_offset(pgd_p, pte_linear); \
} while(0)

#endif

#define PMD_PRESENT(pmd_p) \
do { \
    if (!pmd_present(*(pmd_p)))	\
    { \
        return PAGING_FAULT_SIGBUS_INT;   /* Something bad happened; generate SIGBUS */ \
        /* alternatively we could generate a NOPAGE_OOM "out of memory" */ \
    } \
} while(0)

#ifdef pte_offset_atomic
#define PTE_OFFSET(pte, pmd_p, pte_linear) \
do { \
    pte_t* pte_p; \
    pte_p = pte_offset_atomic(pmd_p, pte_linear); \
    pte = *pte_p; \
    pte_kunmap(pte_p); \
} while(0)
#else
#ifdef pte_offset_map
#define PTE_OFFSET(pte, pmd_p, pte_linear) \
do { \
    pte_t* pte_p; \
    pte_p = pte_offset_map(pmd_p, pte_linear); \
    pte = *pte_p; \
    pte_unmap(pte_p); \
} while(0)
#else
#ifdef pte_offset_kernel
#define PTE_OFFSET(pte, pmd_p, pte_linear) \
do { \
    pte_t* pte_p; \
    pte_p = pte_offset_kernel(pmd_p, pte_linear); \
    pte = *pte_p; \
} while(0)
#else
#define PTE_OFFSET(pte, pmd_p, pte_linear) \
do { \
    pte_t* pte_p; \
    pte_p = pte_offset(pmd_p, pte_linear); \
    pte = *pte_p; \
} while(0)
#endif
#endif
#endif

#define PTE_PRESENT(pte) \
do { \
    if (!pte_present(pte)) \
    { \
        return PAGING_FAULT_SIGBUS_INT;   /* Something bad happened; generate SIGBUS */ \
        /* alternatively we could generate a NOPAGE_OOM "out of memory" */ \
    } \
} while(0)

#ifdef pfn_to_page
#define PMD_PAGE(pmd) pmd_page(pmd)
#else /* for old 2.4 kernels */
#define PMD_PAGE(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
#endif

#if !defined(CONFIG_SMP) || defined(CONFIG_SUSPEND_SMP) || defined(CONFIG_PM_SLEEP_SMP) // ACPI not working on older SMP kernel (prior to 2.6.13) 
#define FIREGL_POWER_MANAGEMENT
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
#define PMSG_EVENT(pmsg_state) (pmsg_state).event
#else
#define PMSG_EVENT(pmsg_state) (pmsg_state)
/* For old kernels without PM_EVENT_xxx defines, define them 
 * in consistent with the power state used in these kernels.
 * */
#define PM_EVENT_SUSPEND 3
#endif

/*****************************************************************************/

struct vm_area_struct;
struct semaphore;
struct drm_device;
struct firegl_pcie_mem;

/*****************************************************************************/

typedef unsigned long __ke_dev_t;
typedef unsigned long __ke_off_t;
#ifdef __x86_64__
typedef long __ke_ssize_t;
typedef unsigned long __ke_size_t;
#else
typedef int __ke_ssize_t;
typedef unsigned int __ke_size_t;
#endif
typedef unsigned char __ke_u8;
typedef unsigned short __ke_u16;
typedef unsigned int __ke_u32;
typedef unsigned long long __ke_u64;
typedef unsigned long long __ke_dma_addr_t;
typedef long long __ke_loff_t;

// note: assigning uniqe types to originally non interchangeable types
typedef struct { int uniqe3; } __ke_sigset_t;
typedef struct { int uniqe7; } __ke_file_operations_t;

typedef	int (*__ke_read_proc_t)(
    char* page, char** start, __ke_off_t off, int count, int* eof, void* data);

typedef struct {
    const char*             name;
    __ke_read_proc_t        f;
    __ke_file_operations_t* fops;
} __ke_proc_list_t;

extern __ke_proc_list_t KCL_PROC_FileList[];

typedef struct {
    unsigned long           signature;
    int                     privdevcount; // number of privdev structs
    __ke_proc_list_t *      proclist;
    const char *            name;
	unsigned int	        major_version;
	unsigned int	        minor_version;
	unsigned int            patchlevel;
	const char *	        date;
    __ke_sigset_t *         psigmask;
    void *                  privglobal; // private global context
} __ke_device_t;

/*****************************************************************************/

/** KCL declarations */

/** Type definitions for variables containing OS dependent data 
 *
 * These type definitions are used for data that need to be saved in the
 * proprietary code but is not interpreted by the proprietary code in any way.
 * To manipulate values of these types proprietary code must use only KCL functions
 *
 * To be of the safe side, propietary code has to use these type definitions to
 * declare local variables storing values received from KCL functions.  
 * However, legacy code is allowed to use compatible
 * types.  Compiler is supposed to catch dangerous type conversions
 *
 * In each implementation of KCL, it needs to make sure that the size of the KCL
 * defined type is greater or equal to the size of the corresponding OS type.
 * This can by done by checking which KCL functions use each particular type,
 * and what is the corresponding OS type
 * 
 */
typedef int             KCL_TYPE_Pid;       /** Process identifier */
typedef int             KCL_TYPE_Tgid;      /** Thread Group identifier */
typedef int             KCL_TYPE_Uid;       /** User identifier */

/** Atomic variables
 * This type is defined using struct to make sure compiled code will
 * always refer to the memory containing the atomic variable (prevent
 * compiler from aliasing this memory)
 * Since atomic variables are intended for using in the concurrent
 * environment, volatile is used
 */
typedef struct { volatile unsigned int counter; } KCL_TYPE_Atomic;

/** OS independent constant definitions */

typedef enum
{
    KCL_ERROR_DEVICE_RESOURCE_BUSY,
    KCL_ERROR_INVALID_ARGUMENT,
    KCL_ERROR_PERMISSION_DENIED,
    KCL_ERROR_INVALID_ADDRESS,
    KCL_ERROR_INPUT_OUTPUT,
    KCL_ERROR_INVALID_SLOT,
    KCL_ERROR_OUT_OF_MEMORY,
    KCL_ERROR_OPERATION_NOT_PERMITTED,
    KCL_ERROR_DEVICE_NOT_EXIST,
    KCL_ERROR_INTERRUPTED_SYSTEM_CALL,
    KCL_ERROR_SIGNAL_INTERRUPTED_SYSTEM_CALL,
    KCL_ERROR_CORRUPTED_SHARED_LIB,
    KCL_ERROR_NUM
} KCL_ENUM_ErrorCode;

typedef enum
{
    KCL_PROCESS_STATE_READY_TO_RUN,
    KCL_PROCESS_STATE_UNINTERRUPTIBLE_SLEEP,
    KCL_PROCESS_STATE_INTERRUPTIBLE_SLEEP,
    KCL_PROCESS_STATE_NUM
} KCL_ENUM_ProcessState;

typedef enum
{
    KCL_SECURITY_CAP_GENERAL_SYS_ADMIN,
    KCL_SECURITY_CAP_IPC_LOCK,
    KCL_SECURITY_CAP_NUM
} KCL_ENUM_PosixSecurityCap;

typedef enum
{
    KCL_KERNEL_CONF_PARAM_HUGE_MEM,
    KCL_KERNEL_CONF_PARAM_NUM
} KCL_ENUM_KernelConfigParam;


typedef struct {
	unsigned long totalram;		// Total usable main memory size 
	unsigned long freeram;		// Available memory size (low memory)
	unsigned long totalhigh;	// Total high memory size
	unsigned long freehigh;		// Available high memory size 
	unsigned int mem_unit;		// Memory unit size in bytes 
}KCL_SYS_MEM_INFO;

/** KCL function declarations */

extern void          ATI_API_CALL KCL_GlobalKernelScheduler(void);
extern int           ATI_API_CALL KCL_GetSignalStatus(void);
extern unsigned int  ATI_API_CALL KCL_CurrentProcessIsTerminating(void);
extern void          ATI_API_CALL KCL_SetCurrentProcessState(KCL_ENUM_ProcessState state);
extern const char*   ATI_API_CALL KCL_GetModuleParamString(void);
extern KCL_TYPE_Pid  ATI_API_CALL KCL_GetPid(void);
extern KCL_TYPE_Tgid ATI_API_CALL KCL_GetTgid(void);
extern KCL_TYPE_Uid  ATI_API_CALL KCL_GetEffectiveUid(void);
extern void          ATI_API_CALL KCL_DelayInMicroSeconds(unsigned long usecs);
extern void          ATI_API_CALL KCL_DelayUseTSC(unsigned long usecs);
extern unsigned long ATI_API_CALL KCL_ConvertAddressVirtualToPhysical(void* address);
extern unsigned long long ATI_API_CALL KCL_MapVirtualToPhysical(KCL_PCI_DevHandle pdev, void* address, unsigned long size);
extern void          ATI_API_CALL KCL_UnmapVirtualToPhysical(KCL_PCI_DevHandle pdev, unsigned long long bus_addr, unsigned long size);
extern unsigned long ATI_API_CALL KCL_MapPageToPfn(KCL_PCI_DevHandle pdev, void* page);
extern void          ATI_API_CALL KCL_UnmapPageToPfn(KCL_PCI_DevHandle pdev, unsigned long long bus_addr);
extern void*         ATI_API_CALL KCL_ConvertPageToKernelAddress(void* page);
extern unsigned int  ATI_API_CALL KCL_IsPageInHighMem(void* page);

extern void*         ATI_API_CALL KCL_GetHighMemory(void);
extern int           ATI_API_CALL KCL_GetErrorCode(KCL_ENUM_ErrorCode errcode);
extern void          ATI_API_CALL KCL_GlobalKernelLock(void);
extern void          ATI_API_CALL KCL_GlobalKernelUnlock(void);
extern int           ATI_API_CALL KCL_PosixSecurityCapCheck(KCL_ENUM_PosixSecurityCap cap);
extern int           ATI_API_CALL KCL_PosixSecurityCapSetIPCLock(unsigned int lock);
extern unsigned long ATI_API_CALL KCL_GetAvailableRamPages(void);
extern void          ATI_API_CALL KCL_GetSystemMemInfo(KCL_SYS_MEM_INFO* info);
extern void          ATI_API_CALL KCL_ReserveMemPage(void* pt);
extern void          ATI_API_CALL KCL_UnreserveMemPage(void* pt);
extern void          ATI_API_CALL KCL_LockMemPage(void* pt);
extern void          ATI_API_CALL KCL_UnlockMemPage(void* pt);
extern int           ATI_API_CALL KCL_KernelConfigParamIsDefined(KCL_ENUM_KernelConfigParam param);
extern int           ATI_API_CALL KCL_SetPageCache(void* virt, int pages,int enable);
extern int           ATI_API_CALL KCL_SetPageCache_Array(unsigned long *pt, int pages, int enable);
extern void          ATI_API_CALL KCL_AtomicInc(KCL_TYPE_Atomic* v);
extern void          ATI_API_CALL KCL_AtomicDec(KCL_TYPE_Atomic* v);
extern void          ATI_API_CALL KCL_AtomicAdd(KCL_TYPE_Atomic* v, int val);
extern void          ATI_API_CALL KCL_AtomicSub(KCL_TYPE_Atomic* v, int val);
extern int           ATI_API_CALL KCL_AtomicGet(KCL_TYPE_Atomic* v);
extern void          ATI_API_CALL KCL_AtomicSet(KCL_TYPE_Atomic* v, int val);
extern int           ATI_API_CALL KCL_AtomicIncAndTest(KCL_TYPE_Atomic* v);
extern int           ATI_API_CALL KCL_AtomicDecAndTest(KCL_TYPE_Atomic* v);
extern void          ATI_API_CALL KCL_AtomicSetBit(int nr, volatile void * addr);
extern void          ATI_API_CALL KCL_AtomicClearBit(int nr, volatile void * addr);
extern void          ATI_API_CALL KCL_AtomicToggleBit(int nr, volatile void* addr);
extern int           ATI_API_CALL KCL_AtomicTestBit(int nr, volatile void* addr);
extern int           ATI_API_CALL KCL_AtomicTestAndSetBit(int nr, volatile void* addr);
extern int           ATI_API_CALL KCL_AtomicTestAndClearBit(int nr, volatile void* addr);
extern int           ATI_API_CALL KCL_AtomicTestAndToggleBit(int nr, volatile void* addr);
extern int           ATI_API_CALL KCL_PosixSecurityCapCheck(KCL_ENUM_PosixSecurityCap cap);

/*****************************************************************************/

extern int ATI_API_CALL drm_name_info(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
extern int ATI_API_CALL firegl_bios_version(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
extern int ATI_API_CALL firegl_interrupt_info(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
extern int ATI_API_CALL drm_mem_info(char* buf, char** start, __ke_off_t offset, int len, int *eof, void *data);
extern int ATI_API_CALL drm_mem_info1(char* buf, char** start, __ke_off_t offset, int len, int *eof, void *data);
extern int ATI_API_CALL drm_vm_info(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
extern int ATI_API_CALL drm_clients_info(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
extern int ATI_API_CALL firegl_lock_info(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
#ifdef DEBUG
extern int ATI_API_CALL drm_bq_info(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
#endif
extern int ATI_API_CALL firegl_interrupt_open(void* data, KCL_IO_FILE_Handle file);
extern int ATI_API_CALL firegl_interrupt_release(KCL_IO_FILE_Handle file);
extern unsigned int ATI_API_CALL firegl_interrupt_read(
                                    KCL_IO_FILE_Handle user_file, 
                                    char *user_buf, 
                                    __ke_size_t user_buf_size, 
                                    __ke_loff_t *user_file_pos);
extern unsigned int ATI_API_CALL firegl_interrupt_poll(
        KCL_IO_FILE_Handle user_file, KCL_IO_FILE_PollTableHandle pt);
extern int ATI_API_CALL firegl_interrupt_write(
                                    KCL_IO_FILE_Handle user_file,
                                    const char *user_buf, 
                                    __ke_size_t user_buf_size, 
                                    __ke_loff_t *user_file_pos);

extern int ATI_API_CALL firegl_debug_proc_read(char* buf, char** start, __ke_off_t offset, int len, int* eof, void* data);
extern int ATI_API_CALL firegl_debug_proc_write(void* file, const char *buffer, unsigned long count, void *data); 

/*****************************************************************************/

extern int ATI_API_CALL firegl_private_init (__ke_device_t *);
extern void ATI_API_CALL firegl_private_cleanup (__ke_device_t *);
extern int ATI_API_CALL firegl_init(__ke_device_t*);
extern int ATI_API_CALL firegl_open(int minor, KCL_IO_FILE_Handle filp);
extern int ATI_API_CALL firegl_release(KCL_IO_FILE_Handle filp);
extern int ATI_API_CALL firegl_ioctl(
                        KCL_IO_FILE_Handle filp,
                        unsigned int cmd,
                        unsigned long arg);

#ifdef __x86_64__
extern long ATI_API_CALL firegl_compat_ioctl(
                        KCL_IO_FILE_Handle filp,
                        unsigned int cmd,
                        unsigned long arg);
#endif

/*****************************************************************************/

extern int ATI_API_CALL firegl_mmap(KCL_IO_FILE_Handle filp, struct vm_area_struct* vma);
extern void ATI_API_CALL drm_vm_open(struct vm_area_struct* vma);
extern void ATI_API_CALL drm_vm_close(struct vm_area_struct* vma);
extern void* ATI_API_CALL firegl_get_dev_from_vm(  struct vm_area_struct* vma );
extern void* ATI_API_CALL firegl_get_pcie_from_vm(  struct vm_area_struct* vma );
extern void* ATI_API_CALL firegl_get_pciemem_from_addr( struct vm_area_struct* vma, unsigned long addr );
extern unsigned long ATI_API_CALL firegl_get_pcie_pageaddr_from_vm(  struct vm_area_struct* vma, struct firegl_pcie_mem* pciemem, unsigned long offset);
extern void* ATI_API_CALL firegl_get_pagelist_from_vm(  struct vm_area_struct* vma );
extern unsigned long ATI_API_CALL firegl_get_addr_from_vm(  struct vm_area_struct* vma);
extern unsigned long ATI_API_CALL firegl_get_pagetable_page_from_vm(struct vm_area_struct* vma);
extern void* ATI_API_CALL mc_heap_get_page(void *vma, unsigned long long offset);

/*****************************************************************************/

extern void ATI_API_CALL KCL_SIGNAL_ConfigureMask(__ke_sigset_t *pSigMask);
extern int ATI_API_CALL firegl_sig_notifier(void *priv);
extern int              KCL_SIGNAL_Notifier(void *priv);
extern void ATI_API_CALL KCL_SIGNAL_BlockAll(int (*notifier)(void *priv), void *pPriv, __ke_sigset_t *pSigMask);
extern void ATI_API_CALL KCL_SIGNAL_UnblockAll(void);

extern unsigned long ATI_API_CALL __ke__cmpxchg(volatile void *ptr, unsigned long old,                      
                      unsigned long new, int size);

#define __ke_cmpxchg(ptr,o,n)                        \
  ((__typeof__(*(ptr)))__ke__cmpxchg((ptr),(unsigned long)(o),      \
                 (unsigned long)(n),sizeof(*(ptr))))
/*****************************************************************************/

extern __ke_dev_t ATI_API_CALL KCL_DEVICE_GetNumber(__ke_device_t *dev);

extern void ATI_API_CALL KCL_MODULE_IncUseCount(void);
extern void ATI_API_CALL KCL_MODULE_DecUseCount(void);

extern void ATI_API_CALL KCL_SEMAPHORE_STATIC_Down(__ke_device_t *dev, int idx);
extern void ATI_API_CALL KCL_SEMAPHORE_STATIC_Up(__ke_device_t *dev, int idx);
#define __KE_MAX_SEMAPHORES 4
extern void ATI_API_CALL KCL_SEMAPHORE_Init(struct semaphore* sem, int value);
extern __ke_size_t ATI_API_CALL KCL_SEMAPHORE_GetObjSize(void);
extern void ATI_API_CALL KCL_SEMAPHORE_DownUninterruptible(struct semaphore* sem);
extern void ATI_API_CALL KCL_SEMAPHORE_Up(struct semaphore* sem);

//PPLIB adding interruptible down for semaphore
extern int ATI_API_CALL KCL_SEMAPHORE_DownInterruptible(struct semaphore* sem);
//PPLIB end

extern void ATI_API_CALL KCL_SPINLOCK_STATIC_Grab(__ke_device_t *dev, int ndx);
extern void ATI_API_CALL KCL_SPINLOCK_STATIC_Release(__ke_device_t *dev, int ndx);
	#define __KE_MAX_SPINLOCKS 8

int ATI_API_CALL __ke_vsprintf(char *buf, const char *fmt, va_list ap);
int ATI_API_CALL __ke_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap);

extern int ATI_API_CALL KCL_CopyFromUserSpace(void* to, const void* from, __ke_size_t size);
extern int ATI_API_CALL KCL_CopyToUserSpace(void* to, const void* from, __ke_size_t size);

extern void* ATI_API_CALL KCL_MEM_SmallBufferAlloc(__ke_size_t size);
extern void* ATI_API_CALL KCL_MEM_SmallBufferAllocAtomic(__ke_size_t size);
extern void ATI_API_CALL KCL_MEM_SmallBufferFree(void* p);
extern void* ATI_API_CALL __ke_vmalloc(__ke_size_t size);
extern void* ATI_API_CALL KCL_MEM_Alloc(__ke_size_t size);
extern void* ATI_API_CALL KCL_MEM_AllocAtomic(__ke_size_t size);
extern void ATI_API_CALL KCL_MEM_Free(void* p);
extern void* ATI_API_CALL KCL_MEM_AllocPageFrame(void);
extern void* ATI_API_CALL KCL_MEM_AllocContiguousPageFrames(int order);
extern void ATI_API_CALL KCL_MEM_FreePageFrame(void* pt);
extern void ATI_API_CALL KCL_MEM_FreePageFrames(void* pt, int order);

extern void* ATI_API_CALL KCL_MEM_AllocPageForGart(void);
extern void ATI_API_CALL KCL_MEM_FreePageForGart(void* pt);

extern void ATI_API_CALL KCL_MEM_IncPageUseCount(void* pt);
extern void ATI_API_CALL KCL_MEM_DecPageUseCount(void* pt);
extern void ATI_API_CALL KCL_MEM_IncPageCount_Mapping(void* page);
extern int ATI_API_CALL KCL_MEM_VerifyReadAccess(void* addr, __ke_size_t size);
extern int ATI_API_CALL KCL_MEM_VerifyWriteAccess(void* addr, __ke_size_t size);
extern unsigned long ATI_API_CALL KCL_GetPageTableByVirtAddr(unsigned long virtual_addr, unsigned long* page_addr);
extern __ke_dma_addr_t ATI_API_CALL KCL_GetDmaPhysAddr(unsigned long virtual_addr);
extern int ATI_API_CALL KCL_TestAndClearPageDirtyFlag(unsigned long virtual_addr);
extern unsigned long ATI_API_CALL KCL_MEM_AllocLinearAddrInterval(KCL_IO_FILE_Handle  file, unsigned long addr, unsigned long len, unsigned long pgoff);
extern int ATI_API_CALL KCL_MEM_ReleaseLinearAddrInterval(unsigned long addr, unsigned long len);
extern void* ATI_API_CALL KCL_MEM_MapPageList(unsigned long *pagelist, unsigned int count);
#ifdef FIREGL_USWC_SUPPORT
extern void* ATI_API_CALL KCL_MEM_MapPageListWc(unsigned long *pagelist, unsigned int count);
#endif
extern void ATI_API_CALL KCL_MEM_Unmap(void* addr);
extern unsigned long ATI_API_CALL KCL_GetInitKerPte(unsigned long address);


/*****************************************************************************/

extern int ATI_API_CALL KCL_MEM_FlushCpuCaches(void);
extern void ATI_API_CALL KCL_PageCache_Flush(void);

/*****************************************************************************/

extern int ATI_API_CALL KCL_MEM_MTRR_Support(void);
extern int ATI_API_CALL KCL_MEM_MTRR_AddRegionWc(unsigned long base, unsigned long size);
extern int ATI_API_CALL KCL_MEM_MTRR_DeleteRegion(int reg, unsigned long base, unsigned long size);

extern int ATI_API_CALL KCL_is_pat_enabled(void);

/*****************************************************************************/

extern int ATI_API_CALL KCL_InstallInterruptHandler(unsigned int irq, void (*ATI_API_CALL handler)(void*), const char *dev_name, void *context, int useMSI);
extern void ATI_API_CALL KCL_UninstallInterruptHandler(unsigned int irq, void *context);

extern int ATI_API_CALL KCL_RequestMSI(void* context);
extern void ATI_API_CALL KCL_DisableMSI(void* context);

/*****************************************************************************/

extern void* ATI_API_CALL KCL_MEM_VM_GetRegionFilePrivateData(struct vm_area_struct* vma);
extern void* ATI_API_CALL KCL_MEM_VM_GetRegionPrivateData(struct vm_area_struct* vma);
extern unsigned long ATI_API_CALL KCL_MEM_VM_GetRegionStart(struct vm_area_struct* vma);
extern unsigned long ATI_API_CALL KCL_MEM_VM_GetRegionEnd(struct vm_area_struct* vma);
extern unsigned long ATI_API_CALL KCL_MEM_VM_GetRegionMapOffset(struct vm_area_struct* vma);
enum __ke_vm_maptype
{
    __KE_ADPT,
    __KE_SHM,
    __KE_CTX,
    __KE_PCI_BQS,
    __KE_AGP_BQS,
    __KE_AGP,
    __KE_SG,
    __KE_KMAP,
    __KE_GART_USWC,
    __KE_GART_CACHEABLE,
    __KE_ADPT_REG
};
extern char* ATI_API_CALL KCL_MEM_VM_GetRegionFlagsStr(struct vm_area_struct* vma, char* buf);
extern char* ATI_API_CALL KCL_MEM_VM_GetRegionProtFlagsStr(struct vm_area_struct* vma, char* buf);
extern char* ATI_API_CALL KCL_MEM_VM_GetRegionPhysAddrStr(struct vm_area_struct* vma,
                                   char* buf, 
                                   unsigned long linear_address, 
                                   __ke_dma_addr_t* phys_address);
extern int ATI_API_CALL KCL_MEM_VM_MapRegion(KCL_IO_FILE_Handle filp,
                                    struct vm_area_struct* vma,
                                    unsigned long long offset,
                                    enum __ke_vm_maptype type,
                                    int readonly,
                                    void *private_data);

/*****************************************************************************/

extern int ATI_API_CALL firegl_pci_save_state(KCL_PCI_DevHandle pdev, struct drm_device* dev);
extern int ATI_API_CALL firegl_pci_restore_state(KCL_PCI_DevHandle pdev, struct drm_device* dev);
extern int ATI_API_CALL firegl_cail_powerdown(struct drm_device* dev, __ke_u32 state);
extern int ATI_API_CALL firegl_cail_powerup(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_save_framebuffer(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_restore_framebuffer(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_save_onchip_ram(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_restore_onchip_ram(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_restore_atigart(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_disable_interrupts(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_enable_interrupts(struct drm_device* dev);
extern void ATI_API_CALL firegl_pm_lock_highmem_gart(struct drm_device* dev, int lock);

/*****************************************************************************/

extern int ATI_API_CALL KCL_PM_Is_SuspendToRam(unsigned int state);

/*****************************************************************************/

/* global constants */
extern const char*          KCL_SYSINFO_OsVersionString;
extern const unsigned long  KCL_SYSINFO_OsVersionCode;
extern const unsigned int   KCL_SYSINFO_PageSize;

extern const unsigned long  KCL_SYSINFO_BinaryModuleSupport;
extern const unsigned long  KCL_SYSINFO_SmpSupport;
extern const unsigned long  KCL_SYSINFO_PaeSupport;

/* global vars that are in fact constants */
extern unsigned long        KCL_SYSINFO_TimerTicksPerSecond;

/*****************************************************************************/

#ifndef __GFP_COMP
#define __GFP_COMP 0
#endif

#ifdef FIREGL_USWC_SUPPORT

#ifndef MSR_IA32_CR_PAT
#define MSR_IA32_CR_PAT     0x277
#endif

#ifndef cpu_has_pat
#define cpu_has_pat  test_bit(X86_FEATURE_PAT, (void *) &boot_cpu_data.x86_capability)
#endif

#ifndef cpu_has_pge
#define cpu_has_pge test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability)
#endif

/* 2.6.29 defines pgprot_writecombine as a macro which resolves to a
 * GPL-only function with the same name. So we always use our own
 * definition on 2.6.29 and later. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) \
    && defined (pgprot_writecombine)
#undef pgprot_writecombine
#endif
#ifndef pgprot_writecombine
#define pgprot_writecombine(prot) __pgprot((pgprot_val(prot) & ~(_PAGE_PCD)) | _PAGE_PWT)
#endif

#ifndef pgprot_noncached
#define pgprot_noncached(prot) __pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT)
#endif

#endif //FIREGL_USWC_SUPPORT


/*****************************************************************************
*                                                                            *
* Declarations for Kernel Abstraction Services                               *
*                                                                            *
******************************************************************************/
typedef void ATI_API_CALL (*KAS_CallbackWrapper_t)(void* proutine, void* pcontext);
typedef unsigned int ATI_API_CALL (*KAS_CallbackWrapperRet_t)(void* proutine, void* pcontext);

/** \brief Type definition for KAS initialization */
typedef struct tag_KAS_Initialize_t
{
    unsigned long exec_level_invalid;
    unsigned long exec_level_init;
    unsigned long exec_level_regular;
    unsigned long exec_level_idh;
    unsigned long exec_level_ih;
    KAS_CallbackWrapper_t callback_wrapper;
    KAS_CallbackWrapperRet_t callback_wrapper_ret;
} KAS_Initialize_t;

/** \brief Type definition for Interrupt Handling Routine */
typedef unsigned int (*KAS_IhRoutine_t)(void* pIhContext);

/** \brief Types of routines */
#define KAS_ROUTINE_TYPE_INVALID    0
#define KAS_ROUTINE_TYPE_REGULAR    1
#define KAS_ROUTINE_TYPE_IDH        2
#define KAS_ROUTINE_TYPE_IH         3

/** \brief Types of spinlocks */
#define KAS_SPINLOCK_TYPE_INVALID   0
#define KAS_SPINLOCK_TYPE_REGULAR   1
#define KAS_SPINLOCK_TYPE_IDH       2
#define KAS_SPINLOCK_TYPE_IH        3

/** \brief Return codes */
#define KAS_RETCODE_OK              0
#define KAS_RETCODE_ERROR           1
#define KAS_RETCODE_TIMEOUT         2
#define KAS_RETCODE_SIGNAL          3

/** \brief Interface functions */
extern unsigned int  ATI_API_CALL KAS_Initialize(KAS_Initialize_t* pinit);
extern unsigned int  ATI_API_CALL KAS_Ih_Execute(KAS_IhRoutine_t ih_routine,
                                                 void* ih_context);
extern unsigned int  ATI_API_CALL KAS_ExecuteAtLevel(void* pSyncRoutine,
                                                     void* pContext,
                                                     unsigned long sync_level);
extern unsigned long ATI_API_CALL KAS_GetExecutionLevel(void);

extern unsigned int  ATI_API_CALL KAS_Idh_GetObjectSize(void);
extern unsigned int  ATI_API_CALL KAS_Idh_Initialize(void* hIdh,
                                                     void* pfnIdhRoutine,
                                                     void* pIdhContext);
extern unsigned int  ATI_API_CALL KAS_Idh_Queue(void* hIdh);

extern unsigned int  ATI_API_CALL KAS_Spinlock_GetObjectSize(void);
extern unsigned int  ATI_API_CALL KAS_Spinlock_Initialize(void* hSpinLock,
                                             unsigned int spinlock_type);
extern unsigned int  ATI_API_CALL KAS_Spinlock_Acquire(void* hSpinLock);
extern unsigned int  ATI_API_CALL KAS_Spinlock_Release(void* hSpinLock);

extern unsigned int  ATI_API_CALL KAS_SlabCache_GetObjectSize(void);
extern unsigned int  ATI_API_CALL KAS_SlabCache_Initialize(void* hSlabCache,
                                                    unsigned int iEntrySize,
                                                    unsigned int access_type);
extern unsigned int  ATI_API_CALL KAS_SlabCache_Destroy(void* hSlabCache);
extern void*         ATI_API_CALL KAS_SlabCache_AllocEntry(void* hSlabCache);
extern unsigned int  ATI_API_CALL KAS_SlabCache_FreeEntry(void* hSlabCache,
                                                          void* pvEntry);

extern unsigned int  ATI_API_CALL KAS_Event_GetObjectSize(void);
extern unsigned int  ATI_API_CALL KAS_Event_Initialize(void* hEvent);
extern unsigned int  ATI_API_CALL KAS_Event_Set(void* hEvent);
extern unsigned int  ATI_API_CALL KAS_Event_Clear(void* hEvent);
extern unsigned int  ATI_API_CALL KAS_Event_WaitForEvent(void* hEvent,
                                                    unsigned long long timeout,
                                                    unsigned int timeout_use);

extern unsigned int  ATI_API_CALL KAS_Mutex_GetObjectSize(void);
extern unsigned int  ATI_API_CALL KAS_Mutex_Initialize(void* hMutex);
extern unsigned int  ATI_API_CALL KAS_Mutex_Acquire(void* hMutex,
                                                    unsigned long long timeout,
                                                    unsigned int timeout_use);
extern unsigned int  ATI_API_CALL KAS_Mutex_Release(void* hMutex);

extern unsigned int  ATI_API_CALL KAS_Thread_GetObjectSize(void);
extern unsigned int  ATI_API_CALL KAS_Thread_Start(void* hThread,
                                                   void* routine,
                                                   void* pcontext);
extern unsigned int  ATI_API_CALL KAS_Thread_WaitForFinish(void* hThread);
extern unsigned int  ATI_API_CALL KAS_Thread_Finish(void* hThread);

extern unsigned int  ATI_API_CALL KAS_InterlockedList_GetListHeadSize(void);
extern unsigned int  ATI_API_CALL KAS_InterlockedList_GetListEntrySize(void);
extern unsigned int  ATI_API_CALL KAS_InterlockedList_Initialize(
                                                    void* hListHead,
                                                    unsigned int access_type);
extern unsigned int  ATI_API_CALL KAS_InterlockedList_InsertAtTail(
                                                      void* hListHead,
                                                      void* hListEntry,
                                                      void** phPrevEntry);
extern unsigned int  ATI_API_CALL KAS_InterlockedList_InsertAtHead(
                                                      void* hListHead,
                                                      void* hListEntry,
                                                      void** phPrevEntry);
extern unsigned int  ATI_API_CALL KAS_InterlockedList_RemoveAtHead(
                                                      void* hListHead,
                                                      void** phRemovedEntry);

extern unsigned int  ATI_API_CALL KAS_AtomicCompareExchangeUnsignedInt(
                                                unsigned int *puiDestination,
                                                unsigned int uiExchange,
                                                unsigned int uiComparand);

extern unsigned int  ATI_API_CALL KAS_AtomicExchangeUnsignedInt(
                                                unsigned int *puiDestination,
                                                unsigned int uiExchange);

extern unsigned int  ATI_API_CALL KAS_AtomicExchangeAddUnsignedInt(
                                                unsigned int *puiDestination,
                                                unsigned int uiAdd);

extern unsigned int  ATI_API_CALL KAS_AtomicAddInt(
                                                unsigned int *puiDestination,
                                                int iAdd);

extern void*         ATI_API_CALL KAS_AtomicCompareExchangePointer(
                                                        void* *ppvDestination,
                                                        void* pvExchange,
                                                        void* pvComparand);

extern void*         ATI_API_CALL KAS_AtomicExchangePointer(
                                                        void* *ppvDestination,
                                                        void* pvExchange);

extern unsigned long ATI_API_CALL KAS_GetTickCounter(void);
extern unsigned long ATI_API_CALL KAS_GetTicksPerSecond(void);
extern  long ATI_API_CALL KAS_ScheduleTimeout(long n_jiffies);

/******************************************************************************
**
**  Interface layer to asyncIO layer
**
*******************************************************************************/
#define FIREGL_ASYNCIO_MAX_DEV      32    /* Currently hardcode to 32  */
#define FIREGL_ASYNCIO_MAX_FILE     32   /* Currently hardcode to 32 */
#define FIREGL_ASYNCIO_MAX_SEMA     ((FIREGL_ASYNCIO_MAX_FILE+1)*FIREGL_ASYNCIO_MAX_DEV)

extern void * ATI_API_CALL KCL_SEMAPHORE_ASYNCIO_Alloc(void);
extern void ATI_API_CALL KCL_SEMAPHORE_ASYNCIO_Free(struct semaphore *pSema);
extern void ATI_API_CALL KCL_SEMAPHORE_ASYNCIO_Init(void);

typedef enum {
    __KE_POLLIN = 0,
    __KE_POLLRDNORM,
    __KE_EAGAIN,
    __KE_FASYNC_ON,
    __KE_FASYNC_OFF,
    __KE_SIGIO,
    __KE_ESPIPE,
    __KE_EINTR
} __ke_asynio_contant_t;

extern int ATI_API_CALL KCL_SYSINFO_MapConstant(int contant);

extern __ke_ssize_t ATI_API_CALL firegl_asyncio_read( KCL_IO_FILE_Handle filp,
                                                      char *buf, 
                                                      __ke_size_t size,
                                                      __ke_loff_t *off_ptr);

extern __ke_ssize_t ATI_API_CALL firegl_asyncio_write( KCL_IO_FILE_Handle filp,
                                                       const char *buf, 
                                                       __ke_size_t size,
                                                       __ke_loff_t *off_ptr);

extern unsigned int ATI_API_CALL firegl_asyncio_poll(
        KCL_IO_FILE_Handle filp, KCL_IO_FILE_PollTableHandle table);

extern int ATI_API_CALL firegl_asyncio_fasync(int fd, 
                                              KCL_IO_FILE_Handle filp,
                                              int mode);


extern void *ATI_API_CALL KCL_lock_init(void);
extern void ATI_API_CALL KCL_lock_deinit(void *plock);
extern void ATI_API_CALL KCL_spin_lock(void *lock);
extern void ATI_API_CALL KCL_spin_unlock(void *lock);
extern void ATI_API_CALL KCL_get_random_bytes(void *buf, int nbytes);
extern void* ATI_API_CALL KCL_get_pubdev(void);

extern void ATI_API_CALL adapter_chain_init(void);
extern void ATI_API_CALL adapter_chain_cleanup(void);
extern void ATI_API_CALL cf_object_init(void);
extern void ATI_API_CALL cf_object_cleanup(void);
extern int ATI_API_CALL firegl_init_device_list(int num_of_devices);
extern void ATI_API_CALL firegl_cleanup_device_heads(void);
extern int ATI_API_CALL firegl_get_dev(void *pubdev, KCL_PCI_DevHandle pdev);
extern void *ATI_API_CALL firegl_find_device(int minor);
extern void* ATI_API_CALL firegl_query_pcidev(KCL_PCI_DevHandle pdev);
extern int ATI_API_CALL firegl_init_32compat_ioctls(void);
extern void ATI_API_CALL firegl_kill_32compat_ioctls(void);
extern int ATI_API_CALL firegl_uswc_user_disabled(void);

#endif /* _FIREGL_PUBLIC_H_ */
