lwip-users
[Top][All Lists]
Advanced

[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 */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]