/*
 * (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>
#include <command.h>
#include <stdio_dev.h>
#include <net.h>

DECLARE_GLOBAL_DATA_PTR;

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)
{
	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)
{
	struct stdio_dev 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 = stdio_register (&dev);

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