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

📄 if_egl.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* if_egl.c - Interphase Eagle 4207 Ethernet network interface driver *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02l,15jul97,spm  removed calls to init routine from ioctl support (SPR #8831)02k,19may97,spm  eliminated all compiler warnings02j,15may97,spm  reverted to bcopy routines for mbufs in BSD 4.402i,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.402h,23apr93,caf  ansification: added cast to cacheInvalidate parameter.02g,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h02f,15jan93,rfs  Non-functional.  Comments and documentation changes.02e,09sep92,gae  documentation tweaks.02d,18jul92,smb  Changed errno.h to errnoLib.h.02c,08jul92,ajm  made cache safe02b,26may92,rrr  the tree shuffle                 -changed includes to have absolute path from h/02a,16jan92,gae  major cleanup: more ANSI fixes, eliminated occassional fatal                 bootrom crashes (reports only 1 in 100 receive errors),                 nearly made work on 68k, eliminated bit fields.01c,07oct91,rrr  some fixes.01b,04oct91,rrr  passed through the ansification filter                 -changed functions to ansi style                 -changed includes to have absolute path from h/                 -fixed #else and #endif                 -changed TINY and UTINY to INT8 and UINT8                 -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY & O_RDWR                 -changed VOID to void                 -changed copyright notice01a,14nov90,ajm   written for vxWorks using Unix driver as a base.*//*DESCRIPTIONGENERAL INFORMATIONThis module implements the Interphase Eagle 4207 Ethernet networkinterface driver.This driver was created to support the MIPS-based BSPs that are supportedby WRS.  It is therefore not considered generic.  It has not been verifiedto work with other BSPs, and hence is not supported for all targets.BOARD LAYOUTThe diagram below shows the relevant jumpers for VxWorks configuration.Default values: I/O address 0x00004000, Short Addressing (A16,D16)..bS______________________________              _______________________________|             P1             |  Eagle 4207  |             P2              ||                            ----------------                             ||               SW1 SW2 SW3                 JA7 -.                        ||               "   "   "                                                 ||               -   "   "                                                 ||               -   "   "                                                 ||               -   -   "                                                 ||               -   "   "                                                 ||               -   -   "                                                 ||               -   -   "                                                 ||               -   "   "                                                 ||       Short I/O Adr                                                     ||                                                                         ||                                                                         ||                                                                         ||                                                                         ||                                                                         ||                                                                         ||                                                                         ||                                                                         ||                                                                         ||_________________________________________________________________________|.bEEXTERNAL INTERFACEThis driver provides the standard external interface.There is one user-callable routine: eglattach().  See the manual entry for thisroutine for usage details.SEE ALSO: ifLib*//*Copyright (C) 1987,1988 Interphase CorporationAny use, copy or alteration is strictly prohibitedunless authorized by Interphase.Porting priveledge granted to Wind River Systems on Jan. 9, 1992 by:Rob Brant - Interphase FAE, 214-919-9110 - rbrant@iphase.com*/#include "vxWorks.h"#include "cacheLib.h"#include "net/mbuf.h"#include "net/protosw.h"#include "sys/ioctl.h"#include "sys/socket.h"#include "errnoLib.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/in_var.h"#include "netinet/if_ether.h"#include "iv.h"#include "vme.h"#include "stdlib.h"#include "memLib.h"#include "logLib.h"#include "iosLib.h"#include "intLib.h"#include "ioLib.h"#include "vxLib.h"#include "stdio.h"#include "net/if_subr.h"#include "netLib.h"#include "sysLib.h"#include "drv/netif/if_egl.h"/* Externals */IMPORT int      sysClkRateGet ();IMPORT int      sysBusIntAck ();IMPORT ULONG    tickGet ();IMPORT STATUS   taskDelay ();IMPORT FUNCPTR  etherInputHookRtn;IMPORT FUNCPTR  etherOutputHookRtn;#define NEGL    4       /* Maximum number of Eagle units supported */#define BLOCKMODE       TRUE    /* allow block mode transmisions */#define NOINT           0       /* don't want interrupt */#define INT             1       /* want interrupt */#define EGL_TOPT        (TT_NORMAL | MEMT_32BIT | VME_AM_EXT_USR_DATA)#define EGL_TOPT_BLK    (TT_BLOCK  | MEMT_32BIT | VME_AM_EXT_USR_ASCENDING)#define EGL_MTU         (ETHERMTU+18)   /* Max Packet size, 1500+14+4 */#define NUM_CQE         MAX_CQE         /* Num Command Queue Entries *//* Next two MUST be power of 2 */#define EGL_RX_NRINGS    16              /* Num LANCE Rx Rings */#define EGL_TX_NRINGS   16              /* Num LANCE Tx Rings */#define EGL_RX_BUFSZ    2000            /* Max Rx packet */#define EGL_TX_BUFSZ    2000            /* Max Tx packet */#define EGL_RX_NBUFF    20              /* Num receive buffers (max possible) */#define EGL_RX_SLOTS    20              /* Num receive workq entries */#define EGL_TX_NBUFF    16              /* Num transmit buffers */#define EGL_TX_SLOTS    16              /* Num transmit workq entries */#define EGL_RX_IOPBF    0               /* Receive IOPB starting offset */#define EGL_TX_IOPBF    (EGL_RX_IOPBF+EGL_RX_NBUFF)#define EGL_MS_SLOTS    1               /* Num misc workq entries */#define EGL_DM_SLOTS    1               /* Num DMA workq entries */#define EGL_RX_PRIORITY 1               /* Receive workq priority */#define EGL_TX_PRIORITY 1               /* Transmit workq priority */#define EGL_MS_PRIORITY 1               /* misc workq priority */#define EGL_DM_PRIORITY 1               /* DMA workq priority */#define EGL_RX_WDIV     0               /* Num receive workq processed */#define EGL_TX_WDIV     0               /* Num transmit workq processed */#define EGL_MS_WDIV     0               /* Num misc workq processed */#define EGL_DM_WDIV     0               /* Num DMA workq processed */#define EGL_NHBUF       1               /* Num Host Managed Buffers */#define EGL_NIBUF       16              /* Num Internal Tx Buffers */#define EGL_BURST       0               /* Send Whole Message */#define TXINC(x) ((x) = (ULONG)(++x&(EGL_TX_NBUFF-1)))#define TXDEC(x) ((x) = (ULONG)(--x&(EGL_TX_NBUFF-1)))#define TXFULL(x) ((x) == EGL_TX_NBUFF)typedef struct eth_buf    {    struct      eth_buf *eth_next;      /* next buffer in chain */    u_char      eth_dat[EGL_MTU];       /* data storage */    ULONG       eth_dat_adr;            /* bus address of data */    int         eth_len;                /* actual data usage */    IOPB        *iopb;                  /* associated iopb */    } ETH_BUF;#define ETH_BUF_SIZE    sizeof(ETH_BUF)#define ETH_BUF_COUNT   (EGL_RX_NRINGS + EGL_TX_NRINGS)ETH_BUF *eth_free = NULL;#define GET_ETH_BUF(buf) \        { int ms = splimp ();                   \          if (((buf)=eth_free) != NULL)         \          {                                     \                eth_free = (buf)->eth_next;     \                (buf)->eth_next = NULL;         \          }                                     \          else                                  \                panic("out of ETH buffers");    \          splx (ms);                            \        }#define REL_ETH_BUF(buf) \        { int ms = splimp ();                   \          (buf)->eth_next = eth_free;           \          eth_free = (buf);                     \          splx (ms);                            \          (buf)->eth_len = 0;                   \        }/** Invalidate the CPU cache since the start and end of an mbuf may occupy* the same secondary cache line as other data.  Even if we flush and* invalidate before performing I/O, other data in the line may have been* read, causing the old data to be placed back in the cache.  We then will* see stale data after the I/O completes (this occurred in an SA system* where the mbuf header is in the same secondary cache line as the data --* and we end up reading mbuf->m_len after invalidating the CPU cache).*/#define egl_ioflush(eth_buf) \    { \    ULONG physical = K1_TO_PHYS(((ULONG)&eth_buf->eth_dat[0])); \    cacheInvalidate (DATA_CACHE, (void *) PHYS_TO_K0(physical), \                     eth_buf->eth_len); \    }int eglAM       = VME_AM_EXT_USR_DATA;  /* 32-bit addresses */int eglMemWidth = 4;                    /* VME bcopy transfers = 1,2,4 */int delay_mult = 13;    /* tuned on the STAR MVP (VLANE = 1) *//* * DELAY(n) should be n microseconds, roughly. * [taskDelay(1) at 60Mhz == 16666 usecs.] */#define DELAY(n)        { \        register int ix = delay_mult*(n); \        while (--ix > 0); \        }/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, egl_if, * which the routing code uses to locate the interface.  This structure * contains the output queue for the interface, its address, ... */typedef struct egl_softc {    struct arpcom egl_ac;       /* Ethernet Common Part */#define egl_if          egl_ac.ac_if     /* network-visible interface */#define egl_enaddr      egl_ac.ac_enaddr /* hardware Ethernet address */    SHIO        *eglAddr;       /* Pointer to I/O Space */    USHORT      xmit_vec;       /* Transmit Interrupt Vector */    USHORT      xmiterr_vec;    /* Transmit Error Interrupt Vector*/    USHORT      rcv_vec;        /* Receive Interrupt Vector */    USHORT      rcverr_vec;     /* Receive Error Interrupt Vector*/    USHORT      qav_vec;        /* Queue Available Interrupt Vector */    ETH_BUF     *egl_tbinfo[EGL_TX_NBUFF]; /* phys addrs of txbufs */    ETH_BUF     *egl_rbinfo[EGL_RX_NBUFF]; /* phys addrs of rxbufs */    ULONG       egl_txadd;      /* add index to xmit packet ring */    ULONG       egl_txrem;      /* remove index to xmit packet ring */    CQE         *egl_cqe;       /* index for feed queue */    ULONG       egl_qmode;      /* queue mode is started */    ULONG       egl_qfull;      /* feed queue is full */    ULONG       egl_txcnt;      /* # of mbufs queued in tbuf array */    ULONG       egl_quecnt;     /* # of transmit commands queued on Eagle */    ULONG       egl_csr0miss;   /* driver count of receive misses */    ULONG       egl_csr0mem;    /* driver count of LANCE memory errors */    CSTB        egl_cstb;       /* Firmware info */    int         eglIntLevel;    /* VME interrupt level */    int         eglIntVec;      /* VME interrupt vector */    CSB         CSBstats;       /* copy of CSB for tracking statistics */} EGL_SOFTC;LOCAL EGL_SOFTC *egl_softc [NEGL];#if     CPU_FAMILY!=MIPS#define sysWbFlush()#define K0_TO_PHYS(x)   (x)#define K1_TO_PHYS(x)   (x)#define  PHYS_TO_K0(x)   (x)#define PHYS_TO_K1(x)   (x)#endif  /* CPU_FAMILY!=MIPS *//* * Macros to set various bits in Queue Entry Control Register (QECR) * of the Command Queue Entry (CQE). *//* Tell Eagle to initiate action on this cqe */#define CQE_GO(qecr)            { sysWbFlush(); qecr = M_QECR_GO; }/* Check if cqe is available */#define CQE_BUSY(qecr)  (qecr & M_QECR_GO)/* Clear cqe GO bit; when should host be doing this??? */#define CQE_CLR_BUSY(qecr)      { sysWbFlush(); qecr &= ~M_QECR_GO; }/* Indicate that any commands that are queued up should be aborted on error */#define CQE_AA_GO(qecr) { sysWbFlush(); qecr |= (M_QECR_GO + M_QECR_AA);}/* Get the next command queue entry in the command queue XXX bad macro */#define INC_CQE(cqe) ((x)==&shio->sh_CQE[NUM_CQE-1] ? &shio->sh_CQE[0] ? cqe+1)/* * Macros to check/set bits in the Command Response Status (CRSW) field of the * Command Response Block (CRB). *//* clear the crsw */#define CRB_CLR_DONE(crsw)       { crsw = 0; sysWbFlush(); }/*#define CRB_CLR_DONE(crsw)     { crsw &= ~M_CRSW_CRBV; sysWbFlush();}*//* Check if command is done */#define CRB_DONE(crsw)          (crsw & M_CRSW_CRBV)/* Check is the command represented by this CRB is done. */#define CRB_COMPLETE(crsw)       (crsw & (M_CRSW_CRBV | M_CRSW_CC))/* Check if the command to start queue mode has completed. */#define CRB_QSTARTED(crsw)      (crsw & (M_CRSW_CRBV | M_CRSW_QMS))/* Check if this command queue entry is available. */#define CRB_QAVAIL(crsw)        (crsw & (M_CRSW_CRBV | M_CRSW_QEA))#define CRB_ERROR(crsw)         (crsw & (M_CRSW_ER | M_CRSW_EX))/* Define to display error/status messages. */#undef EGL_DEBUG/* forward declarations */int eglattach ();int eglShow (int unit, BOOL zap);static int  egl_config (int unit, int itype);static int  egl_hangrcv (int unit, int index);static int  egl_init (int unit);static void egl_intr (int unit);static int  egl_ioctl (struct ifnet *ifp, int cmd, caddr_t data);static int  egl_iworkq (int unit, int itype);#ifdef BSD43_DRIVERstatic int  egl_output (struct ifnet *ifp,struct mbuf *m0,struct sockaddr *dst);#endifstatic int  egl_physreset (int unit);static void egl_qint (int unit, EGL_SOFTC *egl);static void egl_recv (int unit, int len, ETH_BUF *eth_buf);static int  egl_reset (int unit);static void egl_rint (int unit, EGL_SOFTC *egl, int index, int len);static void egl_setiopbs (int unit);#ifdef BSD43_DRIVERstatic void egl_start (int unit);#elsestatic void egl_start (EGL_SOFTC *egl);#endifstatic void egl_tint (int unit, EGL_SOFTC *egl, int index);static int  egl_wait (volatile CRB *crb);/********************************************************************************* eglattach - publish the interface, and initialize the driver and device** This routine attaches an `egl' Ethernet interface to the network if the* interface exists.  The routine makes the interface available by filling in* the network interface record.  The system will initialize the interface* when it is ready to accept packets.** RETURNS: OK or ERROR.*/int eglattach    (    int unit,           /* unit number */    char *addr,         /* address of Eagle's shared memory */    int ivec,           /* interrupt vector to connect to */    int ilevel          /* interrupt level */    )    {    EGL_SOFTC *egl;    ETH_BUF *eth_buf;    int ix;    USHORT status;    char *pool;    volatile SHIO *pEglDev = (SHIO *) addr;#ifdef EGL_DEBUG    printf ("egl%d: attaching at vector = %d, level = %d, addr = %#x\n",             unit, ivec, ilevel, addr);#endif  /* EGL_DEBUG */    /* wait for kernel reset to finish */    ix = 15 * sysClkRateGet () / 2;     /* 15 seconds (1/30th sec. below) */    while (vxMemProbe ((char *) &pEglDev->sh_MCSB, O_RDONLY,                        sizeof (USHORT), (char *)&status) != OK)        {        if (--ix < 0)            {            errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);#ifdef EGL_DEBUG            printf (            "eglattach: controller not present at %#x, status register = %#x\n",                    addr, status);#endif            return (ERROR);            }        taskDelay (sysClkRateGet () / 30);      /* 1/30th of a second */        }    pool = (char*)calloc (1, (ETH_BUF_COUNT + 1) * ETH_BUF_SIZE);    if (pool == NULL)        return (ERROR);    pool = (char *)((int)pool+ETH_BUF_SIZE - ((int)pool & (ETH_BUF_SIZE - 1)));    eth_buf = (ETH_BUF *)pool;    for (ix = 0; ix < ETH_BUF_COUNT; ix++)        {        REL_ETH_BUF(eth_buf);        if (sysLocalToBusAdrs (eglAM, &eth_buf->eth_dat[0],                               (char **)&eth_buf->eth_dat_adr) == ERROR)            {#ifdef EGL_DEBUG            printf ("egl: local address %#x to bus address (AM = %#x) failed\n",                    &eth_buf->eth_dat[0], eglAM);#endif            return (ERROR);            }        eth_buf++;        }    /* allocate and initialize Eagle descriptor */    egl = (EGL_SOFTC *) calloc (1, sizeof (EGL_SOFTC));    if (egl == NULL)        return (ERROR);    egl_softc [unit] = egl;             /* set ptr to egl descriptor in array */    egl->eglAddr = (SHIO *) addr;               /* remember device address */    /* reset the device */    if (egl_physreset (unit) != 0)        {#ifdef EGL_DEBUG        printf ("egl%d: reset failure.\n", unit);#endif        errnoSet (S_ioLib_DEVICE_ERROR);        return (ERROR);        }    bcopy ((char*)&pEglDev->sh_CSTB, (char*)&egl->egl_cstb, sizeof(CSTB));    bzero ((char*)egl->egl_cstb.cstb_FILT, sizeof(egl->egl_cstb.cstb_FILT));    /* configure the settings */    if (egl_config (unit, NOINT) == -1)        {#ifdef EGL_DEBUG        printf ("egl%d: configuration failure.\n", unit);#endif        errnoSet (S_ioLib_DEVICE_ERROR);        return (ERROR);        }    egl->xmit_vec    = LVL_VCT(ilevel,ivec+0);    egl->xmiterr_vec = LVL_VCT(ilevel,ivec+1);    egl->rcv_vec     = LVL_VCT(ilevel,ivec+2);    egl->rcverr_vec  = LVL_VCT(ilevel,ivec+3);    egl->qav_vec     = LVL_VCT(ilevel,ivec+4);    bcopy ((char*)egl->egl_cstb.cstb_PHY, (char*)egl->egl_enaddr,          sizeof(egl->egl_cstb.cstb_PHY));    egl->eglIntLevel = ilevel;    egl->eglIntVec   = ivec;#ifdef BSD43_DRIVER    ether_attach (&egl->egl_if, unit, "egl", egl_init, egl_ioctl,                    egl_output, egl_reset);#else

⌨️ 快捷键说明

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