/*
 *
 * gdb-agent.c
 *
 * Written by Vicente Esteve LLoret <viesllo@inf.upv.es>
 * Copyright (C) Feb, 2003 OCERA Consortium.
 *
 * 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 version 2.
 *
 * RTLinux Serial interface to GDB stub
 *
 */

#include <rtl_conf.h>

#if CONFIG_RTL_GDBAGENT 

#include <arch/rtl_io.h>
#include <rtl_sync.h>
#include <rtl_core.h>
#include <rtl_fifo.h>
#include <rtl_sched.h>
#include <rtl_mutex.h>

/* #define RTL_DEBUG_PRINT */
#include <rtl_debug.h>
#include "rt_comP.h"

#define COMBASE 0x3f8
#define LSR (COMBASE + 5)
#define TBE 0x20
#define RDA 0x01
#define RT_COM_RXB  0x00
#define RT_COM_TXB  0x00
#define RT_COM_IER  0x01
#define RT_COM_IIR  0x02
#define RT_COM_FCR  0x02
#define RT_COM_LCR  0x03
#define RT_COM_MCR  0x04
#define RT_COM_LSR  0x05
#define RT_COM_MSR  0x06
#define RT_COM_DLL  0x00
#define RT_COM_DLM  0x01
/* bit masks which may be written to the MCR using ModemControl */
#define RT_COM_DTR          0x01     /* data Terminal Ready        */
#define RT_COM_RTS          0x02     /* Request To Send            */
#define RT_COM_Out1         0x04
#define RT_COM_Out2         0x08
#define RT_COM_LoopBack     0x10

#define RT_COM_PARITY_EVEN  0x18
#define RT_COM_PARITY_NONE  0x00
#define RT_COM_PARITY_ODD   0x08




char getDebugChar(void)
{
 char c;

 while ((rtl_inb(LSR) & RDA) != RDA) {};
 c = rtl_inb(COMBASE);
 return c;
}

int putDebugChar(char chr)
{
  char c = (char) chr;
  while ((rtl_inb(LSR) & TBE) != TBE) {};
  rtl_outb(c,COMBASE);
  return 1;
}

/**
 * Calls from init_module + cleanup_module have baud == 0; in these cases we
 * only do some cleanup.
 *
 * To allocate a port, give usefull setup parameter, to deallocate give negative
 * baud.
 * @param com        Number corresponding to internal port numbering scheme.
 *                   This is esp. the index of the rt_com_table to use.
 * @param baud       Data transmission rate to use [Byte/s].
 * @param parity     Parity for transmission protocol.
 *                   (RT_COM_PARITY_EVEN, RT_COM_PARITY_ODD or RT_COM_PARITY_NONE)
 * @param stopbits   Number of stopbits to use. 1 gives you one stopbit, 2
 *                   actually gives really two stopbits for wordlengths of
 *                   6 - 8 bit, but 1.5 stopbits for a wordlength of 5 bits.
 * @param wordlength Number of bits per word (5 - 8 bits).
 *
 * @author Jens Michaelsen, Jochen Küpper
 * @version 1999/07/20
 */
void rt_com_setup( unsigned int com, int baud, unsigned int parity,
				   unsigned int stopbits, unsigned int wordlength )
{
	unsigned int base = COMBASE;
	unsigned int divider, par = parity;
        int ier;
        int baud_base=115200;	
	/* Stop everything, set DLAB */
	rtl_outb( 0x00, base + RT_COM_IER );
	rtl_outb( 0x80, base + RT_COM_LCR );

	/* clear irq */
	rtl_inb( base + RT_COM_IIR );
	rtl_inb( base + RT_COM_LSR );
	rtl_inb( base + RT_COM_RXB );
	rtl_inb( base + RT_COM_MSR );

	if( 0 == baud ) {
		/* return */
	} else if( 0 > baud ) {
	} else {
		divider = baud_base / baud;
		rtl_outb( divider % 256, base + RT_COM_DLL );
		rtl_outb( divider / 256, base + RT_COM_DLM );
		/* bits 3,4 + 5 determine parity */
		if( par & 0xC7 )
			par = RT_COM_PARITY_NONE;
		/* set transmission parameters and clear DLAB */
		rtl_outb( ( wordlength - 5 ) + ( ( stopbits - 1 ) << 2 ) + par, base + RT_COM_LCR );
		rtl_outb( RT_COM_DTR + RT_COM_RTS +  RT_COM_Out1 + RT_COM_Out2, base + RT_COM_MCR );
		ier = 0x00;
		rtl_outb( ier, base + RT_COM_IER );
                rtl_outb(0xC1,COMBASE + RT_COM_FCR);
	}
	return;
}

void test_com(void)
{
  char c=0;
  int aux=aux;
  while (1) 
 {    
   c = getDebugChar();
   PutChar(aux,5,c,0x12);
   putDebugChar(c);
//   c++;
   aux++;
   if (aux==20) aux=3;
 };
};

int init_gdbagent(void)
{
  rt_com_setup(0, 9600, RT_COM_PARITY_NONE, 1, 8);  
//  test_com(); 
  set_debug_traps();
  return 0;
}

#endif //CONFIG_RTL_GDBAGENT 
