/* * Principal Author: Matthew Jacob * Copyright (c) 1999, 2001 by Traakan Software * 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. * * Additional Copyright (c) 2001 by Parag Patel * under same licence for MII PHY code. */ /* * Softc definitions for the Intel Gigabit Ethernet driver. * * Guidance and inspiration from David Greenman's * if_fxp driver gratefully acknowledged here. */ /* * Platform specific defines and inline functions go here. * Look further below for more generic structures. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/errno.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/device.h> #include <sys/timeout.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/if_media.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 #include "bpfilter.h" #if NBPFILTER > 0 #include <net/bpf.h> #include <net/bpfdesc.h> #endif #include <uvm/uvm_extern.h> #include <machine/bus.h> #include <machine/intr.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> #include <dev/pci/if_wxreg.h> #include <dev/mii/mii.h> #include <dev/mii/miivar.h> struct wxmdvar { struct device dev; /* generic device structures */ void * ih; /* interrupt handler cookie */ struct arpcom arpcom; /* ethernet common part */ pci_chipset_tag_t pci_pc; pcitag_t pci_tag; u_int32_t cmdw; struct timeout tmo; /* handle for timeouts */ bus_space_tag_t st; /* bus space tag */ bus_space_handle_t sh; /* bus space handle */ struct ifmedia ifm; int locked; struct mii_data mii_data; int spl; }; #define wx_dev w.dev #define wx_enaddr w.arpcom.ac_enaddr #define wx_cmdw w.cmdw #define wx_media w.ifm #define wx_tmo w.tmo #define wx_if w.arpcom.ac_if #define wx_name w.dev.dv_xname #define IOCTL_CMD_TYPE u_long #define WXMALLOC(len) malloc(len, M_DEVBUF, M_NOWAIT) #define WXFREE(ptr) free(ptr, M_DEVBUF) #define SOFTC_IFP(ifp) ifp->if_softc #define WX_BPFTAP_ARG(ifp) (ifp)->if_bpf #define TIMEOUT(sc, func, arg, time) VTIMEOUT(sc, func, arg, time) #define VTIMEOUT(sc, func, arg, time) {timeout_set(&(sc)->wx_tmo, func, arg); timeout_add(&(sc)->wx_tmo, time);} #define UNTIMEOUT(f, arg, sc) timeout_del(&(sc)->wx_tmo) #define INLINE inline #define WX_LOCK(wx) if (wx->w.locked++ == 0) wx->w.spl = splimp() #define WX_UNLOCK(wx) if (wx->w.locked) { \ if (--wx->w.locked == 0) \ splx(wx->w.spl); \ } #define WX_ILOCK(_sc) #define WX_IUNLK(_sc) #define WX_SOFTC_FROM_MII_ARG(x) (wx_softc_t *) x #define WX_MII_FROM_SOFTC(x) (&x->w.mii_data) #define vm_offset_t vaddr_t #define READ_CSR _read_csr #define WRITE_CSR _write_csr typedef unsigned long intptr_t; /* * Transmit soft descriptor, used to manage packets as they come in. */ typedef struct rxpkt { struct mbuf *dptr; /* pointer to receive frame */ u_int32_t dma_addr; /* dma address */ } rxpkt_t; /* * Transmit soft descriptor, used to manage packets as they are transmitted. */ typedef struct txpkt { struct txpkt *next; /* next in a chain */ struct mbuf *dptr; /* pointer to mbuf being sent */ u_int32_t sidx; /* start index */ u_int32_t eidx; /* end index */ } txpkt_t; typedef struct wx_softc { /* * OS dependent storage... must be first... */ struct wxmdvar w; /* * misc goodies */ u_int32_t : 22, wx_needreinit : 1, wx_mii : 1, /* non-zero if we have a PHY */ wx_no_flow : 1, wx_ilos : 1, wx_no_ilos : 1, wx_verbose : 1, wx_debug : 1, ane_failed : 1, linkup : 1, all_mcasts : 1; u_int32_t wx_idnrev; /* chip revision && PCI ID */ u_int16_t wx_cfg1; u_int16_t wx_unused; u_int32_t wx_ienable; /* current ienable to use */ u_int32_t wx_dcr; /* dcr used */ u_int32_t wx_icr; /* last icr */ /* * Statistics, soft && hard */ u_int32_t wx_intr; u_int32_t wx_linkintr; u_int32_t wx_rxintr; u_int32_t wx_txqe; u_int32_t wx_xmitgc; u_int32_t wx_xmitpullup; u_int32_t wx_xmitcluster; u_int32_t wx_xmitputback; u_int32_t wx_xmitwanted; u_int32_t wx_xmitblocked; u_int32_t wx_xmitrunt; u_int32_t wx_rxnobuf; u_int32_t wx_oddpkt; /* * Soft copies of multicast addresses. We're only * using (right now) the rest of the receive address * registers- not the hashed multicast table. */ u_int8_t wx_mcaddr[WX_RAL_TAB_SIZE-1][6]; u_int8_t wx_nmca; /* # active multicast addrs */ /* * Receive Management * We have software and shared memory rings in a buddy store format. */ wxrd_t *rdescriptors; /* receive descriptor ring */ rxpkt_t *rbase; /* base of soft rdesc list */ u_int16_t rnxt; /* next descriptor to check */ u_int16_t _pad; struct mbuf *rpending; /* pending partial packet */ /* * Transmit Management * We have software and shared memory rings in a buddy store format. */ txpkt_t *tbase; /* base of soft soft management */ txpkt_t *tbsyf, *tbsyl; /* linked busy list */ wxtd_t *tdescriptors; /* transmit descriptor ring */ u_int16_t tnxtfree; /* next free index (circular) */ u_int16_t tactive; /* # active */ } wx_softc_t; /* * We offset the the receive frame header by two bytes so that the actual * payload is 32 bit aligned. On platforms that require strict structure * alignment, this means that the ethernet frame header may have to be shifted * to align it at interrupt time, but because it's such a small amount * (fourteen bytes) and processors have gotten pretty fast, that's okay. * It may even turn out on some platforms that this doesn't have to happen. */ #define WX_RX_OFFSET_VALUE 2 /* * Tunable Parameters. * * Descriptor lengths must be in multiples of 8. */ #define WX_MAX_TDESC 256 /* number of transmit descriptors */ #define T_NXT_IDX(x) ((x + 1) & (WX_MAX_TDESC - 1)) #define T_PREV_IDX(x) ((x - 1) & (WX_MAX_TDESC - 1)) #define WX_MAX_RDESC 256 /* number of receive descriptors */ #ifdef PADDED_CELL #define RXINCR 2 #else #define RXINCR 1 #endif #define R_NXT_IDX(x) ((x + RXINCR) & (WX_MAX_RDESC - 1)) #define R_PREV_IDX(x) ((x - RXINCR) & (WX_MAX_RDESC - 1)) /* * Link Up timeout, in milliseconds. */ #define WX_LINK_UP_TIMEOUT 500