diff options
| author | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2007-11-21 21:19:24 +0100 | 
|---|---|---|
| committer | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2007-11-25 18:35:17 +0100 | 
| commit | 2439e4bfa111babf4bc07ba20efbf3e36036813e (patch) | |
| tree | 21e94282acdc681bdde2ccc270bd401254124d00 /drivers/net/netconsole.c | |
| parent | 352d259130b349fe9593b8dada641bd78a9659e5 (diff) | |
| download | olio-uboot-2014.01-2439e4bfa111babf4bc07ba20efbf3e36036813e.tar.xz olio-uboot-2014.01-2439e4bfa111babf4bc07ba20efbf3e36036813e.zip | |
drivers/net : move net drivers to drivers/net
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Diffstat (limited to 'drivers/net/netconsole.c')
| -rw-r--r-- | drivers/net/netconsole.c | 267 | 
1 files changed, 267 insertions, 0 deletions
| diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c new file mode 100644 index 000000000..69089f92c --- /dev/null +++ b/drivers/net/netconsole.c @@ -0,0 +1,267 @@ +/* + * (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> + +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) +{ +	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 */ |