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

#ifndef CONFIG_NET_MULTI
#error define CONFIG_NET_MULTI to use netconsole
#endif

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")) {
		nc_ip = getenv_IPaddr ("ncip");
		if (!nc_ip)
			return -1;	/* ncip is 0.0.0.0 */
		char *p = strchr (getenv ("ncip"), ':');
		if (p)
			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)
{
	if (output_recursion)
		return;
	output_recursion = 1;

	int len = strlen (s);

	if (len > 512)
		len = 512;

	nc_send_packet (s, len);

	output_recursion = 0;
}

int nc_getc (void)
{
	input_recursion = 1;

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

	input_recursion = 0;

	uchar c = input_buffer[input_offset];
	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 */
