/****************************************************************************
 *                                                                          *
 * 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      *
 *                                                                          *
 ****************************************************************************/

/** \brief Implementation of KCL debug supporting interfaces
 *
 * CONVENTIONS
 *
 * Public symbols:
 * - prefixed with KCL_DEBUG
 * - are not static
 * - declared in the corresponding header
 *
 * Private symbols:
 * - prefixed with kcl
 * - are static
 * - not declared in the corresponding header
 *
 */

#include <asm-generic/errno-base.h> //for EINVAL definition

#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sysrq.h>

#include "kcl_debug.h"

extern int ATI_API_CALL firegl_debug_kbd_handler(void);
extern int ATI_API_CALL firegl_debug_dump(void);

extern void* ATI_API_CALL KCL_MEM_SmallBufferAllocAtomic(unsigned long size);
extern void ATI_API_CALL KCL_MEM_SmallBufferFree(void* p);

static void kcl_debug_sysrq_handler(int key,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
                                    struct pt_regs* pt_regs,
#endif
                                    struct tty_struct* tty)
{
    firegl_debug_kbd_handler();
}

static void kcl_debug_sysrq_dump_handler(int key,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
                                         struct pt_regs* pt_regs,
#endif
                                         struct tty_struct* tty)
{
    firegl_debug_dump();
}

static struct sysrq_key_op kcl_debug_sysrq_op =
{
    .handler        = kcl_debug_sysrq_handler,
    .help_msg       = "fGldbg",
    .action_msg     = "FGLDBG"
};

static struct sysrq_key_op kcl_debug_sysrq_dump_op =
{
    .handler        = kcl_debug_sysrq_dump_handler,
    .help_msg       = "fgLdump",
    .action_msg     = "FGLDUMP",
};

/** \brief Print debug information to the OS debug console
 *  \param fmt printf-like formatting string
 *  \param ... printf-like parameters
 */
void ATI_API_CALL KCL_DEBUG_Print(const char* fmt, ...)
{

    char* buffer=KCL_MEM_SmallBufferAllocAtomic(MAX_STRING_LENGTH);
    va_list marker;

    if(buffer == NULL)
        return ;

    va_start(marker, fmt);
    vsprintf(buffer, fmt, marker);
    va_end(marker);

    printk(buffer);
    KCL_MEM_SmallBufferFree(buffer);
}

/** \brief Register keyboard handler for internal debugging
 *  \param enable 1 to register the handler, 0 to unregister it
 *  \return 0
 */
int ATI_API_CALL KCL_DEBUG_RegKbdHandler(int enable)
{
    if(enable)
    {
        register_sysrq_key('g', &kcl_debug_sysrq_op);
    }
    else
    {
        unregister_sysrq_key('g', &kcl_debug_sysrq_op);
    }

    return 0;
}

/** \brief Register keyboard handler to dump module internal state
 *  \param enable 1 to register the handler, 0 to unregister it
 *  \return 0
 */
int ATI_API_CALL KCL_DEBUG_RegKbdDumpHandler(int enable)
{
    if(enable)
    {
        register_sysrq_key('l', &kcl_debug_sysrq_dump_op);
    }
    else
    {
        unregister_sysrq_key('l', &kcl_debug_sysrq_dump_op);
    }

    return 0;
}

/** \brief Dump most recent OS and CPU state to the system console
 */
void ATI_API_CALL KCL_DEBUG_OsDump(void)
{
    dump_stack();
}

/* FIXME: this is temporary workaround to support code using old naming convention */

void ATI_API_CALL __ke_printk(const char* fmt, ...)
{
    char* buffer=KCL_MEM_SmallBufferAllocAtomic(MAX_STRING_LENGTH);
    va_list marker;

    if(buffer ==NULL)
        return; 

    va_start(marker, fmt);
    vsprintf(buffer, fmt, marker);
    va_end(marker);

    printk(buffer);

    KCL_MEM_SmallBufferFree(buffer);
}

/* End of FIXME */


