[U-Boot] [PATCH] keymile add the common parts of the HDLC driver

Gary Jennejohn garyj at denx.de
Sun Nov 9 12:36:15 CET 2008


This implements the ICN protocol used across the backplane and is needed
by all the keymile boards.

Signed-off-by: Gary Jennejohn <garyj at denx.de>
---

checkpatch.pl reports an ERROR which is false.

 board/keymile/common/keymile_hdlc_enet.c |  620 ++++++++++++++++++++++++++++++
 board/keymile/common/keymile_hdlc_enet.h |  129 ++++++
 2 files changed, 749 insertions(+), 0 deletions(-)
 create mode 100644 board/keymile/common/keymile_hdlc_enet.c
 create mode 100644 board/keymile/common/keymile_hdlc_enet.h

diff --git a/board/keymile/common/keymile_hdlc_enet.c b/board/keymile/common/keymile_hdlc_enet.c
new file mode 100644
index 0000000..141371b
--- /dev/null
+++ b/board/keymile/common/keymile_hdlc_enet.c
@@ -0,0 +1,620 @@
+/*
+ * (C) Copyright 2008
+ * Gary Jennejohn, DENX Software Engineering GmbH, garyj at denx.de.
+ *
+ * Based in part on cpu/mpc8260/ether_scc.c.
+ *
+ * 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 <malloc.h>
+#include <net.h>
+
+#ifdef CONFIG_KEYMILE_HDLC_ENET
+#ifdef TEST_IT
+#include <command.h>
+#endif
+
+#include "keymile_hdlc_enet.h"
+
+extern char keymile_slot;	/* our slot number in the backplane */
+
+/* Allow up to about 50 ms for sending */
+#define TOUT_LOOP	50000
+
+/*
+ * Since, except during initialization, ethact is always HDLC ETHERNET
+ * while we're in the driver, just use serial_printf() everywhere for
+ * output.  This avoids possible conflicts when netconsole is being
+ * used.
+ */
+#define dprintf(fmt, args...)	serial_printf(fmt, ##args)
+
+/* Cannot use the storage from net.c because we allocate larger buffers */
+static volatile uchar MyPktBuf[HDLC_PKTBUFSRX * PKT_MAXBLR_SIZE + PKTALIGN];
+static volatile uchar *MyRxPackets[HDLC_PKTBUFSRX]; /* Receive packet */
+
+static unsigned int keymile_rxIdx;	/* index of the current RX buffer */
+
+static IPaddr_t cachedNumbers[CACHEDNUMBERS]; /* 4 bytes per entry */
+void initCachedNumbers(int);
+
+/*
+  * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+  *  immr->udata_bd address on Dual-Port RAM
+  * Provide for Double Buffering
+  */
+typedef volatile struct CommonBufferDescriptor {
+    cbd_t txbd;			/* Tx BD */
+    cbd_t rxbd[HDLC_PKTBUFSRX];	/* Rx BD */
+} RTXBD;
+
+/*
+ * This must be extern because it is allocated in DPRAM using CPM-sepcific
+ * code.
+ */
+static RTXBD *rtx;
+
+static int keymile_hdlc_enet_send(struct eth_device *, volatile void *, int);
+static int keymile_hdlc_enet_recv(struct eth_device *);
+void keymile_hdlc_enet_init_bds(RTXBD *);
+extern int keymile_hdlc_enet_init(struct eth_device *, bd_t *);
+extern void keymile_hdlc_enet_halt(struct eth_device *);
+
+/* flags in the buffer descriptor not defined anywhere else */
+#define BD_SC_CT	BD_SC_CD
+#define BD_SC_CR	0x04
+#define BD_SC_DE	0x80
+#ifndef BD_SC_TC
+#define BD_SC_TC	((ushort)0x0400)	/* Transmit CRC */
+#endif
+#define BD_SC_FIRST	BD_SC_TC
+#define BD_SC_STATS (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_CR | BD_SC_CD \
+		| BD_SC_OV | BD_SC_DE)
+
+#if defined(TEST_RX) || defined(TEST_TX) || defined(TEST_IT)
+static void hexdump(unsigned char *buf, int len)
+{
+	int i;
+	const int bytesPerLine = 32;
+
+	if (len > 4 * bytesPerLine)
+		len = 4 * bytesPerLine;
+	dprintf("\t address: %08x\n", (unsigned int)buf);
+	for (i = 0; i < len; i++) {
+		if (i % bytesPerLine == 0)
+			dprintf("%04x: ", (unsigned short)i);
+		dprintf("%02x ", buf[i]);
+		if ((i + 1) % bytesPerLine == 0) {
+			dprintf("\n");
+			continue;
+		}
+		if ((i + 1) % 8 == 0)
+			printf(" ");
+	}
+	if (len % bytesPerLine)
+		dprintf("\n");
+}
+#endif
+
+int keymile_hdlc_enet_initialize(bd_t *bis)
+{
+	struct eth_device *dev;
+
+	dev = (struct eth_device *) malloc(sizeof *dev);
+	memset(dev, 0, sizeof *dev);
+#ifdef TEST_IT
+	seth = dev;
+#endif
+
+	sprintf(dev->name, "HDLC ETHERNET");
+	dev->init   = keymile_hdlc_enet_init;
+	dev->halt   = keymile_hdlc_enet_halt;
+	dev->send   = keymile_hdlc_enet_send;
+	dev->recv   = keymile_hdlc_enet_recv;
+
+	eth_register(dev);
+
+	return 1;
+}
+
+/*
+ * This is called from the board-specific driver after rtx is allocated.
+ */
+void keymile_hdlc_enet_init_bds(RTXBD *board_rtx)
+{
+	volatile cbd_t *bdp;
+	int i;
+
+	rtx = board_rtx;
+	keymile_rxIdx = 0;
+	/*
+	 * Initialize the buffer descriptors.
+	 */
+	bdp = &rtx->txbd;
+	bdp->cbd_sc = 0;
+	bdp->cbd_bufaddr = 0;
+	bdp->cbd_sc = BD_SC_WRAP;
+
+	/*
+	 *	Setup RX packet buffers, aligned correctly.
+	 *	Borrowed from net/net.c.
+	 */
+	MyRxPackets[0] = &MyPktBuf[0] + (PKTALIGN - 1);
+	MyRxPackets[0] -= (ulong)MyRxPackets[0] % PKTALIGN;
+	for (i = 1; i < HDLC_PKTBUFSRX; i++)
+		MyRxPackets[i] = MyRxPackets[0] + i * PKT_MAXBLR_SIZE;
+
+	bdp = &rtx->rxbd[0];
+	for (i = 0; i < HDLC_PKTBUFSRX; i++) {
+		bdp->cbd_sc = BD_SC_EMPTY;
+		/* Leave space at the start for INET header. */
+		bdp->cbd_bufaddr = (unsigned int)(MyRxPackets[i] +
+			INET_HDR_ALIGN);
+		bdp++;
+	}
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+}
+
+/*
+ * This returns the current port number for NETCONSOLE.  If nc_port
+ * in netconsole.c weren't declared static we wouldn't need this.
+ */
+static short get_netcons_port(void)
+{
+	char *p;
+	short nc_port;
+
+	nc_port = 6666; /* default */
+
+	p = getenv("ncip");
+	if (p != NULL) {
+		p = strchr(p, ':');
+		if (p != NULL)
+			nc_port = simple_strtoul(p + 1, NULL, 10);
+	}
+
+	return htons(nc_port);
+}
+
+/*
+ * Read the port numbers from the variables
+ */
+void initCachedNumbers(int verbose)
+{
+	char *str;
+	ushort port;
+
+	/* already in network order */
+	cachedNumbers[IP_ADDR] = getenv_IPaddr("ipaddr");
+	/* already in network order */
+	cachedNumbers[IP_SERVER] = getenv_IPaddr("serverip");
+	str = getenv("tftpsrcp");
+	if (str != NULL) {
+		/* avoid doing htons() again and again */
+		port = htons((ushort)simple_strtol(str, NULL, 10));
+		cachedNumbers[TFTP_SRC_PORT] = port;
+	} else
+		/* this can never be a valid port number */
+		cachedNumbers[TFTP_SRC_PORT] = (ulong)-1;
+	str = getenv("tftpdstp");
+	if (str != NULL) {
+		/* avoid doing htons() again and again */
+		port = htons((ushort)simple_strtol(str, NULL, 10));
+		cachedNumbers[TFTP_DST_PORT] = port;
+	} else
+		/* this is the default value */
+		cachedNumbers[TFTP_DST_PORT] = htons(WELL_KNOWN_PORT);
+	/* already in network order */
+	cachedNumbers[NETCONS_PORT] = get_netcons_port();
+	if (verbose) {
+		dprintf("\nIP Number Initialization:\n");
+		dprintf(" ip address          %08lx\n", cachedNumbers[IP_ADDR]);
+		dprintf(" server ip address   %08lx\n",
+			cachedNumbers[IP_SERVER]);
+		dprintf(" tftp client port    %ld\n",
+			cachedNumbers[TFTP_SRC_PORT]);
+		dprintf(" tftp server port    %ld\n",
+			cachedNumbers[TFTP_DST_PORT]);
+		dprintf(" netcons port        %ld\n",
+			cachedNumbers[NETCONS_PORT]);
+		dprintf(" slot number (hex)   %02x\n", keymile_slot);
+	}
+}
+
+static void keymile_hdlc_enet_doarp(volatile void *packet, int len)
+{
+	ARP_t *arp;
+	IPaddr_t src_ip; /* U-Boot's IP */
+	IPaddr_t dest_ip; /* the mgcoge's IP */
+	unsigned char *packet_copy = malloc(len);
+
+	/*
+	 * Handling an ARP request means that a new transfer has started.
+	 * Update our cached parameters now.
+	 */
+	initCachedNumbers(0); /* may reinit port numbers */
+
+	/* special handling required for ARP */
+	arp = (ARP_t *)(packet + ETHER_HDR_SIZE);
+	/*
+	 *	XXXX
+	 * This is pretty dirty!  NetReceive only uses
+	 * a few fields when handling an ARP reply, so
+	 * we only modify those here.  This could
+	 * result in catastrophic failure at a later
+	 * time if the handler is modified!
+	 */
+	arp->ar_op = htons(ARPOP_REPLY);
+	/* save his/our IP */
+	src_ip = NetReadIP(&arp->ar_data[6]);
+	dest_ip = NetReadIP(&arp->ar_data[16]);
+	/* copy target IP to source IP */
+	NetCopyIP(&arp->ar_data[6], &dest_ip);
+	/* copy our IP to the right place */
+	NetCopyIP(&arp->ar_data[16], &src_ip);
+	/* always use 0x7f as the MAC for the coge */
+	arp->ar_data[0] = HDLC_UACUA;
+	/*
+	 * copy the packet
+	 * if NetReceive wants to write to stdout, it may overwrite packet
+	 * especially if stdout is set to nc!
+	 *
+	 * However, if the malloc() above fails then we can still try the
+	 * original packet, rather than causing the transfer to fail.
+	 */
+	if (packet_copy != NULL) {
+		memcpy(packet_copy, (char *)packet, len);
+		NetReceive(packet_copy, len);
+		free(packet_copy);
+	} else
+		NetReceive(packet, len);
+}
+
+/*
+ * NOTE all callers ignore the returned value!
+ * At the moment this only handles ARP Requests, TFTP and NETCONSOLE.
+ */
+static int keymile_hdlc_enet_send(struct eth_device *dev, volatile void *packet,
+	int len)
+{
+	int j;
+	uint data_addr;
+	int data_len;
+	struct icn_hdr header;
+	struct icn_frame *frame;
+	Ethernet_t *et;
+	ARP_t *arp;
+	IP_t *ip;
+
+	if (len > (MAX_FRAME_LENGTH - sizeof(header)))
+		return -1;
+
+	frame = NULL;
+	et = NULL;
+	arp = NULL;
+	ip = NULL;
+
+	j = 0;
+	while ((rtx->txbd.cbd_sc & BD_SC_READY) && (j < TOUT_LOOP)) {
+		/* will also trigger Wd if needed, but maybe too often  */
+		udelay(1);
+		j++;
+	}
+	if (j >= TOUT_LOOP) {
+		dprintf("TX not ready sc %x\n", rtx->txbd.cbd_sc);
+		return -1;
+	}
+
+	/*
+	 * First check for an ARP Request since this requires special handling.
+	 */
+	if (len >= (ARP_HDR_SIZE + ETHER_HDR_SIZE)) {
+		et = (Ethernet_t *)packet;
+		arp = (ARP_t *)(((char *)et) + ETHER_HDR_SIZE);
+		/* ARP and REQUEST? */
+		if (et->et_protlen == PROT_ARP &&
+			arp->ar_op == htons(ARPOP_REQUEST)) {
+			/* just short-circuit the request on the U-Boot side */
+			keymile_hdlc_enet_doarp(packet, len);
+			return 0;
+		}
+	}
+
+	/*
+	 * GJ - I suppose the assumption here that len will always be
+	 * > INET_HDR_SIZE is alright as long as the network stack
+	 * isn't changed.
+	 * Do not send INET header.
+	 */
+	data_len = len + sizeof(header) - INET_HDR_SIZE;
+	frame = (struct icn_frame *) (((char *)packet) + INET_HDR_SIZE -
+		sizeof(header));
+
+#ifdef TEST_TX
+	printf("frame: %08x, ", frame);
+	hexdump((unsigned char *)packet, data_len + INET_HDR_SIZE);
+#endif
+
+	data_addr = (uint)frame;
+	if (len >= (IP_HDR_SIZE + ETHER_HDR_SIZE))
+		ip = (IP_t *)(packet + ETHER_HDR_SIZE);
+	/* Is it TFTP? TFTP always uses UDP and the cached dport */
+	if (ip != NULL && ip->ip_p == IPPROTO_UDP && ip->udp_dst ==
+			(ushort)cachedNumbers[TFTP_DST_PORT]) {
+		/* just in case the port wasn't set in the environment */
+		if (cachedNumbers[TFTP_SRC_PORT] == (ulong)-1)
+			cachedNumbers[TFTP_SRC_PORT] = ip->udp_src;
+		frame->hdr.application = MGS_TFTP;
+	}
+	/*
+	 * Is it NETCONSOLE?  NETCONSOLE always uses UDP.
+	 */
+	else if (ip != NULL && ip->ip_p == IPPROTO_UDP
+		&& ip->udp_dst == (ushort)cachedNumbers[NETCONS_PORT]) {
+			frame->hdr.application = MGS_NETCONS;
+	} else {
+		/* reject unknown packets */
+		/* may do some check on frame->hdr.application */
+		dprintf("Unknown packet type in %s, rejected\n",
+			__func__);
+		return -1;
+	}
+	/*
+	 * Could extract the target's slot ID from its MAC here,
+	 * but u-boot only wants to talk to the active server.
+	 *
+	 * avoid setting new source address when moving to another slot
+	 */
+	frame->hdr.src_addr = keymile_slot;
+	frame->hdr.dest_addr = HDLC_UACUA;
+#ifdef TEST_TX
+	{
+		dprintf("TX: ");
+		hexdump((unsigned char *)data_addr, data_len);
+	}
+#endif
+
+	flush_cache(data_addr, data_len);
+	rtx->txbd.cbd_bufaddr = data_addr;
+	rtx->txbd.cbd_datlen = data_len;
+	rtx->txbd.cbd_sc |= (BD_SC_READY | BD_SC_TC | BD_SC_LAST | BD_SC_WRAP);
+
+	while ((rtx->txbd.cbd_sc & BD_SC_READY) && (j < TOUT_LOOP)) {
+		/* will also trigger Wd if needed, but maybe too often  */
+		udelay(1);
+		j++;
+	}
+	if (j >= TOUT_LOOP)
+		dprintf("TX timeout\n");
+#ifdef ET_DEBUG
+	dprintf("cycles: %d    status: %x\n", j, rtx->txbd.cbd_sc);
+#endif
+	j = (rtx->txbd.cbd_sc & BD_SC_STATS); /* return only status bits */
+	return j;
+}
+
+/*
+ * During a receive, the RxIdx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int keymile_hdlc_enet_recv(struct eth_device *dev)
+{
+	int length;
+	unsigned char app;
+	struct icn_frame *fp;
+	Ethernet_t *ep;
+	IP_t *ip;
+
+	for (;;) {
+		if (rtx->rxbd[keymile_rxIdx].cbd_sc & BD_SC_EMPTY) {
+			length = -1;
+			break;	/* nothing received - leave for() loop */
+		}
+
+		length = rtx->rxbd[keymile_rxIdx].cbd_datlen;
+#ifdef TEST_RX
+		dprintf("packet %d bytes long\n", length);
+#endif
+
+		/*
+		 * BD_SC_BR -> LG bit
+		 * BD_SC_FR -> NO bit
+		 * BD_SC_PR -> AB bit
+		 * BD_SC_NAK -> CR bit
+		 * 0x80 -> DE bit
+		 */
+		if (rtx->rxbd[keymile_rxIdx].cbd_sc & BD_SC_STATS) {
+#ifdef ET_DEBUG
+			dprintf("err: %x\n", rtx->rxbd[keymile_rxIdx].cbd_sc);
+#endif
+		} else if (length > MAX_FRAME_LENGTH) { /* can't happen */
+#ifdef ET_DEBUG
+			dprintf("err: packet too big\n");
+#endif
+		} else {
+			fp = (struct icn_frame *)(MyRxPackets[keymile_rxIdx] +
+				INET_HDR_ALIGN - INET_HDR_SIZE);
+#ifdef TEST_RX
+			dprintf("RX %d: ", keymile_rxIdx);
+			hexdump((unsigned char *)MyRxPackets[keymile_rxIdx],
+				INET_HDR_ALIGN + INET_HDR_SIZE + 4);
+#endif
+			/* copy icn header to the beginning */
+			memcpy(fp, ((char *)fp + INET_HDR_SIZE),
+				sizeof(struct icn_hdr));
+			app = fp->hdr.application;
+			if (app == MGS_NETCONS || app == MGS_TFTP) {
+				struct icn_hdr *ih = &fp->hdr;
+				unsigned char icn_src_addr = ih->src_addr;
+				unsigned char icn_dest_addr = ih->dest_addr;
+
+				/*
+				 * expand header by INET_HDR_SIZE
+				 */
+				length += INET_HDR_SIZE;
+				/* initalize header */
+				memset((char *)fp->data, 0x00, INET_HDR_SIZE);
+				ep = (Ethernet_t *)fp->data;
+				/* set MACs */
+				ep->et_dest[0] = icn_dest_addr;
+				ep->et_src[0] = icn_src_addr;
+				ep->et_protlen = htons(PROT_IP);
+				/* set ip stuff */
+				ip = (IP_t *)(fp->data + ETHER_HDR_SIZE);
+				/* set ip addresses */
+				ip->ip_src = cachedNumbers[IP_SERVER];
+				ip->ip_dst = cachedNumbers[IP_ADDR];
+				/* ip length */
+				ip->ip_len = htons(length - ETHER_HDR_SIZE -
+					REMOVE);
+				/* ip proto */
+				ip->ip_p = IPPROTO_UDP;
+				switch (app) {
+				case MGS_TFTP:
+					/* swap src/dst port numbers */
+					ip->udp_src = (ushort)
+						cachedNumbers[TFTP_DST_PORT];
+					ip->udp_dst = (ushort)
+						cachedNumbers[TFTP_SRC_PORT];
+					ip->udp_len = ip->ip_len -
+						IP_HDR_SIZE_NO_UDP;
+					ip->udp_xsum = 0;
+					break;
+				case MGS_NETCONS:
+					ip->udp_src = (ushort)
+						cachedNumbers[NETCONS_PORT];
+					/*
+					 * in drivers/net/netconsole.c src port
+					 * equals dest port
+					 */
+					ip->udp_dst = ip->udp_src;
+					ip->udp_len = ip->ip_len -
+						IP_HDR_SIZE_NO_UDP;
+					ip->udp_xsum = 0;
+					break;
+				}
+				/* ip version */
+				ip->ip_hl_v = (0x40) | (0x0f &
+					(IP_HDR_SIZE_NO_UDP / 4));
+				ip->ip_tos = 0;
+				ip->ip_id = 0;
+				/* flags, fragment offset */
+				ip->ip_off = htons(0x4000);
+				ip->ip_ttl = 255; /* time to live */
+				/* have to fixup the checksum */
+				ip->ip_sum = ~NetCksum((uchar *)ip,
+					IP_HDR_SIZE_NO_UDP / 2);
+				/*
+				 * Pass the packet up to the protocol layers
+				 * but remove dest_addr, src_addr, application
+				 * and the CRC.
+				 */
+#ifdef TEST_RX
+				hexdump((unsigned char *)fp->data,
+					INET_HDR_SIZE + 4);
+#endif
+				NetReceive(fp->data, length - REMOVE);
+			} else {
+				/*
+				 * the other application types are not yet
+				 * supported by u-boot.
+				 */
+				/* normally drop it */
+#ifdef TEST_NO
+				/* send it anyway */
+				fp = (struct icn_frame *)
+					(MyRxPackets[keymile_rxIdx] +
+						INET_HDR_ALIGN);
+				NetReceive(fp->data, length - REMOVE);
+#endif
+			}
+		}
+
+		/* Give the buffer back to the SCC. */
+		rtx->rxbd[keymile_rxIdx].cbd_datlen = 0;
+
+		/* wrap around buffer index when necessary */
+		if ((keymile_rxIdx + 1) >= HDLC_PKTBUFSRX) {
+			rtx->rxbd[HDLC_PKTBUFSRX - 1].cbd_sc =
+				(BD_SC_WRAP | BD_SC_EMPTY);
+			keymile_rxIdx = 0;
+		} else {
+			rtx->rxbd[keymile_rxIdx].cbd_sc = BD_SC_EMPTY;
+			keymile_rxIdx++;
+		}
+	}
+	return length;
+}
+
+#ifdef TEST_IT
+/* simple send test routine */
+int hdlc_enet_stest(struct cmd_tbl_s *a, int b, int c, char **d)
+{
+	unsigned char pkt[2];
+	int ret;
+
+	dprintf("enter stest\n");
+	/* may have to initialize things */
+	if (seth->state != ETH_STATE_ACTIVE) {
+		/* the bd_t* is not used */
+		if (seth->init(seth, NULL) >= 0)
+			seth->state = ETH_STATE_ACTIVE;
+	}
+	pkt[0] = 0xea;
+	pkt[1] = 0xae;
+	ret = keymile_hdlc_enet_send(seth, pkt, 2);
+	dprintf("return from send %x\n", ret);
+	dprintf("exit stest\n");
+	return ret;
+}
+U_BOOT_CMD(
+	stest, 1, 1, hdlc_enet_stest,
+	"stest	- simple send test for hdlc_enet\n",
+	"no arguments\n"
+);
+/* simple receive test routine */
+int hdlc_enet_rtest(struct cmd_tbl_s *a, int b, int c, char **d)
+{
+	int ret;
+
+	dprintf("enter rtest\n");
+	/* may have to initialize things */
+	if (seth->state != ETH_STATE_ACTIVE) {
+		/* the bd_t* is not used */
+		if (seth->init(seth, NULL) >= 0)
+			seth->state = ETH_STATE_ACTIVE;
+	}
+	ret = keymile_hdlc_enet_recv(seth);
+	dprintf("return from recv %x\n", ret);
+	dprintf("exit rtest\n");
+	return ret;
+}
+U_BOOT_CMD(
+	rtest, 1, 1, hdlc_enet_rtest,
+	"rtest	- simple receive test for hdlc_enet\n",
+	"no arguments\n"
+);
+#endif
+
+#endif /* CONFIG_KEYMILE_HDLC_ENET */
diff --git a/board/keymile/common/keymile_hdlc_enet.h b/board/keymile/common/keymile_hdlc_enet.h
new file mode 100644
index 0000000..965bd5a
--- /dev/null
+++ b/board/keymile/common/keymile_hdlc_enet.h
@@ -0,0 +1,129 @@
+/*
+ * (C) Copyright 2008
+ * Gary Jennejohn, DENX Software Engineering GmbH, garyj at 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
+ */
+
+#ifndef _KEYMILE_HDLC_ENET_H_
+#define _KEYMILE_HDLC_ENET_H_
+
+/* Unfortuantely, we have do this to get the flag defines in the cbd_t */
+#ifdef CONFIG_MGSUVD
+#include <commproc.h>
+#endif
+#ifdef CONFIG_MGCOGE
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+#endif
+
+/*
+ * Defines for the ICN protocol used for communication over HDLC
+ * on the backplane between MGSUVDs and MGCOGEs.
+ */
+
+/*
+ * MAC which is reserved for communication (0x00 - 0xff in the last byte,
+ * which is the slot number)
+ */
+
+/*
+ * A DLL frame looks like this:
+ *  8 bit  |  8 bit     |  8 bit |  8 bit     | n * 8 bit| 16 bit|  8 bit
+ *  opening| destination| source | application|  data    |  FCS  | closing
+ *   flag  |  address   | address|            |          |       |  flag
+ *  (HW)      (APP)       (APP)      (APP)       (APP)      (HW)   (HW)
+ */
+
+/*
+ * The opening flag, the FCS and the closing flag are set by the hardware so
+ * they are not reflected in this struct.
+ */
+struct icn_hdr {
+	unsigned char dest_addr;
+	unsigned char src_addr;
+	unsigned char application;
+} __attribute__((packed));
+
+#define ICNHDR_LEN	(sizeof(struct icn_hdr))
+#define CRC_LEN		(sizeof(short))
+/* bytes to remove from packet before sending it upstream */
+#define REMOVE		(ICNHDR_LEN + CRC_LEN)
+
+struct icn_frame {
+	struct icn_hdr hdr;
+	unsigned char data[0];	/* a place holder */
+} __attribute__((packed));
+
+/* Address field */
+#define HDLC_UUA	0x00 /* Unicast Unit Address */
+#define HDLC_UUA_MASK	0x3f /* the last 6 bits contain the slot number */
+#define SET_HDLC_UUA(x) ((HDLC_UUA | ((x) & HDLC_UUA_MASK)))
+#define HDLC_UACUA	0x7f /* Unicast Active Control Unit Address */
+#define HDLC_BCAST	0xff /* broadcast */
+
+/* Application field */
+#define MGS_UUSP	0x00
+#define MGS_UREP	0x01
+#define MGS_IUP		0x02
+#define MGS_UTA		0x03
+#define MGS_MDS		0x04
+#define MGS_ITIME	0x05
+/* added by DENX */
+#define MGS_NETCONS	0x06	/* netconsole */
+#define MGS_TFTP	0x07
+
+/* Useful defines for buffer sizes, etc. */
+#define HDLC_PKTBUFSRX		32
+#define MAX_FRAME_LENGTH	1500 /* ethernet frame size */
+			 /*   14        +    28     */
+#define INET_HDR_SIZE	(ETHER_HDR_SIZE + IP_HDR_SIZE)
+#define INET_HDR_ALIGN	(((INET_HDR_SIZE + PKTALIGN - 1) / PKTALIGN) * PKTALIGN)
+/* INET_HDR_SIZE is stripped off */
+#define PKT_MAXBLR_SIZE	(MAX_FRAME_LENGTH + INET_HDR_ALIGN)
+
+/*
+ * It is too slow to read always the port numbers and IP addresses from the
+ * string variables.
+ * cachedNumbers is meant to cache it.
+ * THIS IS ONLY A SPEED IMPROVEMENT!
+ */
+enum {
+	IP_ADDR = 0,	/* getenv_IPaddr("serverip"); */
+	IP_SERVER,	/* getenv_IPaddr("ipaddr"); */
+	TFTP_SRC_PORT,	/* simple_strtol(getenv("tftpsrcp"), NULL, 10); */
+	TFTP_DST_PORT,	/* simple_strtol(getenv("tftpdstp"), NULL, 10); */
+	NETCONS_PORT,	/* simple_strtol(getenv("ncip"), NULL, 10); */
+	CACHEDNUMBERS
+};
+
+#define WELL_KNOWN_PORT 69	/* Well known TFTP port # */
+
+/* define this to create a test commend (htest) */
+#undef TEST_IT
+#ifdef TEST_IT
+/* have to save a copy of the eth_device for the test command's use */
+struct eth_device *seth;
+#endif
+/* define this for outputting of received packets */
+#undef TEST_RX
+/* define this for outputting of packets being sent */
+#undef TEST_TX
+
+#endif /* _KEYMILE_HDLC_ENET_H_ */
-- 
1.5.4.3


---
Gary Jennejohn
*********************************************************************
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de
*********************************************************************


More information about the U-Boot mailing list