⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 greth.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  RTEMS driver for Opencores Ethernet Controller * *  Weakly based on dec21140 rtems driver and open_eth linux driver *  Written by Jiri Gaisler, Gaisler Research * *  The license and distribution terms for this file may be *  found in found in the file LICENSE in this distribution or at *  http://www.OARcorp.com/rtems/license.html. * *  $Id: greth.c,v 1.1.2.1 2006/04/24 18:42:38 joel Exp $ */#include <rtems.h>#define GRETH_SUPPORTED#include <bsp.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include "greth.h"#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#ifdef malloc#undef malloc#endif#ifdef free#undef free#endif/*#define GRETH_DEBUG*/#ifdef CPU_U32_FIXextern void ipalign(struct mbuf *m);#endif/* * Number of OCs supported by this driver */#define NOCDRIVER	1/* * Receive buffer size -- Allow for a full ethernet packet including CRC */#define RBUF_SIZE 1518#define	ET_MINLEN 64		/* minimum message length *//* * RTEMS event used by interrupt handler to signal driver tasks. * This must not be any of the events used by the network task synchronization. */#define INTERRUPT_EVENT	RTEMS_EVENT_1/* * RTEMS event used to start transmit daemon. * This must not be the same as INTERRUPT_EVENT. */#define START_TRANSMIT_EVENT	RTEMS_EVENT_2 /* event to send when tx buffers become available */#define GRETH_TX_WAIT_EVENT  RTEMS_EVENT_3 /* suspend when all TX descriptors exhausted */ /*#define GRETH_SUSPEND_NOTXBUF */#if (MCLBYTES < RBUF_SIZE)# error "Driver must have MCLBYTES > RBUF_SIZE"#endif/* Ethernet buffer descriptor */typedef struct _greth_rxtxdesc {   volatile unsigned32 ctrl; /* Length and status */   unsigned32 *addr;         /* Buffer pointer */} greth_rxtxdesc;/* * Per-device data */struct greth_softc{   struct arpcom arpcom;      greth_regs *regs;      int acceptBroadcast;   rtems_id rxDaemonTid;   rtems_id txDaemonTid;      unsigned int tx_ptr;   unsigned int rx_ptr;   unsigned int txbufs;   unsigned int rxbufs;   greth_rxtxdesc *txdesc;   greth_rxtxdesc *rxdesc;   struct mbuf **rxmbuf;   rtems_vector_number vector;       /*    * Statistics    */   unsigned long rxInterrupts;      unsigned long rxPackets;   unsigned long rxLengthError;   unsigned long rxNonOctet;   unsigned long rxBadCRC;   unsigned long rxOverrun;      unsigned long txInterrupts;      unsigned long txDeferred;   unsigned long txHeartbeat;   unsigned long txLateCollision;   unsigned long txRetryLimit;   unsigned long txUnderrun;};static struct greth_softc greth;static char *almalloc(int sz){        char *tmp;        tmp = calloc(1,2*sz);        tmp = (char *) (((int)tmp+sz) & ~(sz -1));        return(tmp);}/* GRETH interrupt handler */static rtems_isrgreth_interrupt_handler (rtems_vector_number v){    unsigned32 status;    /* read and clear interrupt cause */    status = greth.regs->status;    greth.regs->status = status;    /* Frame received? */    if (status & (GRETH_STATUS_RXERR | GRETH_STATUS_RXIRQ))      {        greth.rxInterrupts++;        rtems_event_send (greth.rxDaemonTid, INTERRUPT_EVENT);      }#ifdef GRETH_SUSPEND_NOTXBUF    if (status & (GRETH_STATUS_TXERR | GRETH_STATUS_TXIRQ))      {        greth.txInterrupts++;        rtems_event_send (greth.txDaemonTid, GRETH_TX_WAIT_EVENT);      }#endif      /*#ifdef __leon__      LEON_Clear_interrupt(v-0x10);#endif      */}static unsigned32 read_mii(unsigned32 addr){    while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {}    greth.regs->mdio_ctrl = addr << 6 | GRETH_MDIO_READ;    while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {}    if (!(greth.regs->mdio_ctrl & GRETH_MDIO_LINKFAIL))        return((greth.regs->mdio_ctrl >> 16) & 0xFFFF);    else {	printf("greth: failed to read mii\n");	return (0);    }}static void write_mii(unsigned32 addr, unsigned32 data){    while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {}    greth.regs->mdio_ctrl =     ((data & 0xFFFF) << 16) | (addr << 8) | GRETH_MDIO_WRITE;    while (greth.regs->mdio_ctrl & GRETH_MDIO_BUSY) {}}/* * Initialize the ethernet hardware */static voidgreth_initialize_hardware (struct greth_softc *sc){    struct mbuf *m;    int i;    int fd;        greth_regs *regs;    regs = sc->regs;    /* Reset the controller.  */    greth.rxInterrupts = 0;    greth.rxPackets = 0;    regs->ctrl = 0;    regs->ctrl = GRETH_CTRL_RST;	/* Reset ON */    regs->ctrl = 0;			/* Reset OFF */        /* reset PHY and wait for complettion */    /*    */    write_mii(0, 0x8000);    while (read_mii(0) & 0x8000) {}    fd = regs->mdio_ctrl >> 24; /*duplex mode*/    printf("greth: driver attached, PHY config : 0x%04x\n", read_mii(0));    /* Initialize rx/tx descriptor pointers */    sc->txdesc = (greth_rxtxdesc *) almalloc(1024);    sc->rxdesc = (greth_rxtxdesc *) almalloc(1024);    sc->tx_ptr = 0;    sc->rx_ptr = 0;    regs->txdesc = (int) sc->txdesc;    regs->rxdesc = (int) sc->rxdesc;        sc->rxmbuf = calloc(sc->rxbufs, sizeof(*sc->rxmbuf));    for (i = 0; i < sc->txbufs; i++)      {          sc->txdesc[i].addr = (unsigned32 *) calloc(1, GRETH_MAXBUF_LEN);#ifdef GRETH_DEBUG	  printf("TXBUF: %08x\n", (int) sc->txdesc[i].addr);#endif      }    /*printf("RXbufs: %i\n", sc->rxbufs);*/    for (i = 0; i < sc->rxbufs; i++)      {          MGETHDR (m, M_WAIT, MT_DATA);          MCLGET (m, M_WAIT);	  m->m_pkthdr.rcvif = &sc->arpcom.ac_if;          sc->rxmbuf[i] = m;	  sc->rxdesc[i].addr = (unsigned32 *) mtod(m, unsigned32 *);          sc->rxdesc[i].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ;#ifdef GRETH_DEBUG	  printf("RXBUF: %08x\n", (int) sc->rxdesc[i].addr);#endif      }    sc->rxdesc[sc->rxbufs - 1].ctrl |= GRETH_RXD_WRAP;    /* set ethernet address.  */    regs->mac_addr_msb =       sc->arpcom.ac_enaddr[0] << 8 | sc->arpcom.ac_enaddr[1];    regs->mac_addr_lsb =       sc->arpcom.ac_enaddr[2] << 24 | sc->arpcom.ac_enaddr[3] << 16 |      sc->arpcom.ac_enaddr[4] << 8 | sc->arpcom.ac_enaddr[5];    /* install interrupt vector */    set_vector(greth_interrupt_handler, sc->vector, 1);    /* clear all pending interrupts */    regs->status = 0xffffffff;#ifdef GRETH_SUSPEND_NOTXBUF    regs->ctrl |= GRETH_CTRL_TXIRQ;#endif    regs->ctrl |= GRETH_CTRL_RXEN | (fd << 4) | GRETH_CTRL_RXIRQ;}static voidgreth_rxDaemon (void *arg){    struct ether_header *eh;    struct greth_softc *dp = (struct greth_softc *) &greth;    struct ifnet *ifp = &dp->arpcom.ac_if;    struct mbuf *m;    unsigned int len, len_status, bad;    rtems_event_set events;        /*printf("Started RxDaemon\n");*/    for (;;)      {        rtems_bsdnet_event_receive (INTERRUPT_EVENT,                                    RTEMS_WAIT | RTEMS_EVENT_ANY,                                    RTEMS_NO_TIMEOUT, &events);        #ifdef GRETH_ETH_DEBUG    printf ("r\n");#endif    /*printf("Packet received\n");*/            while (!((len_status =		   dp->rxdesc[dp->rx_ptr].ctrl) & GRETH_RXD_ENABLE))	    {              /*printf("Status: %x\n", dp->rxdesc[dp->rx_ptr].ctrl);*/		bad = 0;                if (len_status & GRETH_RXD_TOOLONG)		  {		      dp->rxLengthError++;		      bad = 1;		  }		if (len_status & GRETH_RXD_DRIBBLE)		  {		      dp->rxNonOctet++;		      bad = 1;		  }		if (len_status & GRETH_RXD_CRCERR)		  {		      dp->rxBadCRC++;		      bad = 1;		  }		if (len_status & GRETH_RXD_OVERRUN)		  {		      dp->rxOverrun++;		      bad = 1;		  }                if (!bad)		  {                    /*printf("Received Ok packet\n");*/		      /* pass on the packet in the receive buffer */                    len = len_status & 0x7FF;                    m = dp->rxmbuf[dp->rx_ptr];                    m->m_len = m->m_pkthdr.len =                      len - sizeof (struct ether_header);                    /*printf("Packet of length: %i\n", len);*/                    eh = mtod (m, struct ether_header *);                    m->m_data += sizeof (struct ether_header);                    /*printf("Mbuf handling done\n");*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -