Home | History | Annotate | Line # | Download | only in pci
if_wm.c revision 1.1
      1  1.1  thorpej /*	$NetBSD: if_wm.c,v 1.1 2002/03/28 04:54:35 thorpej Exp $	*/
      2  1.1  thorpej 
      3  1.1  thorpej /*
      4  1.1  thorpej  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
      5  1.1  thorpej  * All rights reserved.
      6  1.1  thorpej  *
      7  1.1  thorpej  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  1.1  thorpej  *
      9  1.1  thorpej  * Redistribution and use in source and binary forms, with or without
     10  1.1  thorpej  * modification, are permitted provided that the following conditions
     11  1.1  thorpej  * are met:
     12  1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     13  1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     14  1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     16  1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     17  1.1  thorpej  * 3. All advertising materials mentioning features or use of this software
     18  1.1  thorpej  *    must display the following acknowledgement:
     19  1.1  thorpej  *	This product includes software developed for the NetBSD Project by
     20  1.1  thorpej  *	Wasabi Systems, Inc.
     21  1.1  thorpej  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  1.1  thorpej  *    or promote products derived from this software without specific prior
     23  1.1  thorpej  *    written permission.
     24  1.1  thorpej  *
     25  1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  1.1  thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  1.1  thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  1.1  thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  1.1  thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  1.1  thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  1.1  thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  1.1  thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  1.1  thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  1.1  thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  1.1  thorpej  * POSSIBILITY OF SUCH DAMAGE.
     36  1.1  thorpej  */
     37  1.1  thorpej 
     38  1.1  thorpej /*
     39  1.1  thorpej  * Register description for the Intel i82542 (``Wiseman''),
     40  1.1  thorpej  * i82543 (``Livengood''), and i82544 (``Cordova'') Gigabit
     41  1.1  thorpej  * Ethernet chips.
     42  1.1  thorpej  *
     43  1.1  thorpej  * TODO (in order of importance):
     44  1.1  thorpej  *
     45  1.1  thorpej  *	- Fix hw VLAN assist.
     46  1.1  thorpej  *
     47  1.1  thorpej  *	- Make GMII work on the Livengood.
     48  1.1  thorpej  *
     49  1.1  thorpej  *	- Fix out-bound IP header checksums.
     50  1.1  thorpej  *
     51  1.1  thorpej  *	- Fix UDP checksums.
     52  1.1  thorpej  *
     53  1.1  thorpej  *	- Jumbo frames -- requires changes to network stack due to
     54  1.1  thorpej  *	  lame buffer length handling on chip.
     55  1.1  thorpej  *
     56  1.1  thorpej  * ...and, of course, performance tuning.
     57  1.1  thorpej  */
     58  1.1  thorpej 
     59  1.1  thorpej #include "bpfilter.h"
     60  1.1  thorpej 
     61  1.1  thorpej #include <sys/param.h>
     62  1.1  thorpej #include <sys/systm.h>
     63  1.1  thorpej #include <sys/callout.h>
     64  1.1  thorpej #include <sys/mbuf.h>
     65  1.1  thorpej #include <sys/malloc.h>
     66  1.1  thorpej #include <sys/kernel.h>
     67  1.1  thorpej #include <sys/socket.h>
     68  1.1  thorpej #include <sys/ioctl.h>
     69  1.1  thorpej #include <sys/errno.h>
     70  1.1  thorpej #include <sys/device.h>
     71  1.1  thorpej #include <sys/queue.h>
     72  1.1  thorpej 
     73  1.1  thorpej #include <uvm/uvm_extern.h>		/* for PAGE_SIZE */
     74  1.1  thorpej 
     75  1.1  thorpej #include <net/if.h>
     76  1.1  thorpej #include <net/if_dl.h>
     77  1.1  thorpej #include <net/if_media.h>
     78  1.1  thorpej #include <net/if_ether.h>
     79  1.1  thorpej 
     80  1.1  thorpej #if NBPFILTER > 0
     81  1.1  thorpej #include <net/bpf.h>
     82  1.1  thorpej #endif
     83  1.1  thorpej 
     84  1.1  thorpej #include <netinet/in.h>			/* XXX for struct ip */
     85  1.1  thorpej #include <netinet/in_systm.h>		/* XXX for struct ip */
     86  1.1  thorpej #include <netinet/ip.h>			/* XXX for struct ip */
     87  1.1  thorpej 
     88  1.1  thorpej #include <machine/bus.h>
     89  1.1  thorpej #include <machine/intr.h>
     90  1.1  thorpej #include <machine/endian.h>
     91  1.1  thorpej 
     92  1.1  thorpej #include <dev/mii/mii.h>
     93  1.1  thorpej #include <dev/mii/miivar.h>
     94  1.1  thorpej #include <dev/mii/mii_bitbang.h>
     95  1.1  thorpej 
     96  1.1  thorpej #include <dev/pci/pcireg.h>
     97  1.1  thorpej #include <dev/pci/pcivar.h>
     98  1.1  thorpej #include <dev/pci/pcidevs.h>
     99  1.1  thorpej 
    100  1.1  thorpej #include <dev/pci/if_wmreg.h>
    101  1.1  thorpej 
    102  1.1  thorpej #ifdef WM_DEBUG
    103  1.1  thorpej #define	WM_DEBUG_LINK		0x01
    104  1.1  thorpej #define	WM_DEBUG_TX		0x02
    105  1.1  thorpej #define	WM_DEBUG_RX		0x04
    106  1.1  thorpej #define	WM_DEBUG_GMII		0x08
    107  1.1  thorpej int	wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK;
    108  1.1  thorpej 
    109  1.1  thorpej #define	DPRINTF(x, y)	if (wm_debug & (x)) printf y
    110  1.1  thorpej #else
    111  1.1  thorpej #define	DPRINTF(x, y)	/* nothing */
    112  1.1  thorpej #endif /* WM_DEBUG */
    113  1.1  thorpej 
    114  1.1  thorpej /*
    115  1.1  thorpej  * Transmit descriptor list size.  This is arbitrary, but allocate
    116  1.1  thorpej  * enough descriptors for 128 pending transmissions, and 8 segments
    117  1.1  thorpej  * per packet.  This MUST work out to a power of 2, and also must
    118  1.1  thorpej  * be evenly divisible by 8.
    119  1.1  thorpej  */
    120  1.1  thorpej #define	WM_NTXSEGS		8
    121  1.1  thorpej 
    122  1.1  thorpej #define	WM_TXQUEUELEN		128
    123  1.1  thorpej #define	WM_TXQUEUELEN_MASK	(WM_TXQUEUELEN - 1)
    124  1.1  thorpej #define	WM_NTXDESC		(WM_TXQUEUELEN * WM_NTXSEGS)
    125  1.1  thorpej #define	WM_NTXDESC_MASK		(WM_NTXDESC - 1)
    126  1.1  thorpej #define	WM_NEXTTX(x)		(((x) + 1) & WM_NTXDESC_MASK)
    127  1.1  thorpej #define	WM_NEXTTXS(x)		(((x) + 1) & WM_TXQUEUELEN_MASK)
    128  1.1  thorpej 
    129  1.1  thorpej /*
    130  1.1  thorpej  * The interrupt mitigation feature of the Wiseman is pretty cool -- as
    131  1.1  thorpej  * long as you're transmitting, you don't have to take an interrupt at
    132  1.1  thorpej  * all.  However, we force an interrupt to happen every N + 1 packets
    133  1.1  thorpej  * in order to kick us in a reasonable amount of time when we run out
    134  1.1  thorpej  * of descriptors.
    135  1.1  thorpej  */
    136  1.1  thorpej #define	WM_TXINTR_MASK		7
    137  1.1  thorpej 
    138  1.1  thorpej /*
    139  1.1  thorpej  * Receive descriptor list size.  We have one Rx buffer for normal
    140  1.1  thorpej  * sized packets.  Jumbo packets consume 5 Rx buffers for a full-sized
    141  1.1  thorpej  * packet.  We allocate 128 receive descriptors, each with a 2k
    142  1.1  thorpej  * buffer (MCLBYTES), which gives us room for 25 jumbo packets.
    143  1.1  thorpej  */
    144  1.1  thorpej #define	WM_NRXDESC		128
    145  1.1  thorpej #define	WM_NRXDESC_MASK		(WM_NRXDESC - 1)
    146  1.1  thorpej #define	WM_NEXTRX(x)		(((x) + 1) & WM_NRXDESC_MASK)
    147  1.1  thorpej #define	WM_PREVRX(x)		(((x) - 1) & WM_NRXDESC_MASK)
    148  1.1  thorpej 
    149  1.1  thorpej /*
    150  1.1  thorpej  * Control structures are DMA'd to the i82542 chip.  We allocate them in
    151  1.1  thorpej  * a single clump that maps to a single DMA segment to make serveral things
    152  1.1  thorpej  * easier.
    153  1.1  thorpej  */
    154  1.1  thorpej struct wm_control_data {
    155  1.1  thorpej 	/*
    156  1.1  thorpej 	 * The transmit descriptors.
    157  1.1  thorpej 	 */
    158  1.1  thorpej 	wiseman_txdesc_t wcd_txdescs[WM_NTXDESC];
    159  1.1  thorpej 
    160  1.1  thorpej 	/*
    161  1.1  thorpej 	 * The receive descriptors.
    162  1.1  thorpej 	 */
    163  1.1  thorpej 	wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC];
    164  1.1  thorpej };
    165  1.1  thorpej 
    166  1.1  thorpej #define	WM_CDOFF(x)	offsetof(struct wm_control_data, x)
    167  1.1  thorpej #define	WM_CDTXOFF(x)	WM_CDOFF(wcd_txdescs[(x)])
    168  1.1  thorpej #define	WM_CDRXOFF(x)	WM_CDOFF(wcd_rxdescs[(x)])
    169  1.1  thorpej 
    170  1.1  thorpej /*
    171  1.1  thorpej  * Software state for transmit jobs.
    172  1.1  thorpej  */
    173  1.1  thorpej struct wm_txsoft {
    174  1.1  thorpej 	struct mbuf *txs_mbuf;		/* head of our mbuf chain */
    175  1.1  thorpej 	bus_dmamap_t txs_dmamap;	/* our DMA map */
    176  1.1  thorpej 	int txs_firstdesc;		/* first descriptor in packet */
    177  1.1  thorpej 	int txs_lastdesc;		/* last descriptor in packet */
    178  1.1  thorpej };
    179  1.1  thorpej 
    180  1.1  thorpej /*
    181  1.1  thorpej  * Software state for receive buffers.  Each descriptor gets a
    182  1.1  thorpej  * 2k (MCLBYTES) buffer and a DMA map.  For packets which fill
    183  1.1  thorpej  * more than one buffer, we chain them together.
    184  1.1  thorpej  */
    185  1.1  thorpej struct wm_rxsoft {
    186  1.1  thorpej 	struct mbuf *rxs_mbuf;		/* head of our mbuf chain */
    187  1.1  thorpej 	bus_dmamap_t rxs_dmamap;	/* our DMA map */
    188  1.1  thorpej };
    189  1.1  thorpej 
    190  1.1  thorpej /*
    191  1.1  thorpej  * Software state per device.
    192  1.1  thorpej  */
    193  1.1  thorpej struct wm_softc {
    194  1.1  thorpej 	struct device sc_dev;		/* generic device information */
    195  1.1  thorpej 	bus_space_tag_t sc_st;		/* bus space tag */
    196  1.1  thorpej 	bus_space_handle_t sc_sh;	/* bus space handle */
    197  1.1  thorpej 	bus_dma_tag_t sc_dmat;		/* bus DMA tag */
    198  1.1  thorpej 	struct ethercom sc_ethercom;	/* ethernet common data */
    199  1.1  thorpej 	void *sc_sdhook;		/* shutdown hook */
    200  1.1  thorpej 
    201  1.1  thorpej 	int sc_type;			/* chip type; see below */
    202  1.1  thorpej 	int sc_flags;			/* flags; see below */
    203  1.1  thorpej 
    204  1.1  thorpej 	void *sc_ih;			/* interrupt cookie */
    205  1.1  thorpej 
    206  1.1  thorpej 	struct mii_data sc_mii;		/* MII/media information */
    207  1.1  thorpej 
    208  1.1  thorpej 	struct callout sc_tick_ch;	/* tick callout */
    209  1.1  thorpej 
    210  1.1  thorpej 	bus_dmamap_t sc_cddmamap;	/* control data DMA map */
    211  1.1  thorpej #define	sc_cddma	sc_cddmamap->dm_segs[0].ds_addr
    212  1.1  thorpej 
    213  1.1  thorpej 	/*
    214  1.1  thorpej 	 * Software state for the transmit and receive descriptors.
    215  1.1  thorpej 	 */
    216  1.1  thorpej 	struct wm_txsoft sc_txsoft[WM_TXQUEUELEN];
    217  1.1  thorpej 	struct wm_rxsoft sc_rxsoft[WM_NRXDESC];
    218  1.1  thorpej 
    219  1.1  thorpej 	/*
    220  1.1  thorpej 	 * Control data structures.
    221  1.1  thorpej 	 */
    222  1.1  thorpej 	struct wm_control_data *sc_control_data;
    223  1.1  thorpej #define	sc_txdescs	sc_control_data->wcd_txdescs
    224  1.1  thorpej #define	sc_rxdescs	sc_control_data->wcd_rxdescs
    225  1.1  thorpej 
    226  1.1  thorpej #ifdef WM_EVENT_COUNTERS
    227  1.1  thorpej 	/* Event counters. */
    228  1.1  thorpej 	struct evcnt sc_ev_txsstall;	/* Tx stalled due to no txs */
    229  1.1  thorpej 	struct evcnt sc_ev_txdstall;	/* Tx stalled due to no txd */
    230  1.1  thorpej 	struct evcnt sc_ev_txintr;	/* Tx interrupts */
    231  1.1  thorpej 	struct evcnt sc_ev_rxintr;	/* Rx interrupts */
    232  1.1  thorpej 	struct evcnt sc_ev_linkintr;	/* Link interrupts */
    233  1.1  thorpej 
    234  1.1  thorpej 	struct evcnt sc_ev_rxipsum;	/* IP checksums checked in-bound */
    235  1.1  thorpej 	struct evcnt sc_ev_rxtusum;	/* TCP/UDP cksums checked in-bound */
    236  1.1  thorpej 	struct evcnt sc_ev_txipsum;	/* IP checksums comp. out-bound */
    237  1.1  thorpej 	struct evcnt sc_ev_txtusum;	/* TCP/UDP cksums comp. out-bound */
    238  1.1  thorpej 
    239  1.1  thorpej 	struct evcnt sc_ev_txseg1;	/* Tx packets w/ 1 segment */
    240  1.1  thorpej 	struct evcnt sc_ev_txseg2;	/* Tx packets w/ 2 segments */
    241  1.1  thorpej 	struct evcnt sc_ev_txseg3;	/* Tx packets w/ 3 segments */
    242  1.1  thorpej 	struct evcnt sc_ev_txseg4;	/* Tx packets w/ 4 segments */
    243  1.1  thorpej 	struct evcnt sc_ev_txseg5;	/* Tx packets w/ 5 segments */
    244  1.1  thorpej 	struct evcnt sc_ev_txsegmore;	/* Tx packets w/ more than 5 segments */
    245  1.1  thorpej 	struct evcnt sc_ev_txdrop;	/* Tx packets dropped (too many segs) */
    246  1.1  thorpej 
    247  1.1  thorpej 	struct evcnt sc_ev_tu;		/* Tx underrun */
    248  1.1  thorpej #endif /* WM_EVENT_COUNTERS */
    249  1.1  thorpej 
    250  1.1  thorpej 	bus_addr_t sc_tdt_reg;		/* offset of TDT register */
    251  1.1  thorpej 
    252  1.1  thorpej 	int	sc_txfree;		/* number of free Tx descriptors */
    253  1.1  thorpej 	int	sc_txnext;		/* next ready Tx descriptor */
    254  1.1  thorpej 
    255  1.1  thorpej 	int	sc_txsfree;		/* number of free Tx jobs */
    256  1.1  thorpej 	int	sc_txsnext;		/* next free Tx job */
    257  1.1  thorpej 	int	sc_txsdirty;		/* dirty Tx jobs */
    258  1.1  thorpej 
    259  1.1  thorpej 	bus_addr_t sc_rdt_reg;		/* offset of RDT register */
    260  1.1  thorpej 
    261  1.1  thorpej 	int	sc_rxptr;		/* next ready Rx descriptor/queue ent */
    262  1.1  thorpej 	int	sc_rxdiscard;
    263  1.1  thorpej 	int	sc_rxlen;
    264  1.1  thorpej 	struct mbuf *sc_rxhead;
    265  1.1  thorpej 	struct mbuf *sc_rxtail;
    266  1.1  thorpej 	struct mbuf **sc_rxtailp;
    267  1.1  thorpej 
    268  1.1  thorpej 	uint32_t sc_ctrl;		/* prototype CTRL register */
    269  1.1  thorpej #if 0
    270  1.1  thorpej 	uint32_t sc_ctrl_ext;		/* prototype CTRL_EXT register */
    271  1.1  thorpej #endif
    272  1.1  thorpej 	uint32_t sc_icr;		/* prototype interrupt bits */
    273  1.1  thorpej 	uint32_t sc_tctl;		/* prototype TCTL register */
    274  1.1  thorpej 	uint32_t sc_rctl;		/* prototype RCTL register */
    275  1.1  thorpej 	uint32_t sc_txcw;		/* prototype TXCW register */
    276  1.1  thorpej 	uint32_t sc_tipg;		/* prototype TIPG register */
    277  1.1  thorpej 
    278  1.1  thorpej 	int sc_tbi_linkup;		/* TBI link status */
    279  1.1  thorpej 	int sc_tbi_anstate;		/* autonegotiation state */
    280  1.1  thorpej 
    281  1.1  thorpej 	int sc_mchash_type;		/* multicast filter offset */
    282  1.1  thorpej };
    283  1.1  thorpej 
    284  1.1  thorpej #define	WM_RXCHAIN_RESET(sc)						\
    285  1.1  thorpej do {									\
    286  1.1  thorpej 	(sc)->sc_rxtailp = &(sc)->sc_rxhead;				\
    287  1.1  thorpej 	*(sc)->sc_rxtailp = NULL;					\
    288  1.1  thorpej 	(sc)->sc_rxlen = 0;						\
    289  1.1  thorpej } while (/*CONSTCOND*/0)
    290  1.1  thorpej 
    291  1.1  thorpej #define	WM_RXCHAIN_LINK(sc, m)						\
    292  1.1  thorpej do {									\
    293  1.1  thorpej 	*(sc)->sc_rxtailp = (sc)->sc_rxtail = (m);			\
    294  1.1  thorpej 	(sc)->sc_rxtailp = &(m)->m_next;				\
    295  1.1  thorpej } while (/*CONSTCOND*/0)
    296  1.1  thorpej 
    297  1.1  thorpej /* sc_type */
    298  1.1  thorpej #define	WM_T_WISEMAN_2_0	0	/* Wiseman (i82542) 2.0 (really old) */
    299  1.1  thorpej #define	WM_T_WISEMAN_2_1	1	/* Wiseman (i82542) 2.1+ (old) */
    300  1.1  thorpej #define	WM_T_LIVENGOOD		2	/* Livengood (i82543) */
    301  1.1  thorpej #define	WM_T_CORDOVA		3	/* Cordova (i82544) */
    302  1.1  thorpej 
    303  1.1  thorpej /* sc_flags */
    304  1.1  thorpej #define	WM_F_HAS_MII		0x01	/* has MII */
    305  1.1  thorpej 
    306  1.1  thorpej #ifdef WM_EVENT_COUNTERS
    307  1.1  thorpej #define	WM_EVCNT_INCR(ev)	(ev)->ev_count++
    308  1.1  thorpej #else
    309  1.1  thorpej #define	WM_EVCNT_INCR(ev)	/* nothing */
    310  1.1  thorpej #endif
    311  1.1  thorpej 
    312  1.1  thorpej #define	CSR_READ(sc, reg)						\
    313  1.1  thorpej 	bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
    314  1.1  thorpej #define	CSR_WRITE(sc, reg, val)						\
    315  1.1  thorpej 	bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
    316  1.1  thorpej 
    317  1.1  thorpej #define	WM_CDTXADDR(sc, x)	((sc)->sc_cddma + WM_CDTXOFF((x)))
    318  1.1  thorpej #define	WM_CDRXADDR(sc, x)	((sc)->sc_cddma + WM_CDRXOFF((x)))
    319  1.1  thorpej 
    320  1.1  thorpej #define	WM_CDTXSYNC(sc, x, n, ops)					\
    321  1.1  thorpej do {									\
    322  1.1  thorpej 	int __x, __n;							\
    323  1.1  thorpej 									\
    324  1.1  thorpej 	__x = (x);							\
    325  1.1  thorpej 	__n = (n);							\
    326  1.1  thorpej 									\
    327  1.1  thorpej 	/* If it will wrap around, sync to the end of the ring. */	\
    328  1.1  thorpej 	if ((__x + __n) > WM_NTXDESC) {					\
    329  1.1  thorpej 		bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,	\
    330  1.1  thorpej 		    WM_CDTXOFF(__x), sizeof(wiseman_txdesc_t) *		\
    331  1.1  thorpej 		    (WM_NTXDESC - __x), (ops));				\
    332  1.1  thorpej 		__n -= (WM_NTXDESC - __x);				\
    333  1.1  thorpej 		__x = 0;						\
    334  1.1  thorpej 	}								\
    335  1.1  thorpej 									\
    336  1.1  thorpej 	/* Now sync whatever is left. */				\
    337  1.1  thorpej 	bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,		\
    338  1.1  thorpej 	    WM_CDTXOFF(__x), sizeof(wiseman_txdesc_t) * __n, (ops));	\
    339  1.1  thorpej } while (/*CONSTCOND*/0)
    340  1.1  thorpej 
    341  1.1  thorpej #define	WM_CDRXSYNC(sc, x, ops)						\
    342  1.1  thorpej do {									\
    343  1.1  thorpej 	bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,		\
    344  1.1  thorpej 	   WM_CDRXOFF((x)), sizeof(wiseman_rxdesc_t), (ops));		\
    345  1.1  thorpej } while (/*CONSTCOND*/0)
    346  1.1  thorpej 
    347  1.1  thorpej #define	WM_INIT_RXDESC(sc, x)						\
    348  1.1  thorpej do {									\
    349  1.1  thorpej 	struct wm_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)];		\
    350  1.1  thorpej 	wiseman_rxdesc_t *__rxd = &(sc)->sc_rxdescs[(x)];		\
    351  1.1  thorpej 	struct mbuf *__m = __rxs->rxs_mbuf;				\
    352  1.1  thorpej 									\
    353  1.1  thorpej 	/*								\
    354  1.1  thorpej 	 * Note: We scoot the packet forward 2 bytes in the buffer	\
    355  1.1  thorpej 	 * so that the payload after the Ethernet header is aligned	\
    356  1.1  thorpej 	 * to a 4-byte boundary.					\
    357  1.1  thorpej 	 *								\
    358  1.1  thorpej 	 * XXX BRAINDAMAGE ALERT!					\
    359  1.1  thorpej 	 * The stupid chip uses the same size for every buffer, which	\
    360  1.1  thorpej 	 * is set in the Receive Control register.  We are using the 2K	\
    361  1.1  thorpej 	 * size option, but what we REALLY want is (2K - 2)!  For this	\
    362  1.1  thorpej 	 * reason, we can't accept packets longer than the standard	\
    363  1.1  thorpej 	 * Ethernet MTU, without incurring a big penalty to copy every	\
    364  1.1  thorpej 	 * incoming packet to a new, suitably aligned buffer.		\
    365  1.1  thorpej 	 *								\
    366  1.1  thorpej 	 * We'll need to make some changes to the layer 3/4 parts of	\
    367  1.1  thorpej 	 * the stack (to copy the headers to a new buffer if not	\
    368  1.1  thorpej 	 * aligned) in order to support large MTU on this chip.  Lame.	\
    369  1.1  thorpej 	 */								\
    370  1.1  thorpej 	__m->m_data = __m->m_ext.ext_buf + 2;				\
    371  1.1  thorpej 									\
    372  1.1  thorpej 	__rxd->wrx_addr.wa_low =					\
    373  1.1  thorpej 	    htole32(__rxs->rxs_dmamap->dm_segs[0].ds_addr + 2);		\
    374  1.1  thorpej 	__rxd->wrx_addr.wa_high = 0;					\
    375  1.1  thorpej 	__rxd->wrx_len = 0;						\
    376  1.1  thorpej 	__rxd->wrx_cksum = 0;						\
    377  1.1  thorpej 	__rxd->wrx_status = 0;						\
    378  1.1  thorpej 	__rxd->wrx_errors = 0;						\
    379  1.1  thorpej 	__rxd->wrx_special = 0;						\
    380  1.1  thorpej 	WM_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
    381  1.1  thorpej 									\
    382  1.1  thorpej 	CSR_WRITE((sc), (sc)->sc_rdt_reg, (x));				\
    383  1.1  thorpej } while (/*CONSTCOND*/0)
    384  1.1  thorpej 
    385  1.1  thorpej void	wm_start(struct ifnet *);
    386  1.1  thorpej void	wm_watchdog(struct ifnet *);
    387  1.1  thorpej int	wm_ioctl(struct ifnet *, u_long, caddr_t);
    388  1.1  thorpej int	wm_init(struct ifnet *);
    389  1.1  thorpej void	wm_stop(struct ifnet *, int);
    390  1.1  thorpej 
    391  1.1  thorpej void	wm_shutdown(void *);
    392  1.1  thorpej 
    393  1.1  thorpej void	wm_reset(struct wm_softc *);
    394  1.1  thorpej void	wm_rxdrain(struct wm_softc *);
    395  1.1  thorpej int	wm_add_rxbuf(struct wm_softc *, int);
    396  1.1  thorpej void	wm_read_eeprom(struct wm_softc *, int, int, u_int16_t *);
    397  1.1  thorpej void	wm_tick(void *);
    398  1.1  thorpej 
    399  1.1  thorpej void	wm_set_filter(struct wm_softc *);
    400  1.1  thorpej 
    401  1.1  thorpej int	wm_intr(void *);
    402  1.1  thorpej void	wm_txintr(struct wm_softc *);
    403  1.1  thorpej void	wm_rxintr(struct wm_softc *);
    404  1.1  thorpej void	wm_linkintr(struct wm_softc *, uint32_t);
    405  1.1  thorpej 
    406  1.1  thorpej void	wm_tbi_mediainit(struct wm_softc *);
    407  1.1  thorpej int	wm_tbi_mediachange(struct ifnet *);
    408  1.1  thorpej void	wm_tbi_mediastatus(struct ifnet *, struct ifmediareq *);
    409  1.1  thorpej 
    410  1.1  thorpej void	wm_tbi_set_linkled(struct wm_softc *);
    411  1.1  thorpej void	wm_tbi_check_link(struct wm_softc *);
    412  1.1  thorpej 
    413  1.1  thorpej void	wm_gmii_reset(struct wm_softc *);
    414  1.1  thorpej 
    415  1.1  thorpej int	wm_gmii_livengood_readreg(struct device *, int, int);
    416  1.1  thorpej void	wm_gmii_livengood_writereg(struct device *, int, int, int);
    417  1.1  thorpej 
    418  1.1  thorpej int	wm_gmii_cordova_readreg(struct device *, int, int);
    419  1.1  thorpej void	wm_gmii_cordova_writereg(struct device *, int, int, int);
    420  1.1  thorpej 
    421  1.1  thorpej void	wm_gmii_statchg(struct device *);
    422  1.1  thorpej 
    423  1.1  thorpej void	wm_gmii_mediainit(struct wm_softc *);
    424  1.1  thorpej int	wm_gmii_mediachange(struct ifnet *);
    425  1.1  thorpej void	wm_gmii_mediastatus(struct ifnet *, struct ifmediareq *);
    426  1.1  thorpej 
    427  1.1  thorpej int	wm_match(struct device *, struct cfdata *, void *);
    428  1.1  thorpej void	wm_attach(struct device *, struct device *, void *);
    429  1.1  thorpej 
    430  1.1  thorpej int	wm_copy_small = 0;
    431  1.1  thorpej 
    432  1.1  thorpej struct cfattach wm_ca = {
    433  1.1  thorpej 	sizeof(struct wm_softc), wm_match, wm_attach,
    434  1.1  thorpej };
    435  1.1  thorpej 
    436  1.1  thorpej /*
    437  1.1  thorpej  * Devices supported by this driver.
    438  1.1  thorpej  */
    439  1.1  thorpej const struct wm_product {
    440  1.1  thorpej 	pci_vendor_id_t		wmp_vendor;
    441  1.1  thorpej 	pci_product_id_t	wmp_product;
    442  1.1  thorpej 	const char		*wmp_name;
    443  1.1  thorpej 	int			wmp_type;
    444  1.1  thorpej 	int			wmp_flags;
    445  1.1  thorpej #define	WMP_F_1000X		0x01
    446  1.1  thorpej #define	WMP_F_1000T		0x02
    447  1.1  thorpej } wm_products[] = {
    448  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82542,
    449  1.1  thorpej 	  "Intel i82542 1000BASE-X Ethernet",
    450  1.1  thorpej 	  WM_T_WISEMAN_2_1,	WMP_F_1000X },
    451  1.1  thorpej 
    452  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82543_FIBER,
    453  1.1  thorpej 	  "Intel i82543 1000BASE-X Ethernet",
    454  1.1  thorpej 	  WM_T_LIVENGOOD,	WMP_F_1000X },
    455  1.1  thorpej 
    456  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82543_SC,
    457  1.1  thorpej 	  "Intel i82543-SC 1000BASE-X Ethernet",
    458  1.1  thorpej 	  WM_T_LIVENGOOD,	WMP_F_1000X },
    459  1.1  thorpej 
    460  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82543_COPPER,
    461  1.1  thorpej 	  "Intel i82543 1000BASE-T Ethernet",
    462  1.1  thorpej 	  WM_T_LIVENGOOD,	WMP_F_1000T },
    463  1.1  thorpej 
    464  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82544_XT,
    465  1.1  thorpej 	  "Intel i82544 1000BASE-T Ethernet",
    466  1.1  thorpej 	  WM_T_CORDOVA,		WMP_F_1000T },
    467  1.1  thorpej 
    468  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82544_XF,
    469  1.1  thorpej 	  "Intel i82544 1000BASE-X Ethernet",
    470  1.1  thorpej 	  WM_T_CORDOVA,		WMP_F_1000X },
    471  1.1  thorpej 
    472  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82544GC,
    473  1.1  thorpej 	  "Intel i82544GC 1000BASE-T Ethernet",
    474  1.1  thorpej 	  WM_T_CORDOVA,		WMP_F_1000T },
    475  1.1  thorpej 
    476  1.1  thorpej 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82544GC_64,
    477  1.1  thorpej 	  "Intel i82544GC 1000BASE-T Ethernet",
    478  1.1  thorpej 	  WM_T_CORDOVA,		WMP_F_1000T },
    479  1.1  thorpej 
    480  1.1  thorpej 	{ 0,			0,
    481  1.1  thorpej 	  NULL,
    482  1.1  thorpej 	  0,			0 },
    483  1.1  thorpej };
    484  1.1  thorpej 
    485  1.1  thorpej static const struct wm_product *
    486  1.1  thorpej wm_lookup(const struct pci_attach_args *pa)
    487  1.1  thorpej {
    488  1.1  thorpej 	const struct wm_product *wmp;
    489  1.1  thorpej 
    490  1.1  thorpej 	for (wmp = wm_products; wmp->wmp_name != NULL; wmp++) {
    491  1.1  thorpej 		if (PCI_VENDOR(pa->pa_id) == wmp->wmp_vendor &&
    492  1.1  thorpej 		    PCI_PRODUCT(pa->pa_id) == wmp->wmp_product)
    493  1.1  thorpej 			return (wmp);
    494  1.1  thorpej 	}
    495  1.1  thorpej 	return (NULL);
    496  1.1  thorpej }
    497  1.1  thorpej 
    498  1.1  thorpej int
    499  1.1  thorpej wm_match(struct device *parent, struct cfdata *cf, void *aux)
    500  1.1  thorpej {
    501  1.1  thorpej 	struct pci_attach_args *pa = aux;
    502  1.1  thorpej 
    503  1.1  thorpej 	if (wm_lookup(pa) != NULL)
    504  1.1  thorpej 		return (1);
    505  1.1  thorpej 
    506  1.1  thorpej 	return (0);
    507  1.1  thorpej }
    508  1.1  thorpej 
    509  1.1  thorpej void
    510  1.1  thorpej wm_attach(struct device *parent, struct device *self, void *aux)
    511  1.1  thorpej {
    512  1.1  thorpej 	struct wm_softc *sc = (void *) self;
    513  1.1  thorpej 	struct pci_attach_args *pa = aux;
    514  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    515  1.1  thorpej 	pci_chipset_tag_t pc = pa->pa_pc;
    516  1.1  thorpej 	pci_intr_handle_t ih;
    517  1.1  thorpej 	const char *intrstr = NULL;
    518  1.1  thorpej 	bus_space_tag_t memt;
    519  1.1  thorpej 	bus_space_handle_t memh;
    520  1.1  thorpej 	bus_dma_segment_t seg;
    521  1.1  thorpej 	int memh_valid;
    522  1.1  thorpej 	int i, rseg, error;
    523  1.1  thorpej 	const struct wm_product *wmp;
    524  1.1  thorpej 	uint8_t enaddr[ETHER_ADDR_LEN];
    525  1.1  thorpej 	uint16_t myea[ETHER_ADDR_LEN / 2], cfg1, cfg2, swdpin;
    526  1.1  thorpej 	pcireg_t preg, memtype;
    527  1.1  thorpej 	int pmreg;
    528  1.1  thorpej 
    529  1.1  thorpej 	callout_init(&sc->sc_tick_ch);
    530  1.1  thorpej 
    531  1.1  thorpej 	wmp = wm_lookup(pa);
    532  1.1  thorpej 	if (wmp == NULL) {
    533  1.1  thorpej 		printf("\n");
    534  1.1  thorpej 		panic("wm_attach: impossible");
    535  1.1  thorpej 	}
    536  1.1  thorpej 
    537  1.1  thorpej 	sc->sc_dmat = pa->pa_dmat;
    538  1.1  thorpej 
    539  1.1  thorpej 	preg = PCI_REVISION(pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG));
    540  1.1  thorpej 	printf(": %s, rev. %d\n", wmp->wmp_name, preg);
    541  1.1  thorpej 
    542  1.1  thorpej 	sc->sc_type = wmp->wmp_type;
    543  1.1  thorpej 	if (sc->sc_type < WM_T_LIVENGOOD) {
    544  1.1  thorpej 		if (preg < 2) {
    545  1.1  thorpej 			printf("%s: Wiseman must be at least rev. 2\n",
    546  1.1  thorpej 			    sc->sc_dev.dv_xname);
    547  1.1  thorpej 			return;
    548  1.1  thorpej 		}
    549  1.1  thorpej 		if (preg < 3)
    550  1.1  thorpej 			sc->sc_type = WM_T_WISEMAN_2_0;
    551  1.1  thorpej 	}
    552  1.1  thorpej 
    553  1.1  thorpej 	/*
    554  1.1  thorpej 	 * Map the device.
    555  1.1  thorpej 	 */
    556  1.1  thorpej 	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WM_PCI_MMBA);
    557  1.1  thorpej 	switch (memtype) {
    558  1.1  thorpej 	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
    559  1.1  thorpej 	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
    560  1.1  thorpej 		memh_valid = (pci_mapreg_map(pa, WM_PCI_MMBA,
    561  1.1  thorpej 		    memtype, 0, &memt, &memh, NULL, NULL) == 0);
    562  1.1  thorpej 		break;
    563  1.1  thorpej 	default:
    564  1.1  thorpej 		memh_valid = 0;
    565  1.1  thorpej 	}
    566  1.1  thorpej 
    567  1.1  thorpej 	if (memh_valid) {
    568  1.1  thorpej 		sc->sc_st = memt;
    569  1.1  thorpej 		sc->sc_sh = memh;
    570  1.1  thorpej 	} else {
    571  1.1  thorpej 		printf("%s: unable to map device registers\n",
    572  1.1  thorpej 		    sc->sc_dev.dv_xname);
    573  1.1  thorpej 		return;
    574  1.1  thorpej 	}
    575  1.1  thorpej 
    576  1.1  thorpej 	/* Enable bus mastering.  Disable MWI on the Wiseman 2.0. */
    577  1.1  thorpej 	preg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
    578  1.1  thorpej 	preg |= PCI_COMMAND_MASTER_ENABLE;
    579  1.1  thorpej 	if (sc->sc_type < WM_T_WISEMAN_2_1)
    580  1.1  thorpej 		preg &= ~PCI_COMMAND_INVALIDATE_ENABLE;
    581  1.1  thorpej 	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, preg);
    582  1.1  thorpej 
    583  1.1  thorpej 	/* Get it out of power save mode, if needed. */
    584  1.1  thorpej 	if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
    585  1.1  thorpej 		preg = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3;
    586  1.1  thorpej 		if (preg == 3) {
    587  1.1  thorpej 			/*
    588  1.1  thorpej 			 * The card has lost all configuration data in
    589  1.1  thorpej 			 * this state, so punt.
    590  1.1  thorpej 			 */
    591  1.1  thorpej 			printf("%s: unable to wake from power state D3\n",
    592  1.1  thorpej 			    sc->sc_dev.dv_xname);
    593  1.1  thorpej 			return;
    594  1.1  thorpej 		}
    595  1.1  thorpej 		if (preg != 0) {
    596  1.1  thorpej 			printf("%s: waking up from power state D%d\n",
    597  1.1  thorpej 			    sc->sc_dev.dv_xname, preg);
    598  1.1  thorpej 			pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0);
    599  1.1  thorpej 		}
    600  1.1  thorpej 	}
    601  1.1  thorpej 
    602  1.1  thorpej 	/*
    603  1.1  thorpej 	 * Map and establish our interrupt.
    604  1.1  thorpej 	 */
    605  1.1  thorpej 	if (pci_intr_map(pa, &ih)) {
    606  1.1  thorpej 		printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname);
    607  1.1  thorpej 		return;
    608  1.1  thorpej 	}
    609  1.1  thorpej 	intrstr = pci_intr_string(pc, ih);
    610  1.1  thorpej 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wm_intr, sc);
    611  1.1  thorpej 	if (sc->sc_ih == NULL) {
    612  1.1  thorpej 		printf("%s: unable to establish interrupt",
    613  1.1  thorpej 		    sc->sc_dev.dv_xname);
    614  1.1  thorpej 		if (intrstr != NULL)
    615  1.1  thorpej 			printf(" at %s", intrstr);
    616  1.1  thorpej 		printf("\n");
    617  1.1  thorpej 		return;
    618  1.1  thorpej 	}
    619  1.1  thorpej 	printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
    620  1.1  thorpej 
    621  1.1  thorpej 	/*
    622  1.1  thorpej 	 * Allocate the control data structures, and create and load the
    623  1.1  thorpej 	 * DMA map for it.
    624  1.1  thorpej 	 */
    625  1.1  thorpej 	if ((error = bus_dmamem_alloc(sc->sc_dmat,
    626  1.1  thorpej 	    sizeof(struct wm_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,
    627  1.1  thorpej 	    0)) != 0) {
    628  1.1  thorpej 		printf("%s: unable to allocate control data, error = %d\n",
    629  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    630  1.1  thorpej 		goto fail_0;
    631  1.1  thorpej 	}
    632  1.1  thorpej 
    633  1.1  thorpej 	if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
    634  1.1  thorpej 	    sizeof(struct wm_control_data), (caddr_t *)&sc->sc_control_data,
    635  1.1  thorpej 	    BUS_DMA_COHERENT)) != 0) {
    636  1.1  thorpej 		printf("%s: unable to map control data, error = %d\n",
    637  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    638  1.1  thorpej 		goto fail_1;
    639  1.1  thorpej 	}
    640  1.1  thorpej 
    641  1.1  thorpej 	if ((error = bus_dmamap_create(sc->sc_dmat,
    642  1.1  thorpej 	    sizeof(struct wm_control_data), 1,
    643  1.1  thorpej 	    sizeof(struct wm_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
    644  1.1  thorpej 		printf("%s: unable to create control data DMA map, "
    645  1.1  thorpej 		    "error = %d\n", sc->sc_dev.dv_xname, error);
    646  1.1  thorpej 		goto fail_2;
    647  1.1  thorpej 	}
    648  1.1  thorpej 
    649  1.1  thorpej 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
    650  1.1  thorpej 	    sc->sc_control_data, sizeof(struct wm_control_data), NULL,
    651  1.1  thorpej 	    0)) != 0) {
    652  1.1  thorpej 		printf("%s: unable to load control data DMA map, error = %d\n",
    653  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    654  1.1  thorpej 		goto fail_3;
    655  1.1  thorpej 	}
    656  1.1  thorpej 
    657  1.1  thorpej 	/*
    658  1.1  thorpej 	 * Create the transmit buffer DMA maps.
    659  1.1  thorpej 	 */
    660  1.1  thorpej 	for (i = 0; i < WM_TXQUEUELEN; i++) {
    661  1.1  thorpej 		if ((error = bus_dmamap_create(sc->sc_dmat, ETHER_MAX_LEN_JUMBO,
    662  1.1  thorpej 		    WM_NTXSEGS, MCLBYTES, 0, 0,
    663  1.1  thorpej 		    &sc->sc_txsoft[i].txs_dmamap)) != 0) {
    664  1.1  thorpej 			printf("%s: unable to create Tx DMA map %d, "
    665  1.1  thorpej 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
    666  1.1  thorpej 			goto fail_4;
    667  1.1  thorpej 		}
    668  1.1  thorpej 	}
    669  1.1  thorpej 
    670  1.1  thorpej 	/*
    671  1.1  thorpej 	 * Create the receive buffer DMA maps.
    672  1.1  thorpej 	 */
    673  1.1  thorpej 	for (i = 0; i < WM_NRXDESC; i++) {
    674  1.1  thorpej 		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
    675  1.1  thorpej 		    MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
    676  1.1  thorpej 			printf("%s: unable to create Rx DMA map %d, "
    677  1.1  thorpej 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
    678  1.1  thorpej 			goto fail_5;
    679  1.1  thorpej 		}
    680  1.1  thorpej 		sc->sc_rxsoft[i].rxs_mbuf = NULL;
    681  1.1  thorpej 	}
    682  1.1  thorpej 
    683  1.1  thorpej 	/*
    684  1.1  thorpej 	 * Reset the chip to a known state.
    685  1.1  thorpej 	 */
    686  1.1  thorpej 	wm_reset(sc);
    687  1.1  thorpej 
    688  1.1  thorpej 	/*
    689  1.1  thorpej 	 * Read the Ethernet address from the EEPROM.
    690  1.1  thorpej 	 */
    691  1.1  thorpej 	wm_read_eeprom(sc, EEPROM_OFF_MACADDR,
    692  1.1  thorpej 	    sizeof(myea) / sizeof(myea[0]), myea);
    693  1.1  thorpej 	enaddr[0] = myea[0] & 0xff;
    694  1.1  thorpej 	enaddr[1] = myea[0] >> 8;
    695  1.1  thorpej 	enaddr[2] = myea[1] & 0xff;
    696  1.1  thorpej 	enaddr[3] = myea[1] >> 8;
    697  1.1  thorpej 	enaddr[4] = myea[2] & 0xff;
    698  1.1  thorpej 	enaddr[5] = myea[2] >> 8;
    699  1.1  thorpej 
    700  1.1  thorpej 	printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
    701  1.1  thorpej 	    ether_sprintf(enaddr));
    702  1.1  thorpej 
    703  1.1  thorpej 	/*
    704  1.1  thorpej 	 * Read the config info from the EEPROM, and set up various
    705  1.1  thorpej 	 * bits in the control registers based on their contents.
    706  1.1  thorpej 	 */
    707  1.1  thorpej 	wm_read_eeprom(sc, EEPROM_OFF_CFG1, 1, &cfg1);
    708  1.1  thorpej 	wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &cfg2);
    709  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA)
    710  1.1  thorpej 		wm_read_eeprom(sc, EEPROM_OFF_SWDPIN, 1, &swdpin);
    711  1.1  thorpej 
    712  1.1  thorpej 	if (cfg1 & EEPROM_CFG1_ILOS)
    713  1.1  thorpej 		sc->sc_ctrl |= CTRL_ILOS;
    714  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA) {
    715  1.1  thorpej 		sc->sc_ctrl |=
    716  1.1  thorpej 		    ((swdpin >> EEPROM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
    717  1.1  thorpej 		    CTRL_SWDPIO_SHIFT;
    718  1.1  thorpej 		sc->sc_ctrl |=
    719  1.1  thorpej 		    ((swdpin >> EEPROM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
    720  1.1  thorpej 		    CTRL_SWDPINS_SHIFT;
    721  1.1  thorpej 	} else {
    722  1.1  thorpej 		sc->sc_ctrl |=
    723  1.1  thorpej 		    ((cfg1 >> EEPROM_CFG1_SWDPIO_SHIFT) & 0xf) <<
    724  1.1  thorpej 		    CTRL_SWDPIO_SHIFT;
    725  1.1  thorpej 	}
    726  1.1  thorpej 
    727  1.1  thorpej #if 0
    728  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA) {
    729  1.1  thorpej 		if (cfg1 & EEPROM_CFG1_IPS0)
    730  1.1  thorpej 			sc->sc_ctrl_ext |= CTRL_EXT_IPS;
    731  1.1  thorpej 		if (cfg1 & EEPROM_CFG1_IPS1)
    732  1.1  thorpej 			sc->sc_ctrl_ext |= CTRL_EXT_IPS1;
    733  1.1  thorpej 		sc->sc_ctrl_ext |=
    734  1.1  thorpej 		    ((swdpin >> (EEPROM_SWDPIN_SWDPIO_SHIFT + 4)) & 0xd) <<
    735  1.1  thorpej 		    CTRL_EXT_SWDPIO_SHIFT;
    736  1.1  thorpej 		sc->sc_ctrl_ext |=
    737  1.1  thorpej 		    ((swdpin >> (EEPROM_SWDPIN_SWDPIN_SHIFT + 4)) & 0xd) <<
    738  1.1  thorpej 		    CTRL_EXT_SWDPINS_SHIFT;
    739  1.1  thorpej 	} else {
    740  1.1  thorpej 		sc->sc_ctrl_ext |=
    741  1.1  thorpej 		    ((cfg2 >> EEPROM_CFG2_SWDPIO_SHIFT) & 0xf) <<
    742  1.1  thorpej 		    CTRL_EXT_SWDPIO_SHIFT;
    743  1.1  thorpej 	}
    744  1.1  thorpej #endif
    745  1.1  thorpej 
    746  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
    747  1.1  thorpej #if 0
    748  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL_EXT, sc->sc_ctrl_ext);
    749  1.1  thorpej #endif
    750  1.1  thorpej 
    751  1.1  thorpej 	/*
    752  1.1  thorpej 	 * Set up some register offsets that are different between
    753  1.1  thorpej 	 * the Wiseman and the Livengood and later chips.
    754  1.1  thorpej 	 */
    755  1.1  thorpej 	if (sc->sc_type < WM_T_LIVENGOOD) {
    756  1.1  thorpej 		sc->sc_rdt_reg = WMREG_OLD_RDT0;
    757  1.1  thorpej 		sc->sc_tdt_reg = WMREG_OLD_TDT;
    758  1.1  thorpej 	} else {
    759  1.1  thorpej 		sc->sc_rdt_reg = WMREG_RDT;
    760  1.1  thorpej 		sc->sc_tdt_reg = WMREG_TDT;
    761  1.1  thorpej 	}
    762  1.1  thorpej 
    763  1.1  thorpej 	/*
    764  1.1  thorpej 	 * Determine if we should use flow control.  We should
    765  1.1  thorpej 	 * always use it, unless we're on a Wiseman < 2.1.
    766  1.1  thorpej 	 */
    767  1.1  thorpej 	if (sc->sc_type >= WM_T_WISEMAN_2_1)
    768  1.1  thorpej 		sc->sc_ctrl |= CTRL_TFCE | CTRL_RFCE;
    769  1.1  thorpej 
    770  1.1  thorpej 	/*
    771  1.1  thorpej 	 * Determine if we're TBI or GMII mode, and initialize the
    772  1.1  thorpej 	 * media structures accordingly.
    773  1.1  thorpej 	 */
    774  1.1  thorpej 	if (sc->sc_type < WM_T_LIVENGOOD ||
    775  1.1  thorpej 	    (CSR_READ(sc, WMREG_STATUS) & STATUS_TBIMODE) != 0) {
    776  1.1  thorpej 		if (wmp->wmp_flags & WMP_F_1000T)
    777  1.1  thorpej 			printf("%s: WARNING: TBIMODE set on 1000BASE-T "
    778  1.1  thorpej 			    "product!\n", sc->sc_dev.dv_xname);
    779  1.1  thorpej 		wm_tbi_mediainit(sc);
    780  1.1  thorpej 	} else {
    781  1.1  thorpej 		if (wmp->wmp_flags & WMP_F_1000X)
    782  1.1  thorpej 			printf("%s: WARNING: TBIMODE clear on 1000BASE-X "
    783  1.1  thorpej 			    "product!\n", sc->sc_dev.dv_xname);
    784  1.1  thorpej 		wm_gmii_mediainit(sc);
    785  1.1  thorpej 	}
    786  1.1  thorpej 
    787  1.1  thorpej 	ifp = &sc->sc_ethercom.ec_if;
    788  1.1  thorpej 	strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
    789  1.1  thorpej 	ifp->if_softc = sc;
    790  1.1  thorpej 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    791  1.1  thorpej 	ifp->if_ioctl = wm_ioctl;
    792  1.1  thorpej 	ifp->if_start = wm_start;
    793  1.1  thorpej 	ifp->if_watchdog = wm_watchdog;
    794  1.1  thorpej 	ifp->if_init = wm_init;
    795  1.1  thorpej 	ifp->if_stop = wm_stop;
    796  1.1  thorpej 	IFQ_SET_READY(&ifp->if_snd);
    797  1.1  thorpej 
    798  1.1  thorpej 	/*
    799  1.1  thorpej 	 * If we're a Livengood or greater, we can support VLANs.
    800  1.1  thorpej 	 */
    801  1.1  thorpej 	if (sc->sc_type >= WM_T_LIVENGOOD)
    802  1.1  thorpej 		sc->sc_ethercom.ec_capabilities |=
    803  1.1  thorpej 		    ETHERCAP_VLAN_MTU /* XXXJRT | ETHERCAP_VLAN_HWTAGGING */;
    804  1.1  thorpej 
    805  1.1  thorpej 	/*
    806  1.1  thorpej 	 * We can perform TCPv4 and UDPv4 checkums in-bound.  Only
    807  1.1  thorpej 	 * on Livengood and later.
    808  1.1  thorpej 	 */
    809  1.1  thorpej 	if (sc->sc_type >= WM_T_LIVENGOOD)
    810  1.1  thorpej 		ifp->if_capabilities |=
    811  1.1  thorpej 		    IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
    812  1.1  thorpej 
    813  1.1  thorpej 	/*
    814  1.1  thorpej 	 * Attach the interface.
    815  1.1  thorpej 	 */
    816  1.1  thorpej 	if_attach(ifp);
    817  1.1  thorpej 	ether_ifattach(ifp, enaddr);
    818  1.1  thorpej 
    819  1.1  thorpej #ifdef WM_EVENT_COUNTERS
    820  1.1  thorpej 	/* Attach event counters. */
    821  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txsstall, EVCNT_TYPE_MISC,
    822  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txsstall");
    823  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txdstall, EVCNT_TYPE_MISC,
    824  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txdstall");
    825  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txintr, EVCNT_TYPE_INTR,
    826  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txintr");
    827  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR,
    828  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "rxintr");
    829  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_linkintr, EVCNT_TYPE_INTR,
    830  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "linkintr");
    831  1.1  thorpej 
    832  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC,
    833  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "rxipsum");
    834  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_rxtusum, EVCNT_TYPE_MISC,
    835  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "rxtusum");
    836  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC,
    837  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txipsum");
    838  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txtusum, EVCNT_TYPE_MISC,
    839  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txtusum");
    840  1.1  thorpej 
    841  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txseg1, EVCNT_TYPE_MISC,
    842  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txseg1");
    843  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txseg2, EVCNT_TYPE_MISC,
    844  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txseg2");
    845  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txseg3, EVCNT_TYPE_MISC,
    846  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txseg3");
    847  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txseg4, EVCNT_TYPE_MISC,
    848  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txseg4");
    849  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txseg5, EVCNT_TYPE_MISC,
    850  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txseg5");
    851  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txsegmore, EVCNT_TYPE_MISC,
    852  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txsegmore");
    853  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_txdrop, EVCNT_TYPE_MISC,
    854  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "txdrop");
    855  1.1  thorpej 
    856  1.1  thorpej 	evcnt_attach_dynamic(&sc->sc_ev_tu, EVCNT_TYPE_MISC,
    857  1.1  thorpej 	    NULL, sc->sc_dev.dv_xname, "tu");
    858  1.1  thorpej #endif /* WM_EVENT_COUNTERS */
    859  1.1  thorpej 
    860  1.1  thorpej 	/*
    861  1.1  thorpej 	 * Make sure the interface is shutdown during reboot.
    862  1.1  thorpej 	 */
    863  1.1  thorpej 	sc->sc_sdhook = shutdownhook_establish(wm_shutdown, sc);
    864  1.1  thorpej 	if (sc->sc_sdhook == NULL)
    865  1.1  thorpej 		printf("%s: WARNING: unable to establish shutdown hook\n",
    866  1.1  thorpej 		    sc->sc_dev.dv_xname);
    867  1.1  thorpej 	return;
    868  1.1  thorpej 
    869  1.1  thorpej 	/*
    870  1.1  thorpej 	 * Free any resources we've allocated during the failed attach
    871  1.1  thorpej 	 * attempt.  Do this in reverse order and fall through.
    872  1.1  thorpej 	 */
    873  1.1  thorpej  fail_5:
    874  1.1  thorpej 	for (i = 0; i < WM_NRXDESC; i++) {
    875  1.1  thorpej 		if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
    876  1.1  thorpej 			bus_dmamap_destroy(sc->sc_dmat,
    877  1.1  thorpej 			    sc->sc_rxsoft[i].rxs_dmamap);
    878  1.1  thorpej 	}
    879  1.1  thorpej  fail_4:
    880  1.1  thorpej 	for (i = 0; i < WM_TXQUEUELEN; i++) {
    881  1.1  thorpej 		if (sc->sc_txsoft[i].txs_dmamap != NULL)
    882  1.1  thorpej 			bus_dmamap_destroy(sc->sc_dmat,
    883  1.1  thorpej 			    sc->sc_txsoft[i].txs_dmamap);
    884  1.1  thorpej 	}
    885  1.1  thorpej 	bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
    886  1.1  thorpej  fail_3:
    887  1.1  thorpej 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
    888  1.1  thorpej  fail_2:
    889  1.1  thorpej 	bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
    890  1.1  thorpej 	    sizeof(struct wm_control_data));
    891  1.1  thorpej  fail_1:
    892  1.1  thorpej 	bus_dmamem_free(sc->sc_dmat, &seg, rseg);
    893  1.1  thorpej  fail_0:
    894  1.1  thorpej 	return;
    895  1.1  thorpej }
    896  1.1  thorpej 
    897  1.1  thorpej /*
    898  1.1  thorpej  * wm_shutdown:
    899  1.1  thorpej  *
    900  1.1  thorpej  *	Make sure the interface is stopped at reboot time.
    901  1.1  thorpej  */
    902  1.1  thorpej void
    903  1.1  thorpej wm_shutdown(void *arg)
    904  1.1  thorpej {
    905  1.1  thorpej 	struct wm_softc *sc = arg;
    906  1.1  thorpej 
    907  1.1  thorpej 	wm_stop(&sc->sc_ethercom.ec_if, 1);
    908  1.1  thorpej }
    909  1.1  thorpej 
    910  1.1  thorpej /*
    911  1.1  thorpej  * wm_tx_cksum:
    912  1.1  thorpej  *
    913  1.1  thorpej  *	Set up TCP/IP checksumming parameters for the
    914  1.1  thorpej  *	specified packet.
    915  1.1  thorpej  */
    916  1.1  thorpej static int
    917  1.1  thorpej wm_tx_cksum(struct wm_softc *sc, struct mbuf *m0, uint32_t *cmdp,
    918  1.1  thorpej     uint32_t *fieldsp)
    919  1.1  thorpej {
    920  1.1  thorpej 	struct livengood_tcpip_ctxdesc *t;
    921  1.1  thorpej 	uint32_t fields = 0, tcmd = 0, ipcs, tucs;
    922  1.1  thorpej 	struct ip *ip;
    923  1.1  thorpej 	int offset, iphl;
    924  1.1  thorpej 
    925  1.1  thorpej 	/*
    926  1.1  thorpej 	 * XXX It would be nice if the mbuf pkthdr had offset
    927  1.1  thorpej 	 * fields for the protocol headers.
    928  1.1  thorpej 	 */
    929  1.1  thorpej 
    930  1.1  thorpej 	/* XXX Assumes normal Ethernet encap. */
    931  1.1  thorpej 	offset = ETHER_HDR_LEN;
    932  1.1  thorpej 
    933  1.1  thorpej 	/* XXX */
    934  1.1  thorpej 	if (m0->m_len < (offset + sizeof(struct ip))) {
    935  1.1  thorpej 		printf("%s: wm_tx_cksum: need to m_pullup, "
    936  1.1  thorpej 		    "packet dropped\n", sc->sc_dev.dv_xname);
    937  1.1  thorpej 		return (EINVAL);
    938  1.1  thorpej 	}
    939  1.1  thorpej 
    940  1.1  thorpej 	ip = (struct ip *) (mtod(m0, caddr_t) + offset);
    941  1.1  thorpej 	iphl = ip->ip_hl << 2;
    942  1.1  thorpej 
    943  1.1  thorpej 	if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) {
    944  1.1  thorpej 		WM_EVCNT_INCR(&sc->sc_ev_txipsum);
    945  1.1  thorpej 		tcmd |= htole32(WTX_TCPIP_CMD_IP);
    946  1.1  thorpej 		fields |= htole32(WTX_IXSM);
    947  1.1  thorpej 		ipcs = htole32(WTX_TCPIP_IPCSS(offset) |
    948  1.1  thorpej 		    WTX_TCPIP_IPCSO(offsetof(struct ip, ip_sum)) |
    949  1.1  thorpej 		    WTX_TCPIP_IPCSE(offset + iphl - 1));
    950  1.1  thorpej 	} else
    951  1.1  thorpej 		ipcs = 0;
    952  1.1  thorpej 
    953  1.1  thorpej 	offset += iphl;
    954  1.1  thorpej 
    955  1.1  thorpej 	if (m0->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
    956  1.1  thorpej 		WM_EVCNT_INCR(&sc->sc_ev_txtusum);
    957  1.1  thorpej 		tcmd |= WTX_TCPIP_CMD_TCP;
    958  1.1  thorpej 		fields |= htole32(WTX_TXSM);
    959  1.1  thorpej 		tucs = htole32(WTX_TCPIP_TUCSS(offset) |
    960  1.1  thorpej 		    WTX_TCPIP_TUCSO(offset + m0->m_pkthdr.csum_data) |
    961  1.1  thorpej 		    WTX_TCPIP_TUCSE(0) /* rest of packet */);
    962  1.1  thorpej 	} else
    963  1.1  thorpej 		tucs = 0;
    964  1.1  thorpej 
    965  1.1  thorpej 	/* Fill in the context descriptor. */
    966  1.1  thorpej 	t = (struct livengood_tcpip_ctxdesc *) &sc->sc_txdescs[sc->sc_txnext];
    967  1.1  thorpej 	t->tcpip_ipcs = ipcs;
    968  1.1  thorpej 	t->tcpip_tucs = tucs;
    969  1.1  thorpej 	t->tcpip_cmdlen = htole32(WTX_CMD_DEXT | WTX_DTYP_C) | tcmd;
    970  1.1  thorpej 	t->tcpip_seg = 0;
    971  1.1  thorpej 	WM_CDTXSYNC(sc, sc->sc_txnext, 1, BUS_DMASYNC_PREWRITE);
    972  1.1  thorpej 
    973  1.1  thorpej 	sc->sc_txnext = WM_NEXTTX(sc->sc_txnext);
    974  1.1  thorpej 
    975  1.1  thorpej 	*cmdp = WTX_CMD_DEXT | WTC_DTYP_D;
    976  1.1  thorpej 	*fieldsp = fields;
    977  1.1  thorpej 
    978  1.1  thorpej 	return (0);
    979  1.1  thorpej }
    980  1.1  thorpej 
    981  1.1  thorpej /*
    982  1.1  thorpej  * wm_start:		[ifnet interface function]
    983  1.1  thorpej  *
    984  1.1  thorpej  *	Start packet transmission on the interface.
    985  1.1  thorpej  */
    986  1.1  thorpej void
    987  1.1  thorpej wm_start(struct ifnet *ifp)
    988  1.1  thorpej {
    989  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
    990  1.1  thorpej 	struct mbuf *m0/*, *m*/;
    991  1.1  thorpej 	struct wm_txsoft *txs;
    992  1.1  thorpej 	bus_dmamap_t dmamap;
    993  1.1  thorpej 	int error, nexttx, lasttx, ofree, seg;
    994  1.1  thorpej 	uint32_t cksumcmd, cksumfields;
    995  1.1  thorpej 
    996  1.1  thorpej 	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
    997  1.1  thorpej 		return;
    998  1.1  thorpej 
    999  1.1  thorpej 	/*
   1000  1.1  thorpej 	 * Remember the previous number of free descriptors.
   1001  1.1  thorpej 	 */
   1002  1.1  thorpej 	ofree = sc->sc_txfree;
   1003  1.1  thorpej 
   1004  1.1  thorpej 	/*
   1005  1.1  thorpej 	 * Loop through the send queue, setting up transmit descriptors
   1006  1.1  thorpej 	 * until we drain the queue, or use up all available transmit
   1007  1.1  thorpej 	 * descriptors.
   1008  1.1  thorpej 	 */
   1009  1.1  thorpej 	for (;;) {
   1010  1.1  thorpej 		/* Grab a packet off the queue. */
   1011  1.1  thorpej 		IFQ_POLL(&ifp->if_snd, m0);
   1012  1.1  thorpej 		if (m0 == NULL)
   1013  1.1  thorpej 			break;
   1014  1.1  thorpej 
   1015  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1016  1.1  thorpej 		    ("%s: TX: have packet to transmit: %p\n",
   1017  1.1  thorpej 		    sc->sc_dev.dv_xname, m0));
   1018  1.1  thorpej 
   1019  1.1  thorpej 		/* Get a work queue entry. */
   1020  1.1  thorpej 		if (sc->sc_txsfree == 0) {
   1021  1.1  thorpej 			DPRINTF(WM_DEBUG_TX,
   1022  1.1  thorpej 			    ("%s: TX: no free job descriptors\n",
   1023  1.1  thorpej 				sc->sc_dev.dv_xname));
   1024  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txsstall);
   1025  1.1  thorpej 			break;
   1026  1.1  thorpej 		}
   1027  1.1  thorpej 
   1028  1.1  thorpej 		txs = &sc->sc_txsoft[sc->sc_txsnext];
   1029  1.1  thorpej 		dmamap = txs->txs_dmamap;
   1030  1.1  thorpej 
   1031  1.1  thorpej 		/*
   1032  1.1  thorpej 		 * Load the DMA map.  If this fails, the packet either
   1033  1.1  thorpej 		 * didn't fit in the allotted number of segments, or we
   1034  1.1  thorpej 		 * were short on resources.  For the too-many-segments
   1035  1.1  thorpej 		 * case, we simply report an error and drop the packet,
   1036  1.1  thorpej 		 * since we can't sanely copy a jumbo packet to a single
   1037  1.1  thorpej 		 * buffer.
   1038  1.1  thorpej 		 */
   1039  1.1  thorpej 		error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
   1040  1.1  thorpej 		    BUS_DMA_WRITE|BUS_DMA_NOWAIT);
   1041  1.1  thorpej 		if (error) {
   1042  1.1  thorpej 			if (error == EFBIG) {
   1043  1.1  thorpej 				WM_EVCNT_INCR(&sc->sc_ev_txdrop);
   1044  1.1  thorpej 				printf("%s: Tx packet consumes too many "
   1045  1.1  thorpej 				    "DMA segments, dropping...\n",
   1046  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1047  1.1  thorpej 				IFQ_DEQUEUE(&ifp->if_snd, m0);
   1048  1.1  thorpej 				m_freem(m0);
   1049  1.1  thorpej 				continue;
   1050  1.1  thorpej 			}
   1051  1.1  thorpej 			/*
   1052  1.1  thorpej 			 * Short on resources, just stop for now.
   1053  1.1  thorpej 			 */
   1054  1.1  thorpej 			DPRINTF(WM_DEBUG_TX,
   1055  1.1  thorpej 			    ("%s: TX: dmamap load failed: %d\n",
   1056  1.1  thorpej 			    sc->sc_dev.dv_xname, error));
   1057  1.1  thorpej 			break;
   1058  1.1  thorpej 		}
   1059  1.1  thorpej 
   1060  1.1  thorpej 		/*
   1061  1.1  thorpej 		 * Ensure we have enough descriptors free to describe
   1062  1.1  thorpej 		 * the packet.  Note, we always reserve one descriptor
   1063  1.1  thorpej 		 * at the end of the ring due to the semantics of the
   1064  1.1  thorpej 		 * TDT register, plus one more in the event we need
   1065  1.1  thorpej 		 * to re-load checksum offload context.
   1066  1.1  thorpej 		 */
   1067  1.1  thorpej 		if (dmamap->dm_nsegs > (sc->sc_txfree - 2)) {
   1068  1.1  thorpej 			/*
   1069  1.1  thorpej 			 * Not enough free descriptors to transmit this
   1070  1.1  thorpej 			 * packet.  We haven't committed anything yet,
   1071  1.1  thorpej 			 * so just unload the DMA map, put the packet
   1072  1.1  thorpej 			 * pack on the queue, and punt.  Notify the upper
   1073  1.1  thorpej 			 * layer that there are no more slots left.
   1074  1.1  thorpej 			 */
   1075  1.1  thorpej 			DPRINTF(WM_DEBUG_TX,
   1076  1.1  thorpej 			    ("%s: TX: need %d descriptors, have %d\n",
   1077  1.1  thorpej 			    sc->sc_dev.dv_xname, dmamap->dm_nsegs,
   1078  1.1  thorpej 			    sc->sc_txfree - 1));
   1079  1.1  thorpej 			ifp->if_flags |= IFF_OACTIVE;
   1080  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, dmamap);
   1081  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txdstall);
   1082  1.1  thorpej 			break;
   1083  1.1  thorpej 		}
   1084  1.1  thorpej 
   1085  1.1  thorpej 		IFQ_DEQUEUE(&ifp->if_snd, m0);
   1086  1.1  thorpej 
   1087  1.1  thorpej 		/*
   1088  1.1  thorpej 		 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
   1089  1.1  thorpej 		 */
   1090  1.1  thorpej 
   1091  1.1  thorpej 		/* Sync the DMA map. */
   1092  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
   1093  1.1  thorpej 		    BUS_DMASYNC_PREWRITE);
   1094  1.1  thorpej 
   1095  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1096  1.1  thorpej 		    ("%s: TX: packet has %d DMA segments\n",
   1097  1.1  thorpej 		    sc->sc_dev.dv_xname, dmamap->dm_nsegs));
   1098  1.1  thorpej 
   1099  1.1  thorpej #ifdef WM_EVENT_COUNTERS
   1100  1.1  thorpej 		switch (dmamap->dm_nsegs) {
   1101  1.1  thorpej 		case 1:
   1102  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txseg1);
   1103  1.1  thorpej 			break;
   1104  1.1  thorpej 		case 2:
   1105  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txseg2);
   1106  1.1  thorpej 			break;
   1107  1.1  thorpej 		case 3:
   1108  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txseg3);
   1109  1.1  thorpej 			break;
   1110  1.1  thorpej 		case 4:
   1111  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txseg4);
   1112  1.1  thorpej 			break;
   1113  1.1  thorpej 		case 5:
   1114  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txseg5);
   1115  1.1  thorpej 			break;
   1116  1.1  thorpej 		default:
   1117  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txsegmore);
   1118  1.1  thorpej 			break;
   1119  1.1  thorpej 		}
   1120  1.1  thorpej #endif /* WM_EVENT_COUNTERS */
   1121  1.1  thorpej 
   1122  1.1  thorpej 		/*
   1123  1.1  thorpej 		 * Set up checksum offload parameters for
   1124  1.1  thorpej 		 * this packet.
   1125  1.1  thorpej 		 */
   1126  1.1  thorpej 		if (m0->m_pkthdr.csum_flags &
   1127  1.1  thorpej 		    (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
   1128  1.1  thorpej 			if (wm_tx_cksum(sc, m0, &cksumcmd, &cksumfields) != 0) {
   1129  1.1  thorpej 				/* Error message already displayed. */
   1130  1.1  thorpej 				m_freem(m0);
   1131  1.1  thorpej 				bus_dmamap_unload(sc->sc_dmat, dmamap);
   1132  1.1  thorpej 				continue;
   1133  1.1  thorpej 			}
   1134  1.1  thorpej 		} else {
   1135  1.1  thorpej 			cksumcmd = 0;
   1136  1.1  thorpej 			cksumfields = 0;
   1137  1.1  thorpej 		}
   1138  1.1  thorpej 
   1139  1.1  thorpej 		/*
   1140  1.1  thorpej 		 * Initialize the transmit descriptor.
   1141  1.1  thorpej 		 */
   1142  1.1  thorpej 		for (nexttx = sc->sc_txnext, seg = 0;
   1143  1.1  thorpej 		     seg < dmamap->dm_nsegs;
   1144  1.1  thorpej 		     seg++, nexttx = WM_NEXTTX(nexttx)) {
   1145  1.1  thorpej 			/*
   1146  1.1  thorpej 			 * Note: we currently only use 32-bit DMA
   1147  1.1  thorpej 			 * addresses.
   1148  1.1  thorpej 			 */
   1149  1.1  thorpej 			sc->sc_txdescs[nexttx].wtx_addr.wa_low =
   1150  1.1  thorpej 			    htole32(dmamap->dm_segs[seg].ds_addr);
   1151  1.1  thorpej 			sc->sc_txdescs[nexttx].wtx_cmdlen = cksumcmd |
   1152  1.1  thorpej 			    htole32(dmamap->dm_segs[seg].ds_len);
   1153  1.1  thorpej 			sc->sc_txdescs[nexttx].wtx_fields.wtxu_bits =
   1154  1.1  thorpej 			    cksumfields;
   1155  1.1  thorpej 			lasttx = nexttx;
   1156  1.1  thorpej 
   1157  1.1  thorpej 			DPRINTF(WM_DEBUG_TX,
   1158  1.1  thorpej 			    ("%s: TX: desc %d: low 0x%08x, len 0x%04x\n",
   1159  1.1  thorpej 			    sc->sc_dev.dv_xname, nexttx,
   1160  1.1  thorpej 			    (uint32_t) dmamap->dm_segs[seg].ds_addr,
   1161  1.1  thorpej 			    (uint32_t) dmamap->dm_segs[seg].ds_len));
   1162  1.1  thorpej 		}
   1163  1.1  thorpej 
   1164  1.1  thorpej 		/*
   1165  1.1  thorpej 		 * Set up the command byte on the last descriptor of
   1166  1.1  thorpej 		 * the packet.  If we're in the interrupt delay window,
   1167  1.1  thorpej 		 * delay the interrupt.
   1168  1.1  thorpej 		 */
   1169  1.1  thorpej 		sc->sc_txdescs[lasttx].wtx_cmdlen |=
   1170  1.1  thorpej 		    htole32(WTX_CMD_EOP | WTX_CMD_IFCS | WTX_CMD_RS |
   1171  1.1  thorpej 		    WTX_CMD_RPS);
   1172  1.1  thorpej 		if (sc->sc_txsnext & WM_TXINTR_MASK)
   1173  1.1  thorpej 			sc->sc_txdescs[lasttx].wtx_cmdlen |=
   1174  1.1  thorpej 			    htole32(WTX_CMD_IDE);
   1175  1.1  thorpej 
   1176  1.1  thorpej #if 0 /* XXXJRT */
   1177  1.1  thorpej 		/*
   1178  1.1  thorpej 		 * If VLANs are enabled and the packet has a VLAN tag, set
   1179  1.1  thorpej 		 * up the descriptor to encapsulate the packet for us.
   1180  1.1  thorpej 		 *
   1181  1.1  thorpej 		 * This is only valid on the last descriptor of the packet.
   1182  1.1  thorpej 		 */
   1183  1.1  thorpej 		if (sc->sc_ethercom.ec_nvlans != 0 &&
   1184  1.1  thorpej 		    (m = m_aux_find(m0, AF_LINK, ETHERTYPE_VLAN)) != NULL) {
   1185  1.1  thorpej 			sc->sc_txdescs[lasttx].wtx_cmdlen |=
   1186  1.1  thorpej 			    htole32(WTX_CMD_VLE);
   1187  1.1  thorpej 			sc->sc_txdescs[lasttx].wtx_fields.wtxu_fields.wtxu_vlan
   1188  1.1  thorpej 			    = htole16(*mtod(m, int *) & 0xffff);
   1189  1.1  thorpej 		}
   1190  1.1  thorpej #endif /* XXXJRT */
   1191  1.1  thorpej 
   1192  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1193  1.1  thorpej 		    ("%s: TX: desc %d: cmdlen 0x%08x\n", sc->sc_dev.dv_xname,
   1194  1.1  thorpej 		    lasttx, sc->sc_txdescs[lasttx].wtx_cmdlen));
   1195  1.1  thorpej 
   1196  1.1  thorpej 		/* Sync the descriptors we're using. */
   1197  1.1  thorpej 		WM_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,
   1198  1.1  thorpej 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   1199  1.1  thorpej 
   1200  1.1  thorpej 		/* Give the packet to the chip. */
   1201  1.1  thorpej 		CSR_WRITE(sc, sc->sc_tdt_reg, nexttx);
   1202  1.1  thorpej 
   1203  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1204  1.1  thorpej 		    ("%s: TX: TDT -> %d\n", sc->sc_dev.dv_xname, nexttx));
   1205  1.1  thorpej 
   1206  1.1  thorpej 		/*
   1207  1.1  thorpej 		 * Store a pointer to the packet so we can free it later,
   1208  1.1  thorpej 		 * and remember that txdirty will be once the packet is
   1209  1.1  thorpej 		 * done.
   1210  1.1  thorpej 		 */
   1211  1.1  thorpej 		txs->txs_mbuf = m0;
   1212  1.1  thorpej 		txs->txs_firstdesc = sc->sc_txnext;
   1213  1.1  thorpej 		txs->txs_lastdesc = lasttx;
   1214  1.1  thorpej 
   1215  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1216  1.1  thorpej 		    ("%s: TX: finished transmitting packet, job %d\n",
   1217  1.1  thorpej 		    sc->sc_dev.dv_xname, sc->sc_txsnext));
   1218  1.1  thorpej 
   1219  1.1  thorpej 		/* Advance the tx pointer. */
   1220  1.1  thorpej 		sc->sc_txfree -= dmamap->dm_nsegs;
   1221  1.1  thorpej 		sc->sc_txnext = nexttx;
   1222  1.1  thorpej 
   1223  1.1  thorpej 		sc->sc_txsfree--;
   1224  1.1  thorpej 		sc->sc_txsnext = WM_NEXTTXS(sc->sc_txsnext);
   1225  1.1  thorpej 
   1226  1.1  thorpej #if NBPFILTER > 0
   1227  1.1  thorpej 		/* Pass the packet to any BPF listeners. */
   1228  1.1  thorpej 		if (ifp->if_bpf)
   1229  1.1  thorpej 			bpf_mtap(ifp->if_bpf, m0);
   1230  1.1  thorpej #endif /* NBPFILTER > 0 */
   1231  1.1  thorpej 	}
   1232  1.1  thorpej 
   1233  1.1  thorpej 	if (sc->sc_txsfree == 0 || sc->sc_txfree == 0) {
   1234  1.1  thorpej 		/* No more slots; notify upper layer. */
   1235  1.1  thorpej 		ifp->if_flags |= IFF_OACTIVE;
   1236  1.1  thorpej 	}
   1237  1.1  thorpej 
   1238  1.1  thorpej 	if (sc->sc_txfree != ofree) {
   1239  1.1  thorpej 		/* Set a watchdog timer in case the chip flakes out. */
   1240  1.1  thorpej 		ifp->if_timer = 5;
   1241  1.1  thorpej 	}
   1242  1.1  thorpej }
   1243  1.1  thorpej 
   1244  1.1  thorpej /*
   1245  1.1  thorpej  * wm_watchdog:		[ifnet interface function]
   1246  1.1  thorpej  *
   1247  1.1  thorpej  *	Watchdog timer handler.
   1248  1.1  thorpej  */
   1249  1.1  thorpej void
   1250  1.1  thorpej wm_watchdog(struct ifnet *ifp)
   1251  1.1  thorpej {
   1252  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   1253  1.1  thorpej 
   1254  1.1  thorpej 	/*
   1255  1.1  thorpej 	 * Since we're using delayed interrupts, sweep up
   1256  1.1  thorpej 	 * before we report an error.
   1257  1.1  thorpej 	 */
   1258  1.1  thorpej 	wm_txintr(sc);
   1259  1.1  thorpej 
   1260  1.1  thorpej 	if (sc->sc_txfree != WM_NTXDESC) {
   1261  1.1  thorpej 		printf("%s: device timeout (txfree %d txsfree %d)\n",
   1262  1.1  thorpej 		    sc->sc_dev.dv_xname, sc->sc_txfree, sc->sc_txsfree);
   1263  1.1  thorpej 		ifp->if_oerrors++;
   1264  1.1  thorpej 
   1265  1.1  thorpej 		/* Reset the interface. */
   1266  1.1  thorpej 		(void) wm_init(ifp);
   1267  1.1  thorpej 	}
   1268  1.1  thorpej 
   1269  1.1  thorpej 	/* Try to get more packets going. */
   1270  1.1  thorpej 	wm_start(ifp);
   1271  1.1  thorpej }
   1272  1.1  thorpej 
   1273  1.1  thorpej /*
   1274  1.1  thorpej  * wm_ioctl:		[ifnet interface function]
   1275  1.1  thorpej  *
   1276  1.1  thorpej  *	Handle control requests from the operator.
   1277  1.1  thorpej  */
   1278  1.1  thorpej int
   1279  1.1  thorpej wm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
   1280  1.1  thorpej {
   1281  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   1282  1.1  thorpej 	struct ifreq *ifr = (struct ifreq *) data;
   1283  1.1  thorpej 	int s, error;
   1284  1.1  thorpej 
   1285  1.1  thorpej 	s = splnet();
   1286  1.1  thorpej 
   1287  1.1  thorpej 	switch (cmd) {
   1288  1.1  thorpej 	case SIOCSIFMEDIA:
   1289  1.1  thorpej 	case SIOCGIFMEDIA:
   1290  1.1  thorpej 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
   1291  1.1  thorpej 		break;
   1292  1.1  thorpej 
   1293  1.1  thorpej 	default:
   1294  1.1  thorpej 		error = ether_ioctl(ifp, cmd, data);
   1295  1.1  thorpej 		if (error == ENETRESET) {
   1296  1.1  thorpej 			/*
   1297  1.1  thorpej 			 * Multicast list has changed; set the hardware filter
   1298  1.1  thorpej 			 * accordingly.
   1299  1.1  thorpej 			 */
   1300  1.1  thorpej 			wm_set_filter(sc);
   1301  1.1  thorpej 			error = 0;
   1302  1.1  thorpej 		}
   1303  1.1  thorpej 		break;
   1304  1.1  thorpej 	}
   1305  1.1  thorpej 
   1306  1.1  thorpej 	/* Try to get more packets going. */
   1307  1.1  thorpej 	wm_start(ifp);
   1308  1.1  thorpej 
   1309  1.1  thorpej 	splx(s);
   1310  1.1  thorpej 	return (error);
   1311  1.1  thorpej }
   1312  1.1  thorpej 
   1313  1.1  thorpej /*
   1314  1.1  thorpej  * wm_intr:
   1315  1.1  thorpej  *
   1316  1.1  thorpej  *	Interrupt service routine.
   1317  1.1  thorpej  */
   1318  1.1  thorpej int
   1319  1.1  thorpej wm_intr(void *arg)
   1320  1.1  thorpej {
   1321  1.1  thorpej 	struct wm_softc *sc = arg;
   1322  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1323  1.1  thorpej 	uint32_t icr;
   1324  1.1  thorpej 	int wantinit, handled = 0;
   1325  1.1  thorpej 
   1326  1.1  thorpej 	for (wantinit = 0; wantinit == 0;) {
   1327  1.1  thorpej 		icr = CSR_READ(sc, WMREG_ICR);
   1328  1.1  thorpej 		if ((icr & sc->sc_icr) == 0)
   1329  1.1  thorpej 			break;
   1330  1.1  thorpej 
   1331  1.1  thorpej 		handled = 1;
   1332  1.1  thorpej 
   1333  1.1  thorpej 		if (icr & (ICR_RXDMT0|ICR_RXT0)) {
   1334  1.1  thorpej 			DPRINTF(WM_DEBUG_RX,
   1335  1.1  thorpej 			    ("%s: RX: got Rx intr 0x%08x\n",
   1336  1.1  thorpej 			    sc->sc_dev.dv_xname,
   1337  1.1  thorpej 			    icr & (ICR_RXDMT0|ICR_RXT0)));
   1338  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_rxintr);
   1339  1.1  thorpej 			wm_rxintr(sc);
   1340  1.1  thorpej 		}
   1341  1.1  thorpej 
   1342  1.1  thorpej 		if (icr & ICR_TXDW) {
   1343  1.1  thorpej 			DPRINTF(WM_DEBUG_TX,
   1344  1.1  thorpej 			    ("%s: TX: got TXDW interrupt\n",
   1345  1.1  thorpej 			    sc->sc_dev.dv_xname));
   1346  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_txintr);
   1347  1.1  thorpej 			wm_txintr(sc);
   1348  1.1  thorpej 		}
   1349  1.1  thorpej 
   1350  1.1  thorpej 		if (icr & (ICR_LSC|ICR_RXSEQ|ICR_RXCFG)) {
   1351  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_linkintr);
   1352  1.1  thorpej 			wm_linkintr(sc, icr);
   1353  1.1  thorpej 		}
   1354  1.1  thorpej 
   1355  1.1  thorpej 		if (icr & ICR_RXO) {
   1356  1.1  thorpej 			printf("%s: Receive overrun\n", sc->sc_dev.dv_xname);
   1357  1.1  thorpej 			wantinit = 1;
   1358  1.1  thorpej 		}
   1359  1.1  thorpej 	}
   1360  1.1  thorpej 
   1361  1.1  thorpej 	if (handled) {
   1362  1.1  thorpej 		if (wantinit)
   1363  1.1  thorpej 			wm_init(ifp);
   1364  1.1  thorpej 
   1365  1.1  thorpej 		/* Try to get more packets going. */
   1366  1.1  thorpej 		wm_start(ifp);
   1367  1.1  thorpej 	}
   1368  1.1  thorpej 
   1369  1.1  thorpej 	return (handled);
   1370  1.1  thorpej }
   1371  1.1  thorpej 
   1372  1.1  thorpej /*
   1373  1.1  thorpej  * wm_txintr:
   1374  1.1  thorpej  *
   1375  1.1  thorpej  *	Helper; handle transmit interrupts.
   1376  1.1  thorpej  */
   1377  1.1  thorpej void
   1378  1.1  thorpej wm_txintr(struct wm_softc *sc)
   1379  1.1  thorpej {
   1380  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1381  1.1  thorpej 	struct wm_txsoft *txs;
   1382  1.1  thorpej 	uint8_t status;
   1383  1.1  thorpej 	int i;
   1384  1.1  thorpej 
   1385  1.1  thorpej 	ifp->if_flags &= ~IFF_OACTIVE;
   1386  1.1  thorpej 
   1387  1.1  thorpej 	/*
   1388  1.1  thorpej 	 * Go through the Tx list and free mbufs for those
   1389  1.1  thorpej 	 * frams which have been transmitted.
   1390  1.1  thorpej 	 */
   1391  1.1  thorpej 	for (i = sc->sc_txsdirty; sc->sc_txsfree != WM_TXQUEUELEN;
   1392  1.1  thorpej 	     i = WM_NEXTTXS(i), sc->sc_txsfree++) {
   1393  1.1  thorpej 		txs = &sc->sc_txsoft[i];
   1394  1.1  thorpej 
   1395  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1396  1.1  thorpej 		    ("%s: TX: checking job %d\n", sc->sc_dev.dv_xname, i));
   1397  1.1  thorpej 
   1398  1.1  thorpej 		WM_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,
   1399  1.1  thorpej 		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   1400  1.1  thorpej 
   1401  1.1  thorpej 		status = le32toh(sc->sc_txdescs[
   1402  1.1  thorpej 		    txs->txs_lastdesc].wtx_fields.wtxu_bits);
   1403  1.1  thorpej 		if ((status & WTX_ST_DD) == 0)
   1404  1.1  thorpej 			break;
   1405  1.1  thorpej 
   1406  1.1  thorpej 		DPRINTF(WM_DEBUG_TX,
   1407  1.1  thorpej 		    ("%s: TX: job %d done: descs %d..%d\n",
   1408  1.1  thorpej 		    sc->sc_dev.dv_xname, i, txs->txs_firstdesc,
   1409  1.1  thorpej 		    txs->txs_lastdesc));
   1410  1.1  thorpej 
   1411  1.1  thorpej 		/*
   1412  1.1  thorpej 		 * XXX We should probably be using the statistics
   1413  1.1  thorpej 		 * XXX registers, but I don't know if they exist
   1414  1.1  thorpej 		 * XXX on chips before the Cordova.
   1415  1.1  thorpej 		 */
   1416  1.1  thorpej 
   1417  1.1  thorpej #ifdef WM_EVENT_COUNTERS
   1418  1.1  thorpej 		if (status & WTX_ST_TU)
   1419  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_tu);
   1420  1.1  thorpej #endif /* WM_EVENT_COUNTERS */
   1421  1.1  thorpej 
   1422  1.1  thorpej 		if (status & (WTX_ST_EC|WTX_ST_LC)) {
   1423  1.1  thorpej 			ifp->if_oerrors++;
   1424  1.1  thorpej 			if (status & WTX_ST_LC)
   1425  1.1  thorpej 				printf("%s: late collision\n",
   1426  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1427  1.1  thorpej 			else if (status & WTX_ST_EC) {
   1428  1.1  thorpej 				ifp->if_collisions += 16;
   1429  1.1  thorpej 				printf("%s: excessive collisions\n",
   1430  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1431  1.1  thorpej 			}
   1432  1.1  thorpej 		} else
   1433  1.1  thorpej 			ifp->if_opackets++;
   1434  1.1  thorpej 
   1435  1.1  thorpej 		sc->sc_txfree += txs->txs_dmamap->dm_nsegs;
   1436  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
   1437  1.1  thorpej 		    0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
   1438  1.1  thorpej 		bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
   1439  1.1  thorpej 		m_freem(txs->txs_mbuf);
   1440  1.1  thorpej 		txs->txs_mbuf = NULL;
   1441  1.1  thorpej 	}
   1442  1.1  thorpej 
   1443  1.1  thorpej 	/* Update the dirty transmit buffer pointer. */
   1444  1.1  thorpej 	sc->sc_txsdirty = i;
   1445  1.1  thorpej 	DPRINTF(WM_DEBUG_TX,
   1446  1.1  thorpej 	    ("%s: TX: txsdirty -> %d\n", sc->sc_dev.dv_xname, i));
   1447  1.1  thorpej 
   1448  1.1  thorpej 	/*
   1449  1.1  thorpej 	 * If there are no more pending transmissions, cancel the watchdog
   1450  1.1  thorpej 	 * timer.
   1451  1.1  thorpej 	 */
   1452  1.1  thorpej 	if (sc->sc_txsfree == WM_TXQUEUELEN)
   1453  1.1  thorpej 		ifp->if_timer = 0;
   1454  1.1  thorpej }
   1455  1.1  thorpej 
   1456  1.1  thorpej /*
   1457  1.1  thorpej  * wm_rxintr:
   1458  1.1  thorpej  *
   1459  1.1  thorpej  *	Helper; handle receive interrupts.
   1460  1.1  thorpej  */
   1461  1.1  thorpej void
   1462  1.1  thorpej wm_rxintr(struct wm_softc *sc)
   1463  1.1  thorpej {
   1464  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1465  1.1  thorpej 	struct wm_rxsoft *rxs;
   1466  1.1  thorpej 	struct mbuf *m;
   1467  1.1  thorpej 	int i, len;
   1468  1.1  thorpej 	uint8_t status, errors;
   1469  1.1  thorpej 
   1470  1.1  thorpej 	for (i = sc->sc_rxptr;; i = WM_NEXTRX(i)) {
   1471  1.1  thorpej 		rxs = &sc->sc_rxsoft[i];
   1472  1.1  thorpej 
   1473  1.1  thorpej 		DPRINTF(WM_DEBUG_RX,
   1474  1.1  thorpej 		    ("%s: RX: checking descriptor %d\n",
   1475  1.1  thorpej 		    sc->sc_dev.dv_xname, i));
   1476  1.1  thorpej 
   1477  1.1  thorpej 		WM_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   1478  1.1  thorpej 
   1479  1.1  thorpej 		status = sc->sc_rxdescs[i].wrx_status;
   1480  1.1  thorpej 		errors = sc->sc_rxdescs[i].wrx_errors;
   1481  1.1  thorpej 		len = le16toh(sc->sc_rxdescs[i].wrx_len);
   1482  1.1  thorpej 
   1483  1.1  thorpej 		if ((status & WRX_ST_DD) == 0) {
   1484  1.1  thorpej 			/*
   1485  1.1  thorpej 			 * We have processed all of the receive descriptors.
   1486  1.1  thorpej 			 */
   1487  1.1  thorpej 			break;
   1488  1.1  thorpej 		}
   1489  1.1  thorpej 
   1490  1.1  thorpej 		if (__predict_false(sc->sc_rxdiscard)) {
   1491  1.1  thorpej 			DPRINTF(WM_DEBUG_RX,
   1492  1.1  thorpej 			    ("%s: RX: discarding contents of descriptor %d\n",
   1493  1.1  thorpej 			    sc->sc_dev.dv_xname, i));
   1494  1.1  thorpej 			WM_INIT_RXDESC(sc, i);
   1495  1.1  thorpej 			if (status & WRX_ST_EOP) {
   1496  1.1  thorpej 				/* Reset our state. */
   1497  1.1  thorpej 				DPRINTF(WM_DEBUG_RX,
   1498  1.1  thorpej 				    ("%s: RX: resetting rxdiscard -> 0\n",
   1499  1.1  thorpej 				    sc->sc_dev.dv_xname));
   1500  1.1  thorpej 				sc->sc_rxdiscard = 0;
   1501  1.1  thorpej 			}
   1502  1.1  thorpej 			continue;
   1503  1.1  thorpej 		}
   1504  1.1  thorpej 
   1505  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1506  1.1  thorpej 		    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
   1507  1.1  thorpej 
   1508  1.1  thorpej 		m = rxs->rxs_mbuf;
   1509  1.1  thorpej 
   1510  1.1  thorpej 		/*
   1511  1.1  thorpej 		 * Add a new receive buffer to the ring.
   1512  1.1  thorpej 		 */
   1513  1.1  thorpej 		if (wm_add_rxbuf(sc, i) != 0) {
   1514  1.1  thorpej 			/*
   1515  1.1  thorpej 			 * Failed, throw away what we've done so
   1516  1.1  thorpej 			 * far, and discard the rest of the packet.
   1517  1.1  thorpej 			 */
   1518  1.1  thorpej 			ifp->if_ierrors++;
   1519  1.1  thorpej 			bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1520  1.1  thorpej 			    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   1521  1.1  thorpej 			WM_INIT_RXDESC(sc, i);
   1522  1.1  thorpej 			if ((status & WRX_ST_EOP) == 0)
   1523  1.1  thorpej 				sc->sc_rxdiscard = 1;
   1524  1.1  thorpej 			if (sc->sc_rxhead != NULL)
   1525  1.1  thorpej 				m_freem(sc->sc_rxhead);
   1526  1.1  thorpej 			WM_RXCHAIN_RESET(sc);
   1527  1.1  thorpej 			DPRINTF(WM_DEBUG_RX,
   1528  1.1  thorpej 			    ("%s: RX: Rx buffer allocation failed, "
   1529  1.1  thorpej 			    "dropping packet%s\n", sc->sc_dev.dv_xname,
   1530  1.1  thorpej 			    sc->sc_rxdiscard ? " (discard)" : ""));
   1531  1.1  thorpej 			continue;
   1532  1.1  thorpej 		}
   1533  1.1  thorpej 
   1534  1.1  thorpej 		WM_RXCHAIN_LINK(sc, m);
   1535  1.1  thorpej 
   1536  1.1  thorpej 		m->m_len = len;
   1537  1.1  thorpej 
   1538  1.1  thorpej 		DPRINTF(WM_DEBUG_RX,
   1539  1.1  thorpej 		    ("%s: RX: buffer at %p len %d\n",
   1540  1.1  thorpej 		    sc->sc_dev.dv_xname, m->m_data, len));
   1541  1.1  thorpej 
   1542  1.1  thorpej 		/*
   1543  1.1  thorpej 		 * If this is not the end of the packet, keep
   1544  1.1  thorpej 		 * looking.
   1545  1.1  thorpej 		 */
   1546  1.1  thorpej 		if ((status & WRX_ST_EOP) == 0) {
   1547  1.1  thorpej 			sc->sc_rxlen += len;
   1548  1.1  thorpej 			DPRINTF(WM_DEBUG_RX,
   1549  1.1  thorpej 			    ("%s: RX: not yet EOP, rxlen -> %d\n",
   1550  1.1  thorpej 			    sc->sc_dev.dv_xname, sc->sc_rxlen));
   1551  1.1  thorpej 			continue;
   1552  1.1  thorpej 		}
   1553  1.1  thorpej 
   1554  1.1  thorpej 		/*
   1555  1.1  thorpej 		 * Okay, we have the entire packet now...
   1556  1.1  thorpej 		 */
   1557  1.1  thorpej 		*sc->sc_rxtailp = NULL;
   1558  1.1  thorpej 		m = sc->sc_rxhead;
   1559  1.1  thorpej 		len += sc->sc_rxlen;
   1560  1.1  thorpej 
   1561  1.1  thorpej 		WM_RXCHAIN_RESET(sc);
   1562  1.1  thorpej 
   1563  1.1  thorpej 		DPRINTF(WM_DEBUG_RX,
   1564  1.1  thorpej 		    ("%s: RX: have entire packet, len -> %d\n",
   1565  1.1  thorpej 		    sc->sc_dev.dv_xname, len));
   1566  1.1  thorpej 
   1567  1.1  thorpej 		/*
   1568  1.1  thorpej 		 * If an error occurred, update stats and drop the packet.
   1569  1.1  thorpej 		 */
   1570  1.1  thorpej 		if (errors &
   1571  1.1  thorpej 		     (WRX_ER_CE|WRX_ER_SE|WRX_ER_SEQ|WRX_ER_CXE|WRX_ER_RXE)) {
   1572  1.1  thorpej 			ifp->if_ierrors++;
   1573  1.1  thorpej 			if (errors & WRX_ER_SE)
   1574  1.1  thorpej 				printf("%s: symbol error\n",
   1575  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1576  1.1  thorpej 			else if (errors & WRX_ER_SEQ)
   1577  1.1  thorpej 				printf("%s: receive sequence error\n",
   1578  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1579  1.1  thorpej 			else if (errors & WRX_ER_CE)
   1580  1.1  thorpej 				printf("%s: CRC error\n",
   1581  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1582  1.1  thorpej 			m_freem(m);
   1583  1.1  thorpej 			continue;
   1584  1.1  thorpej 		}
   1585  1.1  thorpej 
   1586  1.1  thorpej 		/*
   1587  1.1  thorpej 		 * No errors.  Receive the packet.
   1588  1.1  thorpej 		 *
   1589  1.1  thorpej 		 * Note, we have configured the chip to include the
   1590  1.1  thorpej 		 * CRC with every packet.
   1591  1.1  thorpej 		 */
   1592  1.1  thorpej 		m->m_flags |= M_HASFCS;
   1593  1.1  thorpej 		m->m_pkthdr.rcvif = ifp;
   1594  1.1  thorpej 		m->m_pkthdr.len = len;
   1595  1.1  thorpej 
   1596  1.1  thorpej #if 0 /* XXXJRT */
   1597  1.1  thorpej 		/*
   1598  1.1  thorpej 		 * If VLANs are enabled, VLAN packets have been unwrapped
   1599  1.1  thorpej 		 * for us.  Associate the tag with the packet.
   1600  1.1  thorpej 		 */
   1601  1.1  thorpej 		if (sc->sc_ethercom.ec_nvlans != 0 &&
   1602  1.1  thorpej 		    (status & WRX_ST_VP) != 0) {
   1603  1.1  thorpej 			struct mbuf *vtag;
   1604  1.1  thorpej 
   1605  1.1  thorpej 			vtag = m_aux_add(m, AF_LINK, ETHERTYPE_VLAN);
   1606  1.1  thorpej 			if (vtag == NULL) {
   1607  1.1  thorpej 				ifp->if_ierrors++;
   1608  1.1  thorpej 				printf("%s: unable to allocate VLAN tag\n",
   1609  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1610  1.1  thorpej 				m_freem(m);
   1611  1.1  thorpej 				continue;
   1612  1.1  thorpej 			}
   1613  1.1  thorpej 
   1614  1.1  thorpej 			*mtod(m, int *) =
   1615  1.1  thorpej 			    le16toh(sc->sc_rxdescs[i].wrx_special);
   1616  1.1  thorpej 			vtag->m_len = sizeof(int);
   1617  1.1  thorpej 		}
   1618  1.1  thorpej #endif /* XXXJRT */
   1619  1.1  thorpej 
   1620  1.1  thorpej 		/*
   1621  1.1  thorpej 		 * Set up checksum info for this packet.
   1622  1.1  thorpej 		 */
   1623  1.1  thorpej 		if (status & WRX_ST_IPCS) {
   1624  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_rxipsum);
   1625  1.1  thorpej 			m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
   1626  1.1  thorpej 			if (errors & WRX_ER_IPE)
   1627  1.1  thorpej 				m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
   1628  1.1  thorpej 		}
   1629  1.1  thorpej 		if (status & WRX_ST_TCPCS) {
   1630  1.1  thorpej 			/*
   1631  1.1  thorpej 			 * Note: we don't know if this was TCP or UDP,
   1632  1.1  thorpej 			 * so we just set both bits, and expect the
   1633  1.1  thorpej 			 * upper layers to deal.
   1634  1.1  thorpej 			 */
   1635  1.1  thorpej 			WM_EVCNT_INCR(&sc->sc_ev_rxtusum);
   1636  1.1  thorpej 			m->m_pkthdr.csum_flags |= M_CSUM_TCPv4|M_CSUM_UDPv4;
   1637  1.1  thorpej 			if (errors & WRX_ER_TCPE)
   1638  1.1  thorpej 				m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
   1639  1.1  thorpej 		}
   1640  1.1  thorpej 
   1641  1.1  thorpej 		ifp->if_ipackets++;
   1642  1.1  thorpej 
   1643  1.1  thorpej #if NBPFILTER > 0
   1644  1.1  thorpej 		/* Pass this up to any BPF listeners. */
   1645  1.1  thorpej 		if (ifp->if_bpf)
   1646  1.1  thorpej 			bpf_mtap(ifp->if_bpf, m);
   1647  1.1  thorpej #endif /* NBPFILTER > 0 */
   1648  1.1  thorpej 
   1649  1.1  thorpej 		/* Pass it on. */
   1650  1.1  thorpej 		(*ifp->if_input)(ifp, m);
   1651  1.1  thorpej 	}
   1652  1.1  thorpej 
   1653  1.1  thorpej 	/* Update the receive pointer. */
   1654  1.1  thorpej 	sc->sc_rxptr = i;
   1655  1.1  thorpej 
   1656  1.1  thorpej 	DPRINTF(WM_DEBUG_RX,
   1657  1.1  thorpej 	    ("%s: RX: rxptr -> %d\n", sc->sc_dev.dv_xname, i));
   1658  1.1  thorpej }
   1659  1.1  thorpej 
   1660  1.1  thorpej /*
   1661  1.1  thorpej  * wm_linkintr:
   1662  1.1  thorpej  *
   1663  1.1  thorpej  *	Helper; handle link interrupts.
   1664  1.1  thorpej  */
   1665  1.1  thorpej void
   1666  1.1  thorpej wm_linkintr(struct wm_softc *sc, uint32_t icr)
   1667  1.1  thorpej {
   1668  1.1  thorpej 	uint32_t status;
   1669  1.1  thorpej 
   1670  1.1  thorpej 	/*
   1671  1.1  thorpej 	 * If we get a link status interrupt on a 1000BASE-T
   1672  1.1  thorpej 	 * device, just fall into the normal MII tick path.
   1673  1.1  thorpej 	 */
   1674  1.1  thorpej 	if (sc->sc_flags & WM_F_HAS_MII) {
   1675  1.1  thorpej 		if (icr & ICR_LSC) {
   1676  1.1  thorpej 			DPRINTF(WM_DEBUG_LINK,
   1677  1.1  thorpej 			    ("%s: LINK: LSC -> mii_tick\n",
   1678  1.1  thorpej 			    sc->sc_dev.dv_xname));
   1679  1.1  thorpej 			mii_tick(&sc->sc_mii);
   1680  1.1  thorpej 		} else if (icr & ICR_RXSEQ) {
   1681  1.1  thorpej 			DPRINTF(WM_DEBUG_LINK,
   1682  1.1  thorpej 			    ("%s: LINK Receive sequence error\n",
   1683  1.1  thorpej 			    sc->sc_dev.dv_xname));
   1684  1.1  thorpej 		}
   1685  1.1  thorpej 		return;
   1686  1.1  thorpej 	}
   1687  1.1  thorpej 
   1688  1.1  thorpej 	/*
   1689  1.1  thorpej 	 * If we are now receiving /C/, check for link again in
   1690  1.1  thorpej 	 * a couple of link clock ticks.
   1691  1.1  thorpej 	 */
   1692  1.1  thorpej 	if (icr & ICR_RXCFG) {
   1693  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK, ("%s: LINK: receiving /C/\n",
   1694  1.1  thorpej 		    sc->sc_dev.dv_xname));
   1695  1.1  thorpej 		sc->sc_tbi_anstate = 2;
   1696  1.1  thorpej 	}
   1697  1.1  thorpej 
   1698  1.1  thorpej 	if (icr & ICR_LSC) {
   1699  1.1  thorpej 		status = CSR_READ(sc, WMREG_STATUS);
   1700  1.1  thorpej 		if (status & STATUS_LU) {
   1701  1.1  thorpej 			DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> up %s\n",
   1702  1.1  thorpej 			    sc->sc_dev.dv_xname,
   1703  1.1  thorpej 			    (status & STATUS_FD) ? "FDX" : "HDX"));
   1704  1.1  thorpej 			sc->sc_tctl &= ~TCTL_COLD(0x3ff);
   1705  1.1  thorpej 			if (status & STATUS_FD)
   1706  1.1  thorpej 				sc->sc_tctl |=
   1707  1.1  thorpej 				    TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
   1708  1.1  thorpej 			else
   1709  1.1  thorpej 				sc->sc_tctl |=
   1710  1.1  thorpej 				    TCTL_COLD(TX_COLLISION_DISTANCE_HDX);
   1711  1.1  thorpej 			CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
   1712  1.1  thorpej 			sc->sc_tbi_linkup = 1;
   1713  1.1  thorpej 		} else {
   1714  1.1  thorpej 			DPRINTF(WM_DEBUG_LINK, ("%s: LINK: LSC -> down\n",
   1715  1.1  thorpej 			    sc->sc_dev.dv_xname));
   1716  1.1  thorpej 			sc->sc_tbi_linkup = 0;
   1717  1.1  thorpej 		}
   1718  1.1  thorpej 		sc->sc_tbi_anstate = 2;
   1719  1.1  thorpej 		wm_tbi_set_linkled(sc);
   1720  1.1  thorpej 	} else if (icr & ICR_RXSEQ) {
   1721  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK,
   1722  1.1  thorpej 		    ("%s: LINK: Receive sequence error\n",
   1723  1.1  thorpej 		    sc->sc_dev.dv_xname));
   1724  1.1  thorpej 	}
   1725  1.1  thorpej }
   1726  1.1  thorpej 
   1727  1.1  thorpej /*
   1728  1.1  thorpej  * wm_tick:
   1729  1.1  thorpej  *
   1730  1.1  thorpej  *	One second timer, used to check link status, sweep up
   1731  1.1  thorpej  *	completed transmit jobs, etc.
   1732  1.1  thorpej  */
   1733  1.1  thorpej void
   1734  1.1  thorpej wm_tick(void *arg)
   1735  1.1  thorpej {
   1736  1.1  thorpej 	struct wm_softc *sc = arg;
   1737  1.1  thorpej 	int s;
   1738  1.1  thorpej 
   1739  1.1  thorpej 	s = splnet();
   1740  1.1  thorpej 
   1741  1.1  thorpej 	if (sc->sc_flags & WM_F_HAS_MII)
   1742  1.1  thorpej 		mii_tick(&sc->sc_mii);
   1743  1.1  thorpej 	else
   1744  1.1  thorpej 		wm_tbi_check_link(sc);
   1745  1.1  thorpej 
   1746  1.1  thorpej 	splx(s);
   1747  1.1  thorpej 
   1748  1.1  thorpej 	callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);
   1749  1.1  thorpej }
   1750  1.1  thorpej 
   1751  1.1  thorpej /*
   1752  1.1  thorpej  * wm_reset:
   1753  1.1  thorpej  *
   1754  1.1  thorpej  *	Reset the i82542 chip.
   1755  1.1  thorpej  */
   1756  1.1  thorpej void
   1757  1.1  thorpej wm_reset(struct wm_softc *sc)
   1758  1.1  thorpej {
   1759  1.1  thorpej 	int i;
   1760  1.1  thorpej 
   1761  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, CTRL_RST);
   1762  1.1  thorpej 	delay(10000);
   1763  1.1  thorpej 
   1764  1.1  thorpej 	for (i = 0; i < 1000; i++) {
   1765  1.1  thorpej 		if ((CSR_READ(sc, WMREG_CTRL) & CTRL_RST) == 0)
   1766  1.1  thorpej 			return;
   1767  1.1  thorpej 		delay(20);
   1768  1.1  thorpej 	}
   1769  1.1  thorpej 
   1770  1.1  thorpej 	if (CSR_READ(sc, WMREG_CTRL) & CTRL_RST)
   1771  1.1  thorpej 		printf("%s: WARNING: reset failed to complete\n",
   1772  1.1  thorpej 		    sc->sc_dev.dv_xname);
   1773  1.1  thorpej }
   1774  1.1  thorpej 
   1775  1.1  thorpej /*
   1776  1.1  thorpej  * wm_init:		[ifnet interface function]
   1777  1.1  thorpej  *
   1778  1.1  thorpej  *	Initialize the interface.  Must be called at splnet().
   1779  1.1  thorpej  */
   1780  1.1  thorpej int
   1781  1.1  thorpej wm_init(struct ifnet *ifp)
   1782  1.1  thorpej {
   1783  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   1784  1.1  thorpej 	struct wm_rxsoft *rxs;
   1785  1.1  thorpej 	int i, error = 0;
   1786  1.1  thorpej 	uint32_t reg;
   1787  1.1  thorpej 
   1788  1.1  thorpej 	/* Cancel any pending I/O. */
   1789  1.1  thorpej 	wm_stop(ifp, 0);
   1790  1.1  thorpej 
   1791  1.1  thorpej 	/* Reset the chip to a known state. */
   1792  1.1  thorpej 	wm_reset(sc);
   1793  1.1  thorpej 
   1794  1.1  thorpej 	/* Initialize the transmit descriptor ring. */
   1795  1.1  thorpej 	memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
   1796  1.1  thorpej 	WM_CDTXSYNC(sc, 0, WM_NTXDESC,
   1797  1.1  thorpej 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   1798  1.1  thorpej 	sc->sc_txfree = WM_NTXDESC;
   1799  1.1  thorpej 	sc->sc_txnext = 0;
   1800  1.1  thorpej 
   1801  1.1  thorpej 	if (sc->sc_type < WM_T_LIVENGOOD) {
   1802  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_TBDAH, 0);
   1803  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_TBDAL, WM_CDTXADDR(sc, 0));
   1804  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_TDLEN, sizeof(sc->sc_txdescs));
   1805  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_TDH, 0);
   1806  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_TDT, 0);
   1807  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_TIDV, 64);
   1808  1.1  thorpej 	} else {
   1809  1.1  thorpej 		CSR_WRITE(sc, WMREG_TBDAH, 0);
   1810  1.1  thorpej 		CSR_WRITE(sc, WMREG_TBDAL, WM_CDTXADDR(sc, 0));
   1811  1.1  thorpej 		CSR_WRITE(sc, WMREG_TDLEN, sizeof(sc->sc_txdescs));
   1812  1.1  thorpej 		CSR_WRITE(sc, WMREG_TDH, 0);
   1813  1.1  thorpej 		CSR_WRITE(sc, WMREG_TDT, 0);
   1814  1.1  thorpej 		CSR_WRITE(sc, WMREG_TIDV, 64);
   1815  1.1  thorpej 
   1816  1.1  thorpej 		CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
   1817  1.1  thorpej 		    TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
   1818  1.1  thorpej 		CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) |
   1819  1.1  thorpej 		    RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1));
   1820  1.1  thorpej 	}
   1821  1.1  thorpej 	CSR_WRITE(sc, WMREG_TQSA_LO, 0);
   1822  1.1  thorpej 	CSR_WRITE(sc, WMREG_TQSA_HI, 0);
   1823  1.1  thorpej 
   1824  1.1  thorpej 	/* Initialize the transmit job descriptors. */
   1825  1.1  thorpej 	for (i = 0; i < WM_TXQUEUELEN; i++)
   1826  1.1  thorpej 		sc->sc_txsoft[i].txs_mbuf = NULL;
   1827  1.1  thorpej 	sc->sc_txsfree = WM_TXQUEUELEN;
   1828  1.1  thorpej 	sc->sc_txsnext = 0;
   1829  1.1  thorpej 	sc->sc_txsdirty = 0;
   1830  1.1  thorpej 
   1831  1.1  thorpej 	/*
   1832  1.1  thorpej 	 * Initialize the receive descriptor and receive job
   1833  1.1  thorpej 	 * descriptor rings.
   1834  1.1  thorpej 	 */
   1835  1.1  thorpej 	if (sc->sc_type < WM_T_LIVENGOOD) {
   1836  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDBAH0, 0);
   1837  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDBAL0, WM_CDRXADDR(sc, 0));
   1838  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDLEN0, sizeof(sc->sc_rxdescs));
   1839  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDH0, 0);
   1840  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDT0, 0);
   1841  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDTR0, 64 | RDTR_FPD);
   1842  1.1  thorpej 
   1843  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDBA1_HI, 0);
   1844  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDBA1_LO, 0);
   1845  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDLEN1, 0);
   1846  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDH1, 0);
   1847  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDT1, 0);
   1848  1.1  thorpej 		CSR_WRITE(sc, WMREG_OLD_RDTR1, 0);
   1849  1.1  thorpej 	} else {
   1850  1.1  thorpej 		CSR_WRITE(sc, WMREG_RDBAH, 0);
   1851  1.1  thorpej 		CSR_WRITE(sc, WMREG_RDBAL, WM_CDRXADDR(sc, 0));
   1852  1.1  thorpej 		CSR_WRITE(sc, WMREG_RDLEN, sizeof(sc->sc_rxdescs));
   1853  1.1  thorpej 		CSR_WRITE(sc, WMREG_RDH, 0);
   1854  1.1  thorpej 		CSR_WRITE(sc, WMREG_RDT, 0);
   1855  1.1  thorpej 		CSR_WRITE(sc, WMREG_RDTR, 64 | RDTR_FPD);
   1856  1.1  thorpej 	}
   1857  1.1  thorpej 	for (i = 0; i < WM_NRXDESC; i++) {
   1858  1.1  thorpej 		rxs = &sc->sc_rxsoft[i];
   1859  1.1  thorpej 		if (rxs->rxs_mbuf == NULL) {
   1860  1.1  thorpej 			if ((error = wm_add_rxbuf(sc, i)) != 0) {
   1861  1.1  thorpej 				printf("%s: unable to allocate or map rx "
   1862  1.1  thorpej 				    "buffer %d, error = %d\n",
   1863  1.1  thorpej 				    sc->sc_dev.dv_xname, i, error);
   1864  1.1  thorpej 				/*
   1865  1.1  thorpej 				 * XXX Should attempt to run with fewer receive
   1866  1.1  thorpej 				 * XXX buffers instead of just failing.
   1867  1.1  thorpej 				 */
   1868  1.1  thorpej 				wm_rxdrain(sc);
   1869  1.1  thorpej 				goto out;
   1870  1.1  thorpej 			}
   1871  1.1  thorpej 		} else
   1872  1.1  thorpej 			WM_INIT_RXDESC(sc, i);
   1873  1.1  thorpej 	}
   1874  1.1  thorpej 	sc->sc_rxptr = 0;
   1875  1.1  thorpej 	sc->sc_rxdiscard = 0;
   1876  1.1  thorpej 	WM_RXCHAIN_RESET(sc);
   1877  1.1  thorpej 
   1878  1.1  thorpej 	/*
   1879  1.1  thorpej 	 * Clear out the VLAN table -- we don't use it (yet).
   1880  1.1  thorpej 	 */
   1881  1.1  thorpej 	CSR_WRITE(sc, WMREG_VET, 0);
   1882  1.1  thorpej 	for (i = 0; i < WM_VLAN_TABSIZE; i++)
   1883  1.1  thorpej 		CSR_WRITE(sc, WMREG_VFTA + (i << 2), 0);
   1884  1.1  thorpej 
   1885  1.1  thorpej 	/*
   1886  1.1  thorpej 	 * Set up flow-control parameters.
   1887  1.1  thorpej 	 *
   1888  1.1  thorpej 	 * XXX Values could probably stand some tuning.
   1889  1.1  thorpej 	 */
   1890  1.1  thorpej 	if (sc->sc_ctrl & (CTRL_RFCE|CTRL_TFCE)) {
   1891  1.1  thorpej 		CSR_WRITE(sc, WMREG_FCAL, FCAL_CONST);
   1892  1.1  thorpej 		CSR_WRITE(sc, WMREG_FCAH, FCAH_CONST);
   1893  1.1  thorpej 		CSR_WRITE(sc, WMREG_FCT, ETHERTYPE_FLOWCONTROL);
   1894  1.1  thorpej 
   1895  1.1  thorpej 		if (sc->sc_type < WM_T_LIVENGOOD) {
   1896  1.1  thorpej 			CSR_WRITE(sc, WMREG_OLD_FCRTH, FCRTH_DFLT);
   1897  1.1  thorpej 			CSR_WRITE(sc, WMREG_OLD_FCRTL, FCRTL_DFLT);
   1898  1.1  thorpej 		} else {
   1899  1.1  thorpej 			CSR_WRITE(sc, WMREG_FCRTH, FCRTH_DFLT);
   1900  1.1  thorpej 			CSR_WRITE(sc, WMREG_FCRTL, FCRTL_DFLT);
   1901  1.1  thorpej 		}
   1902  1.1  thorpej 		CSR_WRITE(sc, WMREG_FCTTV, FCTTV_DFLT);
   1903  1.1  thorpej 	}
   1904  1.1  thorpej 
   1905  1.1  thorpej #if 0 /* XXXJRT */
   1906  1.1  thorpej 	/* Deal with VLAN enables. */
   1907  1.1  thorpej 	if (sc->sc_ethercom.ec_nvlans != 0)
   1908  1.1  thorpej 		sc->sc_ctrl |= CTRL_VME;
   1909  1.1  thorpej 	else
   1910  1.1  thorpej #endif /* XXXJRT */
   1911  1.1  thorpej 		sc->sc_ctrl &= ~CTRL_VME;
   1912  1.1  thorpej 
   1913  1.1  thorpej 	/* Write the control registers. */
   1914  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
   1915  1.1  thorpej #if 0
   1916  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL_EXT, sc->sc_ctrl_ext);
   1917  1.1  thorpej #endif
   1918  1.1  thorpej 
   1919  1.1  thorpej 	/*
   1920  1.1  thorpej 	 * Set up checksum offload parameters.
   1921  1.1  thorpej 	 */
   1922  1.1  thorpej 	reg = CSR_READ(sc, WMREG_RXCSUM);
   1923  1.1  thorpej 	if (ifp->if_capenable & IFCAP_CSUM_IPv4)
   1924  1.1  thorpej 		reg |= RXCSUM_IPOFL;
   1925  1.1  thorpej 	else
   1926  1.1  thorpej 		reg &= ~RXCSUM_IPOFL;
   1927  1.1  thorpej 	if (ifp->if_capenable & (IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4))
   1928  1.1  thorpej 		reg |= RXCSUM_TUOFL;
   1929  1.1  thorpej 	else
   1930  1.1  thorpej 		reg &= ~RXCSUM_TUOFL;
   1931  1.1  thorpej 	CSR_WRITE(sc, WMREG_RXCSUM, reg);
   1932  1.1  thorpej 
   1933  1.1  thorpej 	/*
   1934  1.1  thorpej 	 * Set up the interrupt registers.
   1935  1.1  thorpej 	 */
   1936  1.1  thorpej 	CSR_WRITE(sc, WMREG_IMC, 0xffffffffU);
   1937  1.1  thorpej 	sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 |
   1938  1.1  thorpej 	    ICR_RXO | ICR_RXT0;
   1939  1.1  thorpej 	if ((sc->sc_flags & WM_F_HAS_MII) == 0)
   1940  1.1  thorpej 		sc->sc_icr |= ICR_RXCFG;
   1941  1.1  thorpej 	CSR_WRITE(sc, WMREG_IMS, sc->sc_icr);
   1942  1.1  thorpej 
   1943  1.1  thorpej 	/* Set up the inter-packet gap. */
   1944  1.1  thorpej 	CSR_WRITE(sc, WMREG_TIPG, sc->sc_tipg);
   1945  1.1  thorpej 
   1946  1.1  thorpej #if 0 /* XXXJRT */
   1947  1.1  thorpej 	/* Set the VLAN ethernetype. */
   1948  1.1  thorpej 	CSR_WRITE(sc, WMREG_VET, ETHERTYPE_VLAN);
   1949  1.1  thorpej #endif
   1950  1.1  thorpej 
   1951  1.1  thorpej 	/*
   1952  1.1  thorpej 	 * Set up the transmit control register; we start out with
   1953  1.1  thorpej 	 * a collision distance suitable for FDX, but update it whe
   1954  1.1  thorpej 	 * we resolve the media type.
   1955  1.1  thorpej 	 */
   1956  1.1  thorpej 	sc->sc_tctl = TCTL_EN | TCTL_PSP | TCTL_CT(TX_COLLISION_THRESHOLD) |
   1957  1.1  thorpej 	    TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
   1958  1.1  thorpej 	CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
   1959  1.1  thorpej 
   1960  1.1  thorpej 	/* Set the media. */
   1961  1.1  thorpej 	(void) (*sc->sc_mii.mii_media.ifm_change)(ifp);
   1962  1.1  thorpej 
   1963  1.1  thorpej 	/*
   1964  1.1  thorpej 	 * Set up the receive control register; we actually program
   1965  1.1  thorpej 	 * the register when we set the receive filter.  Use multicast
   1966  1.1  thorpej 	 * address offset type 0.
   1967  1.1  thorpej 	 *
   1968  1.1  thorpej 	 * Only the Cordova has the ability to strip the incoming
   1969  1.1  thorpej 	 * CRC, so we don't enable that feature.
   1970  1.1  thorpej 	 */
   1971  1.1  thorpej 	sc->sc_mchash_type = 0;
   1972  1.1  thorpej 	sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_2k |
   1973  1.1  thorpej 	    RCTL_DPF | RCTL_MO(sc->sc_mchash_type);
   1974  1.1  thorpej 
   1975  1.1  thorpej 	/* Set the receive filter. */
   1976  1.1  thorpej 	wm_set_filter(sc);
   1977  1.1  thorpej 
   1978  1.1  thorpej 	/* Start the one second link check clock. */
   1979  1.1  thorpej 	callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc);
   1980  1.1  thorpej 
   1981  1.1  thorpej 	/* ...all done! */
   1982  1.1  thorpej 	ifp->if_flags |= IFF_RUNNING;
   1983  1.1  thorpej 	ifp->if_flags &= ~IFF_OACTIVE;
   1984  1.1  thorpej 
   1985  1.1  thorpej  out:
   1986  1.1  thorpej 	if (error)
   1987  1.1  thorpej 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   1988  1.1  thorpej 	return (error);
   1989  1.1  thorpej }
   1990  1.1  thorpej 
   1991  1.1  thorpej /*
   1992  1.1  thorpej  * wm_rxdrain:
   1993  1.1  thorpej  *
   1994  1.1  thorpej  *	Drain the receive queue.
   1995  1.1  thorpej  */
   1996  1.1  thorpej void
   1997  1.1  thorpej wm_rxdrain(struct wm_softc *sc)
   1998  1.1  thorpej {
   1999  1.1  thorpej 	struct wm_rxsoft *rxs;
   2000  1.1  thorpej 	int i;
   2001  1.1  thorpej 
   2002  1.1  thorpej 	for (i = 0; i < WM_NRXDESC; i++) {
   2003  1.1  thorpej 		rxs = &sc->sc_rxsoft[i];
   2004  1.1  thorpej 		if (rxs->rxs_mbuf != NULL) {
   2005  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
   2006  1.1  thorpej 			m_freem(rxs->rxs_mbuf);
   2007  1.1  thorpej 			rxs->rxs_mbuf = NULL;
   2008  1.1  thorpej 		}
   2009  1.1  thorpej 	}
   2010  1.1  thorpej }
   2011  1.1  thorpej 
   2012  1.1  thorpej /*
   2013  1.1  thorpej  * wm_stop:		[ifnet interface function]
   2014  1.1  thorpej  *
   2015  1.1  thorpej  *	Stop transmission on the interface.
   2016  1.1  thorpej  */
   2017  1.1  thorpej void
   2018  1.1  thorpej wm_stop(struct ifnet *ifp, int disable)
   2019  1.1  thorpej {
   2020  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   2021  1.1  thorpej 	struct wm_txsoft *txs;
   2022  1.1  thorpej 	int i;
   2023  1.1  thorpej 
   2024  1.1  thorpej 	/* Stop the one second clock. */
   2025  1.1  thorpej 	callout_stop(&sc->sc_tick_ch);
   2026  1.1  thorpej 
   2027  1.1  thorpej 	if (sc->sc_flags & WM_F_HAS_MII) {
   2028  1.1  thorpej 		/* Down the MII. */
   2029  1.1  thorpej 		mii_down(&sc->sc_mii);
   2030  1.1  thorpej 	}
   2031  1.1  thorpej 
   2032  1.1  thorpej 	/* Stop the transmit and receive processes. */
   2033  1.1  thorpej 	CSR_WRITE(sc, WMREG_TCTL, 0);
   2034  1.1  thorpej 	CSR_WRITE(sc, WMREG_RCTL, 0);
   2035  1.1  thorpej 
   2036  1.1  thorpej 	/* Release any queued transmit buffers. */
   2037  1.1  thorpej 	for (i = 0; i < WM_TXQUEUELEN; i++) {
   2038  1.1  thorpej 		txs = &sc->sc_txsoft[i];
   2039  1.1  thorpej 		if (txs->txs_mbuf != NULL) {
   2040  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
   2041  1.1  thorpej 			m_freem(txs->txs_mbuf);
   2042  1.1  thorpej 			txs->txs_mbuf = NULL;
   2043  1.1  thorpej 		}
   2044  1.1  thorpej 	}
   2045  1.1  thorpej 
   2046  1.1  thorpej 	if (disable)
   2047  1.1  thorpej 		wm_rxdrain(sc);
   2048  1.1  thorpej 
   2049  1.1  thorpej 	/* Mark the interface as down and cancel the watchdog timer. */
   2050  1.1  thorpej 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   2051  1.1  thorpej 	ifp->if_timer = 0;
   2052  1.1  thorpej }
   2053  1.1  thorpej 
   2054  1.1  thorpej /*
   2055  1.1  thorpej  * wm_read_eeprom:
   2056  1.1  thorpej  *
   2057  1.1  thorpej  *	Read data from the serial EEPROM.
   2058  1.1  thorpej  */
   2059  1.1  thorpej void
   2060  1.1  thorpej wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
   2061  1.1  thorpej {
   2062  1.1  thorpej 	uint32_t reg;
   2063  1.1  thorpej 	int i, x;
   2064  1.1  thorpej 
   2065  1.1  thorpej 	for (i = 0; i < wordcnt; i++) {
   2066  1.1  thorpej 		/* Send CHIP SELECT for one clock tick. */
   2067  1.1  thorpej 		CSR_WRITE(sc, WMREG_EECD, EECD_CS);
   2068  1.1  thorpej 		delay(2);
   2069  1.1  thorpej 
   2070  1.1  thorpej 		/* Shift in the READ command. */
   2071  1.1  thorpej 		for (x = 3; x > 0; x--) {
   2072  1.1  thorpej 			reg = EECD_CS;
   2073  1.1  thorpej 			if (UWIRE_OPC_READ & (1 << (x - 1)))
   2074  1.1  thorpej 				reg |= EECD_DI;
   2075  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg);
   2076  1.1  thorpej 			delay(2);
   2077  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
   2078  1.1  thorpej 			delay(2);
   2079  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg);
   2080  1.1  thorpej 			delay(2);
   2081  1.1  thorpej 		}
   2082  1.1  thorpej 
   2083  1.1  thorpej 		/* Shift in address. */
   2084  1.1  thorpej 		for (x = 6; x > 0; x--) {
   2085  1.1  thorpej 			reg = EECD_CS;
   2086  1.1  thorpej 			if ((word + i) & (1 << (x - 1)))
   2087  1.1  thorpej 				reg |= EECD_DI;
   2088  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg);
   2089  1.1  thorpej 			delay(2);
   2090  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
   2091  1.1  thorpej 			delay(2);
   2092  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg);
   2093  1.1  thorpej 			delay(2);
   2094  1.1  thorpej 		}
   2095  1.1  thorpej 
   2096  1.1  thorpej 		/* Shift out the data. */
   2097  1.1  thorpej 		reg = EECD_CS;
   2098  1.1  thorpej 		data[i] = 0;
   2099  1.1  thorpej 		for (x = 16; x > 0; x--) {
   2100  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
   2101  1.1  thorpej 			delay(2);
   2102  1.1  thorpej 			if (CSR_READ(sc, WMREG_EECD) & EECD_DO)
   2103  1.1  thorpej 				data[i] |= (1 << (x - 1));
   2104  1.1  thorpej 			CSR_WRITE(sc, WMREG_EECD, reg);
   2105  1.1  thorpej 			delay(2);
   2106  1.1  thorpej 		}
   2107  1.1  thorpej 
   2108  1.1  thorpej 		/* Clear CHIP SELECT. */
   2109  1.1  thorpej 		CSR_WRITE(sc, WMREG_EECD, 0);
   2110  1.1  thorpej 	}
   2111  1.1  thorpej }
   2112  1.1  thorpej 
   2113  1.1  thorpej /*
   2114  1.1  thorpej  * wm_add_rxbuf:
   2115  1.1  thorpej  *
   2116  1.1  thorpej  *	Add a receive buffer to the indiciated descriptor.
   2117  1.1  thorpej  */
   2118  1.1  thorpej int
   2119  1.1  thorpej wm_add_rxbuf(struct wm_softc *sc, int idx)
   2120  1.1  thorpej {
   2121  1.1  thorpej 	struct wm_rxsoft *rxs = &sc->sc_rxsoft[idx];
   2122  1.1  thorpej 	struct mbuf *m;
   2123  1.1  thorpej 	int error;
   2124  1.1  thorpej 
   2125  1.1  thorpej 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   2126  1.1  thorpej 	if (m == NULL)
   2127  1.1  thorpej 		return (ENOBUFS);
   2128  1.1  thorpej 
   2129  1.1  thorpej 	MCLGET(m, M_DONTWAIT);
   2130  1.1  thorpej 	if ((m->m_flags & M_EXT) == 0) {
   2131  1.1  thorpej 		m_freem(m);
   2132  1.1  thorpej 		return (ENOBUFS);
   2133  1.1  thorpej 	}
   2134  1.1  thorpej 
   2135  1.1  thorpej 	if (rxs->rxs_mbuf != NULL)
   2136  1.1  thorpej 		bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
   2137  1.1  thorpej 
   2138  1.1  thorpej 	rxs->rxs_mbuf = m;
   2139  1.1  thorpej 
   2140  1.1  thorpej 	error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
   2141  1.1  thorpej 	    m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
   2142  1.1  thorpej 	    BUS_DMA_READ|BUS_DMA_NOWAIT);
   2143  1.1  thorpej 	if (error) {
   2144  1.1  thorpej 		printf("%s: unable to load rx DMA map %d, error = %d\n",
   2145  1.1  thorpej 		    sc->sc_dev.dv_xname, idx, error);
   2146  1.1  thorpej 		panic("wm_add_rxbuf");	/* XXX XXX XXX */
   2147  1.1  thorpej 	}
   2148  1.1  thorpej 
   2149  1.1  thorpej 	bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   2150  1.1  thorpej 	    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   2151  1.1  thorpej 
   2152  1.1  thorpej 	WM_INIT_RXDESC(sc, idx);
   2153  1.1  thorpej 
   2154  1.1  thorpej 	return (0);
   2155  1.1  thorpej }
   2156  1.1  thorpej 
   2157  1.1  thorpej /*
   2158  1.1  thorpej  * wm_set_ral:
   2159  1.1  thorpej  *
   2160  1.1  thorpej  *	Set an entery in the receive address list.
   2161  1.1  thorpej  */
   2162  1.1  thorpej static void
   2163  1.1  thorpej wm_set_ral(struct wm_softc *sc, const uint8_t *enaddr, int idx)
   2164  1.1  thorpej {
   2165  1.1  thorpej 	uint32_t ral_lo, ral_hi;
   2166  1.1  thorpej 
   2167  1.1  thorpej 	if (enaddr != NULL) {
   2168  1.1  thorpej 		ral_lo = enaddr[0] | (enaddr[1] << 8) | (enaddr[2] << 16) |
   2169  1.1  thorpej 		    (enaddr[3] << 24);
   2170  1.1  thorpej 		ral_hi = enaddr[4] | (enaddr[5] << 8);
   2171  1.1  thorpej 		ral_hi |= RAL_AV;
   2172  1.1  thorpej 	} else {
   2173  1.1  thorpej 		ral_lo = 0;
   2174  1.1  thorpej 		ral_hi = 0;
   2175  1.1  thorpej 	}
   2176  1.1  thorpej 
   2177  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA) {
   2178  1.1  thorpej 		CSR_WRITE(sc, WMREG_RAL_LO(WMREG_CORDOVA_RAL_BASE, idx),
   2179  1.1  thorpej 		    ral_lo);
   2180  1.1  thorpej 		CSR_WRITE(sc, WMREG_RAL_HI(WMREG_CORDOVA_RAL_BASE, idx),
   2181  1.1  thorpej 		    ral_hi);
   2182  1.1  thorpej 	} else {
   2183  1.1  thorpej 		CSR_WRITE(sc, WMREG_RAL_LO(WMREG_RAL_BASE, idx), ral_lo);
   2184  1.1  thorpej 		CSR_WRITE(sc, WMREG_RAL_HI(WMREG_RAL_BASE, idx), ral_hi);
   2185  1.1  thorpej 	}
   2186  1.1  thorpej }
   2187  1.1  thorpej 
   2188  1.1  thorpej /*
   2189  1.1  thorpej  * wm_mchash:
   2190  1.1  thorpej  *
   2191  1.1  thorpej  *	Compute the hash of the multicast address for the 4096-bit
   2192  1.1  thorpej  *	multicast filter.
   2193  1.1  thorpej  */
   2194  1.1  thorpej static uint32_t
   2195  1.1  thorpej wm_mchash(struct wm_softc *sc, const uint8_t *enaddr)
   2196  1.1  thorpej {
   2197  1.1  thorpej 	static const int lo_shift[4] = { 4, 3, 2, 0 };
   2198  1.1  thorpej 	static const int hi_shift[4] = { 4, 5, 6, 8 };
   2199  1.1  thorpej 	uint32_t hash;
   2200  1.1  thorpej 
   2201  1.1  thorpej 	hash = (enaddr[4] >> lo_shift[sc->sc_mchash_type]) |
   2202  1.1  thorpej 	    (((uint16_t) enaddr[5]) << hi_shift[sc->sc_mchash_type]);
   2203  1.1  thorpej 
   2204  1.1  thorpej 	return (hash & 0xfff);
   2205  1.1  thorpej }
   2206  1.1  thorpej 
   2207  1.1  thorpej /*
   2208  1.1  thorpej  * wm_set_filter:
   2209  1.1  thorpej  *
   2210  1.1  thorpej  *	Set up the receive filter.
   2211  1.1  thorpej  */
   2212  1.1  thorpej void
   2213  1.1  thorpej wm_set_filter(struct wm_softc *sc)
   2214  1.1  thorpej {
   2215  1.1  thorpej 	struct ethercom *ec = &sc->sc_ethercom;
   2216  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   2217  1.1  thorpej 	struct ether_multi *enm;
   2218  1.1  thorpej 	struct ether_multistep step;
   2219  1.1  thorpej 	bus_addr_t mta_reg;
   2220  1.1  thorpej 	uint32_t hash, reg, bit;
   2221  1.1  thorpej 	int i;
   2222  1.1  thorpej 
   2223  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA)
   2224  1.1  thorpej 		mta_reg = WMREG_CORDOVA_MTA;
   2225  1.1  thorpej 	else
   2226  1.1  thorpej 		mta_reg = WMREG_MTA;
   2227  1.1  thorpej 
   2228  1.1  thorpej 	sc->sc_rctl &= ~(RCTL_BAM | RCTL_UPE | RCTL_MPE);
   2229  1.1  thorpej 
   2230  1.1  thorpej 	if (ifp->if_flags & IFF_BROADCAST)
   2231  1.1  thorpej 		sc->sc_rctl |= RCTL_BAM;
   2232  1.1  thorpej 	if (ifp->if_flags & IFF_PROMISC) {
   2233  1.1  thorpej 		sc->sc_rctl |= RCTL_UPE;
   2234  1.1  thorpej 		goto allmulti;
   2235  1.1  thorpej 	}
   2236  1.1  thorpej 
   2237  1.1  thorpej 	/*
   2238  1.1  thorpej 	 * Set the station address in the first RAL slot, and
   2239  1.1  thorpej 	 * clear the remaining slots.
   2240  1.1  thorpej 	 */
   2241  1.1  thorpej 	wm_set_ral(sc, LLADDR(ifp->if_sadl), 0);
   2242  1.1  thorpej 	for (i = 1; i < WM_RAL_TABSIZE; i++)
   2243  1.1  thorpej 		wm_set_ral(sc, NULL, i);
   2244  1.1  thorpej 
   2245  1.1  thorpej 	/* Clear out the multicast table. */
   2246  1.1  thorpej 	for (i = 0; i < WM_MC_TABSIZE; i++)
   2247  1.1  thorpej 		CSR_WRITE(sc, mta_reg + (i << 2), 0);
   2248  1.1  thorpej 
   2249  1.1  thorpej 	ETHER_FIRST_MULTI(step, ec, enm);
   2250  1.1  thorpej 	while (enm != NULL) {
   2251  1.1  thorpej 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
   2252  1.1  thorpej 			/*
   2253  1.1  thorpej 			 * We must listen to a range of multicast addresses.
   2254  1.1  thorpej 			 * For now, just accept all multicasts, rather than
   2255  1.1  thorpej 			 * trying to set only those filter bits needed to match
   2256  1.1  thorpej 			 * the range.  (At this time, the only use of address
   2257  1.1  thorpej 			 * ranges is for IP multicast routing, for which the
   2258  1.1  thorpej 			 * range is big enough to require all bits set.)
   2259  1.1  thorpej 			 */
   2260  1.1  thorpej 			goto allmulti;
   2261  1.1  thorpej 		}
   2262  1.1  thorpej 
   2263  1.1  thorpej 		hash = wm_mchash(sc, enm->enm_addrlo);
   2264  1.1  thorpej 
   2265  1.1  thorpej 		reg = (hash >> 5) & 0x7f;
   2266  1.1  thorpej 		bit = hash & 0x1f;
   2267  1.1  thorpej 
   2268  1.1  thorpej 		hash = CSR_READ(sc, mta_reg + (reg << 2));
   2269  1.1  thorpej 		hash |= 1U << bit;
   2270  1.1  thorpej 
   2271  1.1  thorpej 		/* XXX Hardware bug?? */
   2272  1.1  thorpej 		if (sc->sc_type == WM_T_CORDOVA && (reg & 0xe) == 1) {
   2273  1.1  thorpej 			bit = CSR_READ(sc, mta_reg + ((reg - 1) << 2));
   2274  1.1  thorpej 			CSR_WRITE(sc, mta_reg + (reg << 2), hash);
   2275  1.1  thorpej 			CSR_WRITE(sc, mta_reg + ((reg - 1) << 2), bit);
   2276  1.1  thorpej 		} else
   2277  1.1  thorpej 			CSR_WRITE(sc, mta_reg + (reg << 2), hash);
   2278  1.1  thorpej 
   2279  1.1  thorpej 		ETHER_NEXT_MULTI(step, enm);
   2280  1.1  thorpej 	}
   2281  1.1  thorpej 
   2282  1.1  thorpej 	ifp->if_flags &= ~IFF_ALLMULTI;
   2283  1.1  thorpej 	goto setit;
   2284  1.1  thorpej 
   2285  1.1  thorpej  allmulti:
   2286  1.1  thorpej 	ifp->if_flags |= IFF_ALLMULTI;
   2287  1.1  thorpej 	sc->sc_rctl |= RCTL_MPE;
   2288  1.1  thorpej 
   2289  1.1  thorpej  setit:
   2290  1.1  thorpej 	CSR_WRITE(sc, WMREG_RCTL, sc->sc_rctl);
   2291  1.1  thorpej }
   2292  1.1  thorpej 
   2293  1.1  thorpej /*
   2294  1.1  thorpej  * wm_tbi_mediainit:
   2295  1.1  thorpej  *
   2296  1.1  thorpej  *	Initialize media for use on 1000BASE-X devices.
   2297  1.1  thorpej  */
   2298  1.1  thorpej void
   2299  1.1  thorpej wm_tbi_mediainit(struct wm_softc *sc)
   2300  1.1  thorpej {
   2301  1.1  thorpej 	const char *sep = "";
   2302  1.1  thorpej 
   2303  1.1  thorpej 	if (sc->sc_type < WM_T_LIVENGOOD)
   2304  1.1  thorpej 		sc->sc_tipg = TIPG_WM_DFLT;
   2305  1.1  thorpej 	else
   2306  1.1  thorpej 		sc->sc_tipg = TIPG_LG_DFLT;
   2307  1.1  thorpej 
   2308  1.1  thorpej 	ifmedia_init(&sc->sc_mii.mii_media, 0, wm_tbi_mediachange,
   2309  1.1  thorpej 	    wm_tbi_mediastatus);
   2310  1.1  thorpej 
   2311  1.1  thorpej 	/*
   2312  1.1  thorpej 	 * SWD Pins:
   2313  1.1  thorpej 	 *
   2314  1.1  thorpej 	 *	0 = Link LED (output)
   2315  1.1  thorpej 	 *	1 = Loss Of Signal (input)
   2316  1.1  thorpej 	 */
   2317  1.1  thorpej 	sc->sc_ctrl |= CTRL_SWDPIO(0);
   2318  1.1  thorpej 	sc->sc_ctrl &= ~CTRL_SWDPIO(1);
   2319  1.1  thorpej 
   2320  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
   2321  1.1  thorpej 
   2322  1.1  thorpej #define	ADD(s, m, d)							\
   2323  1.1  thorpej do {									\
   2324  1.1  thorpej 	printf("%s%s", sep, s);						\
   2325  1.1  thorpej 	ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|(m), (d), NULL);	\
   2326  1.1  thorpej 	sep = ", ";							\
   2327  1.1  thorpej } while (/*CONSTCOND*/0)
   2328  1.1  thorpej 
   2329  1.1  thorpej 	printf("%s: ", sc->sc_dev.dv_xname);
   2330  1.1  thorpej 	ADD("1000baseSX", IFM_1000_SX, ANAR_X_HD);
   2331  1.1  thorpej 	ADD("1000baseSX-FDX", IFM_1000_SX|IFM_FDX, ANAR_X_FD);
   2332  1.1  thorpej 	ADD("auto", IFM_AUTO, ANAR_X_FD|ANAR_X_HD);
   2333  1.1  thorpej 	printf("\n");
   2334  1.1  thorpej 
   2335  1.1  thorpej #undef ADD
   2336  1.1  thorpej 
   2337  1.1  thorpej 	ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
   2338  1.1  thorpej }
   2339  1.1  thorpej 
   2340  1.1  thorpej /*
   2341  1.1  thorpej  * wm_tbi_mediastatus:	[ifmedia interface function]
   2342  1.1  thorpej  *
   2343  1.1  thorpej  *	Get the current interface media status on a 1000BASE-X device.
   2344  1.1  thorpej  */
   2345  1.1  thorpej void
   2346  1.1  thorpej wm_tbi_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
   2347  1.1  thorpej {
   2348  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   2349  1.1  thorpej 
   2350  1.1  thorpej 	ifmr->ifm_status = IFM_AVALID;
   2351  1.1  thorpej 	ifmr->ifm_active = IFM_ETHER;
   2352  1.1  thorpej 
   2353  1.1  thorpej 	if (sc->sc_tbi_linkup == 0) {
   2354  1.1  thorpej 		ifmr->ifm_active |= IFM_NONE;
   2355  1.1  thorpej 		return;
   2356  1.1  thorpej 	}
   2357  1.1  thorpej 
   2358  1.1  thorpej 	ifmr->ifm_status |= IFM_ACTIVE;
   2359  1.1  thorpej 	ifmr->ifm_active |= IFM_1000_SX;
   2360  1.1  thorpej 	if (CSR_READ(sc, WMREG_STATUS) & STATUS_FD)
   2361  1.1  thorpej 		ifmr->ifm_active |= IFM_FDX;
   2362  1.1  thorpej }
   2363  1.1  thorpej 
   2364  1.1  thorpej /*
   2365  1.1  thorpej  * wm_tbi_mediachange:	[ifmedia interface function]
   2366  1.1  thorpej  *
   2367  1.1  thorpej  *	Set hardware to newly-selected media on a 1000BASE-X device.
   2368  1.1  thorpej  */
   2369  1.1  thorpej int
   2370  1.1  thorpej wm_tbi_mediachange(struct ifnet *ifp)
   2371  1.1  thorpej {
   2372  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   2373  1.1  thorpej 	struct ifmedia_entry *ife = sc->sc_mii.mii_media.ifm_cur;
   2374  1.1  thorpej 	uint32_t status;
   2375  1.1  thorpej 	int i;
   2376  1.1  thorpej 
   2377  1.1  thorpej 	sc->sc_txcw = ife->ifm_data;
   2378  1.1  thorpej 	if (sc->sc_ctrl & CTRL_RFCE)
   2379  1.1  thorpej 		sc->sc_txcw |= ANAR_X_PAUSE_TOWARDS;
   2380  1.1  thorpej 	if (sc->sc_ctrl & CTRL_TFCE)
   2381  1.1  thorpej 		sc->sc_txcw |= ANAR_X_PAUSE_ASYM;
   2382  1.1  thorpej 	sc->sc_txcw |= TXCW_ANE;
   2383  1.1  thorpej 
   2384  1.1  thorpej 	CSR_WRITE(sc, WMREG_TXCW, sc->sc_txcw);
   2385  1.1  thorpej 	delay(10000);
   2386  1.1  thorpej 
   2387  1.1  thorpej 	sc->sc_tbi_anstate = 0;
   2388  1.1  thorpej 
   2389  1.1  thorpej 	if ((CSR_READ(sc, WMREG_CTRL) & CTRL_SWDPIN(1)) == 0) {
   2390  1.1  thorpej 		/* Have signal; wait for the link to come up. */
   2391  1.1  thorpej 		for (i = 0; i < 50; i++) {
   2392  1.1  thorpej 			delay(10000);
   2393  1.1  thorpej 			if (CSR_READ(sc, WMREG_STATUS) & STATUS_LU)
   2394  1.1  thorpej 				break;
   2395  1.1  thorpej 		}
   2396  1.1  thorpej 
   2397  1.1  thorpej 		status = CSR_READ(sc, WMREG_STATUS);
   2398  1.1  thorpej 		if (status & STATUS_LU) {
   2399  1.1  thorpej 			/* Link is up. */
   2400  1.1  thorpej 			DPRINTF(WM_DEBUG_LINK,
   2401  1.1  thorpej 			    ("%s: LINK: set media -> link up %s\n",
   2402  1.1  thorpej 			    sc->sc_dev.dv_xname,
   2403  1.1  thorpej 			    (status & STATUS_FD) ? "FDX" : "HDX"));
   2404  1.1  thorpej 			sc->sc_tctl &= ~TCTL_COLD(0x3ff);
   2405  1.1  thorpej 			if (status & STATUS_FD)
   2406  1.1  thorpej 				sc->sc_tctl |=
   2407  1.1  thorpej 				    TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
   2408  1.1  thorpej 			else
   2409  1.1  thorpej 				sc->sc_tctl |=
   2410  1.1  thorpej 				    TCTL_COLD(TX_COLLISION_DISTANCE_HDX);
   2411  1.1  thorpej 			CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
   2412  1.1  thorpej 			sc->sc_tbi_linkup = 1;
   2413  1.1  thorpej 		} else {
   2414  1.1  thorpej 			/* Link is down. */
   2415  1.1  thorpej 			DPRINTF(WM_DEBUG_LINK,
   2416  1.1  thorpej 			    ("%s: LINK: set media -> link down\n",
   2417  1.1  thorpej 			    sc->sc_dev.dv_xname));
   2418  1.1  thorpej 			sc->sc_tbi_linkup = 0;
   2419  1.1  thorpej 		}
   2420  1.1  thorpej 	} else {
   2421  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK, ("%s: LINK: set media -> no signal\n",
   2422  1.1  thorpej 		    sc->sc_dev.dv_xname));
   2423  1.1  thorpej 		sc->sc_tbi_linkup = 0;
   2424  1.1  thorpej 	}
   2425  1.1  thorpej 
   2426  1.1  thorpej 	wm_tbi_set_linkled(sc);
   2427  1.1  thorpej 
   2428  1.1  thorpej 	return (0);
   2429  1.1  thorpej }
   2430  1.1  thorpej 
   2431  1.1  thorpej /*
   2432  1.1  thorpej  * wm_tbi_set_linkled:
   2433  1.1  thorpej  *
   2434  1.1  thorpej  *	Update the link LED on 1000BASE-X devices.
   2435  1.1  thorpej  */
   2436  1.1  thorpej void
   2437  1.1  thorpej wm_tbi_set_linkled(struct wm_softc *sc)
   2438  1.1  thorpej {
   2439  1.1  thorpej 
   2440  1.1  thorpej 	if (sc->sc_tbi_linkup)
   2441  1.1  thorpej 		sc->sc_ctrl |= CTRL_SWDPIN(0);
   2442  1.1  thorpej 	else
   2443  1.1  thorpej 		sc->sc_ctrl &= ~CTRL_SWDPIN(0);
   2444  1.1  thorpej 
   2445  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
   2446  1.1  thorpej }
   2447  1.1  thorpej 
   2448  1.1  thorpej /*
   2449  1.1  thorpej  * wm_tbi_check_link:
   2450  1.1  thorpej  *
   2451  1.1  thorpej  *	Check the link on 1000BASE-X devices.
   2452  1.1  thorpej  */
   2453  1.1  thorpej void
   2454  1.1  thorpej wm_tbi_check_link(struct wm_softc *sc)
   2455  1.1  thorpej {
   2456  1.1  thorpej 	uint32_t rxcw, ctrl, status;
   2457  1.1  thorpej 
   2458  1.1  thorpej 	if (sc->sc_tbi_anstate == 0)
   2459  1.1  thorpej 		return;
   2460  1.1  thorpej 	else if (sc->sc_tbi_anstate > 1) {
   2461  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK,
   2462  1.1  thorpej 		    ("%s: LINK: anstate %d\n", sc->sc_dev.dv_xname,
   2463  1.1  thorpej 		    sc->sc_tbi_anstate));
   2464  1.1  thorpej 		sc->sc_tbi_anstate--;
   2465  1.1  thorpej 		return;
   2466  1.1  thorpej 	}
   2467  1.1  thorpej 
   2468  1.1  thorpej 	sc->sc_tbi_anstate = 0;
   2469  1.1  thorpej 
   2470  1.1  thorpej 	rxcw = CSR_READ(sc, WMREG_RXCW);
   2471  1.1  thorpej 	ctrl = CSR_READ(sc, WMREG_CTRL);
   2472  1.1  thorpej 	status = CSR_READ(sc, WMREG_STATUS);
   2473  1.1  thorpej 
   2474  1.1  thorpej 	if ((status & STATUS_LU) == 0) {
   2475  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK,
   2476  1.1  thorpej 		    ("%s: LINK: checklink -> down\n", sc->sc_dev.dv_xname));
   2477  1.1  thorpej 		sc->sc_tbi_linkup = 0;
   2478  1.1  thorpej 	} else {
   2479  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK,
   2480  1.1  thorpej 		    ("%s: LINK: checklink -> up %s\n", sc->sc_dev.dv_xname,
   2481  1.1  thorpej 		    (status & STATUS_FD) ? "FDX" : "HDX"));
   2482  1.1  thorpej 		sc->sc_tctl &= ~TCTL_COLD(0x3ff);
   2483  1.1  thorpej 		if (status & STATUS_FD)
   2484  1.1  thorpej 			sc->sc_tctl |=
   2485  1.1  thorpej 			    TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
   2486  1.1  thorpej 		else
   2487  1.1  thorpej 			sc->sc_tctl |=
   2488  1.1  thorpej 			    TCTL_COLD(TX_COLLISION_DISTANCE_HDX);
   2489  1.1  thorpej 		CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
   2490  1.1  thorpej 		sc->sc_tbi_linkup = 1;
   2491  1.1  thorpej 	}
   2492  1.1  thorpej 
   2493  1.1  thorpej 	wm_tbi_set_linkled(sc);
   2494  1.1  thorpej }
   2495  1.1  thorpej 
   2496  1.1  thorpej /*
   2497  1.1  thorpej  * wm_gmii_reset:
   2498  1.1  thorpej  *
   2499  1.1  thorpej  *	Reset the PHY.
   2500  1.1  thorpej  */
   2501  1.1  thorpej void
   2502  1.1  thorpej wm_gmii_reset(struct wm_softc *sc)
   2503  1.1  thorpej {
   2504  1.1  thorpej 	uint32_t reg;
   2505  1.1  thorpej 
   2506  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA) {
   2507  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET);
   2508  1.1  thorpej 		delay(20000);
   2509  1.1  thorpej 
   2510  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
   2511  1.1  thorpej 		delay(20000);
   2512  1.1  thorpej 	} else {
   2513  1.1  thorpej 		/* The PHY reset pin is active-low. */
   2514  1.1  thorpej 		reg = CSR_READ(sc, WMREG_CTRL_EXT);
   2515  1.1  thorpej 		reg &= ~((CTRL_EXT_SWDPIO_MASK << CTRL_EXT_SWDPIO_SHIFT) |
   2516  1.1  thorpej 		    CTRL_EXT_SWDPIN(4));
   2517  1.1  thorpej 		reg |= CTRL_EXT_SWDPIO(4);
   2518  1.1  thorpej 
   2519  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_SWDPIN(4));
   2520  1.1  thorpej 		delay(10);
   2521  1.1  thorpej 
   2522  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
   2523  1.1  thorpej 		delay(10);
   2524  1.1  thorpej 
   2525  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_SWDPIN(4));
   2526  1.1  thorpej 		delay(10);
   2527  1.1  thorpej #if 0
   2528  1.1  thorpej 		sc->sc_ctrl_ext = reg | CTRL_EXT_SWDPIN(4);
   2529  1.1  thorpej #endif
   2530  1.1  thorpej 	}
   2531  1.1  thorpej }
   2532  1.1  thorpej 
   2533  1.1  thorpej /*
   2534  1.1  thorpej  * wm_gmii_mediainit:
   2535  1.1  thorpej  *
   2536  1.1  thorpej  *	Initialize media for use on 1000BASE-T devices.
   2537  1.1  thorpej  */
   2538  1.1  thorpej void
   2539  1.1  thorpej wm_gmii_mediainit(struct wm_softc *sc)
   2540  1.1  thorpej {
   2541  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   2542  1.1  thorpej 
   2543  1.1  thorpej 	/* We have MII. */
   2544  1.1  thorpej 	sc->sc_flags |= WM_F_HAS_MII;
   2545  1.1  thorpej 
   2546  1.1  thorpej 	sc->sc_tipg = TIPG_1000T_DFLT;
   2547  1.1  thorpej 
   2548  1.1  thorpej 	/*
   2549  1.1  thorpej 	 * Let the chip set speed/duplex on its own based on
   2550  1.1  thorpej 	 * signals from the PHY.
   2551  1.1  thorpej 	 */
   2552  1.1  thorpej 	sc->sc_ctrl |= CTRL_SLU | CTRL_ASDE;
   2553  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
   2554  1.1  thorpej 
   2555  1.1  thorpej 	/* Initialize our media structures and probe the GMII. */
   2556  1.1  thorpej 	sc->sc_mii.mii_ifp = ifp;
   2557  1.1  thorpej 
   2558  1.1  thorpej 	if (sc->sc_type >= WM_T_CORDOVA) {
   2559  1.1  thorpej 		sc->sc_mii.mii_readreg = wm_gmii_cordova_readreg;
   2560  1.1  thorpej 		sc->sc_mii.mii_writereg = wm_gmii_cordova_writereg;
   2561  1.1  thorpej 	} else {
   2562  1.1  thorpej 		sc->sc_mii.mii_readreg = wm_gmii_livengood_readreg;
   2563  1.1  thorpej 		sc->sc_mii.mii_writereg = wm_gmii_livengood_writereg;
   2564  1.1  thorpej 	}
   2565  1.1  thorpej 	sc->sc_mii.mii_statchg = wm_gmii_statchg;
   2566  1.1  thorpej 
   2567  1.1  thorpej 	wm_gmii_reset(sc);
   2568  1.1  thorpej 
   2569  1.1  thorpej 	ifmedia_init(&sc->sc_mii.mii_media, 0, wm_gmii_mediachange,
   2570  1.1  thorpej 	    wm_gmii_mediastatus);
   2571  1.1  thorpej 
   2572  1.1  thorpej 	mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
   2573  1.1  thorpej 	    MII_OFFSET_ANY, 0);
   2574  1.1  thorpej 	if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
   2575  1.1  thorpej 		ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
   2576  1.1  thorpej 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
   2577  1.1  thorpej 	} else
   2578  1.1  thorpej 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
   2579  1.1  thorpej }
   2580  1.1  thorpej 
   2581  1.1  thorpej /*
   2582  1.1  thorpej  * wm_gmii_mediastatus:	[ifmedia interface function]
   2583  1.1  thorpej  *
   2584  1.1  thorpej  *	Get the current interface media status on a 1000BASE-T device.
   2585  1.1  thorpej  */
   2586  1.1  thorpej void
   2587  1.1  thorpej wm_gmii_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
   2588  1.1  thorpej {
   2589  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   2590  1.1  thorpej 
   2591  1.1  thorpej 	mii_pollstat(&sc->sc_mii);
   2592  1.1  thorpej 	ifmr->ifm_status = sc->sc_mii.mii_media_status;
   2593  1.1  thorpej 	ifmr->ifm_active = sc->sc_mii.mii_media_active;
   2594  1.1  thorpej }
   2595  1.1  thorpej 
   2596  1.1  thorpej /*
   2597  1.1  thorpej  * wm_gmii_mediachange:	[ifmedia interface function]
   2598  1.1  thorpej  *
   2599  1.1  thorpej  *	Set hardware to newly-selected media on a 1000BASE-T device.
   2600  1.1  thorpej  */
   2601  1.1  thorpej int
   2602  1.1  thorpej wm_gmii_mediachange(struct ifnet *ifp)
   2603  1.1  thorpej {
   2604  1.1  thorpej 	struct wm_softc *sc = ifp->if_softc;
   2605  1.1  thorpej 
   2606  1.1  thorpej 	if (ifp->if_flags & IFF_UP)
   2607  1.1  thorpej 		mii_mediachg(&sc->sc_mii);
   2608  1.1  thorpej 	return (0);
   2609  1.1  thorpej }
   2610  1.1  thorpej 
   2611  1.1  thorpej #define	MDI_IO		CTRL_SWDPIN(2)
   2612  1.1  thorpej #define	MDI_DIR		CTRL_SWDPIO(2)	/* host -> PHY */
   2613  1.1  thorpej #define	MDI_CLK		CTRL_SWDPIN(3)
   2614  1.1  thorpej 
   2615  1.1  thorpej static void
   2616  1.1  thorpej livengood_mii_sendbits(struct wm_softc *sc, uint32_t data, int nbits)
   2617  1.1  thorpej {
   2618  1.1  thorpej 	uint32_t i, v;
   2619  1.1  thorpej 
   2620  1.1  thorpej 	v = CSR_READ(sc, WMREG_CTRL);
   2621  1.1  thorpej 	v &= ~(MDI_IO|MDI_CLK|(CTRL_SWDPIO_MASK << CTRL_SWDPIO_SHIFT));
   2622  1.1  thorpej 	v |= MDI_DIR | CTRL_SWDPIO(3);
   2623  1.1  thorpej 
   2624  1.1  thorpej 	for (i = 1 << (nbits - 1); i != 0; i >>= 1) {
   2625  1.1  thorpej 		if (data & i)
   2626  1.1  thorpej 			v |= MDI_IO;
   2627  1.1  thorpej 		else
   2628  1.1  thorpej 			v &= ~MDI_IO;
   2629  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, v);
   2630  1.1  thorpej 		delay(10);
   2631  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
   2632  1.1  thorpej 		delay(10);
   2633  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, v);
   2634  1.1  thorpej 		delay(10);
   2635  1.1  thorpej 	}
   2636  1.1  thorpej }
   2637  1.1  thorpej 
   2638  1.1  thorpej static uint32_t
   2639  1.1  thorpej livengood_mii_recvbits(struct wm_softc *sc)
   2640  1.1  thorpej {
   2641  1.1  thorpej 	uint32_t v, i, data = 0;
   2642  1.1  thorpej 
   2643  1.1  thorpej 	v = CSR_READ(sc, WMREG_CTRL);
   2644  1.1  thorpej 	v &= ~(MDI_IO|MDI_CLK|(CTRL_SWDPIO_MASK << CTRL_SWDPIO_SHIFT));
   2645  1.1  thorpej 	v |= CTRL_SWDPIO(3);
   2646  1.1  thorpej 
   2647  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, v);
   2648  1.1  thorpej 	delay(10);
   2649  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
   2650  1.1  thorpej 	delay(10);
   2651  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, v);
   2652  1.1  thorpej 	delay(10);
   2653  1.1  thorpej 
   2654  1.1  thorpej 	for (i = 0; i < 16; i++) {
   2655  1.1  thorpej 		data <<= 1;
   2656  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
   2657  1.1  thorpej 		delay(10);
   2658  1.1  thorpej 		if (CSR_READ(sc, WMREG_CTRL) & MDI_IO)
   2659  1.1  thorpej 			data |= 1;
   2660  1.1  thorpej 		CSR_WRITE(sc, WMREG_CTRL, v);
   2661  1.1  thorpej 		delay(10);
   2662  1.1  thorpej 	}
   2663  1.1  thorpej 
   2664  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, v | MDI_CLK);
   2665  1.1  thorpej 	delay(10);
   2666  1.1  thorpej 	CSR_WRITE(sc, WMREG_CTRL, v);
   2667  1.1  thorpej 	delay(10);
   2668  1.1  thorpej 
   2669  1.1  thorpej 	return (data);
   2670  1.1  thorpej }
   2671  1.1  thorpej 
   2672  1.1  thorpej #undef MDI_IO
   2673  1.1  thorpej #undef MDI_DIR
   2674  1.1  thorpej #undef MDI_CLK
   2675  1.1  thorpej 
   2676  1.1  thorpej /*
   2677  1.1  thorpej  * wm_gmii_livengood_readreg:	[mii interface function]
   2678  1.1  thorpej  *
   2679  1.1  thorpej  *	Read a PHY register on the GMII (Livengood version).
   2680  1.1  thorpej  */
   2681  1.1  thorpej int
   2682  1.1  thorpej wm_gmii_livengood_readreg(struct device *self, int phy, int reg)
   2683  1.1  thorpej {
   2684  1.1  thorpej 	struct wm_softc *sc = (void *) self;
   2685  1.1  thorpej 	int rv;
   2686  1.1  thorpej 
   2687  1.1  thorpej 	livengood_mii_sendbits(sc, 0xffffffffU, 32);
   2688  1.1  thorpej 	livengood_mii_sendbits(sc, reg | (phy << 5) |
   2689  1.1  thorpej 	    (MII_COMMAND_READ << 10) | (MII_COMMAND_START << 12), 14);
   2690  1.1  thorpej 	rv = livengood_mii_recvbits(sc) & 0xffff;
   2691  1.1  thorpej 
   2692  1.1  thorpej 	DPRINTF(WM_DEBUG_GMII,
   2693  1.1  thorpej 	    ("%s: GMII: read phy %d reg %d -> 0x%04x\n",
   2694  1.1  thorpej 	    sc->sc_dev.dv_xname, phy, reg, rv));
   2695  1.1  thorpej 
   2696  1.1  thorpej 	return (rv);
   2697  1.1  thorpej }
   2698  1.1  thorpej 
   2699  1.1  thorpej /*
   2700  1.1  thorpej  * wm_gmii_livengood_writereg:	[mii interface function]
   2701  1.1  thorpej  *
   2702  1.1  thorpej  *	Write a PHY register on the GMII (Livengood version).
   2703  1.1  thorpej  */
   2704  1.1  thorpej void
   2705  1.1  thorpej wm_gmii_livengood_writereg(struct device *self, int phy, int reg, int val)
   2706  1.1  thorpej {
   2707  1.1  thorpej 	struct wm_softc *sc = (void *) self;
   2708  1.1  thorpej 
   2709  1.1  thorpej 	livengood_mii_sendbits(sc, 0xffffffffU, 32);
   2710  1.1  thorpej 	livengood_mii_sendbits(sc, val | (MII_COMMAND_ACK << 16) |
   2711  1.1  thorpej 	    (reg << 18) | (phy << 23) | (MII_COMMAND_WRITE << 28) |
   2712  1.1  thorpej 	    (MII_COMMAND_START << 30), 32);
   2713  1.1  thorpej }
   2714  1.1  thorpej 
   2715  1.1  thorpej /*
   2716  1.1  thorpej  * wm_gmii_cordova_readreg:	[mii interface function]
   2717  1.1  thorpej  *
   2718  1.1  thorpej  *	Read a PHY register on the GMII.
   2719  1.1  thorpej  */
   2720  1.1  thorpej int
   2721  1.1  thorpej wm_gmii_cordova_readreg(struct device *self, int phy, int reg)
   2722  1.1  thorpej {
   2723  1.1  thorpej 	struct wm_softc *sc = (void *) self;
   2724  1.1  thorpej 	uint32_t mdic;
   2725  1.1  thorpej 	int i, rv;
   2726  1.1  thorpej 
   2727  1.1  thorpej 	CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_READ | MDIC_PHYADD(phy) |
   2728  1.1  thorpej 	    MDIC_REGADD(reg));
   2729  1.1  thorpej 
   2730  1.1  thorpej 	for (i = 0; i < 100; i++) {
   2731  1.1  thorpej 		mdic = CSR_READ(sc, WMREG_MDIC);
   2732  1.1  thorpej 		if (mdic & MDIC_READY)
   2733  1.1  thorpej 			break;
   2734  1.1  thorpej 		delay(10);
   2735  1.1  thorpej 	}
   2736  1.1  thorpej 
   2737  1.1  thorpej 	if ((mdic & MDIC_READY) == 0) {
   2738  1.1  thorpej 		printf("%s: MDIC read timed out: phy %d reg %d\n",
   2739  1.1  thorpej 		    sc->sc_dev.dv_xname, phy, reg);
   2740  1.1  thorpej 		rv = 0;
   2741  1.1  thorpej 	} else if (mdic & MDIC_E) {
   2742  1.1  thorpej #if 0 /* This is normal if no PHY is present. */
   2743  1.1  thorpej 		printf("%s: MDIC read error: phy %d reg %d\n",
   2744  1.1  thorpej 		    sc->sc_dev.dv_xname, phy, reg);
   2745  1.1  thorpej #endif
   2746  1.1  thorpej 		rv = 0;
   2747  1.1  thorpej 	} else {
   2748  1.1  thorpej 		rv = MDIC_DATA(mdic);
   2749  1.1  thorpej 		if (rv == 0xffff)
   2750  1.1  thorpej 			rv = 0;
   2751  1.1  thorpej 	}
   2752  1.1  thorpej 
   2753  1.1  thorpej 	return (rv);
   2754  1.1  thorpej }
   2755  1.1  thorpej 
   2756  1.1  thorpej /*
   2757  1.1  thorpej  * wm_gmii_cordova_writereg:	[mii interface function]
   2758  1.1  thorpej  *
   2759  1.1  thorpej  *	Write a PHY register on the GMII.
   2760  1.1  thorpej  */
   2761  1.1  thorpej void
   2762  1.1  thorpej wm_gmii_cordova_writereg(struct device *self, int phy, int reg, int val)
   2763  1.1  thorpej {
   2764  1.1  thorpej 	struct wm_softc *sc = (void *) self;
   2765  1.1  thorpej 	uint32_t mdic;
   2766  1.1  thorpej 	int i;
   2767  1.1  thorpej 
   2768  1.1  thorpej 	CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_WRITE | MDIC_PHYADD(phy) |
   2769  1.1  thorpej 	    MDIC_REGADD(reg) | MDIC_DATA(val));
   2770  1.1  thorpej 
   2771  1.1  thorpej 	for (i = 0; i < 100; i++) {
   2772  1.1  thorpej 		mdic = CSR_READ(sc, WMREG_MDIC);
   2773  1.1  thorpej 		if (mdic & MDIC_READY)
   2774  1.1  thorpej 			break;
   2775  1.1  thorpej 		delay(10);
   2776  1.1  thorpej 	}
   2777  1.1  thorpej 
   2778  1.1  thorpej 	if ((mdic & MDIC_READY) == 0)
   2779  1.1  thorpej 		printf("%s: MDIC write timed out: phy %d reg %d\n",
   2780  1.1  thorpej 		    sc->sc_dev.dv_xname, phy, reg);
   2781  1.1  thorpej 	else if (mdic & MDIC_E)
   2782  1.1  thorpej 		printf("%s: MDIC write error: phy %d reg %d\n",
   2783  1.1  thorpej 		    sc->sc_dev.dv_xname, phy, reg);
   2784  1.1  thorpej }
   2785  1.1  thorpej 
   2786  1.1  thorpej /*
   2787  1.1  thorpej  * wm_gmii_statchg:	[mii interface function]
   2788  1.1  thorpej  *
   2789  1.1  thorpej  *	Callback from MII layer when media changes.
   2790  1.1  thorpej  */
   2791  1.1  thorpej void
   2792  1.1  thorpej wm_gmii_statchg(struct device *self)
   2793  1.1  thorpej {
   2794  1.1  thorpej 	struct wm_softc *sc = (void *) self;
   2795  1.1  thorpej 
   2796  1.1  thorpej 	sc->sc_tctl &= ~TCTL_COLD(0x3ff);
   2797  1.1  thorpej 
   2798  1.1  thorpej 	if (sc->sc_mii.mii_media_active & IFM_FDX) {
   2799  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK,
   2800  1.1  thorpej 		    ("%s: LINK: statchg: FDX\n", sc->sc_dev.dv_xname));
   2801  1.1  thorpej 		sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
   2802  1.1  thorpej 	} else  {
   2803  1.1  thorpej 		DPRINTF(WM_DEBUG_LINK,
   2804  1.1  thorpej 		    ("%s: LINK: statchg: HDX\n", sc->sc_dev.dv_xname));
   2805  1.1  thorpej 		sc->sc_tctl |= TCTL_COLD(TX_COLLISION_DISTANCE_HDX);
   2806  1.1  thorpej 	}
   2807  1.1  thorpej 
   2808  1.1  thorpej 	CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
   2809  1.1  thorpej }
   2810