/*
 * (C) Copyright 2004
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>

#ifdef CONFIG_NETCONSOLE

#include <command.h>
#include <devices.h>
#include <net.h>

static char input_buffer[512];
static int input_size = 0;		/* char count in input buffer */
static int input_offset = 0;		/* offset to valid chars in input buffer */
static int input_recursion = 0;
static int output_recursion = 0;
static int net_timeout;
static uchar nc_ether[6];		/* server enet address */
static IPaddr_t nc_ip;			/* server ip */
static short nc_port;			/* source/target port */
static const char *output_packet;	/* used by first send udp */
static int output_packet_len = 0;

static void nc_wait_arp_handler (uchar * pkt, unsigned dest, unsigned src,
				 unsigned len)
{
	NetState = NETLOOP_SUCCESS;	/* got arp reply - quit net loop */
}

static void nc_handler (uchar * pkt, unsigned dest, unsigned src,
			unsigned len)
{
	if (input_size)
		NetState = NETLOOP_SUCCESS;	/* got input - quit net loop */
}

static void nc_timeout (void)
{
	NetState = NETLOOP_SUCCESS;
}

void NcStart (void)
{
	if (!output_packet_len || memcmp (nc_ether, NetEtherNullAddr, 6)) {
		/* going to check for input packet */
		NetSetHandler (nc_handler);
		NetSetTimeout (net_timeout, nc_timeout);
	} else {
		/* send arp request */
		uchar *pkt;
		NetSetHandler (nc_wait_arp_handler);
		pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
		memcpy (pkt, output_packet, output_packet_len);
		NetSendUDPPacket (nc_ether, nc_ip, nc_port, nc_port, output_packet_len);
	}
}

int nc_input_packet (uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
	int end, chunk;

	if (dest != nc_port || !len)
		return 0;		/* not for us */

	if (input_size == sizeof input_buffer)
		return 1;		/* no space */
	if (len > sizeof input_buffer - input_size)
		len = sizeof input_buffer - input_size;

	end = input_offset + input_size;
	if (end > sizeof input_buffer)
		end -= sizeof input_buffer;

	chunk = len;
	if (end + len > sizeof input_buffer) {
		chunk = sizeof input_buffer - end;
		memcpy(input_buffer, pkt + chunk, len - chunk);
	}
	memcpy (input_buffer + end, pkt, chunk);

	input_size += len;

	return 1;
}

static void nc_send_packet (const char *buf, int len)
{
	DECLARE_GLOBAL_DATA_PTR;

	struct eth_device *eth;
	int inited = 0;
	uchar *pkt;
	uchar *ether;
	IPaddr_t ip;

	if ((eth = eth_get_dev ()) == NULL) {
		return;
	}

	if (!memcmp (nc_ether, NetEtherNullAddr, 6)) {
		if (eth->state == ETH_STATE_ACTIVE)
			return;	/* inside net loop */
		output_packet = buf;
		output_packet_len = len;
		NetLoop (NETCONS);	/* wait for arp reply and send packet */
		output_packet_len = 0;
		return;
	}

	if (eth->state != ETH_STATE_ACTIVE) {
		if (eth_init (gd->bd) < 0)
			return;
		inited = 1;
	}
	pkt = (uchar *) NetTxPacket + NetEthHdrSize () + IP_HDR_SIZE;
	memcpy (pkt, buf, len);
	ether = nc_ether;
	ip = nc_ip;
	NetSendUDPPacket (ether, ip, nc_port, nc_port, len);

	if (inited)
		eth_halt ();
}

int nc_start (void)
{
	int netmask, our_ip;

	nc_port = 6666;		/* default port */

	if (getenv ("ncip")) {
		char *p;

		nc_ip = getenv_IPaddr ("ncip");
		if (!nc_ip)
			return -1;	/* ncip is 0.0.0.0 */
		if ((p = strchr (getenv ("ncip"), ':')) != NULL)
			nc_port = simple_strtoul (p + 1, NULL, 10);
	} else
		nc_ip = ~0;		/* ncip is not set */

	our_ip = getenv_IPaddr ("ipaddr");
	netmask = getenv_IPaddr ("netmask");

	if (nc_ip == ~0 ||				/* 255.255.255.255 */
	    ((netmask & our_ip) == (netmask & nc_ip) &&	/* on the same net */
	    (netmask | nc_ip) == ~0))			/* broadcast to our net */
		memset (nc_ether, 0xff, sizeof nc_ether);
	else
		memset (nc_ether, 0, sizeof nc_ether);	/* force arp request */

	return 0;
}

void nc_putc (char c)
{
	if (output_recursion)
		return;
	output_recursion = 1;

	nc_send_packet (&c, 1);

	output_recursion = 0;
}

void nc_puts (const char *s)
{
	int len;

	if (output_recursion)
		return;
	output_recursion = 1;

	if ((len = strlen (s)) > 512)
		len = 512;

	nc_send_packet (s, len);

	output_recursion = 0;
}

int nc_getc (void)
{
	uchar c;

	input_recursion = 1;

	net_timeout = 0;	/* no timeout */
	while (!input_size)
		NetLoop (NETCONS);

	input_recursion = 0;

	c = input_buffer[input_offset++];

	if (input_offset >= sizeof input_buffer)
		input_offset -= sizeof input_buffer;
	input_size--;

	return c;
}

int nc_tstc (void)
{
	struct eth_device *eth;

	if (input_recursion)
		return 0;

	if (input_size)
		return 1;

	eth = eth_get_dev ();
	if (eth && eth->state == ETH_STATE_ACTIVE)
		return 0;	/* inside net loop */

	input_recursion = 1;

	net_timeout = 1;
	NetLoop (NETCONS);	/* kind of poll */

	input_recursion = 0;

	return input_size != 0;
}

int drv_nc_init (void)
{
	device_t dev;
	int rc;

	memset (&dev, 0, sizeof (dev));

	strcpy (dev.name, "nc");
	dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
	dev.start = nc_start;
	dev.putc = nc_putc;
	dev.puts = nc_puts;
	dev.getc = nc_getc;
	dev.tstc = nc_tstc;

	rc = device_register (&dev);

	return (rc == 0) ? 1 : rc;
}

#endif	/* CONFIG_NETCONSOLE */
