/***************************************************************************************\

Module Name:    mtx_client.c

Description:    This module defines an abstraction layer of the kernel services used by 
                the kernel module.

Comments:       This is simply used to allow the binary to be compatible with kernels 
                compiled with switches that modifies the ABI.  It allows the binary to
                be kernel-independant.

    Copyright (c) 2004, Matrox Graphics Inc.
    All Rights Reserved.

\***************************************************************************************/


/* -------------------------------------------------------------------------------------- *\
                          I N C L U D E S   A N D   U S I N G S
\* -------------------------------------------------------------------------------------- */

#include <asm/delay.h>
#include "mtx_drv.h"

#ifndef DEBUG
#include "MtxCpuOs.inl"
#include "MtxMem.inl"
#endif

/* -------------------------------------------------------------------------------------- *\
                          C O N S T A N T S   A N D   T Y P E S
\* -------------------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------------------- *\
                 G L O B A L   V A R I A B L E S   D E C L A R A T I O N S
\* -------------------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------------------- *\
                   L O C A L   F U N C T I O N   D E C L A R A T I O N S
\* -------------------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------------------- *\
                                         M A C R O S
\* -------------------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------------------- *\
                                           C O D E
\* -------------------------------------------------------------------------------------- */

#ifdef MEMORY_STATS

STACK_LINKAGE void* ClientMemStatsAlloc(size_t size, const char* filename, int line)
{
    return mtx_mem_stats_alloc( size, filename, line );
}

STACK_LINKAGE void ClientMemStatsFree(void* ptr)
{
    mtx_mem_stats_free( ptr );
}
#endif  /* #ifdef MEMORY_STATS */

STACK_LINKAGE void* ClientMemAlloc(size_t size)
{
    return mtx_mem_alloc( size );
}

STACK_LINKAGE void ClientMemFree(void* ptr, size_t size)
{
    mtx_mem_free(ptr, size);
}

STACK_LINKAGE void* ClientIoRemap(unsigned long offset, unsigned long size)
{
    return mtx_mem_io_remap(offset, size);
}

STACK_LINKAGE void ClientIoUnmap(void* ptr)
{
    mtx_mem_io_unmap(ptr);
}

STACK_LINKAGE DWORD ClientRegisterReadDword(HDEVICE hDevice, DWORD ulOffset, DWORD *pdwData)
{
    memReadDword(GetRegisterHandle(hDevice), ulOffset, pdwData);
    return *pdwData;
}

STACK_LINKAGE DWORD ClientRegisterReadWord(HDEVICE hDevice, DWORD ulOffset, WORD *pwData)
{
    memReadWord(GetRegisterHandle(hDevice), ulOffset, pwData);
    return *pwData;
}

STACK_LINKAGE DWORD ClientRegisterReadByte(HDEVICE hDevice, DWORD ulOffset, BYTE *pbData)
{
    memReadByte(GetRegisterHandle(hDevice), ulOffset, pbData);
    return *pbData;
}

STACK_LINKAGE DWORD ClientRegisterWriteDword(HDEVICE hDevice, DWORD ulOffset, DWORD dwData)
{
    memWriteDword(GetRegisterHandle(hDevice), ulOffset, dwData);
    return dwData;
}

STACK_LINKAGE DWORD ClientRegisterWriteWord(HDEVICE hDevice, DWORD ulOffset, WORD wData)
{
    memWriteWord(GetRegisterHandle(hDevice), ulOffset, wData);
    return wData;
}

STACK_LINKAGE DWORD ClientRegisterWriteByte(HDEVICE hDevice, DWORD ulOffset, BYTE bData)
{
    memWriteWord(GetRegisterHandle(hDevice), ulOffset, bData);
    return bData;
}

STACK_LINKAGE BYTE ClientIoReadByte(WORD iPort)
{
    return inb(iPort);
}

STACK_LINKAGE WORD ClientIoReadWord(WORD iPort)
{
    return inw(iPort);
}

STACK_LINKAGE DWORD ClientIoReadDword(WORD iPort)
{
    return inl(iPort);
}

STACK_LINKAGE void ClientIoWriteByte(WORD iPort, BYTE iValue)
{
    return outb(iValue, iPort);
}

STACK_LINKAGE void ClientIoWriteWord(WORD iPort, WORD iValue)
{
    return outw(iValue, iPort);
}

STACK_LINKAGE void ClientIoWriteDword(WORD iPort, DWORD iValue)
{
    return outl(iValue, iPort);
}

STACK_LINKAGE DWORD ClientPciConfigReadByte(PCIHANDLE hDevice, DWORD iOffset, BYTE* piValue)
{
    return pci_read_config_byte((struct pci_dev*) hDevice, iOffset, piValue);
}

STACK_LINKAGE DWORD ClientPciConfigReadWord(PCIHANDLE hDevice, DWORD iOffset, WORD* piValue)
{
    return pci_read_config_word((struct pci_dev*) hDevice, iOffset, piValue);
}

STACK_LINKAGE DWORD ClientPciConfigReadDword(PCIHANDLE hDevice, DWORD iOffset, DWORD* piValue)
{
    return pci_read_config_dword((struct pci_dev*) hDevice, iOffset, piValue);
}

STACK_LINKAGE DWORD ClientPciConfigWriteByte(PCIHANDLE hDevice, DWORD iOffset, BYTE iValue)
{
    return pci_write_config_byte((struct pci_dev*) hDevice, iOffset, iValue);
}

STACK_LINKAGE DWORD ClientPciConfigWriteWord(PCIHANDLE hDevice, DWORD iOffset, WORD iValue)
{
    return pci_write_config_word((struct pci_dev*) hDevice, iOffset, iValue);
}

STACK_LINKAGE DWORD ClientPciConfigWriteDword(PCIHANDLE hDevice, DWORD iOffset, DWORD iValue)
{
    return pci_write_config_dword((struct pci_dev*) hDevice, iOffset, iValue);
}


#define MAX_STRING_LENGTH 255

STACK_LINKAGE void ClientPrintLevel(UINT32 iVerboseLevel, const char* pszFormat, ...)
{
    char    acBuffer[MAX_STRING_LENGTH];
    va_list va;
    size_t  iLogLevelLength;

    switch (iVerboseLevel)
    {
        case MTX_MSG_CRIT:
            sprintf(acBuffer, KERN_CRIT);
            break;
        case MTX_MSG_ERROR:
            sprintf(acBuffer, KERN_ERR);
            break;
        case MTX_MSG_WARNING:
            sprintf(acBuffer, KERN_WARNING);
            break;        
        default:
            sprintf(acBuffer, KERN_INFO);
    }
    
    iLogLevelLength = strlen( acBuffer );
    
    va_start(va, pszFormat);
    vsnprintf(acBuffer + iLogLevelLength, MAX_STRING_LENGTH - iLogLevelLength, pszFormat, va);
    va_end(va);

    printk(acBuffer);
}

STACK_LINKAGE int ClientVSPrintf(char *buf, const char *fmt, va_list args)
{
    return vsprintf(buf, fmt, args);
}

STACK_LINKAGE int ClientVSNPrintf(char *buf, size_t size, const char *fmt, va_list args)
{
    return vsnprintf(buf, size, fmt, args);
}

STACK_LINKAGE void ClientMicroDelay(UINT32 iMicroSecs)
{
    udelay( iMicroSecs );
}

STACK_LINKAGE void ClientSchedule(void)
{
    schedule();
}

STACK_LINKAGE int ClientGetNbCPUs( void )
{
#ifdef KERNEL_2_6
    return num_booting_cpus();
#else
    return smp_num_cpus;
#endif
}

STACK_LINKAGE int ClientCopyFromUserSpace(void* pvKnlData, void* pvUserData, UINT32 ulSize)
{    
    return copy_from_user(pvKnlData, pvUserData, ulSize);
}

STACK_LINKAGE int ClientCopyToUserSpace(void* pvUserData, void* pvKnlData, UINT32 ulSize)
{
    return copy_to_user(pvUserData, pvKnlData, ulSize);   
}

STACK_LINKAGE void ClientAtomicInc(void* pvValue)
{
    atomic_inc( (atomic_t*)pvValue );
}

STACK_LINKAGE void ClientAtomicDec(void* pvValue)
{
    atomic_dec( (atomic_t*)pvValue );
}

STACK_LINKAGE int ClientAtomicDecAndTest(void* pvValue)
{
    return atomic_dec_and_test( (atomic_t*)pvValue );
}
