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

📄 if_xdssonic.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: if_xdssonic.c,v 1.5 1998/12/28 14:13:00 nigel Exp $ *//* *	if_sonic.c: National Semiconductor SONIC Driver *	 *	Copyright (c) 1992 ALGORITHMICS LIMITED  *	ALL RIGHTS RESERVED  *	 *	THIS SOFTWARE PRODUCT CONTAINS THE UNPUBLISHED SOURCE *	CODE OF ALGORITHMICS LIMITED *	 *	The copyright notices above do not evidence any actual  *	or intended publication of such source code. *	 */#define DEBUG#ifndef INET#define INET#endif#include "sys/param.h"#include "sys/systm.h"#include "sys/mbuf.h"#include "sys/protosw.h"#include "sys/socket.h"#include "sys/errno.h"#include "sys/uio.h"#include "sys/ioctl.h"#include "sys/syslog.h"#include "net/if.h"#include "net/if_types.h"#include "net/netisr.h"#include "net/route.h"#ifdef INET#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#endif#include "mips.h"#include "sbd.h"#include "if_sonic.h"#define NSONIC		1	/* number of sonics */#define TINYFRAG	12	/* tx frags < this size count as "tiny" */#define MAXTINIES	3	/* max "tiny" frags, after which we compress */#define SNRETRIES	5	/* max retries on fatal tx errors */#define DBG_TXPKT	0x02#define DBG_RXPKT	0x04int T_sn = 0;#define T_txp		(T_sn & DBG_TXPKT)#define T_rxp		(T_sn & DBG_RXPKT)#ifdef R4000#ifdef XDS#define clean_dcache	mips_clean_dcache#else#define clean_dcache	mips_clean_dcache#endif#else#define clean_dcache	r3k_dclean#endif#define MASK(x)		((x) & 0xffff)/*  * Statistics collected over time  * (same order as enpstats) */struct sn_stats {    int ss_tpacks;		/* transmit ok */    int ss_tmore;		/* transmit more than one retry */    int ss_tone;		/* transmit one retry */    int ss_cerr;		/* transmit failed after retries */    int ss_tdef;		/* transmit deferred */    int ss_tbuff;		/* transmit buffer errors */    int ss_tuflo;		/* transmit silo underflow */    int ss_tlcol;   		/* transmit late collisions */    int ss_tlcar;		/* transmit lost carriers */    int ss_babl;		/* transmit babbling */    int	ss_noheart;		/* transmit no heartbeat */    int ss_tmerr;		/* transmit memory error */    int ss_rpacks;		/* receive ok */    int ss_miss;		/* receive missed packets */    int ss_rcrc;		/* receive crc errors */    int ss_rfram;		/* receive framing errors */    int ss_rbuff;		/* receive buffer errors */    int ss_roflo;		/* receive silo overflow */    int ss_rmerr;		/* receive memory error */};static struct sn_softc {    struct arpcom	sn_ac;#define	sn_if		sn_ac.ac_if	/* network visible interface */#define	sn_enaddr	sn_ac.ac_enaddr	/* hardware ethernet address */    volatile struct sn_reg *sn_csr;	/* hardware pointer */    int 		sn_rxmark;	/* index in rx ring */    int			sn_rramark;	/* index into rra of wp */    volatile struct RXpkt *sn_lrxp;	/* last RDA available to chip */    int			sn_retries;	/* transmit retries */    int			sn_rbe;		/* had an RBE signal */    struct sn_stats	sn_sum;		/* software maintained stats */    u_int		sn_crct;	/* crc tally from chip */    u_int		sn_faet;	/* frame error tally from chip */    u_int		sn_mpt;		/* missed packet tally from chip */    int			sn_rev;		/* chip revision number */} sn_softc[NSONIC];/* Public functions from outside this module */static int	snifinit (int unit);static int	snioctl (struct ifnet *ifp, int cmd, caddr_t data);static int	snifstart (struct ifnet *ifp);static int	snwatch (int unit);static int	snreset (int unit);static void	snintr (int unit);/* Local functions */static int	snrestart (struct sn_softc *sn);static int	snstartup (struct sn_softc *sn);static int	snclosedown (struct sn_softc *sn);static int	snput (struct sn_softc *sn, struct mbuf *m0);static void	sntxint (struct sn_softc *);static void	sntxdump (volatile struct TXpkt *txp);static void	snrxint (struct sn_softc *);static int	snerrint (struct sn_softc *, u_int isr);static struct mbuf *snget (struct sn_softc *sn, caddr_t addr, 			   int dlen, int toff, int tlen);static int	snread (struct sn_softc *, volatile struct RXpkt *);static struct mbuf *sn_fillup (struct mbuf *m0, int minlen);static void	caminitialise (void);static void	camentry (int, u_char *ea);static int	camprogram (struct sn_softc *);static int	allocatebuffers (void);static void	initialise_tda (struct sn_softc *);static void	initialise_rda (struct sn_softc *);static void	initialise_rra (struct sn_softc *);#ifdef MIPSELstatic void	snswapb (u_char *s, u_char *d, int len);static struct mbuf *snswapm (struct mbuf *m);#endifstatic void copy_data_to_host (caddr_t sp, caddr_t dp, int len);static void copy_host_to_data (caddr_t sp, caddr_t dp, int len);static void xds_compress_buffer (caddr_t addr, int len);static void xds_expand_buffer (caddr_t addr, int len);static void sonictxdump (char *msg, struct TXpkt *txp);static void sonicdump (char *msg, volatile struct sn_reg *csr);#if defined(XDSSONICBUG)/* * SONIC buffers need to be aligned 64 bit aligned. * These macros calculate and verify alignment. */#define SONICDW		64#define SONICALIGN	(SONICDW/16)#else/* * SONIC buffers need to be aligned 16 or 32 bit aligned. * These macros calculate and verify alignment. */#define SONICDW		32#define SONICALIGN	(SONICDW/8)#endif#ifdef XDSSONICBUG#define UPPER(x)	(K0_TO_PHYS((x)) >> 17)#define LOWER(x)	((((unsigned int)(x)) >> 1) & 0xffff)#else#define UPPER(x)	(K0_TO_PHYS((x)) >> 16)#define LOWER(x)	(((unsigned int)(x)) & 0xffff)#endif/* * buffer sizes in 32 bit mode * 1 TXpkt is 4 hdr words + (3 * FRAGMAX) + 1 link word  * FRAGMAX == 16 => 54 words == 216 bytes * * 1 RxPkt is 7 words == 28 bytes * 1 Rda   is 4 words == 16 bytes */#define NRRA	32		/* # receive resource descriptors */#define RRAMASK	(NRRA-1)	/* why it must be power of two */#define NRBA	16		/* # receive buffers < NRRA */#define NRDA	NRBA		/* # receive descriptors */#define NTDA	4		/* # transmit descriptors */#define CDASIZE sizeof(struct CDA)#define RRASIZE (NRRA*sizeof(struct RXrsrc))#define RDASIZE (NRDA*sizeof(struct RXpkt))#define TDASIZE (NTDA*sizeof(struct TXpkt))/* size of FCS (CRC) appended to received packets */#define FCSSIZE	4		/* buffer size (enough for 1 max packet 1520 up to cache line boundary) */#ifdef XDSSONICBUG#define RBASIZE	(1536*2)#else#define RBASIZE	1536#endif#ifdef XDS/* * transmit data must be copied into SRAM */#define TBASIZE	RBASIZE#endif/* eobc set for only one packet per buffer */#define EOBC	1520		/* Assumes 32 bit operation *//* total buffer size needed for all descriptors */#define SONICBUFSIZE	((RRASIZE+CDASIZE+RDASIZE+TDASIZE)*2 + SONICALIGN - 1)/* * aligned pointers into sonic buffers */static volatile struct RXrsrc	*rra;	/* receiver resource descriptors */static volatile struct RXpkt	*rda;	/* receiver desriptors */static volatile struct TXpkt	*tda;	/* transmitter descriptors */static volatile struct CDA	*cda;	/* CAM descriptors *//* * receive buffers for sonic accessed by SONIC  * each buffer will hold one ethernet packet */static char	*rba;#ifdef XDSstatic char	*tba;#endif/* Meta transmit descriptors */static struct mtd {  struct mtd		*mtd_link;  volatile struct TXpkt	*mtd_txp;  struct mbuf		*mtd_mbuf;#ifdef XDS  char			*mtd_tba;#endif} mtda[NTDA];static struct mtd *mtdfree;	/* list of free meta transmit descriptors */static struct mtd *mtdhead;	/* head of descriptors assigned to chip */static struct mtd *mtdtail;	/* tail of descriptors assigned to chip */static struct mtd *mtdnext;	/* next descriptor to give to chip */static struct mtd *mtd_alloc (void);static void mtd_free (struct mtd *);static void sntxdone (struct sn_softc *, struct mtd *);/* * eninit(): initialise ethernet * check to see if sonic chip is on the machine  */inteninit (){    int unit = 0;    struct sn_softc *sn = &sn_softc[unit];    struct ifnet *ifp = &sn->sn_if;    volatile struct sn_reg *csr;    int timeout;    u_short dcr;    csr = (struct sn_reg *) PHYS_TO_K1 (SONIC_BASE);        log (LOG_DEBUG, "eninit starting\n");    /* reset Sonic chip */#if defined(XDS)    *(u_int *) PHYS_TO_K1 (VME_SONIC_RES) = RESET_ACTIVE; wbflush ();    DELAY(1000);    *(u_int *) PHYS_TO_K1 (VME_SONIC_RES) = RESET_INACTIVE; wbflush ();#elif defined(P4000)    *(u_int *) PHYS_TO_K1 (NET_RESET_) = RESET_ZERO; wbflush();    DELAY(1000);    *(u_int *) PHYS_TO_K1 (NET_RESET_) = RESET_ONE; wbflush();#else    /* other Algorithmics boards */    *(u_int *) PHYS_TO_K1 (BCRR) &= ~BCRR_ETH; wbflush();    DELAY(1000);    *(u_int *) PHYS_TO_K1 (BCRR) |= BCRR_ETH; wbflush();#endif    DELAY(1000);    if (!(csr->s_cr & CR_RST)) {	log (LOG_ERR, "sonic: did not reset\n");	return;    }    /* config it */    dcr = DCR_ASYNC|DCR_WAIT0|DCR_DW32|DCR_DMABLOCK|DCR_RFT24|DCR_TFT24;    csr->s_dcr = dcr; wbflush();    if ((csr->s_dcr & ~(DCR_USR1|DCR_USR0)) != dcr) {	log (LOG_ERR, "sonic: cannot configure\n");	return;    }    csr->s_imr = 0; wbflush();    sn->sn_rev = csr->s_sr;    ifp = &sn->sn_if;    ifp->if_name	= "en";    ifp->if_unit	= unit;    if (sbdethaddr (sn->sn_enaddr) < 0) {      return;    }    log (LOG_INFO, "%s%d: rev %d, ethernet address: %s\n", 	 sn->sn_if.if_name, sn->sn_if.if_unit, sn->sn_rev, 	 ether_sprintf (sn->sn_enaddr));    /* network management */    ifp->if_type	= IFT_ETHER;    ifp->if_addrlen	= 6;    ifp->if_hdrlen	= 14;    ifp->if_mtu		= ETHERMTU;    ifp->if_flags	= IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;#ifdef DEBUG        ifp->if_flags	|= IFF_DEBUG;#endif    ifp->if_init	= snifinit;    ifp->if_output	= ether_output;		    ifp->if_start	= snifstart;		    ifp->if_ioctl	= snioctl;    ifp->if_watchdog	= snwatch;    ifp->if_reset	= snreset;    ifp->if_timer	= 0;    sn->sn_csr = csr;    if_attach (ifp);#ifdef PROM    if_newaddr(ifp, IFT_ETHER, (caddr_t)((struct arpcom *)ifp)->ac_enaddr);#else#if defined(P4000) && defined(USEINTS)    sbd_setvec (CR_HINT0, IRR(0,IRR0_NET), snintr, unit);#endif    log (LOG_DEBUG, "eninit completed\n");}/* * snifinit: initialise interface. */static intsnifinit (unit)    int unit;{#ifdef notdef    /* let SIOCSIFADDR/FLAGS do the job */    if (unit < NSONIC) {	register struct sn_softc *sn = &sn_softc[unit];	int s = splimp ();	if (snstartup (sn) == 0)	  sn->sn_if.if_flags |= IFF_UP;	(void) splx (s);    }#endif}/* * snioctl: process an ioctl request. */static intsnioctl (struct ifnet *ifp, int cmd, caddr_t data){    struct ifaddr *ifa = (struct ifaddr *)data;    struct ifreq  *ifr = (struct ifreq *)data;    struct sn_softc *sn = &sn_softc[ifp->if_unit];    char *bp;    int error = 0;    int s = splimp();    switch (cmd) {    case SIOCPOLL:	if (ifp->if_flags & IFF_RUNNING)	  snintr (ifp->if_unit);	break;    case SIOCSIFADDR: 	ifp->if_flags |= IFF_UP;	switch (ifa->ifa_addr->sa_family) {#ifdef INET	case AF_INET:	    if (!(error = snstartup (sn))) {		((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;#ifdef PROM		if (IA_SIN(ifa)->sin_addr.s_addr != INADDR_ANY &&		    (IA_SIN(ifa)->sin_addr.s_addr >> IN_CLASSA_NSHIFT)		    != IN_LOOPBACKNET)#endif		    arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);	    }	    break;#endif INET#ifdef NS	case AF_NS:	    {		register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);				if (ns_nullhost(*ina))		  ina->x_host = *(union ns_host *)(ns->ns_addr);		else {		    /* force reset of controller for new address */		    snclosedown (sn);		    bcopy((caddr_t)ina->x_host.c_host,			  (caddr_t)ns->ns_addr, sizeof(ns->ns_addr));		}		error = snstartup (sn);		break;	    }#endif	default:	    error = snstartup (sn);	    break;	}	break;  case SIOCSIFFLAGS:	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) 	  /* UP switched on, but not RUNNING: start up interface */	  error = snstartup (sn);	else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING)	  /* UP switched off, but still RUNNING: close down interface */	  snclosedown (sn);	break;    default: 	error = EINVAL;  }  splx (s);  return (error);}static intsnreset (int unit){    struct sn_softc *sn = &sn_softc[unit];    if (sn->sn_if.if_flags & IFF_UP)      snrestart (sn);}/* * snrestart(): reset and restart the SONIC  * * Called in case of fatal hardware/software errors. */static intsnrestart (struct sn_softc *sn){    int isup = sn->sn_if.if_flags & IFF_UP;    int error;    snclosedown(sn);    error = snstartup(sn);    if (error == 0 && isup) {	/* restart dequeing of tx packets */	sn->sn_if.if_flags |= IFF_UP;	snifstart (&sn->sn_if);    }    return error;}static intsnstartup (struct sn_softc *sn){    volatile struct sn_reg *csr = sn->sn_csr;    u_short rcr;    int error, s;        if (!csr)      /* no such device */      return ENXIO;    if (!sn->sn_if.if_addrlist)      /* no addresses */      return EINVAL;    if (sn->sn_if.if_flags & IFF_RUNNING)      /* already running */      return (0);        s = splhigh ();#if 0    /* unreset it */#if defined(XDS)    *(u_int *) PHYS_TO_K1 (VME_SONIC_RES) = RESET_INACTIVE; wbflush ();#elif defined(P4000)    *(u_int *) PHYS_TO_K1 (NET_RESET_) = RESET_ONE; wbflush();#else    *(u_int *) PHYS_TO_K1 (BCRR) |= BCRR_ETH; wbflush();#endif    DELAY(1000);#endif    if (!(csr->s_cr & CR_RST)) {	error = EIO;	goto bad;    }    log (LOG_INFO, "%s%d: starting interface\n",	 sn->sn_if.if_name, sn->sn_if.if_unit);    /* config it */#if defined(XDS)    csr->s_dcr = DCR_ASYNC|DCR_WAIT1|DCR_DW32|DCR_RFT24|DCR_TFT16;#elif defined(P4000)    csr->s_dcr =       DCR_EXBUS|DCR_LBR|	DCR_ASYNC|DCR_WAIT0|DCR_DW32|DCR_DMABLOCK|DCR_RFT24|DCR_TFT16;#else    csr->s_dcr = 	DCR_ASYNC|DCR_WAIT0|DCR_DW32|DCR_DMABLOCK|DCR_RFT24|DCR_TFT16;#endif/*    csr->s_dcr2 = 0;*/    wbflush ();    rcr = RCR_BRD|RCR_LBNONE;    if (sn->sn_if.if_flags & IFF_PROMISC)      rcr |= RCR_PRO;    csr->s_rcr = rcr;    /* set interrupt mask */    csr->s_imr =      IMR_BREN | IMR_PTXEN | IMR_TXEREN | IMR_HBLEN |	IMR_PRXEN | IMR_RDEEN | IMR_RBAEEN | IMR_RFOEN |	  IMR_CRCEN | IMR_FAEEN | IMR_MPEN;

⌨️ 快捷键说明

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