📄 if_ultra.c
字号:
/* if_ultra.c - SMC Elite Ultra Ethernet network interface driver *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01u,11jan99,aeg fixed multiple semaphore inits in ultraattach ().01t,29jun98,dat SPR 21211. fixes to Interrupt loop. 01s,11jun98,hdn fixed typo in ultraIntr().01r,22apr98,hdn set FINE16 bit in ultraInit(). added a loop to ack pending interrupts in untraIntr().01q,15jul97,spm removed driver initialization from ioctl support (SPR #8831)01p,15may97,spm reverted to bcopy routines for mbufs in BSD 4.401o,07apr97,spm code cleanup and corrected counter for incoming packets01n,17mar97,spm upgraded to BSD 4.4 and corrected statistics counters.01m,14jun95,hdn removed function declarations defined in sysLib.h.01l,01feb95,jdi doc cleanup.01k,29nov94,hdn added a semaphore in ultraPut().01j,12nov94,tmk removed some IMPORTed function decs and included unixLib.h01i,30sep94,hdn implemented two transmit buffers. enabled getting GPOUT and ZWSEN bit of GCR in EEROM. deleted while loop in ultraPut().01h,29nov93,hdn disabled the interrupt in ultraPut(). removed netJobAdd (ultraPut, ..) in ultraIntr().01g,28nov93,hdn changed NULTRA to 1.01f,23nov93,hdn removed cacheInvalidate(). added checking TXP bit before the transmission. 01e,22nov93,hdn added elcdetach () for the warm start.01d,15nov93,hdn added support for Thin Ethernet(10Base2, BNC)01c,05nov93,hdn added cacheFlush() and cacheInvalidate().01b,04nov93,hdn cleaned up.01a,30oct93,hdn written.*//*DESCRIPTIONThis module implements the SMC Elite Ultra Ethernet network interface driver.This driver supports single transmission and multiple reception. TheCurrent register is a write pointer to the ring. The Bound register is aread pointer from the ring. This driver gets the Current register at theinterrupt level and sets the Bound register at the task level. Theinterrupt is never masked at the task level.CONFIGURATIONThe W1 jumper should be set in the position of "Software Configuration".The defined I/O address in config.h must match the one stored in EEROM. The RAM address, the RAM size, and the IRQ level are defined in config.h. IRQ levels 2,3,5,7,10,11,15 are supported.EXTERNAL INTERFACEThe only user-callable routines are ultraattach() and ultraShow():.iP ultraattach() 14publishes the `ultra' interface and initializes the driver and device..iP ultraShow()displays statistics that are collected in the interrupt handler..LP*/#include "vxWorks.h"#include "net/mbuf.h"#include "net/protosw.h"#include "net/unixLib.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 "cacheLib.h"#include "drv/netif/if_ultra.h"/* defines */#define NULTRA 1 /* max number of ULTRA controllers *//* typedefs */typedef struct ifnet IFNET; /* real Interface Data Record *//* globals *//* locals */LOCAL ULTRA_SOFTC ultra_softc [NULTRA];LOCAL IRQ_TABLE irqTable [] = { { 2, 0x15}, { 2, 0x15}, { 2, 0x15}, { 3, 0x19}, { 3, 0x19}, { 5, 0x1d}, { 5, 0x1d}, { 7, 0x51}, { 7, 0x51}, { 7, 0x51}, {10, 0x55}, {11, 0x59}, {11, 0x59}, {11, 0x59}, {11, 0x59}, {15, 0x5d} };LOCAL BOOL ultraAttached = FALSE;LOCAL SEMAPHORE ultraSyncSem; /* syncronization semaphore *//* forward static functions */ void ultraShow (int unit, BOOL zap); void ultradetach (int unit);LOCAL int ultrainit (int unit);LOCAL void ultrareset (int unit);LOCAL int ultraioctl (struct ifnet *ifp, int cmd, caddr_t data);#ifdef BSD43_DRIVERLOCAL int ultraoutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst);#endifLOCAL void ultraInit (int unit);LOCAL void ultraIntr (int unit);LOCAL void ultraGet (int unit);#ifdef BSD43_DRIVERLOCAL void ultraPut (int unit);#elseLOCAL void ultraPut (ULTRA_SOFTC *sc);#endif/********************************************************************************* ultraattach - publish `ultra' interface and initialize device** This routine attaches an `ultra' 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 ultraattach ( int unit, /* unit number */ int ioAddr, /* address of ultra's shared memory */ int ivec, /* interrupt vector to connect to */ int ilevel, /* interrupt level */ int memAddr, /* address of ultra's shared memory */ int memSize, /* size of ultra's shared memory */ int config /* 0: RJ45 + AUI(Thick) 1: RJ45 + BNC(Thin) */ ) { FAST ULTRA_SOFTC *sc = &ultra_softc[unit]; if ((UINT)unit >= NULTRA) { errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT); return (ERROR); } sc->ioAddr = ioAddr; sc->memAddr = memAddr; sc->memSize = memSize; sc->intLevel = irqTable[ilevel].irq; sc->intVec = ivec; sc->config = config; sc->transmitPage[0] = ULTRA_TSTART0; sc->transmitPage[1] = ULTRA_TSTART1; sc->transmitCnt = 0; /* synchronization semaphore must be initialized only once */ if (!ultraAttached) semBInit (&ultraSyncSem, SEM_Q_FIFO, SEM_FULL); (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec), (VOIDFUNCPTR)ultraIntr, unit);#ifdef BSD43_DRIVER ether_attach (&sc->es_if, unit, "ultra", (FUNCPTR)ultrainit, (FUNCPTR)ultraioctl, (FUNCPTR)ultraoutput, (FUNCPTR)ultrareset);#else ether_attach ( (IFNET *) & sc->es_ac, unit, "ultra", (FUNCPTR) ultrainit, (FUNCPTR) ultraioctl, (FUNCPTR) ether_output, /* generic ether_output */ (FUNCPTR) ultrareset ); sc->es_if.if_start = (FUNCPTR) ultraPut;#endif ultrainit (unit); ultraAttached = TRUE; return (OK); }/********************************************************************************* ultrareset - reset the interface** RETURNS: N/A*/LOCAL void ultrareset ( int unit /* device unit number */ ) { FAST ULTRA_SOFTC *sc = &ultra_softc [unit]; int s = splnet (); sc->stat.reset++; sysIntDisablePIC (sc->intLevel); sc->es_if.if_flags = 0; splx (s); }/********************************************************************************* ultrainit - initialize ultra** Restart the link level software on the board and mark the interface up.** RETURNS: 0*/LOCAL int ultrainit ( int unit /* device unit number */ ) { FAST ULTRA_SOFTC *sc = &ultra_softc[unit]; int s = splnet (); ultraInit (unit); sysIntEnablePIC (sc->intLevel); sc->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/ splx (s); return (0); }#ifdef BSD43_DRIVER/********************************************************************************* ultraoutput - ethernet output routine** Encapsulate a packet of type family for the local net.* Use trailer local net encapsulation if enough data in first* packet leaves a multiple of 512 bytes of data in remainder.* If destination is this address or broadcast, send packet to* loop device to kludge around the fact that 3com interfaces can't* talk to themselves.** RETURNS: OK if successful, otherwise errno.*/LOCAL int ultraoutput ( struct ifnet *ifp, /* device structure */ struct mbuf *m0, /* mbuf containing packet */ struct sockaddr *dst /* destination address */ ) { return (ether_output (ifp, m0, dst, (FUNCPTR)ultraPut, &ultra_softc [ifp->if_unit].es_ac)); }#endif/********************************************************************************* ultraioctl - ioctl for interface** RETURNS: OK if successful, otherwise errno.*/LOCAL int ultraioctl ( FAST struct ifnet *ifp, /* device structure */ int cmd, /* ioctl cmd code */ caddr_t data /* ioctl argument */ ) { int status = OK; int s = splimp(); short flags; switch (cmd) { case SIOCSIFADDR: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas ((struct arpcom *)ifp, &IA_SIN (data)->sin_addr); break; case SIOCSIFFLAGS: flags = ifp->if_flags; if (ifp->if_flags & IFF_UP) ifp->if_flags = flags | (IFF_UP | IFF_RUNNING); else ifp->if_flags = flags & ~(IFF_UP|IFF_RUNNING); break; default: status = EINVAL; } splx (s); return (status); }/********************************************************************************* ultraIntr - Ethernet interface interrupt** Hand off reading of packets from the interface to task level.** RETURNS: N/A*/LOCAL void ultraIntr ( int unit /* device unit number */ ) { FAST ULTRA_SOFTC *sc = &ultra_softc[unit]; UCHAR istat; int nCnt = 0; /* Acknowledge interrupt, get Transmit/Receive status */ sc->istat = 0; do { istat = sysInByte (LAN_INTSTAT (sc->ioAddr)); sysOutByte (LAN_INTSTAT (sc->ioAddr), istat); sc->istat |= istat; nCnt ++; } while (istat != 0); sc->tstat = sysInByte (LAN_TSTAT (sc->ioAddr)); sc->rstat = sysInByte (LAN_RSTAT (sc->ioAddr)); /* get xxxCount Reg that is cleared after read access */ sc->stat.interrupts++; sc->stat.collisions += sysInByte (LAN_COLCNT (sc->ioAddr)); sc->stat.aligns += sysInByte (LAN_ALICNT (sc->ioAddr)); sc->stat.crcs += sysInByte (LAN_CRCCNT (sc->ioAddr)); sc->stat.missed += sysInByte (LAN_MPCNT (sc->ioAddr)); if (sc->istat & ISTAT_RXE) /* Receive-error */ { sc->es_if.if_ierrors++; sc->stat.rerror++; if (sc->rstat & RSTAT_OVER) sc->stat.overruns++; if (sc->rstat & RSTAT_DIS) sc->stat.disabled++; if (sc->rstat & RSTAT_DFR) sc->stat.deferring++; } if (sc->istat & (ISTAT_PRX | ISTAT_OVW)) /* Receive, Overwrite */ { if (sc->istat & ISTAT_OVW) { sc->stat.overwrite++; sc->es_if.if_ierrors++; } sysOutByte (LAN_CMD (sc->ioAddr), CMD_PS0); sc->current = sysInByte (LAN_CURR (sc->ioAddr)); sysOutByte (LAN_CMD (sc->ioAddr), 0); if ((sc->flags & RXING) == 0) { sc->flags |= RXING; (void) netJobAdd ((FUNCPTR)ultraGet, unit, 0,0,0,0); } if (sc->rstat & RSTAT_PRX) sc->stat.rnoerror++; } if (sc->istat & (ISTAT_TXE | ISTAT_PTX)) /* Transmit-error, Transmit */ { semGive (&ultraSyncSem);#if FALSE /* BEGIN TEST CODE */ if (sc->es_if.if_snd.ifq_head != NULL) {#ifdef BSD43_DRIVER netJobAdd ((FUNCPTR) ultraPut, unit, 0,0,0,0);#else netJobAdd ((FUNCPTR) ultraPut, (int)sc, 0,0,0,0);#endif }#endif /* END TEST CODE */ if (sc->istat & ISTAT_TXE) { sc->stat.terror++; sc->es_if.if_oerrors++; sc->es_if.if_opackets--; } if (sc->tstat & TSTAT_ABORT) { sc->stat.aborts++; sc->stat.collisions += 16; } if (sc->tstat & TSTAT_UNDER) sc->stat.underruns++; if (sc->tstat & TSTAT_CDH) sc->stat.heartbeats++; if (sc->tstat & TSTAT_OWC) sc->stat.outofwindow++; if (sc->tstat & TSTAT_PTX) sc->stat.tnoerror++; } }/********************************************************************************* ultraGet - read a packet off the interface** Copy packets from a RING into an mbuf and hand it to the next higher layer.** RETURNS: N/A*/LOCAL void ultraGet ( int unit /* device unit number */ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -