km/common: remove hdlc_enet implementation
The hdlc implementation for mgcoge was initially developed, but later on not used. Remove the C files, the references in mgcoge.c and the Makefile to decrease maintenance effort. Signed-off-by: Holger Brunck <holger.brunck@keymile.com> Acked-by: Heiko Schocher <hs@denx.de> cc: Wolfgang Denk <wd@denx.de> cc: Detlev Zundel <dzu@denx.de> cc: Valentin Longchamp <valentin.longchamp@keymile.com> Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
This commit is contained in:
parent
62a813bcac
commit
23512c3158
@ -677,9 +677,6 @@ int ethernet_present(void)
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
#ifdef CONFIG_KEYMILE_HDLC_ENET
|
||||
(void)keymile_hdlc_enet_initialize(bis);
|
||||
#endif
|
||||
if (ethernet_present())
|
||||
return cpu_eth_init(bis);
|
||||
|
||||
|
@ -46,10 +46,6 @@ struct km_bec_fpga {
|
||||
int ethernet_present(void);
|
||||
int ivm_read_eeprom(void);
|
||||
|
||||
#ifdef CONFIG_KEYMILE_HDLC_ENET
|
||||
int keymile_hdlc_enet_initialize(bd_t *bis);
|
||||
#endif
|
||||
|
||||
int set_km_env(void);
|
||||
int fdt_set_node_and_value(void *blob,
|
||||
char *nodename,
|
||||
|
@ -1,620 +0,0 @@
|
||||
/*
|
||||
* (C) Copyright 2008
|
||||
* Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
|
||||
*
|
||||
* Based in part on arch/powerpc/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
|
||||
* 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");
|
||||
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,
|
||||
"simple send test for hdlc_enet",
|
||||
""
|
||||
);
|
||||
/* 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,
|
||||
"simple receive test for hdlc_enet",
|
||||
""
|
||||
);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_KEYMILE_HDLC_ENET */
|
@ -28,8 +28,7 @@ endif
|
||||
|
||||
LIB = $(obj)lib$(BOARD).o
|
||||
|
||||
COBJS := $(BOARD).o ../common/common.o ../common/keymile_hdlc_enet.o \
|
||||
mgcoge_hdlc_enet.o
|
||||
COBJS := $(BOARD).o ../common/common.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS))
|
||||
|
@ -1,276 +0,0 @@
|
||||
/*
|
||||
* (C) Copyright 2008
|
||||
* Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
|
||||
*
|
||||
* Based in part on arch/powerpc/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
|
||||
|
||||
#include "../common/keymile_hdlc_enet.h"
|
||||
|
||||
char keymile_slot; /* our slot number in the backplane */
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
static int already_inited;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
static RTXBD *rtx;
|
||||
|
||||
int keymile_hdlc_enet_init(struct eth_device *, bd_t *);
|
||||
void keymile_hdlc_enet_halt(struct eth_device *);
|
||||
extern void keymile_hdlc_enet_init_bds(RTXBD *);
|
||||
extern void initCachedNumbers(int);
|
||||
|
||||
/* Use SCC1 */
|
||||
#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
|
||||
#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
|
||||
#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
|
||||
CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
|
||||
#define CMXSCR_VALUE (CMXSCR_RS1CS_CLK11|CMXSCR_TS1CS_CLK11)
|
||||
#define MGC_PROFF_HDLC PROFF_SCC1
|
||||
#define MGC_SCC_HDLC 0 /* Index, not number! */
|
||||
|
||||
int keymile_hdlc_enet_init(struct eth_device *dev, bd_t *bis)
|
||||
{
|
||||
/* int i; */
|
||||
uint dpr;
|
||||
/* volatile cbd_t *bdp; */
|
||||
volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
|
||||
volatile cpm8260_t *cp = &(im->im_cpm);
|
||||
volatile scc_t *sccp;
|
||||
volatile scc_hdlc_t *hpr;
|
||||
volatile iop8260_t *iop;
|
||||
|
||||
if (already_inited)
|
||||
return 0;
|
||||
|
||||
hpr = (scc_hdlc_t *)(&im->im_dprambase[MGC_PROFF_HDLC]);
|
||||
sccp = (scc_t *)(&im->im_scc[MGC_SCC_HDLC]);
|
||||
iop = &im->im_ioport;
|
||||
|
||||
/*
|
||||
* Disable receive and transmit just in case.
|
||||
*/
|
||||
sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
|
||||
/*
|
||||
* Avoid exhausting DPRAM, which would cause a panic.
|
||||
*/
|
||||
if (rtx == NULL) {
|
||||
/* dpr is an offset into dpram */
|
||||
dpr = m8260_cpm_dpalloc(sizeof(RTXBD), 8);
|
||||
rtx = (RTXBD *)&im->im_dprambase[dpr];
|
||||
}
|
||||
|
||||
/* We need the slot number for addressing. */
|
||||
keymile_slot = *(char *)(CONFIG_SYS_SLOT_ID_BASE +
|
||||
CONFIG_SYS_SLOT_ID_OFF) & CONFIG_SYS_SLOT_ID_MASK;
|
||||
/*
|
||||
* Be consistent with the Linux driver and set
|
||||
* only enetaddr[0].
|
||||
*
|
||||
* Always add 1 to the slot number so that
|
||||
* there are no problems with an ethaddr which
|
||||
* is all 0s. This should be acceptable because
|
||||
* a board should never have a slot number of 255,
|
||||
* which is the broadcast address. The HDLC addressing
|
||||
* uses only the slot number.
|
||||
*/
|
||||
dev->enetaddr[0] = keymile_slot + 1;
|
||||
#ifdef TEST_IT
|
||||
dprintf("slot %d\n", keymile_slot);
|
||||
#endif
|
||||
|
||||
/* use pd30, pd31 pins for TXD1, RXD1 respectively */
|
||||
iop->iop_ppard |= (0x80000000 >> 30) | (0x80000000 >> 31);
|
||||
iop->iop_pdird |= (0x80000000 >> 30);
|
||||
iop->iop_psord |= (0x80000000 >> 30);
|
||||
|
||||
/* use pc21 as CLK11 */
|
||||
iop->iop_pparc |= (0x80000000 >> 21);
|
||||
iop->iop_pdirc &= ~(0x80000000 >> 21);
|
||||
iop->iop_psorc &= ~(0x80000000 >> 21);
|
||||
|
||||
/* use pc15 as CTS1 */
|
||||
iop->iop_pparc |= (0x80000000 >> 15);
|
||||
iop->iop_pdirc &= ~(0x80000000 >> 15);
|
||||
iop->iop_psorc &= ~(0x80000000 >> 15);
|
||||
|
||||
/*
|
||||
* SI clock routing
|
||||
* use CLK11
|
||||
* this also connects SCC1 to NMSI
|
||||
*/
|
||||
im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr & ~CMXSCR_MASK) |
|
||||
CMXSCR_VALUE;
|
||||
|
||||
/* keymile_rxIdx = 0; */
|
||||
|
||||
/*
|
||||
* Initialize function code registers for big-endian.
|
||||
*/
|
||||
hpr->sh_genscc.scc_rfcr = CPMFCR_EB;
|
||||
hpr->sh_genscc.scc_tfcr = CPMFCR_EB;
|
||||
|
||||
/*
|
||||
* Set maximum bytes per receive buffer.
|
||||
*/
|
||||
hpr->sh_genscc.scc_mrblr = MAX_FRAME_LENGTH;
|
||||
|
||||
/* Setup CRC generator values for HDLC */
|
||||
hpr->sh_cmask = 0x0000F0B8;
|
||||
hpr->sh_cpres = 0x0000FFFF;
|
||||
|
||||
/* Initialize all error counters to 0 */
|
||||
hpr->sh_disfc = 0;
|
||||
hpr->sh_crcec = 0;
|
||||
hpr->sh_abtsc = 0;
|
||||
hpr->sh_nmarc = 0;
|
||||
hpr->sh_retrc = 0;
|
||||
|
||||
/* Set maximum frame length size */
|
||||
hpr->sh_mflr = MAX_FRAME_LENGTH;
|
||||
|
||||
/* set to 1 for per frame processing change later if needed */
|
||||
hpr->sh_rfthr = 1;
|
||||
|
||||
hpr->sh_hmask = 0xff;
|
||||
|
||||
hpr->sh_haddr2 = SET_HDLC_UUA(keymile_slot);
|
||||
hpr->sh_haddr3 = hpr->sh_haddr2;
|
||||
hpr->sh_haddr4 = hpr->sh_haddr2;
|
||||
/* broadcast */
|
||||
hpr->sh_haddr1 = HDLC_BCAST;
|
||||
|
||||
hpr->sh_genscc.scc_rbase = (unsigned int) &rtx->rxbd[0];
|
||||
hpr->sh_genscc.scc_tbase = (unsigned int) &rtx->txbd;
|
||||
|
||||
#if 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;
|
||||
#else
|
||||
keymile_hdlc_enet_init_bds(rtx);
|
||||
#endif
|
||||
|
||||
/* Let's re-initialize the channel now. We have to do it later
|
||||
* than the manual describes because we have just now finished
|
||||
* the BD initialization.
|
||||
*/
|
||||
cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
|
||||
0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
|
||||
while (cp->cp_cpcr & CPM_CR_FLG);
|
||||
|
||||
sccp->scc_gsmrl = SCC_GSMRL_MODE_HDLC;
|
||||
/* CTSS=1 */
|
||||
sccp->scc_gsmrh = SCC_GSMRH_CTSS;
|
||||
/* NOF=0, RTE=1, DRT=0, BUS=1 */
|
||||
sccp->scc_psmr = ((0x8000 >> 6) | (0x8000 >> 10));
|
||||
|
||||
/* loopback for local testing */
|
||||
#ifdef GJTEST
|
||||
dprintf("LOOPBACK!\n");
|
||||
sccp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable all interrupts and clear all pending
|
||||
* events.
|
||||
*/
|
||||
sccp->scc_sccm = 0;
|
||||
sccp->scc_scce = 0xffff;
|
||||
|
||||
/*
|
||||
* And last, enable the transmit and receive processing.
|
||||
*/
|
||||
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
|
||||
dprintf("%s: HDLC ENET Version 0.3 on SCC%d\n", dev->name,
|
||||
MGC_SCC_HDLC + 1);
|
||||
|
||||
/*
|
||||
* We may not get an ARP packet because ARP was already done on
|
||||
* a different interface, so initialize the cached values now.
|
||||
*/
|
||||
initCachedNumbers(1);
|
||||
|
||||
already_inited = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void keymile_hdlc_enet_halt(struct eth_device *dev)
|
||||
{
|
||||
#if 0 /* just return, but keep this for reference */
|
||||
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
|
||||
|
||||
/* maybe should do a graceful stop here? */
|
||||
immr->im_scc[MGC_SCC_HDLC].scc_gsmrl &=
|
||||
~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MGCOGE_HDLC_ENET */
|
Loading…
Reference in New Issue
Block a user