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

	len = strlen(s);
	while (len) {
		int send_len = min(len, 512);
		nc_send_packet(s, send_len);
		len -= send_len;
		s += send_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;
}
