[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lwip-users] lwIP port for Coldfire 5282
From: |
Errin Bechtel |
Subject: |
Re: [lwip-users] lwIP port for Coldfire 5282 |
Date: |
Thu, 4 Nov 2004 04:36:14 -0800 (PST) |
François
Here is what I have. I took the 5272fec.c that was
in cvs and modified it for the 5282.
Errin
--- address@hidden wrote:
> I'm trying to port the lwIP Coldfire 5272 to
> Coldfirre 5282 but the FEC
> looks differents and I'm a newbie on Coldfire. Has
> somebody already done
> the port to give me the fec files ?
>
> Regards,
>
> - François -
>
>
> :.________________
> CONFIDENTIALITE : Ce message et les éventuelles
> pièces attachées sont
> confidentiels. Si vous n'êtes pas dans la liste des
> destinataires,
> veuillez informer l'expéditeur immédiatement et ne
> pas divulguer le
> contenu à une tierce personne, ne pas l'utiliser
> pour quelque raison que
> ce soit, ne pas stocker ou copier l'information
> qu'il contient sur un
> quelconque support.
>
> CONFIDENTIALITY : This e-mail and any attachments
> are confidential and
> may be privileged. If you are not a named
> recipient, please notify the
> sender immediately and do not disclose the contents
> to another person, use
> it for any purpose or store or copy the information
> in any medium.>
_______________________________________________
> lwip-users mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/lwip-users
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <address@hidden>
*
*/
/*
* This file is a skeleton for developing Ethernet network interface
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "mcf5282_if" to replace it with
* something that better describes your network interface.
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "netif/etharp.h"
#include "lwip/tcpip.h"
#include "lwip/dhcp.h"
//#include "httpd.h"
/* Sizing the descriptor rings will depend upon how many pbufs you have
available
* and how big they are. Also on how many frames you might want to input before
dropping
* frames. Generally it is a good idea to buffer one tcp window. This means that
* you won't get a tcp retransmit and your tcp transmissions will be reasonably
fast.
*/
#define NUM_RXBDS 64 // Number of receive descriptor rings
#define NUM_TXBDS 32 // Number of transmit descriptor rings
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
#define FEC_MTU 1518
struct rxbd
{
u16_t flags;
u16_t data_len;
u8_t *p_buf;
};
typedef struct rxbd rxbd_t;
struct txbd
{
u16_t flags;
u16_t data_len;
u8_t *p_buf;
};
typedef struct txbd txbd_t;
struct mcf5282_if
{
rxbd_t rxbd_a[NUM_RXBDS] __attribute__ ((aligned (16))); // Rx
descriptor ring. Must be aligned to double-word
txbd_t txbd_a[NUM_TXBDS] __attribute__ ((aligned (16))); // Tx
descriptor ring. Must be aligned to double-word
struct pbuf *rx_pbuf_a[NUM_RXBDS]; // Array of pbufs corresponding to
payloads in rx desc ring.
struct pbuf *tx_pbuf_a[NUM_TXBDS]; // Array of pbufs corresponding to
payloads in tx desc ring.
unsigned int rx_remove; // Index that driver will remove next
rx frame from.
unsigned int rx_insert; // Index that driver will insert next
empty rx buffer.
unsigned int tx_insert; // Index that driver will insert next
tx frame to.
unsigned int tx_remove; // Index that driver will clean up next
tx buffer.
unsigned int tx_free; // Number of free transmit descriptors.
unsigned int rx_buf_len; // number of bytes in a rx buffer (that
we can use).
struct eth_addr *ethaddr;
} mcf5282_if __attribute__ ((aligned (8)));
struct netif mcf282_fec_netif;
sys_sem_t tx_sem;
sys_sem_t rx_sem;
#define INC_RX_BD_INDEX(idx) do { if (++idx >= NUM_RXBDS) idx = 0; } while (0)
#define INC_TX_BD_INDEX(idx) do { if (++idx >= NUM_TXBDS) idx = 0; } while (0)
#define DEC_TX_BD_INDEX(idx) do { if (idx-- == 0) idx = NUM_TXBDS-1; } while (0)
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
/* Forward declarations. */
void mcf5282_if_input(struct netif *netif);
err_t mcf5282_if_output(struct netif *netif, struct pbuf *p, struct ip_addr
*ipaddr);
void low_level_input(struct netif *netif);
void eth_input(struct pbuf *p, struct netif *netif);
void fill_rx_ring(struct mcf5282_if *mcf5282)
{
struct pbuf *p;
struct rxbd *p_rxbd;
int i = mcf5282->rx_insert;
void *new_payload;
u32_t u_p_pay;
/* Try and fill as many receive buffers as we can */
while (mcf5282->rx_pbuf_a[i] == 0)
{
p = pbuf_alloc(PBUF_RAW, (u16_t) mcf5282->rx_buf_len, PBUF_POOL);
if (p == 0)
/* No pbufs, so can't refill ring */
return;
/* Align payload start to be divisible by 16 as required by HW */
u_p_pay = (u32_t) p->payload;
new_payload = p->payload = (void *) (((u_p_pay + 15) / 16) * 16);
mcf5282->rx_pbuf_a[i] = p;
p_rxbd = &mcf5282->rxbd_a[i];
p_rxbd->p_buf = (u8_t *) new_payload;
p_rxbd->flags = (p_rxbd->flags & MCF5282_FEC_RxBD_W) |
MCF5282_FEC_RxBD_E;
INC_RX_BD_INDEX(mcf5282->rx_insert);
i = mcf5282->rx_insert;
}
}
void fec_disable(struct mcf5282_if *mcf5282)
{
int i;
/* Reset the FEC - equivalent to a hard reset */
MCF5282_FEC_ECR = MCF5282_FEC_ECR_RESET;
/* Wait for the reset sequence to complete */
while (MCF5282_FEC_ECR & MCF5282_FEC_ECR_RESET);
/* Set the Graceful Transmit Stop bit */
//MCF5282_FEC_TCR = (MCF5282_FEC_TCR | MCF5282_FEC_TCR_GTS);
/* Wait for the current transmission to complete */
//while ( !(MCF5282_FEC_EIR & MCF5282_FEC_EIR_GRA));
/* Clear the GRA event */
//MCF5282_FEC_EIR = MCF5282_FEC_EIR_GRA;
/* Disable the FEC */
MCF5282_FEC_ECR = 0;
/* Disable all FEC interrupts by clearing the IMR register */
MCF5282_FEC_EIMR = 0;
/* Clear the GTS bit so frames can be tranmitted when restarted */
MCF5282_FEC_TCR = (MCF5282_FEC_TCR & ~MCF5282_FEC_TCR_GTS);
/* Release all buffers attached to the descriptors. Since the driver
* ALWAYS zeros the pbuf array locations and descriptors when buffers are
* removed, we know we just have to free any non-zero descriptors */
for (i = 0; i < NUM_RXBDS; i++)
if (mcf5282->rx_pbuf_a[i])
{
pbuf_free(mcf5282->rx_pbuf_a[i]);
mcf5282->rx_pbuf_a[i] = 0;
mcf5282->rxbd_a->p_buf = 0;
}
for (i = 0; i < NUM_TXBDS; i++)
if (mcf5282->tx_pbuf_a[i])
{
pbuf_free(mcf5282->tx_pbuf_a[i]);
mcf5282->tx_pbuf_a[i] = 0;
mcf5282->txbd_a->p_buf = 0;
}
}
void fec_enable(struct mcf5282_if *mcf5282)
{
int i;
/* Initialize empty tx descriptor ring */
for(i = 0; i < NUM_TXBDS-1; i++)
mcf5282->txbd_a[i].flags = 0;
/* Set wrap bit for last descriptor */
mcf5282->txbd_a[i].flags = MCF5282_FEC_TxBD_W;
/* initialize tx indexes */
mcf5282->tx_remove = mcf5282->tx_insert = 0;
mcf5282->tx_free = NUM_TXBDS;
/* Initialize empty rx descriptor ring */
for (i = 0; i < NUM_RXBDS-1; i++)
mcf5282->rxbd_a[i].flags = 0;
/* Set wrap bit for last descriptor */
mcf5282->rxbd_a[i].flags = MCF5282_FEC_RxBD_W;
/* Initialize rx indexes */
mcf5282->rx_remove = mcf5282->rx_insert = 0;
/* Fill receive descriptor ring */
fill_rx_ring(mcf5282);
sim->gpio.pehlpar = 0xC0;
sim->gpio.paspar = 0x0F00;
/* Enable FEC */
MCF5282_FEC_ECR = MCF5282_FEC_ECR_ETHER_EN;
/* Allow interrupts by setting IMR register */
MCF5282_FEC_EIMR = MCF5282_FEC_EIMR_RXF | MCF5282_FEC_EIMR_TXF;
/* Indicate that there have been empty receive buffers produced */
MCF5282_FEC_RDAR = 1;
}
void mcf5282fec_tx_cleanup(void)
{
struct pbuf *p;
unsigned int tx_remove_sof;
unsigned int tx_remove_eof;
unsigned int i;
u16_t flags;
struct mcf5282_if *mcf5282 = mcf282_fec_netif.state;
#if SYS_LIGHTWEIGHT_PROT == 1
u32_t old_level;
#endif
tx_remove_sof = tx_remove_eof = mcf5282->tx_remove;
#if defined(MCF5282_DEBUG)
printf("mcf5282fec_tx_cleanup: tx_remove_eof: %d\n", tx_remove_eof);
#endif
/* We must protect reading the flags and then reading the buffer pointer.
They must
both be read together. */
#if SYS_LIGHTWEIGHT_PROT == 1
old_level = sys_arch_protect();
#endif
/* Loop, looking for completed buffers at eof */
while ((((flags = mcf5282->txbd_a[tx_remove_eof].flags) &
MCF5282_FEC_TxBD_R) == 0) &&
(mcf5282->tx_pbuf_a[tx_remove_eof] != 0))
{
/* See if this is last buffer in frame */
if ((flags & MCF5282_FEC_TxBD_L) != 0)
{
i = tx_remove_eof;
/* This frame is complete. Take the frame off backwards */
do
{
p = mcf5282->tx_pbuf_a[i];
mcf5282->tx_pbuf_a[i] = 0;
mcf5282->txbd_a[i].p_buf = 0;
mcf5282->tx_free++;
if (i != tx_remove_sof)
DEC_TX_BD_INDEX(i);
else
break;
} while (1);
#if SYS_LIGHTWEIGHT_PROT == 1
sys_arch_unprotect(old_level);
#endif
#if defined(MCF5282_DEBUG)
printf("mcf5282fec_tx_cleanup: pbuf_free -> 0x%08X\n",
p);
#endif
pbuf_free(p); // Will be head of chain
#if SYS_LIGHTWEIGHT_PROT == 1
old_level = sys_arch_protect();
#endif
/* Look at next descriptor */
INC_TX_BD_INDEX(tx_remove_eof);
tx_remove_sof = tx_remove_eof;
}
else
INC_TX_BD_INDEX(tx_remove_eof);
}
mcf5282->tx_remove = tx_remove_sof;
//MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_TXF; // renable
interrupt
#if SYS_LIGHTWEIGHT_PROT == 1
sys_arch_unprotect(old_level);
#endif
}
void __attribute__ ((interrupt_handler)) mcf5282_fec_int_rxf(void)
{
MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_RXF; // disable rx int
MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF; // clear int flag
sys_sem_signal(rx_sem);
}
void __attribute__ ((interrupt_handler)) mcf5282_fec_int_txf(void)
{
//MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_TXF; // disable tx
int
/* clear interrupt status for tx interrupt */
MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF;
sys_sem_signal(tx_sem);
}
void low_level_init(struct netif *netif)
{
struct mcf5282_if *mcf5282;
struct pbuf *p;
int i;
#ifdef MCF5282_DEBUG
printf("low_level_init\n");
#endif
mcf5282 = netif->state;
fec_disable(mcf5282);
/* set MAC hardware address length */
netif->hwaddr_len = 6;
/* set MAC hardware address */
netif->hwaddr[0] = 0x00;
netif->hwaddr[1] = 0xCF;
netif->hwaddr[2] = 0x52;
netif->hwaddr[3] = 0x82;
netif->hwaddr[4] = 0x00;
netif->hwaddr[5] = 0x01;
/* maximum transfer unit */
netif->mtu = FEC_MTU;
/* broadcast capability */
netif->flags = NETIF_FLAG_BROADCAST;
// install int handlers
SetInterruptVector(MCF52XX_FEC_X_INTF_VECTOR +
MCF52XX_INTC0_VECTOR_BASE, &mcf5282_fec_int_txf);
SetInterruptVector(MCF52XX_FEC_R_INTF_VECTOR +
MCF52XX_INTC0_VECTOR_BASE, &mcf5282_fec_int_rxf);
sim->intc[0].icrn[MCF52XX_FEC_X_INTF_VECTOR] =
MCF52XX_FEC_X_INTF_IACKLPR; // set int level and priority
sim->intc[0].icrn[MCF52XX_FEC_R_INTF_VECTOR] =
MCF52XX_FEC_R_INTF_IACKLPR; // set int level and priority
EnableInterrupt(MCF52XX_FEC_X_INTF_VECTOR);
// enable ints
EnableInterrupt(MCF52XX_FEC_R_INTF_VECTOR);
// enable ints
/* Set the source address for the controller */
MCF5282_FEC_PALR = 0
| (netif->hwaddr[0] <<24)
| (netif->hwaddr[1] <<16)
| (netif->hwaddr[2] <<8)
| (netif->hwaddr[3] <<0);
MCF5282_FEC_PAUR = 0
| (netif->hwaddr[4] <<24)
| (netif->hwaddr[5] <<16);
/* Initialize the hash table registers */
MCF5282_FEC_IAUR = 0;
MCF5282_FEC_IALR = 0;
/* Set Receive Buffer Size. We subtract 16 because the start of the
receive
* buffer MUST be divisible by 16, so depending on where the payload really
* starts in the pbuf, we might be increasing the start point by up to 15
bytes.
* See the alignment code in fill_rx_ring() */
/* There might be an offset to the payload address and we should subtract
* that offset */
p = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
i = 0;
if (p)
{
struct pbuf *q = p;
while ((q = q->next) != 0)
i += q->len;
mcf5282->rx_buf_len = PBUF_POOL_BUFSIZE-16-i;
pbuf_free(p);
}
MCF5282_FEC_EMRBR = (u16_t) mcf5282->rx_buf_len;
/* Point to the start of the circular Rx buffer descriptor queue */
MCF5282_FEC_ERDSR = ((u32_t) &mcf5282->rxbd_a[0]);
/* Point to the start of the circular Tx buffer descriptor queue */
MCF5282_FEC_ETDSR = ((u32_t) &mcf5282->txbd_a[0]);
/* Set the tranceiver interface to MII mode */
MCF5282_FEC_RCR = (FEC_MTU << 16)
| MCF5282_FEC_RCR_MII_MODE
| MCF5282_FEC_RCR_DRT; // half duplex
//| MCF5282_FEC_RCR_PROM;
// accept all frames
/* Only operate in half-duplex, no heart beat control */
MCF5282_FEC_TCR = 0;
/* Set MII bus speed */
MCF5282_FEC_MSCR = 0x0D;
/* Clear MII interrupt status */
//MCF5282_FEC_EIR = MCF5282_FEC_EIMR_MII;
// enable fec
fec_enable(mcf5282);
}
/*
* low_level_output():
*
* Should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
*/
err_t low_level_output(struct netif *netif, struct pbuf *p)
{
struct mcf5282_if *mcf5282 = netif->state;
struct pbuf *q, *r;
char *ptr;
char *pStart;
unsigned int len;
#if SYS_LIGHTWEIGHT_PROT == 1
u32_t old_level;
#endif
#if SYS_LIGHTWEIGHT_PROT == 1
/* Interrupts are disabled through this whole thing to support
multi-threading
* transmit calls. Also this function might be called from an ISR. */
old_level = sys_arch_protect();
#endif
// make sure a descriptor free
if (mcf5282->tx_free)
{
r = pbuf_alloc(PBUF_RAW, p->tot_len + 16, PBUF_RAM);
// alloc mem for buffer
if (r != NULL)
{
ptr = pStart = (void *) ((((DWORD)r->payload + 15) /
16) * 16); // get start address aligned on 16 byte boundary
for(q = p, len = 0; q != NULL; q = q->next)
{
memcpy(ptr + len, q->payload, q->len);
len += q->len;
}
#if defined(MCF5282_DEBUG)
printf("low_level_output: mcf5282->tx_insert: %d\n",
mcf5282->tx_insert);
#endif
// put buffer on descriptor ring
mcf5282->tx_free--;
// dec free descriptors
mcf5282->tx_pbuf_a[mcf5282->tx_insert] = r;
// save pointer to pbuf
mcf5282->txbd_a[mcf5282->tx_insert].p_buf = pStart;
// set start address of data
mcf5282->txbd_a[mcf5282->tx_insert].data_len = len;
// set len of data
#if defined(MCF5282_DEBUG)
printf("low_level_output: pbuf: 0x%08X, buf: 0x%08X,
data_len: %d\n", mcf5282->tx_pbuf_a[mcf5282->tx_insert],
mcf5282->txbd_a[mcf5282->tx_insert].p_buf,
mcf5282->txbd_a[mcf5282->tx_insert].data_len);
printf("p_buf:\n");
printf("\tdest mac: ");
for(len = 0; len < 6; len++)
printf("%02X%c",
((BYTE*)mcf5282->txbd_a[mcf5282->tx_insert].p_buf)[len], len == 5 ? '\n' : ':');
printf("\tsrc mac: ");
for(; len < 12; len++)
printf("%02X%c",
((BYTE*)mcf5282->txbd_a[mcf5282->tx_insert].p_buf)[len], len == 11 ? '\n' :
':');
for(; len <
mcf5282->txbd_a[mcf5282->tx_insert].data_len; len++)
printf("%02X ",
((BYTE*)mcf5282->txbd_a[mcf5282->tx_insert].p_buf)[len]);
printf("\n");
#endif
// set flags
mcf5282->txbd_a[mcf5282->tx_insert].flags = (u16_t)
(MCF5282_FEC_TxBD_R |
(mcf5282->txbd_a[mcf5282->tx_insert].flags &
MCF5282_FEC_TxBD_W) |
(MCF5282_FEC_TxBD_L | MCF5282_FEC_TxBD_TC));
INC_TX_BD_INDEX(mcf5282->tx_insert);
#ifdef LINK_STATS
lwip_stats.link.xmit++;
#endif
/* Indicate that there has been a transmit buffer
produced */
MCF5282_FEC_TDAR = 1;
#if SYS_LIGHTWEIGHT_PROT == 1
sys_arch_unprotect(old_level);
#endif
return ERR_OK;
}
}
/* Drop the frame, we have no place to put it */
#ifdef LINK_STATS
lwip_stats.link.memerr++;
#endif
#if SYS_LIGHTWEIGHT_PROT == 1
sys_arch_unprotect(old_level);
#endif
return ERR_MEM;
}
//err_t low_level_output(struct netif *netif, struct pbuf *p)
//{
// struct pbuf *q;
// struct mcf5282_if *mcf5282 = netif->state;
// int num_desc;
// int num_free;
// unsigned int tx_insert_sof, tx_insert_eof;
// unsigned int i;
//#if SYS_LIGHTWEIGHT_PROT == 1
// u32_t old_level;
//#endif
//
// /* Make sure that there are no PBUF_REF buffers in the chain. These
buffers
// have to be freed immediately and this ethernet driver puts the buffers
on
// the dma chain, so they get freed later */
// p = pbuf_take(p);
//
//#if SYS_LIGHTWEIGHT_PROT == 1
// /* Interrupts are disabled through this whole thing to support
multi-threading
// * transmit calls. Also this function might be called from an ISR. */
// old_level = sys_arch_protect();
//#endif
//
// /* Determine number of descriptors needed */
// num_desc = pbuf_clen(p);
//
// if (num_desc > mcf5282->tx_free)
// {
// /* Drop the frame, we have no place to put it */
//#ifdef LINK_STATS
// lwip_stats.link.memerr++;
//#endif
//#if SYS_LIGHTWEIGHT_PROT == 1
// sys_arch_unprotect(old_level);
//#endif
// return ERR_MEM;
// }
// else
// {
// DWORD i;
//
// /* Increment use count on pbuf */
// pbuf_ref(p);
//
// /* Put buffers on descriptor ring, but don't mark them as ready yet */
// tx_insert_eof = tx_insert_sof = mcf5282->tx_insert;
// q = p;
//
// do
// {
// /*printf("packet: payload 0x%08X -> ", q->payload);
// for(i = 0; i < q->len; i++)
// printf("%02X ", ((BYTE*)q->payload)[i]);
// printf("\n");*/
//
// if((DWORD)q->payload & 3)
// {
// pbuf_header(q, 4 - (DWORD)q->payload & 3);
// }
//
// mcf5282->tx_free--;
// mcf5282->tx_pbuf_a[tx_insert_eof] = q;
// mcf5282->txbd_a[tx_insert_eof].p_buf = q->payload;
// mcf5282->txbd_a[tx_insert_eof].data_len = q->len;
//
// //printf("q->payload: 0x%08X, q->len: %d, p_buf:
0x%08X\n", q->payload, q->len, mcf5282->txbd_a[tx_insert_eof].p_buf);
//
// /*if(((DWORD)mcf5282->txbd_a[tx_insert_eof].p_buf &
0x03))
// {
// printf("low_level_output:
mcf5282->txbd_a[tx_insert_eof].p_buf 0x%08X, not mult. of 4\n",
mcf5282->txbd_a[tx_insert_eof].p_buf);
// abort();
// }*/
//
// q = q->next;
//
// if (q)
// INC_TX_BD_INDEX(tx_insert_eof);
//
// } while (q);
//
// /* Go backwards through descriptor ring setting flags */
// i = tx_insert_eof;
//
// do
// {
// mcf5282->txbd_a[i].flags = (u16_t) (MCF5282_FEC_TxBD_R |
// (mcf5282->txbd_a[i].flags &
MCF5282_FEC_TxBD_W) |
// ((i == tx_insert_eof) ? (MCF5282_FEC_TxBD_L |
MCF5282_FEC_TxBD_TC) : 0));
//
// if (i != tx_insert_sof)
// DEC_TX_BD_INDEX(i);
// else
// break;
// } while (1);
//
// INC_TX_BD_INDEX(tx_insert_eof);
// mcf5282->tx_insert = tx_insert_eof;
//
//#ifdef LINK_STATS
// lwip_stats.link.xmit++;
//#endif
// /* Indicate that there has been a transmit buffer produced */
// MCF5282_FEC_TDAR = 1;
//
//#if SYS_LIGHTWEIGHT_PROT == 1
// sys_arch_unprotect(old_level);
//#endif
// }
//
// return ERR_OK;
//}
/*
* low_level_input():
*
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
*/
void low_level_input(struct netif *netif)
{
u16_t flags;
unsigned int rx_remove_sof;
unsigned int rx_remove_eof;
struct pbuf *p;
struct mcf5282_if *mcf5282 = netif->state;
rx_remove_sof = rx_remove_eof = mcf5282->rx_remove;
/* Loop, looking for filled buffers at eof */
while ((((flags = mcf5282->rxbd_a[rx_remove_eof].flags) &
MCF5282_FEC_RxBD_E) == 0) && (mcf5282->rx_pbuf_a[rx_remove_eof] != 0))
{
/* See if this is last buffer in frame */
if ((flags & MCF5282_FEC_RxBD_L) != 0)
{
/* This frame is ready to go. Start at first descriptor in frame. */
p = 0;
do
{
/* Adjust pbuf length if this is last buffer in frame */
if (rx_remove_sof == rx_remove_eof)
{
mcf5282->rx_pbuf_a[rx_remove_sof]->tot_len =
mcf5282->rx_pbuf_a[rx_remove_sof]->len = (u16_t)
(mcf5282->rxbd_a[rx_remove_sof].data_len - (p ?
p->tot_len : 0));
}
else
mcf5282->rx_pbuf_a[rx_remove_sof]->len =
mcf5282->rx_pbuf_a[rx_remove_sof]->tot_len =
mcf5282->rxbd_a[rx_remove_sof].data_len;
/* Chain pbuf */
if (p == 0)
{
p = mcf5282->rx_pbuf_a[rx_remove_sof]; // First in
chain
p->tot_len = p->len; // Important
since len might have changed
} else
{
pbuf_chain(p, mcf5282->rx_pbuf_a[rx_remove_sof]);
pbuf_free(mcf5282->rx_pbuf_a[rx_remove_sof]);
}
/* Clear pointer to mark descriptor as free */
mcf5282->rx_pbuf_a[rx_remove_sof] = 0;
mcf5282->rxbd_a[rx_remove_sof].p_buf = 0;
if (rx_remove_sof != rx_remove_eof)
INC_RX_BD_INDEX(rx_remove_sof);
else
break;
} while (1);
INC_RX_BD_INDEX(rx_remove_sof);
/* Check error status of frame */
if (flags & (MCF5282_FEC_RxBD_LG |
MCF5282_FEC_RxBD_NO |
MCF5282_FEC_RxBD_CR |
MCF5282_FEC_RxBD_OV))
{
#ifdef LINK_STATS
lwip_stats.link.drop++;
if (flags & MCF5282_FEC_RxBD_LG)
lwip_stats.link.lenerr++; //Jumbo gram
else
if (flags & (MCF5282_FEC_RxBD_NO | MCF5282_FEC_RxBD_OV))
lwip_stats.link.err++;
else
if (flags & MCF5282_FEC_RxBD_CR)
lwip_stats.link.chkerr++; // CRC errors
#endif
/* Drop errored frame */
pbuf_free(p);
} else
{
/* Good frame. increment stat */
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif
eth_input(p, netif);
}
}
INC_RX_BD_INDEX(rx_remove_eof);
}
mcf5282->rx_remove = rx_remove_sof;
/* Fill up empty descriptor rings */
fill_rx_ring(mcf5282);
/* Set rx interrupt bit again */
MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_RXF;
/* Tell fec that we have filled up her ring */
MCF5282_FEC_RDAR = 1;
}
/*
* mcf5282_if_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actual transmission of the packet.
*
*/
err_t mcf5282_if_output(struct netif *netif, struct pbuf *p, struct ip_addr
*ipaddr)
{
/* resolve hardware address, then send (or queue) packet */
return etharp_output(netif, ipaddr, p);
}
void eth_input(struct pbuf *p, struct netif *netif)
{
/* Ethernet protocol layer */
struct eth_hdr *ethhdr;
struct mcf5282_if *mcf5282 = netif->state;
ethhdr = p->payload;
switch (htons(ethhdr->type))
{
case ETHTYPE_IP:
etharp_ip_input(netif, p);
pbuf_header(p, -(WORD)sizeof(struct eth_hdr));
netif->input(p, netif);
break;
case ETHTYPE_ARP:
etharp_arp_input(netif, mcf5282->ethaddr, p);
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
/*
* mcf5282_if_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*/
err_t mcf5282_if_init(struct netif *netif)
{
struct mcf5282_if *mcf5282if = &mcf5282_if;
printf("mcf5282_if_init: %08X\n", (DWORD)&mcf5282_if);
if (mcf5282if == NULL)
{
LWIP_DEBUGF(NETIF_DEBUG, ("mcf5282_if_init: out of memory\n"));
return ERR_MEM;
}
netif->state = mcf5282if;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = mcf5282_if_output;
netif->linkoutput = low_level_output;
netif->mtu = FEC_MTU - 18; // mtu without ethernet header and crc
//netif->input = tcpip_input;
netif->hwaddr_len = 6; /* Ethernet interface */
mcf5282if->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
etharp_init();
return ERR_OK;
}
void arp_timer(void *arg)
{
etharp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
void dhcp_fine_timer(void *arg)
{
dhcp_fine_tmr();
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_fine_timer, NULL);
}
void dhcp_coarse_timer(void *arg)
{
dhcp_coarse_tmr();
sys_timeout(DHCP_COARSE_TIMER_SECS * 1000, dhcp_coarse_timer, NULL);
}
void tcpip_init_done(void *arg)
{
sys_sem_t *sem;
#ifdef DEBUG_PRINTF
printf("tcpip thread: %d\n", TS_GetCurrentTask());
#endif
sem = arg;
sys_sem_signal(*sem);
}
void mcf5282_ethernet_timers_thread(void *arg)
{
sys_sem_t tmr_sem;
tmr_sem = sys_sem_new(0); // create sem
// start timers
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_fine_timer, NULL);
sys_timeout(DHCP_COARSE_TIMER_SECS * 1000, dhcp_coarse_timer, NULL);
while(1)
{
sys_sem_wait(tmr_sem); // wait forever
}
}
/** \brief rx thread
* \author Errin Bechtel
* \date 09-21-2004
*
* <b> Modified:</b><br>
*
* \param *arg
*/
void mcf5282_ethernet_rx_thread(void *arg)
{
while (1)
{
sys_sem_wait(rx_sem);
low_level_input(&mcf282_fec_netif);
}
}
/** \brief transmit thread
* \author Errin Bechtel
* \date 09-21-2004
*
* <b> Modified:</b><br>
*
* \param *arg
*/
void mcf5282_ethernet_thread(void *arg)
{
while (1)
{
sys_sem_wait(tx_sem);
mcf5282fec_tx_cleanup();
}
}
void mcf5282_ethernet_init()
{
sys_sem_t sem;
struct ip_addr ipaddr, netmask, gw;
TS_EnterSystemCritical();
#ifdef STATS
stats_init();
#endif
sys_init();
mem_init();
memp_init();
pbuf_init();
netif_init();
rx_sem = sys_sem_new(0); // create receive semaphore
tx_sem = sys_sem_new(0); // create transmit semaphore
// start new threads for tx, rx and timers
sys_thread_new(mcf5282_ethernet_rx_thread, NULL, DEFAULT_THREAD_PRIO);
sys_thread_new(mcf5282_ethernet_thread, NULL, DEFAULT_THREAD_PRIO);
sys_thread_new(mcf5282_ethernet_timers_thread, NULL,
DEFAULT_THREAD_PRIO);
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(sem);
sys_sem_free(sem);
printf("TCP/IP initialized.\n");
IP4_ADDR(&gw, 0,0,0,0);
IP4_ADDR(&ipaddr, 0,0,0,0);
IP4_ADDR(&netmask, 0,0,0,0);
netif_add(&mcf282_fec_netif, &ipaddr, &netmask, &gw, NULL, mcf5282_if_init,
tcpip_input);
netif_set_default(&mcf282_fec_netif);
//netif_set_up(&mcf282_fec_netif);
TS_LeaveSystemCritical();
dhcp_start(&mcf282_fec_netif); // start dhcp
//httpd_init(); // start web
server
}
void ethernet_stats_display(void)
{
struct mcf5282_if *mcf5282 = mcf282_fec_netif.state;
stats_display();
// print IP address
printf("IP addr: %08X\n", mcf282_fec_netif.ip_addr.addr);
printf("netif_is_up: %d\n", netif_is_up(&mcf282_fec_netif));
printf("tx_free: %d\n", mcf5282->tx_free);
}
#ifndef _FEC_H
#define _FEC_H
#define MCF5282_FEC_EIR sim->fec.eir
#define MCF5282_FEC_EIR_HBERR (0x80000000)
#define MCF5282_FEC_EIR_BABR (0x40000000)
#define MCF5282_FEC_EIR_BABT (0x20000000)
#define MCF5282_FEC_EIR_GRA (0x10000000)
#define MCF5282_FEC_EIR_TXF (0x08000000)
#define MCF5282_FEC_EIR_TXB (0x04000000)
#define MCF5282_FEC_EIR_RXF (0x02000000)
#define MCF5282_FEC_EIR_RXB (0x01000000)
#define MCF5282_FEC_EIR_MII (0x00800000)
#define MCF5282_FEC_EIR_EBERR (0x00400000)
#define MCF5282_FEC_EIR_LC (0x00200000)
#define MCF5282_FEC_EIR_RL (0x00100000)
#define MCF5282_FEC_EIR_UN (0x00080000)
#define MCF5282_FEC_EIMR sim->fec.eimr
#define MCF5282_FEC_EIMR_HBERR (0x80000000)
#define MCF5282_FEC_EIMR_BABR (0x40000000)
#define MCF5282_FEC_EIMR_BABT (0x20000000)
#define MCF5282_FEC_EIMR_GRA (0x10000000)
#define MCF5282_FEC_EIMR_TXF (0x08000000)
#define MCF5282_FEC_EIMR_TXB (0x04000000)
#define MCF5282_FEC_EIMR_RXF (0x02000000)
#define MCF5282_FEC_EIMR_RXB (0x01000000)
#define MCF5282_FEC_EIMR_MII (0x00800000)
#define MCF5282_FEC_EIMR_EBERR (0x00400000)
#define MCF5282_FEC_EIMR_LC (0x00200000)
#define MCF5282_FEC_EIMR_RL (0x00100000)
#define MCF5282_FEC_EIMR_UN (0x00080000)
#define MCF5282_FEC_RDAR sim->fec.rdar
#define MCF5282_FEC_RDAR_R_DES_ACTIVE (0x01000000)
#define MCF5282_FEC_TDAR sim->fec.tdar
#define MCF5282_FEC_TDAR_X_DES_ACTIVE (0x01000000)
#define MCF5282_FEC_ECR sim->fec.ecr
#define MCF5282_FEC_ECR_ETHER_EN (0x00000002)
#define MCF5282_FEC_ECR_RESET (0x00000001)
#define MCF5282_FEC_MMFR sim->fec.mmfr
#define MCF5282_FEC_MMFR_ST (0x40000000)
#define MCF5282_FEC_MMFR_OP_RD (0x20000000)
#define MCF5282_FEC_MMFR_OP_WR (0x10000000)
#define MCF5282_FEC_MMFR_PA(x) (((x)&0x1F)<<23)
#define MCF5282_FEC_MMFR_RA(x) (((x)&0x1F)<<18)
#define MCF5282_FEC_MMFR_TA (0x00020000)
#define MCF5282_FEC_MMFR_DATA(x) (((x)&0xFFFF))
#define MCF5282_FEC_MSCR sim->fec.mscr
#define MCF5282_FEC_MSCR_DIS_PREAMBLE (0x00000008)
#define MCF5282_FEC_MSCR_MII_SPEED(x) (((x)&0x1F)<<1)
#define MCF5282_FEC_MIBC sim->fec.mibc
#define MCF5282_FEC_MIBC_MIB_DISABLE (0x80000000)
#define MCF5282_FEC_MIBC_MIB_IDLE (0x40000000)
#define MCF5282_FEC_RCR sim->fec.rcr
#define MCF5282_FEC_RCR_MAX_FL(x) (((x)&0x07FF)<<16)
#define MCF5282_FEC_RCR_FCE (0x00000020)
#define MCF5282_FEC_RCR_BC_REJ (0x00000010)
#define MCF5282_FEC_RCR_PROM (0x00000008)
#define MCF5282_FEC_RCR_MII_MODE (0x00000004)
#define MCF5282_FEC_RCR_DRT (0x00000002)
#define MCF5282_FEC_RCR_LOOP (0x00000001)
#define MCF5282_FEC_TCR sim->fec.tcr
#define MCF5282_FEC_TCR_RFC_PAUSE (0x00000010)
#define MCF5282_FEC_TCR_TFC_PAUSE (0x00000008)
#define MCF5282_FEC_TCR_FDEN (0x00000004)
#define MCF5282_FEC_TCR_HBC (0x00000002)
#define MCF5282_FEC_TCR_GTS (0x00000001)
#define MCF5282_FEC_PALR sim->fec.palr
#define MCF5282_FEC_PALR_BYTE0(x) (((x)&0xFF)<<24)
#define MCF5282_FEC_PALR_BYTE1(x) (((x)&0xFF)<<16)
#define MCF5282_FEC_PALR_BYTE2(x) (((x)&0xFF)<<8)
#define MCF5282_FEC_PALR_BYTE3(x) (((x)&0xFF))
#define MCF5282_FEC_PAUR sim->fec.paur
#define MCF5282_FEC_PAUR_BYTE4(x) (((x)&0xFF)<<24)
#define MCF5282_FEC_PAUR_BYTE5(x) (((x)&0xFF)<<16)
#define MCF5282_FEC_OPD sim->fec.opd
#define MCF5282_FEC_OPD_PAUSE_DUR(x) (((x)&0xFFFF))
#define MCF5282_FEC_TFWR sim->fec.tfwr
#define MCF5282_FEC_TFWR_X_WMRK_64 (0x00000001)
#define MCF5282_FEC_TFWR_X_WMRK_128 (0x00000002)
#define MCF5282_FEC_TFWR_X_WMRK_192 (0x00000003)
#define MCF5282_FEC_EMRBR sim->fec.emrbr
#define MCF5282_FEC_EMRBR_R_BUF_SIZE(x) (((x)&7F)<<4)
#define MCF5282_FEC_TxBD_R 0x8000
#define MCF5282_FEC_TxBD_TO1 0x4000
#define MCF5282_FEC_TxBD_W 0x2000
#define MCF5282_FEC_TxBD_TO2 0x1000
#define MCF5282_FEC_TxBD_L 0x0800
#define MCF5282_FEC_TxBD_TC 0x0400
#define MCF5282_FEC_TxBD_ABC 0x0200
#define MCF5282_FEC_RxBD_E 0x8000
#define MCF5282_FEC_RxBD_R01 0x4000
#define MCF5282_FEC_RxBD_W 0x2000
#define MCF5282_FEC_RxBD_R02 0x1000
#define MCF5282_FEC_RxBD_L 0x0800
#define MCF5282_FEC_RxBD_M 0x0100
#define MCF5282_FEC_RxBD_BC 0x0080
#define MCF5282_FEC_RxBD_MC 0x0040
#define MCF5282_FEC_RxBD_LG 0x0020
#define MCF5282_FEC_RxBD_NO 0x0010
#define MCF5282_FEC_RxBD_CR 0x0004
#define MCF5282_FEC_RxBD_OV 0x0002
#define MCF5282_FEC_RxBD_TR 0x0001
#define MCF5282_FEC_IAUR sim->fec.iaur
#define MCF5282_FEC_IALR sim->fec.ialr
#define MCF5282_FEC_ERDSR sim->fec.erdsr
#define MCF5282_FEC_ETDSR sim->fec.etdsr
#define MCF52XX_FEC_X_INTF_VECTOR 23
#define MCF52XX_FEC_X_INTB_VECTOR 24
#define MCF52XX_FEC_UN_VECTOR 25
#define MCF52XX_FEC_RL_VECTOR 26
#define MCF52XX_FEC_R_INTF_VECTOR 27
#define MCF52XX_FEC_R_INTB_VECTOR 28
#define MCF52XX_FEC_MII_VECTOR 29
#define MCF52XX_FEC_LC_VECTOR 30
#define MCF52XX_FEC_HBERR_VECTOR 31
#define MCF52XX_FEC_GRA_VECTOR 32
#define MCF52XX_FEC_EBERR_VECTOR 33
#define MCF52XX_FEC_BABT_VECTOR 34
#define MCF52XX_FEC_BABR_VECTOR 35
typedef struct { /* fast ethernet controller */
volatile DWORD eir; /* 1004->1007 interrupt event register
*/
volatile DWORD eimr; /* 1008->100b interrupt mask register */
volatile BYTE pack00[4]; /* 100c->100f */
volatile DWORD rdar; /* 1010->1013 recieve descriptor active
register */
volatile DWORD tdar; /* 1014->1017 transmit descriptor
active register */
volatile BYTE pack01[12]; /* 1018->1023 */
volatile DWORD ecr; /* 1024->1027 ethernet control register
*/
volatile BYTE pack02[24]; /* 1028->103f */
volatile DWORD mdata; /* 1040->1043 mii data register */
volatile DWORD mscr; /* 1044->1047 mii speed control
register */
volatile BYTE pack03[28]; /* 1048->1063 */
volatile DWORD mibc; /* 1064->1067 mib control/status
register */
volatile BYTE pack04[28]; /* 1068->1083 */
volatile DWORD rcr; /* 1084->1087 recieve control register
*/
volatile BYTE pack05[60]; /* 1088->10c3 */
volatile DWORD tcr; /* 10c4->10c7 transmit control register
*/
volatile BYTE pack06[28]; /* 10c8->10e3 */
volatile DWORD palr; /* 10e4->10e7 physical address low
register */
volatile DWORD paur; /* 10e8->10eb physical address high+
type field */
volatile DWORD opd; /* 10ec->10ef opcode + pause duration */
volatile BYTE pack07[40]; /* 10f0->1117 */
volatile DWORD iaur; /* 1118->111b upper 32bits of
individual hash table */
volatile DWORD ialr; /* 111c->111f lower 32bits of
individual hash table */
volatile DWORD gaur; /* 1120->1123 upper 32bits of group
hash table */
volatile DWORD galr; /* 1124->1127 lower 32bits of group
hash table */
volatile BYTE pack08[28]; /* 1128->1143 */
volatile DWORD tfwr; /* 1144->1147 transmit fifo watermark */
volatile BYTE pack09[4]; /* 1148->114b */
volatile DWORD frbr; /* 114c->114f fifo receive bound
register */
volatile DWORD frsr; /* 1150->1153 fifo receive fifo start
registers */
volatile BYTE pack10[44]; /* 1154->117f */
volatile DWORD erdsr; /* 1180->1183 pointer to receive
descriptor ring */
volatile DWORD etdsr; /* 1184->1187 pointer to transmit
descriptor ring */
volatile DWORD emrbr; /* 1188->118b maximum receive buffer
size */
} fecstruct /*__attribute__ ((packed))*/;
#endif /* _FEC_H */