📄 if_fe.c
字号:
/* $Id: if_fe.c,v 1.8 1999/05/13 11:45:22 nigel Exp $ *//* * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 * * This software may be used, modified, copied, distributed, and sold, in * both source and binary form provided that the above copyright, these * terms and the following disclaimer are retained. The name of the author * and/or the contributor may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#define FE_VERSION "if_fe.c ver. 0.8a"/* * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. * To be used with FreeBSD 2.0 RELEASE. * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp> * * This version is intended to be a generic template for various * MB86960A/MB86965A based Ethernet cards. It currently supports * Fujitsu FMV-180 series (i.e., FMV-181 and FMV-182) and Allied- * Telesis AT1700 series and RE2000 series. There are some * unnecessary hooks embedded, which are primarily intended to support * other types of Ethernet cards, but the author is not sure whether * they are useful. * * This software is a derivative work of if_ed.c version 1.56 by David * Greenman available as a part of FreeBSD 2.0 RELEASE source distribution. * * The following lines are retained from the original if_ed.c: * * Copyright (C) 1993, David Greenman. This software may be used, modified, * copied, distributed, and sold, in both source and binary form provided * that the above copyright and these terms are retained. Under no * circumstances is the author responsible for the proper functioning * of this software, nor does the author assume any responsibility * for damages incurred with its use. */#ifdef PROM#define NFE 1#ifndef INET#define INET#endif#else#include "fe.h"#endif#if NBPFILTER > 0#include "bpfilter.h"#endif#ifdef PROM#include "sys/param.h"#include "sys/systm.h"#include "sys/errno.h"#include "sys/ioctl.h"#include "sys/mbuf.h"#include "sys/socket.h"#include "sys/syslog.h"#include "net/if.h"#include "net/if_dl.h"#include "net/if_types.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#ifdef NS#include "netns/ns.h"#include "netns/ns_if.h"#endif#if NBPFILTER > 0#include "net/bpf.h"#include "net/bpfdesc.h"#endif#include "mips.h"#include "sbd.h"#include "mb86960.h"#include "if_fereg.h"#else /* PROM */#include <sys/param.h>#include <sys/systm.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/syslog.h>#include <sys/devconf.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.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#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#include <machine/clock.h>#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>#include <i386/isa/icu.h>#include <i386/isa/ic/mb86960.h>#include <i386/isa/if_fereg.h>#endif /* PROM */#ifdef __GNUC__#define INLINE inline#else#define INLINE#endif/* * Default settings for fe driver specific options. * They can be set in config file by "options" statements. *//* * Debug control. * 0: No debug at all. All debug specific codes are stripped off. * 1: Silent. No debug messages are logged except emergent ones. * 2: Brief. Lair events and/or important information are logged. * 3: Detailed. Logs all information which *may* be useful for debugging. * 4: Trace. All actions in the driver is logged. Super verbose. */#ifndef FE_DEBUG#define FE_DEBUG 1#endif/* * Delay padding of short transmission packets to minimum Ethernet size. * This may or may not gain performance. An EXPERIMENTAL option. */#ifndef FE_DELAYED_PADDING#define FE_DELAYED_PADDING 0#endif/* * Transmit just one packet per a "send"command to 86960. * This option is intended for performance test. An EXPERIMENTAL option. */#ifndef FE_SINGLE_TRANSMISSION#define FE_SINGLE_TRANSMISSION 0#endif#ifndef FE_SYS_BUS_WIDTH#ifdef PROM#define FE_SYS_BUS_WIDTH 8#else#define FE_SYS_BUS_WIDTH 16#endif#endif/* * Device configuration flags. *//* DLCR6 settings. */#define FE_FLAGS_DLCR6_VALUE 0x007F/* Force DLCR6 override. */#define FE_FLAGS_OVERRIDE_DLCR6 0x0080/* A cludge for PCMCIA support. */#define FE_FLAGS_PCMCIA 0x8000/* Shouldn't this be defined somewhere else such as isa_device.h? */#define NO_IOADDR 0xFFFFFFFF/* Identification of the driver version. */static char const fe_version [] = FE_VERSION " / " FE_REG_VERSION;/* * Supported hardware (Ethernet card) types * This information is currently used only for debugging */enum fe_type{ /* For cards which are successfully probed but not identified. */ FE_TYPE_UNKNOWN, /* Fujitsu FMV-180 series. */ FE_TYPE_FMV181, FE_TYPE_FMV182, /* Allied-Telesis AT1700 series and RE2000 series. */ FE_TYPE_AT1700, /* PCMCIA by Fujitsu. */ FE_TYPE_MBH10302, FE_TYPE_MBH10304, /* More can be here. */};/* * Data type for a multicast address filter on 86960. */struct fe_filter { u_char data [ FE_FILTER_LEN ]; };#ifdef PROM#define FE_FILTER_NOTHING 0,0,0,0,0,0,0,0#define FE_FILTER_ALL 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff#endif/* * Special filter values. */static struct fe_filter const fe_filter_nothing = { FE_FILTER_NOTHING };static struct fe_filter const fe_filter_all = { FE_FILTER_ALL };/* * fe_softc: per line info and status */struct fe_softc { /* Used by "common" codes. */ struct arpcom arpcom; /* ethernet common */#ifndef PROM /* Used by config codes. */ struct kern_devconf kdc;/* Kernel configuration database info. */#endif /* Set by probe() and not modified in later phases. */ enum fe_type type; /* interface type code */ char * typestr; /* printable name of the interface. */#ifdef PROM u_int addr; /* MB86960A I/O base address */#else u_short addr; /* MB86960A I/O base address */#endif u_short txb_size; /* size of TX buffer, in bytes */ u_char proto_dlcr4; /* DLCR4 prototype. */ u_char proto_dlcr5; /* DLCR5 prototype. */ u_char proto_dlcr6; /* DLCR6 prototype. */ u_char proto_dlcr7; /* DLCR7 prototype. */ /* Vendor specific hooks. */ void ( * init )( struct fe_softc * ); /* Just before fe_init(). */ void ( * stop )( struct fe_softc * ); /* Just after fe_stop(). */#if NBPFILTER > 0 /* For BPF. */ caddr_t bpf; /* BPF "magic cookie" */#endif /* Transmission buffer management. */ u_short txb_free; /* free bytes in TX buffer */ u_char txb_count; /* number of packets in TX buffer */ u_char txb_sched; /* number of scheduled packets */ u_char txb_padding; /* number of delayed padding bytes */ /* Multicast address filter management. */ u_char filter_change; /* MARs must be changed ASAP. */ struct fe_filter filter;/* new filter value. */} fe_softc[NFE];/* Frequently accessed members in arpcom and kdc. */#define sc_if arpcom.ac_if#define sc_unit arpcom.ac_if.if_unit#define sc_enaddr arpcom.ac_enaddr#ifndef PROM#define sc_dcstate kdc.kdc_state#define sc_description kdc.kdc_description#endif/* * Some entry functions receive a "struct ifnet *" typed pointer as an * argument. It points to arpcom.ac_if of our softc. Remember arpcom.ac_if * is located at very first of the fe_softc struct. So, there is no * difference between "struct fe_softc *" and "struct ifnet *" at the machine * language level. We just cast to turn a "struct ifnet *" value into "struct * fe_softc * value". If this were C++, we would need no such cast at all. */#define IFNET2SOFTC(P) ( ( struct fe_softc * )(P) )/* Public entry point. This is the only functoin which must be external. */void feintr ( int );/* Standard driver entry points. These can be static. */#ifndef PROMint fe_probe ( struct isa_device * );int fe_attach ( struct isa_device * );#endifvoid fe_init ( int );int fe_ioctl ( struct ifnet *, int, caddr_t );void fe_start ( struct ifnet * );void fe_reset ( int );void fe_watchdog ( int );/* Local functions. Order of declaration is confused. FIXME. */#ifndef PROMstatic int fe_probe_fmv ( struct isa_device *, struct fe_softc * );static int fe_probe_ati ( struct isa_device *, struct fe_softc * );static int fe_probe_mbh ( struct isa_device *, struct fe_softc * );static void fe_init_mbh ( struct fe_softc * );#endifstatic int fe_get_packet ( struct fe_softc *, u_short );static void fe_stop ( int );static void fe_tint ( struct fe_softc *, u_char );static void fe_rint ( struct fe_softc *, u_char );static void fe_xmit ( struct fe_softc * );static void fe_write_mbufs ( struct fe_softc *, struct mbuf * );static struct fe_filter fe_mcaf ( struct fe_softc * );static int fe_hash ( u_char * );static void fe_setmode ( struct fe_softc * );static void fe_loadmar ( struct fe_softc * );static void fe_setlinkaddr ( struct fe_softc * );#if FE_DEBUG >= 1static void fe_dump ( int, struct fe_softc *, char * );#endif/* Ethernet constants. To be defined in if_ehter.h? FIXME. */#define ETHER_MIN_LEN 60 /* with header, without CRC. */#define ETHER_MAX_LEN 1514 /* with header, without CRC. */#define ETHER_ADDR_LEN 6 /* number of bytes in an address. */#define ETHER_TYPE_LEN 2 /* number of bytes in a data type field. */#define ETHER_HDR_SIZE 14 /* src addr, dst addr, and data type. */#define ETHER_CRC_LEN 4 /* number of bytes in CRC field. */#ifndef PROM/* Driver struct used in the config code. This must be public (external.) */struct isa_driver fedriver ={ fe_probe, fe_attach, "fe", 0 /* Assume we are insensitive. FIXME. */};/* Initial value for a kdc struct. */static struct kern_devconf const fe_kdc_template ={ 0, 0, 0, "fe", 0, { MDDT_ISA, 0, "net" }, isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, &kdc_isa0, /* We are an ISA device. */ 0, DC_UNCONFIGURED, /* Not yet configured. */ "Ethernet (fe)", /* Tentative description (filled in later.) */ DC_CLS_NETIF /* We are a network interface. */};#endif/* * Fe driver specific constants which relate to 86960/86965. * They are here (not in if_fereg.h), since selection of those * values depend on driver design. I want to keep definitions in * if_fereg.h "clean", so that if someone wrote another driver * for 86960/86965, if_fereg.h were usable unchanged. * * The above statement sounds somothing like it's better to name * it "ic/mb86960.h" but "if_fereg.h"... Should I do so? FIXME. *//* Interrupt masks */#ifndef FE_TMASK#define FE_TMASK ( FE_D0_COLL16 | FE_D0_TXDONE | FE_D0_BUSERR \ | FE_D0_JABBER )#endif#ifndef FE_RMASK#define FE_RMASK ( FE_D3_OVRFLO | FE_D3_CRCERR | FE_D3_BUSERR \ | FE_D3_ALGERR | FE_D3_PKTRDY )#endif/* Maximum number of iterrations for a receive interrupt. */#define FE_MAX_RECV_COUNT ( ( 65536 - 2048 * 2 ) / 64 ) /* Maximum size of SRAM is 65536, * minimum size of transmission buffer in fe is 2x2KB, * and minimum amount of received packet including headers * added by the chip is 64 bytes. * Hence FE_MAX_RECV_COUNT is the upper limit for number * of packets in the receive buffer. *//* * Convenient routines to access contiguous I/O ports. */#ifdef PROMextern void sbdfeoutb (unsigned int base, int offset, u_char v);extern void sbdfeoutsb(unsigned int base, int offset, u_char *addr, int len);extern u_char sbdfeinb(unsigned int base, int offset);extern void sbdfeinsb(unsigned int base, int offset, u_char *addr, int len);extern u_short sbdfeinw(unsigned int base, int offset);extern void sbdfeinsw(unsigned int base, int offset, u_short *addr, int len);extern void sbdfeoutw(unsigned int base, int offset, u_short v);extern void sbdfeoutsw(unsigned int base, int offset, u_short *addr, int len);#define OUTB(base, offset, v) sbdfeoutb (base, offset, v)#define OUTSB(base, offset, addr, len) sbdfeoutsb(base, offset, addr, len)#define INB(base, offset) sbdfeinb(base, offset)#define INSB(base, offset, addr, len) sbdfeinsb(base, offset, addr, len)#define INW(base, offset) sbdfeinw(base, offset)#define INSW(base, offset, addr, len) sbdfeinsw(base, offset, addr, len)#define OUTW(base, offset, v) sbdfeoutw(base, offset, v)#define OUTSW(base, offset, addr, len) sbdfeoutsw(base, offset, addr, len)#else#define OUTB(base,offset,v) outb((base)+(offset),(v))#define OUTSB(base,offset,addr,len) outsb((base)+(offset),(addr),(len))#define INB(base,offset) inb((base)+(offset))#define INSB(base,offset,addr,len) insb((base)+(offset),(addr),(len))#define INW(base,offset) inw((base)+(offset))#define INSW(base,offset,addr,len) insw((base)+(offset), (addr), (len))#define OUTW(base,offset,v) outw((base)+(offset), (v))#define OUTSW(base,offset,addr,len) outsw((base)+(offset), (addr), (len))#endifstatic INLINE voidinblk ( unsigned int base, int offset, u_char * mem, int len ){ while ( --len >= 0 ) { *mem++ = INB( base, offset++ ); }}static INLINE voidoutblk ( unsigned int base, int offset, u_char const * mem, int len ){ while ( --len >= 0 ) { OUTB( base, offset++, *mem++ ); }}#ifndef PROM/* * Hardware probe routines. *//* How and where to probe; to support automatic I/O address detection. */struct fe_probe_list{ int ( * probe ) ( struct isa_device *, struct fe_softc * ); u_short const * addresses;};/* Lists of possible addresses. */static u_short const fe_fmv_addr [] = { 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x300, 0x340, 0 };static u_short const fe_ati_addr [] = { 0x240, 0x260, 0x280, 0x2A0, 0x300, 0x320, 0x340, 0x380, 0 };static struct fe_probe_list const fe_probe_list [] ={ { fe_probe_fmv, fe_fmv_addr }, { fe_probe_ati, fe_ati_addr }, { fe_probe_mbh, NULL }, /* PCMCIAs cannot be auto-detected. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -