📄 if_lnsgi.c
字号:
/* if_lnsgi.c - AMD Am7990 LANCE Ethernet (for SGI) network interface driver *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01k,15jul97,spm removed driver initialization from ioctl support (SPR #8831); added ARP request to SIOCSIFADDR ioctl handler01j,08apr97,spm removed compiler warnings, and errors from changes in if_ln.h01i,07apr97,spm code cleanup, corrected statistics, and upgraded to BSD 4.401h,11aug93,jmm Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h01g,22feb93,jdi documentation cleanup.01f,09sep92,gae documentation tweaks.01e,29jul92,rfs Moved driver specific items here from the header file.01d,22jul92,gae fixed number of parameters to logMsg().01c,23jun92,ajm upgraded to 5.1, ansiized.01b,28apr92,ajm changed lnEnetAddr to lnsgiEnetAddr for board specific driver01a,30mar92,ajm modified if_ln.c 01x for SGI VIP10, becomes target specific*//*DESCRIPTIONThis module implements theAdvanced Micro Devices Am7990 LANCE Ethernet network interface driver for theSilicon Graphics VIP10 board. The only user-callable routine is lnsgiattach(),which publishes the `lnsgi' interface and initializes the driver and device.This driver is a special variant of if_ln, designed for the Silicon Graphics (SGI) VIP10 board.BOARD LAYOUTThis device is on-board. No jumpering diagram is necessary.SEE ALSO: ifLib*/#include "vxWorks.h"#include "iv.h"#include "memLib.h"#include "cacheLib.h"#include "sys/ioctl.h"#include "intLib.h"#include "logLib.h"#include "netLib.h"#include "taskLib.h"#include "etherLib.h"#include "net/mbuf.h"#include "net/protosw.h"#include "net/unixLib.h"#include "sys/socket.h"#include "errno.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#include "net/if_subr.h"#include "drv/netif/if_ln.h"/***** LOCAL DEFINITIONS *****/#define RMD_SIZ sizeof(ln_rmd)#define TMD_SIZ sizeof(ln_tmd)/* Configuration items */#define LN_MIN_FIRST_DATA_CHAIN 96 /* min size of 1st buf in data-chain */#define LN_MAX_MDS 128 /* max number of [r|t]md's for LANCE */#define LN_BUFSIZE (ETHERMTU + sizeof (struct ether_header) + 6)#define LN_RMD_RLEN 5 /* ring size as a power of 2 -- 32 RMD's */#define LN_TMD_TLEN 5 /* same for transmit ring -- 32 TMD's */#define LN_NUM_RESERVES 8 /* have up to 8 reserved RMD's for loans */#define MAX_LN 1 /* max number of LANCE chips on board *//* * If LN_KICKSTART_TX is TRUE the transmitter is kick-started to force a * read of the transmit descriptors, otherwise the internal polling (1.6msec) * will initiate a read of the descriptors. This should be FALSE is there * is any chance of memory latency or chip accesses detaining the LANCE DMA, * which results in a transmitter UFLO error. This can be changed with the * global lnKickStartTx below. */#define LN_KICKSTART_TX FALSE /* TRUE: kick-start transmitter, FALSE: wait for internal poll *//* The definition of the driver control structure */typedef struct ls_softc { struct arpcom ls_ac; /* ethernet common part */ ln_ib *ib; /* ptr to Initialization Block */ struct { int r_po2; /* RMD ring size as a power of 2! */ int r_size; /* RMD ring size (power of 2!) */ int r_index; /* index into RMD ring */ ln_rmd *r_ring; /* RMD ring */ char *r_bufs; /* receive buffers base */ } rmd_ring; struct { int t_po2; /* TMD ring size as a power of 2! */ int t_size; /* TMD ring size (power of 2!) */ int t_index; /* index into TMD ring */ int d_index; /* index into TMD ring */ ln_tmd *t_ring; /* TMD ring */ char *t_bufs; /* transmit buffers base */ } tmd_ring; u_char ls_flags; /* misc control flags */ int ivec; /* interrupt vector */ int ilevel; /* interrupt level */ LN_DEVICE *devAdrs; /* device structure address */ char *memBase; /* LANCE memory pool base */ int memWidth; /* width of data port */ int csr0Errs; /* count of csr0 errors */ int bufSize; /* size of buffer in the LANCE ring */ BOOL canLoanRmds; /* can we loan out rmd's as clusters? */ char *freeBufs[LN_NUM_RESERVES]; /* available reserve buffers */ int nFree; /* number of free reserve buffers */ u_char loanRefCnt[LN_MAX_MDS]; /* reference counts for loaned RMD's */ } DRV_CTRL;#define DRV_CTRL_SIZ sizeof(DRV_CTRL)/* Definitions for the flags field */#define LS_PROMISCUOUS_FLAG 0x1#define LS_MEM_ALLOC_FLAG 0x2#define LS_PAD_USED_FLAG 0x4#define LS_RCV_HANDLING_FLAG 0x8#define LS_START_OUTPUT_FLAG 0x10/* Shorthand structure references */#define ls_if ls_ac.ac_if /* network-visible interface */#define ls_enaddr ls_ac.ac_enaddr /* hardware ethernet address */#define ls_rpo2 rmd_ring.r_po2#define ls_rsize rmd_ring.r_size#define ls_rindex rmd_ring.r_index#define ls_rring rmd_ring.r_ring#define ls_tpo2 tmd_ring.t_po2#define ls_tsize tmd_ring.t_size#define ls_tindex tmd_ring.t_index#define ls_dindex tmd_ring.d_index#define ls_tring tmd_ring.t_ring#define LN_RMD_GIVE_TO_LANCE(pRmd) \ { \ pRmd->lnRMD1 &= 0xff; \ pRmd->rbuf_mcnt = 0; \ pRmd->lnRMD1 |= lnrmd1_OWN; \ }/** The following macros let the MIPS architecture allocate and free dymanic* memory from uncached space. The calls calloc, and cfree do the same* as malloc, and free, they are merely there to aviod macro recursion.*/#define malloc(x) K0_TO_K1(calloc((size_t) (x),\ (size_t) sizeof(char)))#define free(x) cfree((void *) (K1_TO_K0((x))))#define cacheClearEntry(x,y)#define EMAP_ADDR 0xbf920802 /* memory map memory */LOCAL volatile u_short *pEmap = (volatile u_short *) EMAP_ADDR;/* buffer address to emap translation */#define EMAP_PG_SZ (4096)#define EMAP_OFFSET(index) ((index) << 1)#define EMAP_VALUE(buffaddr) ((u_int)(buffaddr) >> 12)/* lance address to physical translation */#define EMAP_PG(addr) (((addr) >> 12) & 0xff)#define EMAP_ENTRY(addr) (pEmap[(EMAP_PG(addr))])#define EADDR(addr) (((EMAP_ENTRY(addr)) << 12) | \ ((u_int)(addr) & 0xfff))#define LNADDR(index,addr) (((index) << 12) | ((u_int)(addr) & 0xfff))/* emap indexes */#define EMAPLEN 256#define IBUF_SZ 2#define RBUF_SZ 64#define TBUF_SZ 64#define RBUF_INDEX 0 /* location of init block */#define TBUF_INDEX (RBUF_INDEX + RBUF_SZ) /* location of rec mbufs */#define IBUF_INDEX (TBUF_INDEX + TBUF_SZ) /* location of xmit mbufs *//* imports */IMPORT void sysWbFlush ();IMPORT void sysLanIntEnable (int ilevel);IMPORT unsigned char lnsgiEnetAddr []; /* ethernet address to load into LANCE *//* globals */int lnsgiLogCount = 0;/* locals */LOCAL int lnTsize = LN_TMD_TLEN; /* deflt xmit ring size as power of 2 */LOCAL int lnRsize = LN_RMD_RLEN; /* deflt recv ring size as power of 2 */LOCAL struct ls_softc *ls_softc [MAX_LN];LOCAL u_int RAPOffset = 128; /* XXX initially 1, calculated in lnReset */LOCAL u_int CSROffset = 0; /* XXX initially 0, calculated in lnReset *//* forward declarations */static int lnInit (int unit);static int lnIoctl (struct ifnet *ifp, int cmd, caddr_t data);#ifdef BSD43_DRIVERstatic int lnOutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst);#endifstatic void lnReset(int unit);static ln_rmd *lnGetFullRMD (struct ls_softc *ls);static ln_tmd *lnGetFreeTMD (struct ls_softc *ls);static STATUS lnRecv (struct ls_softc *ls, ln_rmd *rmd);static void lnChipInit (struct ls_softc *ls);static void lnChipReset (struct ls_softc *ls);static void lnConfig (struct ls_softc *ls);static void lnHandleCsr0Err (struct ls_softc *ls, u_short status);static void lnHandleRecvInt (struct ls_softc *ls);static void lnInt (struct ls_softc *ls);static void lnRmdFree (struct ls_softc *ls, char *pBuf);#ifdef BSD43_DRIVERstatic void lnStartOutput (int unit);#elsestatic void lnStartOutput (DRV_CTRL *ls);#endifstatic void lnCsrWrite (struct ls_softc *ls, int reg, u_short value);static u_short lnCsrRead (struct ls_softc *ls, int reg);static void lnCsrIntWrite (struct ls_softc *ls, int reg, u_short value);static u_short lnCsrIntRead (struct ls_softc *ls, int reg);/********************************************************************************* lnsgiattach - publish the `lnsgi' network interface and initialize the driver and device** This routine attaches an `lnsgi' Ethernet interface to the network if the* interface exists. It makes the interface available by filling in* the network interface record. The system will initialize the interface* when it is ready to accept packets.** The <memAdrs> parameter specifies the location of the interface memory pool;* if NONE, the memory pool will be malloc'ed.** The <memWidth> parameter sets the memory pool's data port width (in bytes);* if NONE, any data width will be used.** BUGS* To zero out LANCE data structures, this routine uses bzero(), which* ignores the <memWidth> specification and uses any size data access to* write to memory.** RETURNS: OK or ERROR.*/STATUS lnsgiattach ( int unit, /* unit number */ char *devAdrs, /* LANCE i/o address */ int ivec, /* interrupt vector */ int ilevel, /* interrupt level */ char *memAdrs, /* address of memory pool (-1 = malloc it) */ ULONG memSize, /* only used if memory pool is NOT malloc()'d */ int memWidth, /* byte-width of data (-1 = any width) */ BOOL usePadding, /* use padding when accessing RAP? */ int bufSize /* size of a buffer in the LANCE ring */ ) { FAST DRV_CTRL * ls; FAST struct ifnet *ifp; FAST unsigned int sz; /* temporary size holder */ char *memPool; /* start of the LANCE memory pool */ if (bufSize == 0) bufSize = LN_BUFSIZE; if ((int) memAdrs != NONE) /* specified memory pool */ { /* * With a specified memory pool we want to maximize * lnRsize and lnTsize */ sz = (memSize - (sizeof (ln_rmd) + sizeof (ln_tmd) + sizeof (ln_ib))) / ((2 * bufSize) + sizeof (ln_rmd) + sizeof (ln_tmd)); sz >>= 1; /* adjust for roundoff */ for (lnRsize = 0; sz != 0; lnRsize++, sz >>= 1) ; lnTsize = lnRsize; /* lnTsize = lnRsize for convenience */ } /* limit ring sizes to reasonable values */ if (lnRsize < 2) lnRsize = 2; /* 4 buffers is reasonable min */ if (lnRsize > 7) lnRsize = 7; /* 128 buffers is max for chip */ /* limit ring sizes to reasonable values */ if (lnTsize < 2) lnTsize = 2; /* 4 buffers is reasonable min */ if (lnTsize > 7) lnTsize = 7; /* 128 buffers is max for chip */ /* calculate the total size of LANCE memory pool. (basic softc structure * is just allocated from free memory pool since LANCE never references). */ sz = ((sizeof (ln_ib)) + (((1 << lnRsize) + 1) * sizeof (ln_rmd)) + (bufSize << lnRsize) + (((1 << lnTsize) + 1) * sizeof (ln_tmd)) + (bufSize << lnTsize)); sz = sz + 6; /* allow for alignment adjustment */ if ((int) memAdrs == NONE) /* if -1 then allocate memPool from free pool */ { memPool = (char *) malloc (sz); /* allocate memory */ if ((int)memPool == NULL) return (ERROR); /* bail out if we don't get memory */ } else { if (memSize < sz) return (ERROR); /* bail out if memSize specified is too small */ memPool = memAdrs; /* set the beginning of pool */ } /* memPool partitioning * -------------------- * * LOW MEMORY * * memPool,ls->ib |-------------------------------------| * | | * | (sizeof (ln_ib)) | * | | * ls->ls_rring |-------------------------------------| * | | * | ((1 << lnRsize) + 1)*sizeof (ln_rmd)| * | | * ls->rmd_ring.r_bufs |-------------------------------------| * | | * | (bufSize << lnRsize) | * | | * ls->ls_tring |-------------------------------------| * | | * | ((1 << lnTsize) + 1)*sizeof (ln_tmd)| * | | * ls->tmd_ring.t_bufs |-------------------------------------| * | | * | (bufSize << lnTsize) | * | | * |-------------------------------------| * * HIGH MEMORY */ /* allocate basic softc structure */ ls = (DRV_CTRL *)malloc (sizeof (DRV_CTRL)); if (ls == NULL) { if ((int) memAdrs == NONE) /* if we malloced memPool */ (void) free (memPool); /* free the memPool */ return (ERROR); } /* zero out entire softc structure */ bzero ( (char *)ls, sizeof (DRV_CTRL)); /* fill in high byte of memory base (A24:A31) and data port width */ ls->memBase = (char *)((ULONG)memPool & 0xff000000); ls->memWidth = memWidth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -