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>master
parent
62a813bcac
commit
23512c3158
@ -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 */ |
|
@ -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