📄 if_eex.c
字号:
/* if_eex.c - Intel EtherExpress 16 network interface driver *//* Copyright 1989-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01k,15jul97,spm added ARP request to SIOCSIFADDR ioctl handler01j,07apr97,spm corrected statistics counter for incoming packets01i,17mar97,spm upgraded to BSD 4.4 and corrected statistics counters.01h,14jun95,hdn removed function declarations defined in sysLib.h.01g,01feb95,jdi doc cleanup.01f,17jan95,jag only send connector select command if NOT auto-detect01e,12nov94,tmk removed some IMPORTed function decs and included unixLib.h01d,20feb94,bcs add attachment type selection, stub for auto-detect01c,13dec93,bcs rearranged initialization, fixed comments01b,04dec93,bcs made functional, added AL_LOC compile-time option01a,28nov93,bcs derived from if_ei.c (rev. 03c,15jan93)*//*DESCRIPTIONThis module implements the Intel EtherExpress 16 PC network interface carddriver. It is specific to that board as used in PC 386/486 hosts.This driver is written using the device's I/O registers exclusively.SIMPLIFYING ASSUMPTIONSThis module assumes a little-endian host (80x86); thus, no endianadjustments are needed to manipulate the 82586 data structures (little-endian).The on-board memory is assumed to be sufficient; thus, no provision is madefor additional buffering in system memory.The "frame descriptor" and "buffer descriptor" structures can be boundinto permanent pairs by pointing each FD at a "chain" of one BD of MTU size.The 82586 receive algorithm fills exactly one BD for each FD; it looks tothe NEXT FD in line for the next BD.The transmit and receive descriptor lists are permanently linked intocircular queues partitioned into sublists designated by the EEX_LISTheaders in the driver control structure. Empty partitions have NULL pointerfields. EL bits are set as needed to tell the 82586 where a partition ends.The lists are managed in strict FIFO fashion; thus the link fields are nevermodified, just ignored if a descriptor is at the end of a list partition.BOARD LAYOUTThis device is soft-configured. No jumpering diagram is required.EXTERNAL INTERFACEThis driver provides the standard external interface with the followingexceptions. All initialization is performed within the attach routine andthere is no separate initialization routine. Therefore, in the global interfacestructure, the function pointer to the init() routine is NULL.There is one user-callable routine, eexattach(). For details on usage,see the manual entry for this routine.EXTERNAL SUPPORT REQUIREMENTSNone.SYSTEM RESOURCE USAGE - one mutual exclusion semaphore - one interrupt vector - one watchdog timer. - 8 bytes in the initialized data section (data) - 912 bytes in the uninitialized data section (bss)The data and bss sections are quoted for the MC68020 architecture and may varyfor other architectures. The code size (text) will vary widely betweenarchitectures, and is thus not quoted here.The device contains on-board buffer memory; no system memory is requiredfor buffering.TUNING HINTSThe only adjustable parameter is the number of TFDs to create in adapter buffermemory. The total number of TFDs and RFDs is 21, given full-frame bufferingand the sizes of the auxiliary structures. eexattach() requires at leastMIN_NUM_RFDS RFDs to exist. More than ten TFDs is not sensiblein typical circumstances.SEE ALSO: ifLib*/#include "vxWorks.h"#include "wdLib.h"#include "iv.h"#include "vme.h"#include "net/mbuf.h"#include "net/protosw.h"#include "socket.h"#include "ioctl.h"#include "errno.h"#include "memLib.h"#include "intLib.h"#include "net/if.h"#include "net/route.h"#include "iosLib.h"#include "errnoLib.h"#include "cacheLib.h"#include "logLib.h"#include "netLib.h"#include "stdio.h"#include "stdlib.h"#include "sysLib.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 /* INET */#include "etherLib.h"#include "net/systm.h"#include "net/unixLib.h"#include "sys/times.h"#include "drv/netif/if_eex.h"#include "net/if_subr.h"/***** LOCAL DEFINITIONS *****/#undef EEX_DEBUG /* Compiles debug output */#undef EEX_DEBUG1 /* dhe 10/24/94 */#define MAX_UNITS 4 /* maximum units to support */#define DEF_NUM_TFDS 8 /* default number of TFDs */#define MIN_NUM_RFDS 4 /* minimum number of RFDs */#define MAX_IRQ 15 /* Highest PC IRQ number */#define EEX_MEMSIZE 0x8000 /* Size of EtherExpress memory */ /* Production units are 32K */#define SCP_OFFSET 0xfff6 /* At top of 64K address space */ /* (aliased in a 32K board) */#define ISCP_OFFSET 0x0000 /* EtherExpress convention */#define SCB_OFFSET 0x0008 /* EtherExpress convention */ /* Supported by hardware feature */#define CFD_OFFSET ( SCB_OFFSET + sizeof (SCB) )#define TFD_OFFSET ( CFD_OFFSET + sizeof (CFD) )/* These should be in a common file but which one? *//* Ethernet attachment type selections */#define ATTACHMENT_DEFAULT 0 /* use card as configured */#define ATTACHMENT_AUI 1 /* AUI (thick, DIX, DB-15) */#define ATTACHMENT_BNC 2 /* BNC (thin, 10BASE-2) */#define ATTACHMENT_RJ45 3 /* RJ-45 (twisted pair, TPE, 10BASE-T)*//* Typedefs for external structures that are not typedef'd in their .h files */typedef struct mbuf MBUF;typedef struct arpcom IDR; /* Interface Data Record wrapper */typedef struct ifnet IFNET; /* real Interface Data Record */typedef struct sockaddr SOCK;/* The definition of our linked list management structure */typedef struct eex_list /* EEX_LIST - 82586 queue head */ { volatile EEX_SHORTLINK head; /* header of list */ volatile EEX_SHORTLINK tail; /* tail of list */ } EEX_LIST;/* Macro to follow TFRAME and RFRAME (TFD/RFD) lists */#define SUCC_FD(fd) ( \ sysOutWord (pDrvCtrl->port + RDPTR, (fd) + RF_LINK), \ sysInWord (pDrvCtrl->port + DXREG) )/* The definition of the driver control structure */typedef struct drv_ctrl { IDR idr; /* interface data record */ BOOL attached; /* indicates attach() called */ CFD *pCfd; /* Scratch CFD to copy to board mem.*/ EEX_SHORTLINK rfdBase; /* RFD pool starts here */ EEX_SHORTLINK lastFd; /* last RFD dhe 10/26/94 */ volatile EEX_LIST rxQueue; /* receive queue */ volatile EEX_SHORTLINK freeRfd; /* first free receive frame */ volatile EEX_LIST tfdQueue; /* free transmit frame descriptors */ volatile EEX_LIST txQueue; /* to be sent queue */ volatile EEX_LIST cblQueue; /* actual chip transmit queue */ volatile EEX_LIST cleanQueue; /* queue of TFDs to cleanup */ volatile BOOL rcvHandling;/* flag, indicates netTask active */ volatile BOOL txCleaning; /* flag, indicates netTask active */ volatile BOOL txIdle; /* flag, indicates idle transmitter */ int nTFDs; /* how many TFDs to create */ int nRFDs; /* how many RFDs to create */ int port; /* base I/O port */ int ivec; /* interrupt vector */ int intLevel; /* interrupt number */ int irqCode; /* encoded value written to IRQ port */ int attachment; /* connector type: BNC, AUI, or TPE */ UINT16 setup; /* base, boot ROM, I/O, AUI/BNC, IRQ */ UINT16 tpeBit; /* bit 0 = 1 && setup AUI bit = 0 for TPE */ MEM_SETUP memSetup; /* everything to set up memory mapping */ WDOG_ID wid; /* watchdog timer for transmit */ long transLocks; /* count for transmit lockup failures */ } DRV_CTRL;#define DRV_CTRL_SIZ sizeof(DRV_CTRL)/***** GLOBALS *****//***** LOCALS *****//* The array of driver control structs */LOCAL DRV_CTRL drvCtrl [MAX_UNITS];/* Encoded IRQ selection numbers for EtherExpress 16 IRQ Control port * Entries correspond to PC IRQ numbers 0-15. A zero entry means the * corresponding IRQ cannot be used by the board; a non-zero entry is * the value needed in the board's interrupt control register to program * the board for the corresponding IRQ. */LOCAL int irqTable [MAX_IRQ + 1] = { 0, 0, 1, 2, 3, 4, 0, 0, 0, 1, 5, 6, 0, 0, 0, 0 };/* following are used only in netTask() context so can be common */LOCAL CFD Cfd; /* expedient for code porting */ /* build commands here then copy */ /* to board memory */LOCAL char buffer [FRAME_SIZE]; /* Copy frames through here *//* forward function declarations */static void eexReset (int unit);static int eexIoctl (IDR *pIDR, int cmd, caddr_t data);#ifdef BSD43_DRIVERstatic int eexOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDestAddr);static void eexTxStartup (int unit);#elsestatic void eexTxStartup (DRV_CTRL *pDrvCtrl);#endifstatic void eexInt (DRV_CTRL *pDrvCtrl);static void eexTxCleanQ (DRV_CTRL *pDrvCtrl);static void eexHandleRecvInt (DRV_CTRL *pDrvCtrl);static STATUS eexReceive (DRV_CTRL *pDrvCtrl, EEX_SHORTLINK rfdOffset);static void eexDiag (int unit);static void eexConfig (int unit);static void eexIASetup (int unit);static void eexRxStartup (DRV_CTRL *pDrvCtrl);static void eexAction (int unit, UINT16 action);static STATUS eexCommand (DRV_CTRL *pDrvCtrl, UINT16 cmd);static void eexTxQPut (DRV_CTRL *pDrvCtrl, EEX_SHORTLINK tfdOffset);static void eexTxQFlush (DRV_CTRL *pDrvCtrl);static void eexRxQPut (DRV_CTRL *pDrvCtrl, EEX_SHORTLINK rfdOffset);static EEX_SHORTLINK eexRxQGet (DRV_CTRL *pDrvCtrl);static BOOL eexRxQFull (DRV_CTRL *pDrvCtrl);static void eexQInit (EEX_LIST *pHead);static EEX_SHORTLINK eexQGet (DRV_CTRL *pDrvCtrl, EEX_LIST *pQueue);static void eexQPut (DRV_CTRL *pDrvCtrl, EEX_LIST *pQueue, EEX_SHORTLINK pNode);static STATUS eexDeviceStart (int unit);static void eexWatchDog(int unit);static STATUS eexEnetAddrGet (DRV_CTRL *pDrvCtrl, char addr[]);static STATUS eex586Init (int unit);static void eex586IntAck (int unit);static void eex586IntEnable (int unit);static void eex586IntDisable (int unit);static void eex586SetReset (int unit);static void eex586ClearReset (int unit);static void eex586ChanAtn (DRV_CTRL *pDrvCtrl);static UINT16 eexReadEEPROM (DRV_CTRL *pDRvCtrl, UINT16 address);static void eexOutBitsEEPROM (int port, int count, UINT16 bits);static UINT16 eexInBitsEEPROM (int port, int count);static void eexDelayEEPROM (void);static void DUMMY (){}/********************************************************************************* eexattach - publish the `eex' network interface and initialize the driver and device** The routine publishes the `eex' interface by filling in a network interface* record and adding this record to the system list. This routine also* initializes the driver and the device to the operational state.** RETURNS: OK or ERROR.** SEE ALSO: ifLib*/STATUS eexattach ( int unit, /* unit number */ int port, /* base I/O address */ int ivec, /* interrupt vector number */ int ilevel, /* interrupt level */ int nTfds, /* # of transmit frames (0=default) */ int attachment /* 0=default, 1=AUI, 2=BNC, 3=TPE */ ) { DRV_CTRL *pDrvCtrl; long size; /* temporary size holder */ /* Sanity check the unit number */ if (unit < 0 || unit >= MAX_UNITS) return (ERROR); /* Ensure single invocation per system life */ pDrvCtrl = & drvCtrl [unit];#ifdef EEX_DEBUG /* dhe 10/20/94 */ logMsg ("eex: eeattach: pDrvCtrl=%x\n", pDrvCtrl, 0, 0, 0, 0, 0);#endif if (pDrvCtrl->attached) return (OK); /* Check interrupt number for sanity and usability */ if (ilevel < 0 || ilevel > MAX_IRQ) return (ERROR); pDrvCtrl->intLevel = ilevel; pDrvCtrl->irqCode = irqTable [ilevel]; if (pDrvCtrl->irqCode == 0) return (ERROR); /* Determine number of Tx and Rx descriptors to use */ pDrvCtrl->nTFDs = (nTfds != 0) ? nTfds : DEF_NUM_TFDS; /* Determine which connector is desired */ switch (attachment) { case ATTACHMENT_DEFAULT: case ATTACHMENT_AUI: case ATTACHMENT_BNC: case ATTACHMENT_RJ45: pDrvCtrl->attachment = attachment; break; default: return (ERROR); /* unknown value */ } /* Find and activate the adapter */ /* Publish the interface record */#ifdef BSD43_DRIVER ether_attach ( (IFNET *) & pDrvCtrl->idr, unit, "eex", (FUNCPTR) NULL, (FUNCPTR) eexIoctl, (FUNCPTR) eexOutput, (FUNCPTR) eexReset);#else ether_attach ( (IFNET *) & pDrvCtrl->idr, unit, "eex", (FUNCPTR) NULL, (FUNCPTR) eexIoctl, (FUNCPTR) ether_output, (FUNCPTR) eexReset ); pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)eexTxStartup;#endif /* Calculate the total size of 82586 memory pool. * Evaluate as a long so it can force nRFDs negative if way too many * TFDs were asked for. */ size = sizeof (SCP) + sizeof (ISCP) + sizeof (SCB) + sizeof (CFD) + /* synch'ed command frame */ (sizeof (TFRAME) * pDrvCtrl->nTFDs); /* pool of transmit frames */ pDrvCtrl->nRFDs = ( (long)EEX_MEMSIZE - size ) / sizeof (RFRAME);#ifdef EEX_DEBUG /* dhe 10/20/94 */ logMsg ("eex: eeattach: nRFDS=%x\n", pDrvCtrl->nRFDs, 0, 0, 0, 0, 0);#endif if (pDrvCtrl->nRFDs < MIN_NUM_RFDS) return (ERROR); /* Save other passed-in parameters */ pDrvCtrl->port = port; /* base I/O address */ pDrvCtrl->ivec = ivec; /* interrupt vector */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -