?? if_fxp.c
字號:
/* $OpenBSD: if_fxp.c,v 1.25 2000/03/30 02:49:35 jason Exp $ *//* $NetBSD: if_fxp.c,v 1.2 1997/06/05 02:01:55 thorpej Exp $ *//* * Copyright (c) 1995, David Greenman * All rights reserved. * * Modifications to support NetBSD: * Copyright (c) 1997 Jason R. Thorpe. All rights reserved. * * Modifications to support MIPS Arch: * Copyright (c) 1999 Opsycon AB (www.opsycon.se). All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 CONTRIBUTORS 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. * * Id: if_fxp.c,v 1.55 1998/08/04 08:53:12 dg Exp *//* * Intel EtherExpress Pro/100B PCI Fast Ethernet driver */#include "bpfilter.h"#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/malloc.h>#include <sys/kernel.h>#include <sys/socket.h>#include <sys/syslog.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_media.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>#endif#ifdef IPX#include <netipx/ipx.h>#include <netipx/ipx_if.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#if defined(__NetBSD__) || defined(__OpenBSD__)#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/device.h>#if defined(__NetBSD__)#include <net/if_ether.h>#include <netinet/if_inarp.h>#endif#if defined(__OpenBSD__)#include <netinet/if_ether.h>#endif#include <vm/vm.h>#include <machine/cpu.h>#include <machine/bus.h>#include <machine/intr.h>#include <dev/mii/miivar.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcireg.h>#include <dev/pci/pcidevs.h>#include <dev/pci/if_fxpreg.h>#include <dev/pci/if_fxpvar.h>#ifdef __alpha__ /* XXX *//* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */#undef vtophys#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)(va))#endif /* __alpha__ */#else /* __FreeBSD__ */#include <sys/sockio.h>#include <netinet/if_ether.h>#include <vm/vm.h> /* for vtophys */#include <vm/vm_param.h> /* for vtophys */#include <vm/pmap.h> /* for vtophys */#include <machine/clock.h> /* for DELAY */#include <pci/pcivar.h>#include <pci/if_fxpreg.h>#include <pci/if_fxpvar.h>#endif /* __NetBSD__ || __OpenBSD__ */#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)/* * NOTE! On the Alpha, we have an alignment constraint. The * card DMAs the packet immediately following the RFA. However, * the first thing in the packet is a 14-byte Ethernet header. * This means that the packet is misaligned. To compensate, * we actually offset the RFA 2 bytes into the cluster. This * aligns the packet after the Ethernet header at a 32-bit * boundary. HOWEVER! This means that the RFA is misaligned! */#ifdef BADPCIBRIDGE#define BADPCIBRIDGE#define RFA_ALIGNMENT_FUDGE 4#else#define RFA_ALIGNMENT_FUDGE 2#endifint fxp_debug = 0;/* * Inline function to copy a 16-bit aligned 32-bit quantity. */static __inline void fxp_lwcopy __P((volatile u_int32_t *, volatile u_int32_t *));static __inline voidfxp_lwcopy(src, dst) volatile u_int32_t *src, *dst;{ volatile u_int16_t *a = (u_int16_t *)src; volatile u_int16_t *b = (u_int16_t *)dst; b[0] = a[0]; b[1] = a[1];}/* * Template for default configuration parameters. * See struct fxp_cb_config for the bit definitions. */static u_char fxp_cb_config_template[] = {#if BYTE_ORDER == BIG_ENDIAN 0x0, 0x0, /* cb_status */ 0x2, 0x80, /* cb_command */ 0xff, 0xff, 0xff, 0xff, /* link_addr */ 0x16, /* 0 */ 0x08, /* 1 */ 0x0, /* 2 */ 0x0, /* 3 */ 0x0, /* 4 */ 0x8, /* 5 */ /* XXX! */ 0xb2, /* 6 */ 0x3, /* 7 */ 0x1, /* 8 */ 0x0, /* 9 */ 0x2e, /* 10 */ 0x0, /* 11 */ 0x60, /* 12 */ 0x0, /* 13 */ 0xf2, /* 14 */ 0x48, /* 15 */ 0x0, /* 16 */ 0x40, /* 17 */ 0xf3, /* 18 */ 0x0, /* 19 */ 0x3f, /* 20 */ 0x5 /* 21 */#else 0x0, 0x0, /* cb_status */ 0x2, 0x80, /* cb_command */ 0xff, 0xff, 0xff, 0xff, /* link_addr */ 0x16, /* 0 */ 0x8, /* 1 */ 0x0, /* 2 */ 0x0, /* 3 */ 0x0, /* 4 */ 0x80, /* 5 */ 0xb2, /* 6 */ 0x3, /* 7 */ 0x1, /* 8 */ 0x0, /* 9 */ 0x2e, /* 10 */ 0x0, /* 11 */ 0x60, /* 12 */ 0x0, /* 13 */ 0xf2, /* 14 */ 0x48, /* 15 */ 0x0, /* 16 */ 0x40, /* 17 */ 0xf3, /* 18 */ 0x0, /* 19 */ 0x3f, /* 20 */ 0x5 /* 21 */#endif};/* Supported media types. */struct fxp_supported_media { const int fsm_phy; /* PHY type */ const int *fsm_media; /* the media array */ const int fsm_nmedia; /* the number of supported media */ const int fsm_defmedia; /* default media for this PHY */};static int fxp_mediachange __P((struct ifnet *));static void fxp_mediastatus __P((struct ifnet *, struct ifmediareq *));static inline void fxp_scb_wait __P((struct fxp_softc *));FXP_INTR_TYPE fxp_intr __P((void *));static void fxp_start __P((struct ifnet *));static int fxp_ioctl __P((struct ifnet *, FXP_IOCTLCMD_TYPE, caddr_t));static int fxp_init __P((void *));static void fxp_stop __P((struct fxp_softc *, int));static void fxp_watchdog __P((struct ifnet *));static int fxp_add_rfabuf __P((struct fxp_softc *, struct mbuf *));static int fxp_mdi_read __P((struct device *, int, int));static void fxp_mdi_write __P((struct device *, int, int, int));static void fxp_autosize_eeprom __P((struct fxp_softc *));static void fxp_statchg __P((struct device *));void fxp_read_eeprom __P((struct fxp_softc *, u_int16_t *, int, int));void fxp_write_eeprom __P((struct fxp_softc *, u_int16_t *, int, int));static int fxp_attach_common __P((struct fxp_softc *, u_int8_t *));void fxp_stats_update __P((void *));#ifdef USE_FXP_MCASTvoid fxp_mc_setup __P((struct fxp_softc *));#endif/* * Set initial transmit threshold at 64 (512 bytes). This is * increased by 64 (512 bytes) at a time, to maximum of 192 * (1536 bytes), if an underrun occurs. */static int tx_threshold = 64;/* * Number of transmit control blocks. This determines the number * of transmit buffers that can be chained in the CB list. * This must be a power of two. */#define FXP_NTXCB 16/* * Number of completed TX commands at which point an interrupt * will be generated to garbage collect the attached buffers. * Must be at least one less than FXP_NTXCB, and should be * enough less so that the transmitter doesn't becomes idle * during the buffer rundown (which would reduce performance). */#define FXP_CXINT_THRESH 12/* * TxCB list index mask. This is used to do list wrap-around. */#define FXP_TXCB_MASK (FXP_NTXCB - 1)/* * Number of receive frame area buffers. These are large so chose * wisely. */#define FXP_NRFABUFS 16/* * Maximum number of seconds that the receiver can be idle before we * assume it's dead and attempt to reset it by reprogramming the * multicast filter. This is part of a work-around for a bug in the * NIC. See fxp_stats_update(). */#define FXP_MAX_RX_IDLE 15/* * IPU: Maximum number of status reads before giving up in fxp_init * because of "bus congestion". */#ifndef FXP_MAX_STATUS_READS#define FXP_MAX_STATUS_READS 500#endif/* * IPU: Delay timer before trying to call fxp_init again * after a "bus congestion" failure. */#ifndef FXP_DELAY_BEFORE_REINIT#define FXP_DELAY_BEFORE_REINIT 2#endif/* * Wait for the previous command to be accepted (but not necessarily * completed). */static inline voidfxp_scb_wait(sc) struct fxp_softc *sc;{ int i = 10000; while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i) DELAY(2);}/************************************************************* * Operating system-specific autoconfiguration glue *************************************************************/#if defined(__BROKEN_INDIRECT_CONFIG) || defined(__OpenBSD__)static int fxp_match __P((struct device *, void *, void *));#elsestatic int fxp_match __P((struct device *, struct cfdata *, void *));#endifstatic void fxp_attach __P((struct device *, struct device *, void *));static void fxp_shutdown __P((void *));void fxp_power __P((int, void *));/* Compensate for lack of a generic ether_ioctl() */static int fxp_ether_ioctl __P((struct ifnet *, FXP_IOCTLCMD_TYPE, caddr_t));#define ether_ioctl fxp_ether_ioctlstruct cfattach fxp_ca = { sizeof(struct fxp_softc), fxp_match, fxp_attach};struct cfdriver fxp_cd = { NULL, "fxp", DV_IFNET};/* * Check if a device is an 82557. */static intfxp_match(parent, match, aux) struct device *parent;#if defined(__BROKEN_INDIRECT_CONFIG) || defined(__OpenBSD__) void *match;#else struct cfdata *match;#endif void *aux;{ struct pci_attach_args *pa = aux; if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) return (0); switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_INTEL_82557: case PCI_PRODUCT_INTEL_82559: case PCI_PRODUCT_INTEL_82559ER: return (1); } return (0);}static voidfxp_attach(parent, self, aux) struct device *parent, *self; void *aux;{ struct fxp_softc *sc = (struct fxp_softc *)self; struct pci_attach_args *pa = aux;/* struct pci_attach_args *pa = (void *)0x800785d0;*/ pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; u_int8_t enaddr[6]; struct ifnet *ifp;#ifdef __OpenBSD__ bus_space_tag_t iot = pa->pa_iot; bus_addr_t iobase; bus_size_t iosize;#endif#ifndef __OpenBSD__ /* * Map control/status registers. */ if (pci_mapreg_map(pa, FXP_PCI_MMBA, PCI_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, NULL, NULL)) { printf(": can't map registers\n"); return; }#else if (pci_io_find(pc, pa->pa_tag, FXP_PCI_IOBA, &iobase, &iosize)) { printf(": can't find i/o space\n"); return; } if (bus_space_map(iot, iobase, iosize, 0, &sc->sc_sh)) { printf(": can't map i/o space\n"); return; } sc->sc_st = iot; sc->sc_pc = pc;#endif /* * Allocate our interrupt. */ if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih);#ifdef __OpenBSD__ sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, fxp_intr, sc, self->dv_xname);#else sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, fxp_intr, sc);#endif if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } /* Do generic parts of attach. */ if (fxp_attach_common(sc, enaddr)) { /* Failed! */ return; }#ifdef __OpenBSD__ ifp = &sc->arpcom.ac_if; bcopy(enaddr, sc->arpcom.ac_enaddr, sizeof(enaddr));#else ifp = &sc->sc_ethercom.ec_if;#endif bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = fxp_ioctl; ifp->if_start = fxp_start; ifp->if_watchdog = fxp_watchdog; printf(": %s, address %s\n", intrstr, ether_sprintf(sc->arpcom.ac_enaddr)); /* * Initialize our media structures and probe the MII. */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = fxp_mdi_read; sc->sc_mii.mii_writereg = fxp_mdi_write; sc->sc_mii.mii_statchg = fxp_statchg; ifmedia_init(&sc->sc_mii.mii_media, 0, fxp_mediachange, fxp_mediastatus); mii_phy_probe(self, &sc->sc_mii, 0xffffffff); /* If no phy found, just use auto mode */ if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL, 0, NULL); printf(FXP_FORMAT ": no phy found, using manual mode\n", FXP_ARGS(sc)); } if (ifmedia_match(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL, 0)) ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL); else if (ifmedia_match(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO, 0)) ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T); /* * Attach the interface. */ if_attach(ifp); /* * Let the system queue as many packets as we have available * TX descriptors. */ ifp->if_snd.ifq_maxlen = FXP_NTXCB - 1;#ifdef __NetBSD__ ether_ifattach(ifp, enaddr);#else ether_ifattach(ifp);#endif#if NBPFILTER > 0#ifdef __OpenBSD__ bpfattach(&sc->arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));#else
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -