📄 if_ene.c
字号:
/* if_ene.c - Novell/Eagle NE2000 network interface driver *//* Copyright 1994-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01i,15jul97,spm removed driver initialization from ioctl support (SPR #8831)01h,15may97,spm reverted to bcopy routines for mbufs in BSD 4.401g,07apr97,spm code cleanup, corrected statistics, and upgraded to BSD 4.401f,25oct96,dat SPR 7352, did not support IRQ 12. Now supports all IRQs. fixed some compiler warnings.01e,14jun95,hdn removed function declarations defined in sysLib.h.01d,01feb95,jdi doc cleanup.01c,12nov94,tmk removed some IMPORTed function decs and included unixLib.h01a,01jan94,bcs written.*//*DESCRIPTIONThis module implements the Novell/Eagle NE2000 network interface driver.There is one user-callable routine, eneattach().BOARD LAYOUTThe diagram below shows the relevant jumpers for VxWorks configuration.Other compatible boards will be jumpered differently; many are jumperless..bS _________________________________________________________ | | | | | WWWWWWWW | | WWWW WWW 87654321 || | 1111 11 1 ........ || | 5432 901 2 ........ || | .... ... 3 ........ || | .... ... || | W | | 1 | | 6 |___ | . |___| | . | |________ ___ ____| | | | | |_______________| |_________________________| W1..W8 1-2 position selects AUI ("DIX") connector 2-3 position selects BNC (10BASE2) connector W9..W11 YYN I/O address 300h, no boot ROM NYN I/O address 320h, no boot ROM YNN I/O address 340h, no boot ROM NNN I/O address 360h, no boot ROM YYY I/O address 300h, boot ROM at paragraph 0c800h NYY I/O address 320h, boot ROM at paragraph 0cc00h YNY I/O address 340h, boot ROM at paragraph 0d000h NNY I/O address 360h, boot ROM at ??? (invalid configuration?) W12 Y IRQ 2 (or 9 if you prefer) W13 Y IRQ 3 W14 Y IRQ 4 W15 Y IRQ 5 (note that only one of W12..W15 may be installed) W16 Y normal ISA bus timing N timing for COMPAQ 286 portable, PS/2 Model 30-286, C&T chipset.bEEXTERNAL INTERFACEThere are two user-callable routines:.iP eneattach() 14publishes the `ene' interface and initializes the driver and device..iP eneShow()displays statistics that are collected in the interrupt handler..LPSee the manual entries for these routines for more detail.SYSTEM RESOURCE USAGE - one interrupt vector - 16 bytes in the uninitialized data section (bss) - 1752 bytes (plus overhead) of malloc'ed memory per unit attachedCAVEATThis driver does not enable the twisted-pair connector on the TaiwaneseETHER-16 compatible board.*//***** includes *****/#include "vxWorks.h"#include "net/mbuf.h"#include "net/unixLib.h"#include "net/protosw.h"#include "ioctl.h"#include "socket.h"#include "errnoLib.h"#include "net/uio.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/in_var.h"#include "netinet/if_ether.h"#include "etherLib.h"#include "vme.h"#include "iv.h"#include "iosLib.h"#include "ioLib.h"#include "memLib.h"#include "net/systm.h"#include "net/if_subr.h"#include "sysLib.h"#include "vxLib.h"#include "stdio.h"#include "intLib.h"#include "logLib.h"#include "string.h"#include "netLib.h"#include "stdlib.h"#include "semLib.h"#include "drv/intrCtl/i8259a.h"#include "drv/netif/if_ene.h"/***** defines *****/#define NENE 4 /* number of boards supported */#undef ENE_DEBUG /* define to include error/status messages. *//***** typedefs *****//* 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;typedef struct { IDR es_ac;#define es_if es_ac.ac_if#define es_enaddr es_ac.ac_enaddr BOOL attached; USHORT eneAddr; UINT memAddr; UINT memSize; int intLevel; int intVec; int config; ENE_STAT eneStat; volatile UCHAR current; /* current-page register at interrupt */ UCHAR nextPacket; /* where the next received packet is */ UCHAR rxFilter; /* receiver configuration */ UCHAR imask; int flags; UINT txreq; char packetBuf [MAX_FRAME_SIZE];/* shared at task level between */ /* eneGet and enePut */ } ENE_SOFTC;/***** locals *****//* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */LOCAL ENE_SOFTC * pEneSoftc [NENE];/***** forward declarations *****/static void enereset (int unit);static int eneinit (int unit);static void eneintr (int unit);static int eneioctl (IFNET * ifp, int cmd, caddr_t data);#ifdef BSD43_DRIVERstatic int eneoutput (IFNET * ifp, MBUF * m0, SOCK * dst);#endifstatic void eneGet (int unit);#ifdef BSD43_DRIVERstatic void enePut (int unit);#elsestatic void enePut (ENE_SOFTC * pSoftc);#endifstatic void eneReset (int unit);static void eneBoardReset (int unit);static void eneGetAddr (int unit);static void eneInit (int unit);static void eneDataOut (int unit, char * pData, UINT16 len, UINT16 eneAddress);static void eneDataIn (int unit, UINT16 eneAddress, UINT16 len, char * pData);static UCHAR eneGetCurr (int unit);static void eneIntEnable (int unit);static void eneOverwriteRecover (int unit, UCHAR cmdStatus); void eneShow (int unit, BOOL zap); void enedetach (int unit);/********************************************************************************* eneattach - publish the `ene' network interface and initialize the driver and device** This routine attaches an `ene' Ethernet interface to the network if the* device 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.** RETURNS: OK or ERROR.** SEE ALSO: ifLib, netShow*/STATUS eneattach ( int unit, /* unit number */ int ioAddr, /* address of ene's shared memory */ int ivec, /* interrupt vector to connect to */ int ilevel /* interrupt level */ ) { FAST ENE_SOFTC * pSoftc; if ((UINT)unit >= NENE) { errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT); return (ERROR); } if (pEneSoftc [unit] == NULL) { pEneSoftc [unit] = malloc (sizeof (ENE_SOFTC)); if (pEneSoftc [unit] == NULL) return (ERROR); bzero ( (char *) pEneSoftc [unit], sizeof (ENE_SOFTC)); } pSoftc = pEneSoftc [unit]; if (pSoftc->attached) return (ERROR); pSoftc->eneAddr = ioAddr; if (ilevel < 0 || ilevel > 14) /* Valid int Level ? */ ilevel = 3; /* default is IRQ3 */ pSoftc->intLevel = ilevel; pSoftc->intVec = ivec; pSoftc->rxFilter = RCON_BROAD; eneBoardReset (unit); /* power-on initialization */ eneInit (unit); /* initialize ENE */ (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec), (VOIDFUNCPTR)eneintr, unit); /* enable interrupt */ eneIntEnable (unit); sysIntEnablePIC (ilevel);#ifdef BSD43_DRIVER ether_attach (&pSoftc->es_if, unit, "ene", (FUNCPTR)eneinit, (FUNCPTR)eneioctl, (FUNCPTR)eneoutput, (FUNCPTR)enereset);#else ether_attach ( &pSoftc->es_if, unit, "ene", (FUNCPTR)eneinit, (FUNCPTR)eneioctl, (FUNCPTR)ether_output, (FUNCPTR)enereset ); pSoftc->es_if.if_start = (FUNCPTR)enePut;#endif eneinit (unit); pSoftc->attached = TRUE; return (OK); }/********************************************************************************* enereset - reset the interface*/static void enereset ( int unit ) { eneReset (unit); }/********************************************************************************* eneinit - initialize ene** Restart the link level software on the board and mark the interface up.** RETURNS: 0*/static int eneinit ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit]; pSoftc->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/ return (0); }/********************************************************************************* eneintr - Ethernet interface interrupt** Hand off reading of packets from the interface to task level.* Tabulate any transmit errors and cue task level to start next output.*/static void eneintr ( int unit ) { FAST ENE_SOFTC * pSoftc = pEneSoftc [unit]; UCHAR intStat; UCHAR txStat; UCHAR rxStat; UCHAR cmdStat; pSoftc->eneStat.interrupts++; sysBusIntAck (pSoftc->intLevel); /* acknowledge int */ /* acknowledge interrupt, get Transmit/Receive status */ intStat = sysInByte (ENE_INTSTAT (pSoftc->eneAddr)); sysOutByte (ENE_INTSTAT (pSoftc->eneAddr), intStat); txStat = sysInByte (ENE_TSTAT (pSoftc->eneAddr)); rxStat = sysInByte (ENE_RSTAT (pSoftc->eneAddr)); /* get xxxCount Reg that is cleared after read access */ pSoftc->eneStat.collisions += sysInByte (ENE_COLCNT (pSoftc->eneAddr)); pSoftc->eneStat.aligns += sysInByte (ENE_ALICNT (pSoftc->eneAddr)); pSoftc->eneStat.crcs += sysInByte (ENE_CRCCNT (pSoftc->eneAddr)); pSoftc->eneStat.missed += sysInByte (ENE_MPCNT (pSoftc->eneAddr)); if (intStat & ISTAT_OVW) /* Overwrite */ { pSoftc->es_if.if_ierrors++; pSoftc->eneStat.overwrite++; cmdStat = sysInByte (ENE_CMD (pSoftc->eneAddr)); sysOutByte (ENE_INTMASK (pSoftc->eneAddr), 0);/* disable board ints.*/ sysOutByte (ENE_CMD (pSoftc->eneAddr), CMD_NODMA | CMD_PAGE0 | CMD_STOP); (void) netJobAdd ( (FUNCPTR)eneOverwriteRecover, unit, cmdStat, 0, 0,0); } if (intStat & ISTAT_RXE) /* Receive-error */ { pSoftc->es_if.if_ierrors++; pSoftc->eneStat.rerror++; if (rxStat & RSTAT_OVER) pSoftc->eneStat.overruns++; if (rxStat & RSTAT_DIS) pSoftc->eneStat.disabled++; if (rxStat & RSTAT_DFR) pSoftc->eneStat.deferring++; } if (intStat & ISTAT_PRX) /* Receive */ { pSoftc->current = eneGetCurr (unit); if ((pSoftc->flags & RXING) == 0) { pSoftc->flags |= RXING; (void) netJobAdd ((FUNCPTR)eneGet, unit, 0,0,0,0); } } if ( (intStat & ISTAT_TXE) != 0) /* Transmit error-packet not sent */ { pSoftc->es_if.if_oerrors++; pSoftc->es_if.if_opackets--; pSoftc->eneStat.terror++; if (txStat & TSTAT_ABORT) { pSoftc->eneStat.aborts++; pSoftc->eneStat.collisions += 16; } if (txStat & TSTAT_UNDER) pSoftc->eneStat.underruns++; } if ( (intStat & ISTAT_PTX) != 0) /* Transmit-packet sent */ { if (txStat & TSTAT_CDH) pSoftc->eneStat.heartbeats++; if (txStat & TSTAT_OWC) pSoftc->eneStat.outofwindow++; if (txStat & TSTAT_PTX) pSoftc->eneStat.tnoerror++; } if ( (intStat & (ISTAT_TXE | ISTAT_PTX)) != 0) /* Transmit complete */ if (pSoftc->es_if.if_snd.ifq_head != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -