if_cas.c revision 210334
167754Smsmith/*-
267754Smsmith * Copyright (C) 2001 Eduardo Horvath.
367754Smsmith * Copyright (c) 2001-2003 Thomas Moestl
467754Smsmith * Copyright (c) 2007-2009 Marius Strobl <marius@FreeBSD.org>
567754Smsmith * All rights reserved.
667754Smsmith *
7217365Sjkim * Redistribution and use in source and binary forms, with or without
8245582Sjkim * modification, are permitted provided that the following conditions
970243Smsmith * are met:
1067754Smsmith * 1. Redistributions of source code must retain the above copyright
11217365Sjkim *    notice, this list of conditions and the following disclaimer.
12217365Sjkim * 2. Redistributions in binary form must reproduce the above copyright
13217365Sjkim *    notice, this list of conditions and the following disclaimer in the
14217365Sjkim *    documentation and/or other materials provided with the distribution.
15217365Sjkim *
16217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
17217365Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18217365Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19217365Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
20217365Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24217365Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2567754Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26217365Sjkim * SUCH DAMAGE.
27217365Sjkim *
28217365Sjkim *	from: NetBSD: gem.c,v 1.21 2002/06/01 23:50:58 lukem Exp
2967754Smsmith *	from: FreeBSD: if_gem.c 182060 2008-08-23 15:03:26Z marius
30217365Sjkim */
31217365Sjkim
32217365Sjkim#include <sys/cdefs.h>
33217365Sjkim__FBSDID("$FreeBSD: head/sys/dev/cas/if_cas.c 210334 2010-07-21 10:05:07Z attilio $");
34217365Sjkim
35217365Sjkim/*
36217365Sjkim * driver for Sun Cassini/Cassini+ and National Semiconductor DP83065
37217365Sjkim * Saturn Gigabit Ethernet controllers
38217365Sjkim */
39217365Sjkim
40217365Sjkim#if 0
41217365Sjkim#define	CAS_DEBUG
42217365Sjkim#endif
4367754Smsmith
4467754Smsmith#include <sys/param.h>
4567754Smsmith#include <sys/systm.h>
4667754Smsmith#include <sys/bus.h>
47167802Sjkim#include <sys/callout.h>
4867754Smsmith#include <sys/endian.h>
49167802Sjkim#include <sys/mbuf.h>
50167802Sjkim#include <sys/malloc.h>
51167802Sjkim#include <sys/kernel.h>
52167802Sjkim#include <sys/lock.h>
53167802Sjkim#include <sys/module.h>
54167802Sjkim#include <sys/mutex.h>
55167802Sjkim#include <sys/refcount.h>
56167802Sjkim#include <sys/resource.h>
5799679Siwasaki#include <sys/rman.h>
58167802Sjkim#include <sys/socket.h>
5999679Siwasaki#include <sys/sockio.h>
6067754Smsmith#include <sys/taskqueue.h>
6199679Siwasaki
62117521Snjl#include <net/bpf.h>
63117521Snjl#include <net/ethernet.h>
64117521Snjl#include <net/if.h>
6599679Siwasaki#include <net/if_arp.h>
66117521Snjl#include <net/if_dl.h>
67117521Snjl#include <net/if_media.h>
68117521Snjl#include <net/if_types.h>
69117521Snjl#include <net/if_vlan_var.h>
7099679Siwasaki
7199679Siwasaki#include <netinet/in.h>
7299679Siwasaki#include <netinet/in_systm.h>
73114237Snjl#include <netinet/ip.h>
74167802Sjkim#include <netinet/tcp.h>
75167802Sjkim#include <netinet/udp.h>
76167802Sjkim
77167802Sjkim#include <machine/bus.h>
78167802Sjkim#if defined(__powerpc__) || defined(__sparc64__)
79167802Sjkim#include <dev/ofw/ofw_bus.h>
80167802Sjkim#include <dev/ofw/openfirm.h>
81167802Sjkim#include <machine/ofw_machdep.h>
82167802Sjkim#endif
83167802Sjkim#include <machine/resource.h>
84167802Sjkim
85167802Sjkim#include <dev/mii/mii.h>
86167802Sjkim#include <dev/mii/miivar.h>
87167802Sjkim
88167802Sjkim#include <dev/cas/if_casreg.h>
89167802Sjkim#include <dev/cas/if_casvar.h>
90167802Sjkim
91167802Sjkim#include <dev/pci/pcireg.h>
92167802Sjkim#include <dev/pci/pcivar.h>
93167802Sjkim
94167802Sjkim#include "miibus_if.h"
95167802Sjkim
96167802Sjkim#define RINGASSERT(n , min, max)					\
97167802Sjkim	CTASSERT(powerof2(n) && (n) >= (min) && (n) <= (max))
98167802Sjkim
99167802SjkimRINGASSERT(CAS_NRXCOMP, 128, 32768);
100167802SjkimRINGASSERT(CAS_NRXDESC, 32, 8192);
101167802SjkimRINGASSERT(CAS_NRXDESC2, 32, 8192);
102167802SjkimRINGASSERT(CAS_NTXDESC, 32, 8192);
103167802Sjkim
104167802Sjkim#undef RINGASSERT
105167802Sjkim
106167802Sjkim#define	CCDASSERT(m, a)							\
107167802Sjkim	CTASSERT((offsetof(struct cas_control_data, m) & ((a) - 1)) == 0)
108167802Sjkim
109167802SjkimCCDASSERT(ccd_rxcomps, CAS_RX_COMP_ALIGN);
110167802SjkimCCDASSERT(ccd_rxdescs, CAS_RX_DESC_ALIGN);
111167802SjkimCCDASSERT(ccd_rxdescs2, CAS_RX_DESC_ALIGN);
112167802Sjkim
113167802Sjkim#undef CCDASSERT
114193267Sjkim
115193267Sjkim#define	CAS_TRIES	10000
116167802Sjkim
117167802Sjkim/*
118167802Sjkim * According to documentation, the hardware has support for basic TCP
119114237Snjl * checksum offloading only, in practice this can be also used for UDP
12099679Siwasaki * however (i.e. the problem of previous Sun NICs that a checksum of 0x0
121167802Sjkim * is not converted to 0xffff no longer exists).
122167802Sjkim */
123167802Sjkim#define	CAS_CSUM_FEATURES	(CSUM_TCP | CSUM_UDP)
124167802Sjkim
125167802Sjkimstatic inline void cas_add_rxdesc(struct cas_softc *sc, u_int idx);
126114237Snjlstatic int	cas_attach(struct cas_softc *sc);
127167802Sjkimstatic int	cas_bitwait(struct cas_softc *sc, bus_addr_t r, uint32_t clr,
128167802Sjkim		    uint32_t set);
129167802Sjkimstatic void	cas_cddma_callback(void *xsc, bus_dma_segment_t *segs,
130167802Sjkim		    int nsegs, int error);
131167802Sjkimstatic void	cas_detach(struct cas_softc *sc);
132114237Snjlstatic int	cas_disable_rx(struct cas_softc *sc);
133167802Sjkimstatic int	cas_disable_tx(struct cas_softc *sc);
134167802Sjkimstatic void	cas_eint(struct cas_softc *sc, u_int status);
135212761Sjkimstatic void	cas_free(void *arg1, void* arg2);
136212761Sjkimstatic void	cas_init(void *xsc);
137212761Sjkimstatic void	cas_init_locked(struct cas_softc *sc);
138212761Sjkimstatic void	cas_init_regs(struct cas_softc *sc);
139212761Sjkimstatic int	cas_intr(void *v);
140212761Sjkimstatic void	cas_intr_task(void *arg, int pending __unused);
141212761Sjkimstatic int	cas_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
142212761Sjkimstatic int	cas_load_txmbuf(struct cas_softc *sc, struct mbuf **m_head);
143212761Sjkimstatic int	cas_mediachange(struct ifnet *ifp);
144167802Sjkimstatic void	cas_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr);
145212761Sjkimstatic void	cas_meminit(struct cas_softc *sc);
146167802Sjkimstatic void	cas_mifinit(struct cas_softc *sc);
14767754Smsmithstatic int	cas_mii_readreg(device_t dev, int phy, int reg);
148167802Sjkimstatic void	cas_mii_statchg(device_t dev);
149167802Sjkimstatic int	cas_mii_writereg(device_t dev, int phy, int reg, int val);
150167802Sjkimstatic void	cas_reset(struct cas_softc *sc);
15167754Smsmithstatic int	cas_reset_rx(struct cas_softc *sc);
15299679Siwasakistatic int	cas_reset_tx(struct cas_softc *sc);
153114237Snjlstatic void	cas_resume(struct cas_softc *sc);
154167802Sjkimstatic u_int	cas_descsize(u_int sz);
155114237Snjlstatic void	cas_rint(struct cas_softc *sc);
156167802Sjkimstatic void	cas_rint_timeout(void *arg);
15767754Smsmithstatic inline void cas_rxcksum(struct mbuf *m, uint16_t cksum);
15867754Smsmithstatic inline void cas_rxcompinit(struct cas_rx_comp *rxcomp);
159114237Snjlstatic u_int	cas_rxcompsize(u_int sz);
16067754Smsmithstatic void	cas_rxdma_callback(void *xsc, bus_dma_segment_t *segs,
161167802Sjkim		    int nsegs, int error);
162114237Snjlstatic void	cas_setladrf(struct cas_softc *sc);
163193267Sjkimstatic void	cas_start(struct ifnet *ifp);
16467754Smsmithstatic void	cas_stop(struct ifnet *ifp);
16569450Smsmithstatic void	cas_suspend(struct cas_softc *sc);
16667754Smsmithstatic void	cas_tick(void *arg);
16799679Siwasakistatic void	cas_tint(struct cas_softc *sc);
16899679Siwasakistatic void	cas_tx_task(void *arg, int pending __unused);
169167802Sjkimstatic inline void cas_txkick(struct cas_softc *sc);
170167802Sjkimstatic void	cas_watchdog(struct cas_softc *sc);
171151937Sjkim
172151937Sjkimstatic devclass_t cas_devclass;
173151937Sjkim
174151937SjkimMODULE_DEPEND(cas, ether, 1, 1, 1);
175151937SjkimMODULE_DEPEND(cas, miibus, 1, 1, 1);
176151937Sjkim
177167802Sjkim#ifdef CAS_DEBUG
178151937Sjkim#include <sys/ktr.h>
179151937Sjkim#define	KTR_CAS		KTR_SPARE2
180151937Sjkim#endif
181151937Sjkim
182151937Sjkimstatic int
18367754Smsmithcas_attach(struct cas_softc *sc)
184107325Siwasaki{
185167802Sjkim	struct cas_txsoft *txs;
186167802Sjkim	struct ifnet *ifp;
187167802Sjkim	int error, i;
188167802Sjkim	uint32_t v;
189167802Sjkim
190114237Snjl	/* Set up ifnet structure. */
19199679Siwasaki	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
192107325Siwasaki	if (ifp == NULL)
193167802Sjkim		return (ENOSPC);
194114237Snjl	ifp->if_softc = sc;
195167802Sjkim	if_initname(ifp, device_get_name(sc->sc_dev),
19667754Smsmith	    device_get_unit(sc->sc_dev));
19767754Smsmith	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
198114237Snjl	ifp->if_start = cas_start;
19967754Smsmith	ifp->if_ioctl = cas_ioctl;
200167802Sjkim	ifp->if_init = cas_init;
201114237Snjl	IFQ_SET_MAXLEN(&ifp->if_snd, CAS_TXQUEUELEN);
202193267Sjkim	ifp->if_snd.ifq_drv_maxlen = CAS_TXQUEUELEN;
20367754Smsmith	IFQ_SET_READY(&ifp->if_snd);
204167802Sjkim
20567754Smsmith	callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0);
20699679Siwasaki	callout_init(&sc->sc_rx_ch, 1);
20799679Siwasaki	/* Create local taskq. */
20899679Siwasaki	TASK_INIT(&sc->sc_intr_task, 0, cas_intr_task, sc);
20999679Siwasaki	TASK_INIT(&sc->sc_tx_task, 1, cas_tx_task, ifp);
210167802Sjkim	sc->sc_tq = taskqueue_create_fast("cas_taskq", M_WAITOK,
211167802Sjkim	    taskqueue_thread_enqueue, &sc->sc_tq);
212167802Sjkim	if (sc->sc_tq == NULL) {
21399679Siwasaki		device_printf(sc->sc_dev, "could not create taskqueue\n");
21467754Smsmith		error = ENXIO;
21567754Smsmith		goto fail_ifnet;
21667754Smsmith	}
217167802Sjkim	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
218167802Sjkim	    device_get_nameunit(sc->sc_dev));
219193267Sjkim
220167802Sjkim	/* Make sure the chip is stopped. */
221167802Sjkim	cas_reset(sc);
222193267Sjkim
223167802Sjkim	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
224167802Sjkim	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
22599146Siwasaki	    BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE, 0, NULL, NULL,
226167802Sjkim	    &sc->sc_pdmatag);
227100966Siwasaki	if (error != 0)
228167802Sjkim		goto fail_taskq;
229193267Sjkim
230167802Sjkim	error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0,
231167802Sjkim	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
232167802Sjkim	    CAS_PAGE_SIZE, 1, CAS_PAGE_SIZE, 0, NULL, NULL, &sc->sc_rdmatag);
233167802Sjkim	if (error != 0)
234151937Sjkim		goto fail_ptag;
235193267Sjkim
236151937Sjkim	error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0,
237193267Sjkim	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
238193267Sjkim	    MCLBYTES * CAS_NTXSEGS, CAS_NTXSEGS, MCLBYTES,
239151937Sjkim	    BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag);
240193267Sjkim	if (error != 0)
241100966Siwasaki		goto fail_rtag;
242193267Sjkim
243193267Sjkim	error = bus_dma_tag_create(sc->sc_pdmatag, CAS_TX_DESC_ALIGN, 0,
244193267Sjkim	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
245193267Sjkim	    sizeof(struct cas_control_data), 1,
246193267Sjkim	    sizeof(struct cas_control_data), 0,
247193267Sjkim	    NULL, NULL, &sc->sc_cdmatag);
248193267Sjkim	if (error != 0)
249193267Sjkim		goto fail_ttag;
250193267Sjkim
251193267Sjkim	/*
252193267Sjkim	 * Allocate the control data structures, create and load the
253193267Sjkim	 * DMA map for it.
254193267Sjkim	 */
255193267Sjkim	if ((error = bus_dmamem_alloc(sc->sc_cdmatag,
256193267Sjkim	    (void **)&sc->sc_control_data,
257193267Sjkim	    BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
258193267Sjkim	    &sc->sc_cddmamap)) != 0) {
259193267Sjkim		device_printf(sc->sc_dev,
260193267Sjkim		    "unable to allocate control data, error = %d\n", error);
261193267Sjkim		goto fail_ctag;
262193267Sjkim	}
263193267Sjkim
264193267Sjkim	sc->sc_cddma = 0;
265193267Sjkim	if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap,
266193267Sjkim	    sc->sc_control_data, sizeof(struct cas_control_data),
267193267Sjkim	    cas_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) {
268193267Sjkim		device_printf(sc->sc_dev,
269193267Sjkim		    "unable to load control data DMA map, error = %d\n",
270193267Sjkim		    error);
271193267Sjkim		goto fail_cmem;
272193267Sjkim	}
273193267Sjkim
274193267Sjkim	/*
275193267Sjkim	 * Initialize the transmit job descriptors.
276193267Sjkim	 */
277193267Sjkim	STAILQ_INIT(&sc->sc_txfreeq);
278193267Sjkim	STAILQ_INIT(&sc->sc_txdirtyq);
279193267Sjkim
280193267Sjkim	/*
281167802Sjkim	 * Create the transmit buffer DMA maps.
282167802Sjkim	 */
283167802Sjkim	error = ENOMEM;
284167802Sjkim	for (i = 0; i < CAS_TXQUEUELEN; i++) {
285167802Sjkim		txs = &sc->sc_txsoft[i];
286167802Sjkim		txs->txs_mbuf = NULL;
28799146Siwasaki		txs->txs_ndescs = 0;
288167802Sjkim		if ((error = bus_dmamap_create(sc->sc_tdmatag, 0,
289167802Sjkim		    &txs->txs_dmamap)) != 0) {
29067754Smsmith			device_printf(sc->sc_dev,
291167802Sjkim			    "unable to create TX DMA map %d, error = %d\n",
292167802Sjkim			    i, error);
293167802Sjkim			goto fail_txd;
294167802Sjkim		}
295167802Sjkim		STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
296167802Sjkim	}
297167802Sjkim
298245582Sjkim	/*
299167802Sjkim	 * Allocate the receive buffers, create and load the DMA maps
300167802Sjkim	 * for them.
301167802Sjkim	 */
302167802Sjkim	for (i = 0; i < CAS_NRXDESC; i++) {
303167802Sjkim		if ((error = bus_dmamem_alloc(sc->sc_rdmatag,
304167802Sjkim		    &sc->sc_rxdsoft[i].rxds_buf, BUS_DMA_WAITOK,
305167802Sjkim		    &sc->sc_rxdsoft[i].rxds_dmamap)) != 0) {
306167802Sjkim			device_printf(sc->sc_dev,
307167802Sjkim			    "unable to allocate RX buffer %d, error = %d\n",
308167802Sjkim			    i, error);
309167802Sjkim			goto fail_rxmem;
310167802Sjkim		}
311167802Sjkim
312167802Sjkim		sc->sc_rxdptr = i;
313250838Sjkim		sc->sc_rxdsoft[i].rxds_paddr = 0;
314250838Sjkim		if ((error = bus_dmamap_load(sc->sc_rdmatag,
315250838Sjkim		    sc->sc_rxdsoft[i].rxds_dmamap, sc->sc_rxdsoft[i].rxds_buf,
316250838Sjkim		    CAS_PAGE_SIZE, cas_rxdma_callback, sc, 0)) != 0 ||
317250838Sjkim		    sc->sc_rxdsoft[i].rxds_paddr == 0) {
318250838Sjkim			device_printf(sc->sc_dev,
319250838Sjkim			    "unable to load RX DMA map %d, error = %d\n",
320167802Sjkim			    i, error);
321250838Sjkim			goto fail_rxmap;
322193267Sjkim		}
323193267Sjkim	}
324193267Sjkim
325193267Sjkim	if ((sc->sc_flags & CAS_SERDES) == 0) {
326193267Sjkim		CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII);
327193267Sjkim		CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4,
328193267Sjkim		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
329193267Sjkim		cas_mifinit(sc);
330193267Sjkim		/*
331193267Sjkim		 * Look for an external PHY.
332193267Sjkim		 */
333193267Sjkim		error = ENXIO;
334193267Sjkim		v = CAS_READ_4(sc, CAS_MIF_CONF);
335193267Sjkim		if ((v & CAS_MIF_CONF_MDI1) != 0) {
336193267Sjkim			v |= CAS_MIF_CONF_PHY_SELECT;
337193267Sjkim			CAS_WRITE_4(sc, CAS_MIF_CONF, v);
338193267Sjkim			CAS_BARRIER(sc, CAS_MIF_CONF, 4,
339193267Sjkim			    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
340193267Sjkim			/* Enable/unfreeze the GMII pins of Saturn. */
341193267Sjkim			if (sc->sc_variant == CAS_SATURN) {
342193267Sjkim				CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0);
343193267Sjkim				CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
344193267Sjkim				    BUS_SPACE_BARRIER_READ |
345193267Sjkim				    BUS_SPACE_BARRIER_WRITE);
346193267Sjkim			}
347193267Sjkim			switch (sc->sc_variant) {
348193267Sjkim			default:
349193267Sjkim				sc->sc_phyad = -1;
350193267Sjkim				break;
351193267Sjkim			}
352193267Sjkim			error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
353193267Sjkim			    cas_mediachange, cas_mediastatus);
354193267Sjkim		}
355193267Sjkim		/*
356193267Sjkim		 * Fall back on an internal PHY if no external PHY was found.
357245582Sjkim		 */
358193267Sjkim		if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) {
359193267Sjkim			v &= ~CAS_MIF_CONF_PHY_SELECT;
360167802Sjkim			CAS_WRITE_4(sc, CAS_MIF_CONF, v);
361167802Sjkim			CAS_BARRIER(sc, CAS_MIF_CONF, 4,
362167802Sjkim			    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
363167802Sjkim			/* Freeze the GMII pins of Saturn for saving power. */
364167802Sjkim			if (sc->sc_variant == CAS_SATURN) {
365167802Sjkim				CAS_WRITE_4(sc, CAS_SATURN_PCFG,
366167802Sjkim				    CAS_SATURN_PCFG_FSI);
367167802Sjkim				CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
36867754Smsmith				    BUS_SPACE_BARRIER_READ |
36967754Smsmith				    BUS_SPACE_BARRIER_WRITE);
37067754Smsmith			}
37167754Smsmith			switch (sc->sc_variant) {
37267754Smsmith			default:
37367754Smsmith				sc->sc_phyad = -1;
37467754Smsmith				break;
37567754Smsmith			}
37667754Smsmith			error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
37767754Smsmith			    cas_mediachange, cas_mediastatus);
37867754Smsmith		}
37967754Smsmith	} else {
38067754Smsmith		/*
38167754Smsmith		 * Use the external PCS SERDES.
38267754Smsmith		 */
38367754Smsmith		CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_SERDES);
384193267Sjkim		CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4, BUS_SPACE_BARRIER_WRITE);
38567754Smsmith		/* Enable/unfreeze the SERDES pins of Saturn. */
38667754Smsmith		if (sc->sc_variant == CAS_SATURN) {
38780062Smsmith			CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0);
388114237Snjl			CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
389167802Sjkim			    BUS_SPACE_BARRIER_WRITE);
39067754Smsmith		}
391193267Sjkim		CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL, CAS_PCS_SERDES_CTRL_ESD);
392245582Sjkim		CAS_BARRIER(sc, CAS_PCS_SERDES_CTRL, 4,
393245582Sjkim		    BUS_SPACE_BARRIER_WRITE);
394245582Sjkim		CAS_WRITE_4(sc, CAS_PCS_CONF, CAS_PCS_CONF_EN);
395245582Sjkim		CAS_BARRIER(sc, CAS_PCS_CONF, 4,
396245582Sjkim		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
397245582Sjkim		sc->sc_phyad = CAS_PHYAD_EXTERNAL;
398245582Sjkim		error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
399245582Sjkim		    cas_mediachange, cas_mediastatus);
400245582Sjkim	}
401245582Sjkim	if (error != 0) {
402245582Sjkim		device_printf(sc->sc_dev, "PHY probe failed: %d\n", error);
403245582Sjkim		goto fail_rxmap;
404245582Sjkim	}
405245582Sjkim	sc->sc_mii = device_get_softc(sc->sc_miibus);
406245582Sjkim
407245582Sjkim	/*
408193267Sjkim	 * From this point forward, the attachment cannot fail.  A failure
409193267Sjkim	 * before this point releases all resources that may have been
410193267Sjkim	 * allocated.
411193267Sjkim	 */
412193267Sjkim
413193267Sjkim	/* Announce FIFO sizes. */
41467754Smsmith	v = CAS_READ_4(sc, CAS_TX_FIFO_SIZE);
415138287Smarks	device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n",
416138287Smarks	    CAS_RX_FIFO_SIZE / 1024, v / 16);
417138287Smarks
418138287Smarks	/* Attach the interface. */
419138287Smarks	ether_ifattach(ifp, sc->sc_enaddr);
42067754Smsmith
42167754Smsmith	/*
42267754Smsmith	 * Tell the upper layer(s) we support long frames/checksum offloads.
42367754Smsmith	 */
424167802Sjkim	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
425193267Sjkim	ifp->if_capabilities = IFCAP_VLAN_MTU;
426193267Sjkim	if ((sc->sc_flags & CAS_NO_CSUM) == 0) {
42767754Smsmith		ifp->if_capabilities |= IFCAP_HWCSUM;
428202771Sjkim		ifp->if_hwassist = CAS_CSUM_FEATURES;
429202771Sjkim	}
430202771Sjkim	ifp->if_capenable = ifp->if_capabilities;
431202771Sjkim
432202771Sjkim	return (0);
433202771Sjkim
434202771Sjkim	/*
435202771Sjkim	 * Free any resources we've allocated during the failed attach
436202771Sjkim	 * attempt.  Do this in reverse order and fall through.
437202771Sjkim	 */
438202771Sjkim fail_rxmap:
439202771Sjkim	for (i = 0; i < CAS_NRXDESC; i++)
44077424Smsmith		if (sc->sc_rxdsoft[i].rxds_paddr != 0)
441202771Sjkim			bus_dmamap_unload(sc->sc_rdmatag,
442193267Sjkim			    sc->sc_rxdsoft[i].rxds_dmamap);
443193267Sjkim fail_rxmem:
444193267Sjkim	for (i = 0; i < CAS_NRXDESC; i++)
445193267Sjkim		if (sc->sc_rxdsoft[i].rxds_buf != NULL)
446193267Sjkim			bus_dmamem_free(sc->sc_rdmatag,
447193267Sjkim			    sc->sc_rxdsoft[i].rxds_buf,
448193267Sjkim			    sc->sc_rxdsoft[i].rxds_dmamap);
449193267Sjkim fail_txd:
450193267Sjkim	for (i = 0; i < CAS_TXQUEUELEN; i++)
451193267Sjkim		if (sc->sc_txsoft[i].txs_dmamap != NULL)
452193267Sjkim			bus_dmamap_destroy(sc->sc_tdmatag,
453193267Sjkim			    sc->sc_txsoft[i].txs_dmamap);
454193267Sjkim	bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap);
455193267Sjkim fail_cmem:
456193267Sjkim	bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data,
457193267Sjkim	    sc->sc_cddmamap);
458193267Sjkim fail_ctag:
459193267Sjkim	bus_dma_tag_destroy(sc->sc_cdmatag);
460193267Sjkim fail_ttag:
461193267Sjkim	bus_dma_tag_destroy(sc->sc_tdmatag);
462193267Sjkim fail_rtag:
463193267Sjkim	bus_dma_tag_destroy(sc->sc_rdmatag);
464193267Sjkim fail_ptag:
465193267Sjkim	bus_dma_tag_destroy(sc->sc_pdmatag);
466193267Sjkim fail_taskq:
467193267Sjkim	taskqueue_free(sc->sc_tq);
468193267Sjkim fail_ifnet:
469193267Sjkim	if_free(ifp);
470193267Sjkim	return (error);
471193267Sjkim}
472193267Sjkim
473193267Sjkimstatic void
474193267Sjkimcas_detach(struct cas_softc *sc)
475193267Sjkim{
476193267Sjkim	struct ifnet *ifp = sc->sc_ifp;
477193267Sjkim	int i;
478193267Sjkim
479193267Sjkim	ether_ifdetach(ifp);
480193267Sjkim	CAS_LOCK(sc);
481241973Sjkim	cas_stop(ifp);
482241973Sjkim	CAS_UNLOCK(sc);
483193267Sjkim	callout_drain(&sc->sc_tick_ch);
484193267Sjkim	callout_drain(&sc->sc_rx_ch);
485241973Sjkim	taskqueue_drain(sc->sc_tq, &sc->sc_intr_task);
486193267Sjkim	taskqueue_drain(sc->sc_tq, &sc->sc_tx_task);
487193267Sjkim	if_free(ifp);
488241973Sjkim	taskqueue_free(sc->sc_tq);
489193267Sjkim	device_delete_child(sc->sc_dev, sc->sc_miibus);
490193267Sjkim
491254745Sjkim	for (i = 0; i < CAS_NRXDESC; i++)
492193267Sjkim		if (sc->sc_rxdsoft[i].rxds_dmamap != NULL)
493254745Sjkim			bus_dmamap_sync(sc->sc_rdmatag,
494254745Sjkim			    sc->sc_rxdsoft[i].rxds_dmamap,
495254745Sjkim			    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
496254745Sjkim	for (i = 0; i < CAS_NRXDESC; i++)
497193267Sjkim		if (sc->sc_rxdsoft[i].rxds_paddr != 0)
498193267Sjkim			bus_dmamap_unload(sc->sc_rdmatag,
499193267Sjkim			    sc->sc_rxdsoft[i].rxds_dmamap);
500193267Sjkim	for (i = 0; i < CAS_NRXDESC; i++)
501193267Sjkim		if (sc->sc_rxdsoft[i].rxds_buf != NULL)
502193267Sjkim			bus_dmamem_free(sc->sc_rdmatag,
50377424Smsmith			    sc->sc_rxdsoft[i].rxds_buf,
50477424Smsmith			    sc->sc_rxdsoft[i].rxds_dmamap);
50577424Smsmith	for (i = 0; i < CAS_TXQUEUELEN; i++)
50667754Smsmith		if (sc->sc_txsoft[i].txs_dmamap != NULL)
50767754Smsmith			bus_dmamap_destroy(sc->sc_tdmatag,
50867754Smsmith			    sc->sc_txsoft[i].txs_dmamap);
50967754Smsmith	CAS_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
51091116Smsmith	bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap);
51191116Smsmith	bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data,
51291116Smsmith	    sc->sc_cddmamap);
51391116Smsmith	bus_dma_tag_destroy(sc->sc_cdmatag);
51467754Smsmith	bus_dma_tag_destroy(sc->sc_tdmatag);
51580062Smsmith	bus_dma_tag_destroy(sc->sc_rdmatag);
51680062Smsmith	bus_dma_tag_destroy(sc->sc_pdmatag);
51780062Smsmith}
518167802Sjkim
519167802Sjkimstatic void
52067754Smsmithcas_suspend(struct cas_softc *sc)
52167754Smsmith{
52278986Smsmith	struct ifnet *ifp = sc->sc_ifp;
52367754Smsmith
52478986Smsmith	CAS_LOCK(sc);
52578986Smsmith	cas_stop(ifp);
52667754Smsmith	CAS_UNLOCK(sc);
52767754Smsmith}
52867754Smsmith
52967754Smsmithstatic void
53067754Smsmithcas_resume(struct cas_softc *sc)
53171867Smsmith{
53267754Smsmith	struct ifnet *ifp = sc->sc_ifp;
53377424Smsmith
53467754Smsmith	CAS_LOCK(sc);
53577424Smsmith	/*
53677424Smsmith	 * On resume all registers have to be initialized again like
53777424Smsmith	 * after power-on.
53877424Smsmith	 */
53977424Smsmith	sc->sc_flags &= ~CAS_INITED;
54077424Smsmith	if (ifp->if_flags & IFF_UP)
54167754Smsmith		cas_init_locked(sc);
54291116Smsmith	CAS_UNLOCK(sc);
54391116Smsmith}
54491116Smsmith
54591116Smsmithstatic inline void
54691116Smsmithcas_rxcksum(struct mbuf *m, uint16_t cksum)
54791116Smsmith{
54891116Smsmith	struct ether_header *eh;
54978986Smsmith	struct ip *ip;
55087031Smsmith	struct udphdr *uh;
55187031Smsmith	uint16_t *opts;
55287031Smsmith	int32_t hlen, len, pktlen;
55387031Smsmith	uint32_t temp32;
55487031Smsmith
55587031Smsmith	pktlen = m->m_pkthdr.len;
55678986Smsmith	if (pktlen < sizeof(struct ether_header) + sizeof(struct ip))
55778986Smsmith		return;
558193267Sjkim	eh = mtod(m, struct ether_header *);
559193267Sjkim	if (eh->ether_type != htons(ETHERTYPE_IP))
560193267Sjkim		return;
561193267Sjkim	ip = (struct ip *)(eh + 1);
562193267Sjkim	if (ip->ip_v != IPVERSION)
563193267Sjkim		return;
564193267Sjkim
565193267Sjkim	hlen = ip->ip_hl << 2;
566193267Sjkim	pktlen -= sizeof(struct ether_header);
567193267Sjkim	if (hlen < sizeof(struct ip))
568193267Sjkim		return;
569193267Sjkim	if (ntohs(ip->ip_len) < hlen)
570231844Sjkim		return;
57177424Smsmith	if (ntohs(ip->ip_len) != pktlen)
572231844Sjkim		return;
573193267Sjkim	if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
57467754Smsmith		return;	/* Cannot handle fragmented packet. */
575193267Sjkim
576107325Siwasaki	switch (ip->ip_p) {
577193267Sjkim	case IPPROTO_TCP:
57891116Smsmith		if (pktlen < (hlen + sizeof(struct tcphdr)))
57967754Smsmith			return;
580128212Snjl		break;
581107325Siwasaki	case IPPROTO_UDP:
58267754Smsmith		if (pktlen < (hlen + sizeof(struct udphdr)))
58367754Smsmith			return;
58467754Smsmith		uh = (struct udphdr *)((uint8_t *)ip + hlen);
58587031Smsmith		if (uh->uh_sum == 0)
58687031Smsmith			return; /* no checksum */
58787031Smsmith		break;
58887031Smsmith	default:
58987031Smsmith		return;
59087031Smsmith	}
59187031Smsmith
59287031Smsmith	cksum = ~cksum;
59387031Smsmith	/* checksum fixup for IP options */
59487031Smsmith	len = hlen - sizeof(struct ip);
59587031Smsmith	if (len > 0) {
59687031Smsmith		opts = (uint16_t *)(ip + 1);
59787031Smsmith		for (; len > 0; len -= sizeof(uint16_t), opts++) {
59887031Smsmith			temp32 = cksum - *opts;
59987031Smsmith			temp32 = (temp32 >> 16) + (temp32 & 65535);
60087031Smsmith			cksum = temp32 & 65535;
60187031Smsmith		}
60267754Smsmith	}
603107325Siwasaki	m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
60467754Smsmith	m->m_pkthdr.csum_data = cksum;
60567754Smsmith}
606114237Snjl
607114237Snjlstatic void
608114237Snjlcas_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
609107325Siwasaki{
610107325Siwasaki	struct cas_softc *sc = xsc;
61167754Smsmith
612107325Siwasaki	if (error != 0)
613107325Siwasaki		return;
614107325Siwasaki	if (nsegs != 1)
615107325Siwasaki		panic("%s: bad control buffer segment count", __func__);
616107325Siwasaki	sc->sc_cddma = segs[0].ds_addr;
617128212Snjl}
618128212Snjl
619128212Snjlstatic void
620128212Snjlcas_rxdma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
621128212Snjl{
622128212Snjl	struct cas_softc *sc = xsc;
62367754Smsmith
624128212Snjl	if (error != 0)
62567754Smsmith		return;
626107325Siwasaki	if (nsegs != 1)
627107325Siwasaki		panic("%s: bad RX buffer segment count", __func__);
628245582Sjkim	sc->sc_rxdsoft[sc->sc_rxdptr].rxds_paddr = segs[0].ds_addr;
629107325Siwasaki}
630128212Snjl
631128212Snjlstatic void
63267754Smsmithcas_tick(void *arg)
633128212Snjl{
63469450Smsmith	struct cas_softc *sc = arg;
635107325Siwasaki	struct ifnet *ifp = sc->sc_ifp;
63667754Smsmith	uint32_t v;
637128212Snjl
63867754Smsmith	CAS_LOCK_ASSERT(sc, MA_OWNED);
63967754Smsmith
640193267Sjkim	/*
641193267Sjkim	 * Unload collision and error counters.
642193267Sjkim	 */
64367754Smsmith	ifp->if_collisions +=
64487031Smsmith	    CAS_READ_4(sc, CAS_MAC_NORM_COLL_CNT) +
64587031Smsmith	    CAS_READ_4(sc, CAS_MAC_FIRST_COLL_CNT);
64687031Smsmith	v = CAS_READ_4(sc, CAS_MAC_EXCESS_COLL_CNT) +
64787031Smsmith	    CAS_READ_4(sc, CAS_MAC_LATE_COLL_CNT);
648107325Siwasaki	ifp->if_collisions += v;
64977424Smsmith	ifp->if_oerrors += v;
65077424Smsmith	ifp->if_ierrors +=
651128212Snjl	    CAS_READ_4(sc, CAS_MAC_RX_LEN_ERR_CNT) +
65267754Smsmith	    CAS_READ_4(sc, CAS_MAC_RX_ALIGN_ERR) +
65367754Smsmith	    CAS_READ_4(sc, CAS_MAC_RX_CRC_ERR_CNT) +
65467754Smsmith	    CAS_READ_4(sc, CAS_MAC_RX_CODE_VIOL);
65567754Smsmith
65667754Smsmith	/*
65767754Smsmith	 * Then clear the hardware counters.
65891116Smsmith	 */
65991116Smsmith	CAS_WRITE_4(sc, CAS_MAC_NORM_COLL_CNT, 0);
66091116Smsmith	CAS_WRITE_4(sc, CAS_MAC_FIRST_COLL_CNT, 0);
66191116Smsmith	CAS_WRITE_4(sc, CAS_MAC_EXCESS_COLL_CNT, 0);
66291116Smsmith	CAS_WRITE_4(sc, CAS_MAC_LATE_COLL_CNT, 0);
66391116Smsmith	CAS_WRITE_4(sc, CAS_MAC_RX_LEN_ERR_CNT, 0);
66491116Smsmith	CAS_WRITE_4(sc, CAS_MAC_RX_ALIGN_ERR, 0);
66567754Smsmith	CAS_WRITE_4(sc, CAS_MAC_RX_CRC_ERR_CNT, 0);
66667754Smsmith	CAS_WRITE_4(sc, CAS_MAC_RX_CODE_VIOL, 0);
667128212Snjl
66867754Smsmith	mii_tick(sc->sc_mii);
66967754Smsmith
67067754Smsmith	if (sc->sc_txfree != CAS_MAXTXFREE)
67167754Smsmith		cas_tint(sc);
67284491Smsmith
67384491Smsmith	cas_watchdog(sc);
67484491Smsmith
67584491Smsmith	callout_reset(&sc->sc_tick_ch, hz, cas_tick, sc);
67684491Smsmith}
67784491Smsmith
67884491Smsmithstatic int
67967754Smsmithcas_bitwait(struct cas_softc *sc, bus_addr_t r, uint32_t clr, uint32_t set)
68067754Smsmith{
68167754Smsmith	int i;
68267754Smsmith	uint32_t reg;
68369450Smsmith
68467754Smsmith	for (i = CAS_TRIES; i--; DELAY(100)) {
68584491Smsmith		reg = CAS_READ_4(sc, r);
68684491Smsmith		if ((reg & clr) == 0 && (reg & set) == set)
68767754Smsmith			return (1);
688209746Sjkim	}
689206117Sjkim	return (0);
690129684Snjl}
691129684Snjl
692209746Sjkimstatic void
693129684Snjlcas_reset(struct cas_softc *sc)
694128212Snjl{
695128212Snjl
696216471Sjkim#ifdef CAS_DEBUG
697216471Sjkim	CTR2(KTR_CAS, "%s: %s", device_get_name(sc->sc_dev), __func__);
698216471Sjkim#endif
699216471Sjkim	/* Disable all interrupts in order to avoid spurious ones. */
700216471Sjkim	CAS_WRITE_4(sc, CAS_INTMASK, 0xffffffff);
701216471Sjkim
702216471Sjkim	cas_reset_rx(sc);
703216471Sjkim	cas_reset_tx(sc);
704128212Snjl
705216471Sjkim	/*
706216471Sjkim	 * Do a full reset modulo the result of the last auto-negotiation
707216471Sjkim	 * when using the SERDES.
708216471Sjkim	 */
709216471Sjkim	CAS_WRITE_4(sc, CAS_RESET, CAS_RESET_RX | CAS_RESET_TX |
710216471Sjkim	    ((sc->sc_flags & CAS_SERDES) != 0 ? CAS_RESET_PCS_DIS : 0));
711216471Sjkim	CAS_BARRIER(sc, CAS_RESET, 4,
712129684Snjl	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
713216471Sjkim	DELAY(3000);
714128212Snjl	if (!cas_bitwait(sc, CAS_RESET, CAS_RESET_RX | CAS_RESET_TX, 0))
715216471Sjkim		device_printf(sc->sc_dev, "cannot reset device\n");
716128212Snjl}
717128212Snjl
718128212Snjlstatic void
719128212Snjlcas_stop(struct ifnet *ifp)
720128212Snjl{
721128212Snjl	struct cas_softc *sc = ifp->if_softc;
722128212Snjl	struct cas_txsoft *txs;
723128212Snjl
72467754Smsmith#ifdef CAS_DEBUG
72567754Smsmith	CTR2(KTR_CAS, "%s: %s", device_get_name(sc->sc_dev), __func__);
726129684Snjl#endif
727129684Snjl
728193267Sjkim	callout_stop(&sc->sc_tick_ch);
729129684Snjl	callout_stop(&sc->sc_rx_ch);
730234623Sjkim
73167754Smsmith	/* Disable all interrupts in order to avoid spurious ones. */
732231844Sjkim	CAS_WRITE_4(sc, CAS_INTMASK, 0xffffffff);
733231844Sjkim
73467754Smsmith	cas_reset_tx(sc);
735234623Sjkim	cas_reset_rx(sc);
736234623Sjkim
73767754Smsmith	/*
738234623Sjkim	 * Release any queued transmit buffers.
73967754Smsmith	 */
74067754Smsmith	while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
74177424Smsmith		STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
74267754Smsmith		if (txs->txs_ndescs != 0) {
74377424Smsmith			bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap,
74477424Smsmith			    BUS_DMASYNC_POSTWRITE);
74577424Smsmith			bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap);
74677424Smsmith			if (txs->txs_mbuf != NULL) {
74777424Smsmith				m_freem(txs->txs_mbuf);
74877424Smsmith				txs->txs_mbuf = NULL;
74977424Smsmith			}
750197104Sjkim		}
751228110Sjkim		STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
752228110Sjkim	}
753235945Sjkim
75467754Smsmith	/*
755235945Sjkim	 * Mark the interface down and cancel the watchdog timer.
75667754Smsmith	 */
75767754Smsmith	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
758220663Sjkim	sc->sc_flags &= ~CAS_LINK;
759220663Sjkim	sc->sc_wdog_timer = 0;
760220663Sjkim}
761220663Sjkim
762220663Sjkimstatic int
763220663Sjkimcas_reset_rx(struct cas_softc *sc)
764220663Sjkim{
765220663Sjkim
766220663Sjkim	/*
767220663Sjkim	 * Resetting while DMA is in progress can cause a bus hang, so we
768220663Sjkim	 * disable DMA first.
769220663Sjkim	 */
770220663Sjkim	cas_disable_rx(sc);
771220663Sjkim	CAS_WRITE_4(sc, CAS_RX_CONF, 0);
772220663Sjkim	CAS_BARRIER(sc, CAS_RX_CONF, 4,
773220663Sjkim	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
77499679Siwasaki	if (!cas_bitwait(sc, CAS_RX_CONF, CAS_RX_CONF_RXDMA_EN, 0))
775193267Sjkim		device_printf(sc->sc_dev, "cannot disable RX DMA\n");
776193267Sjkim
777193267Sjkim	/* Finally, reset the ERX. */
778193267Sjkim	CAS_WRITE_4(sc, CAS_RESET, CAS_RESET_RX |
779193267Sjkim	    ((sc->sc_flags & CAS_SERDES) != 0 ? CAS_RESET_PCS_DIS : 0));
78099679Siwasaki	CAS_BARRIER(sc, CAS_RESET, 4,
781193267Sjkim	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
782193267Sjkim	if (!cas_bitwait(sc, CAS_RESET, CAS_RESET_RX | CAS_RESET_TX, 0)) {
783193267Sjkim		device_printf(sc->sc_dev, "cannot reset receiver\n");
78499679Siwasaki		return (1);
78599679Siwasaki	}
78699679Siwasaki	return (0);
78799679Siwasaki}
78899679Siwasaki
78999679Siwasakistatic int
79099679Siwasakicas_reset_tx(struct cas_softc *sc)
791151937Sjkim{
79299679Siwasaki
793193267Sjkim	/*
794193267Sjkim	 * Resetting while DMA is in progress can cause a bus hang, so we
795151937Sjkim	 * disable DMA first.
796151937Sjkim	 */
797151937Sjkim	cas_disable_tx(sc);
798151937Sjkim	CAS_WRITE_4(sc, CAS_TX_CONF, 0);
799151937Sjkim	CAS_BARRIER(sc, CAS_TX_CONF, 4,
800193267Sjkim	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
80199679Siwasaki	if (!cas_bitwait(sc, CAS_TX_CONF, CAS_TX_CONF_TXDMA_EN, 0))
802193267Sjkim		device_printf(sc->sc_dev, "cannot disable TX DMA\n");
80399679Siwasaki
804193267Sjkim	/* Finally, reset the ETX. */
805193267Sjkim	CAS_WRITE_4(sc, CAS_RESET, CAS_RESET_TX |
806193267Sjkim	    ((sc->sc_flags & CAS_SERDES) != 0 ? CAS_RESET_PCS_DIS : 0));
807193267Sjkim	CAS_BARRIER(sc, CAS_RESET, 4,
808193267Sjkim	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
80999679Siwasaki	if (!cas_bitwait(sc, CAS_RESET, CAS_RESET_RX | CAS_RESET_TX, 0)) {
810193267Sjkim		device_printf(sc->sc_dev, "cannot reset transmitter\n");
811193267Sjkim		return (1);
812193267Sjkim	}
813193267Sjkim	return (0);
814193267Sjkim}
81599679Siwasaki
81699679Siwasakistatic int
817107325Siwasakicas_disable_rx(struct cas_softc *sc)
818193267Sjkim{
819193267Sjkim
820193267Sjkim	CAS_WRITE_4(sc, CAS_MAC_RX_CONF,
821193267Sjkim	    CAS_READ_4(sc, CAS_MAC_RX_CONF) & ~CAS_MAC_RX_CONF_EN);
822193267Sjkim	CAS_BARRIER(sc, CAS_MAC_RX_CONF, 4,
823193267Sjkim	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
824193267Sjkim	return (cas_bitwait(sc, CAS_MAC_RX_CONF, CAS_MAC_RX_CONF_EN, 0));
825193267Sjkim}
826193267Sjkim
827193267Sjkimstatic int
828231844Sjkimcas_disable_tx(struct cas_softc *sc)
829231844Sjkim{
830231844Sjkim
831239340Sjkim	CAS_WRITE_4(sc, CAS_MAC_TX_CONF,
832231844Sjkim	    CAS_READ_4(sc, CAS_MAC_TX_CONF) & ~CAS_MAC_TX_CONF_EN);
833231844Sjkim	CAS_BARRIER(sc, CAS_MAC_TX_CONF, 4,
834231844Sjkim	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
835231844Sjkim	return (cas_bitwait(sc, CAS_MAC_TX_CONF, CAS_MAC_TX_CONF_EN, 0));
836231844Sjkim}
837231844Sjkim
838231844Sjkimstatic inline void
839231844Sjkimcas_rxcompinit(struct cas_rx_comp *rxcomp)
840231844Sjkim{
84199679Siwasaki
84267754Smsmith	rxcomp->crc_word1 = 0;
84367754Smsmith	rxcomp->crc_word2 = 0;
844193267Sjkim	rxcomp->crc_word3 =
845193267Sjkim	    htole64(CAS_SET(ETHER_HDR_LEN + sizeof(struct ip), CAS_RC3_CSO));
846193267Sjkim	rxcomp->crc_word4 = htole64(CAS_RC4_ZERO);
847193267Sjkim}
848193267Sjkim
849114237Snjlstatic void
85067754Smsmithcas_meminit(struct cas_softc *sc)
851167802Sjkim{
85267754Smsmith	int i;
85367754Smsmith
854193267Sjkim	CAS_LOCK_ASSERT(sc, MA_OWNED);
855202771Sjkim
85671867Smsmith	/*
85767754Smsmith	 * Initialize the transmit descriptor ring.
85867754Smsmith	 */
85967754Smsmith	for (i = 0; i < CAS_NTXDESC; i++) {
860193267Sjkim		sc->sc_txdescs[i].cd_flags = 0;
861167802Sjkim		sc->sc_txdescs[i].cd_buf_ptr = 0;
862167802Sjkim	}
86367754Smsmith	sc->sc_txfree = CAS_MAXTXFREE;
86467754Smsmith	sc->sc_txnext = 0;
86567754Smsmith	sc->sc_txwin = 0;
86667754Smsmith
867193267Sjkim	/*
868167802Sjkim	 * Initialize the receive completion ring.
869167802Sjkim	 */
87067754Smsmith	for (i = 0; i < CAS_NRXCOMP; i++)
87167754Smsmith		cas_rxcompinit(&sc->sc_rxcomps[i]);
87267754Smsmith	sc->sc_rxcptr = 0;
87367754Smsmith
874193267Sjkim	/*
875167802Sjkim	 * Initialize the first receive descriptor ring.  We leave
876167802Sjkim	 * the second one zeroed as we don't actually use it.
87767754Smsmith	 */
87867754Smsmith	for (i = 0; i < CAS_NRXDESC; i++)
87967754Smsmith		CAS_INIT_RXDESC(sc, i, i);
88067754Smsmith	sc->sc_rxdptr = 0;
881193267Sjkim
882193267Sjkim	CAS_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
883193267Sjkim}
884193267Sjkim
885193267Sjkimstatic u_int
886193267Sjkimcas_descsize(u_int sz)
887193267Sjkim{
888193267Sjkim
889167802Sjkim	switch (sz) {
890167802Sjkim	case 32:
891167802Sjkim		return (CAS_DESC_32);
89267754Smsmith	case 64:
89367754Smsmith		return (CAS_DESC_64);
89467754Smsmith	case 128:
89567754Smsmith		return (CAS_DESC_128);
896193267Sjkim	case 256:
897167802Sjkim		return (CAS_DESC_256);
898167802Sjkim	case 512:
89967754Smsmith		return (CAS_DESC_512);
90067754Smsmith	case 1024:
90191116Smsmith		return (CAS_DESC_1K);
90267754Smsmith	case 2048:
90367754Smsmith		return (CAS_DESC_2K);
90467754Smsmith	case 4096:
90567754Smsmith		return (CAS_DESC_4K);
90667754Smsmith	case 8192:
907114237Snjl		return (CAS_DESC_8K);
90867754Smsmith	default:
909167802Sjkim		printf("%s: invalid descriptor ring size %d\n", __func__, sz);
910167802Sjkim		return (CAS_DESC_32);
91167754Smsmith	}
91291116Smsmith}
91367754Smsmith
91467754Smsmithstatic u_int
91567754Smsmithcas_rxcompsize(u_int sz)
91667754Smsmith{
91767754Smsmith
91891116Smsmith	switch (sz) {
91991116Smsmith	case 128:
92091116Smsmith		return (CAS_RX_CONF_COMP_128);
92191116Smsmith	case 256:
922114237Snjl		return (CAS_RX_CONF_COMP_256);
92367754Smsmith	case 512:
924167802Sjkim		return (CAS_RX_CONF_COMP_512);
925167802Sjkim	case 1024:
92667754Smsmith		return (CAS_RX_CONF_COMP_1K);
92767754Smsmith	case 2048:
92867754Smsmith		return (CAS_RX_CONF_COMP_2K);
929245582Sjkim	case 4096:
93067754Smsmith		return (CAS_RX_CONF_COMP_4K);
931245582Sjkim	case 8192:
932245582Sjkim		return (CAS_RX_CONF_COMP_8K);
933245582Sjkim	case 16384:
93467754Smsmith		return (CAS_RX_CONF_COMP_16K);
93567754Smsmith	case 32768:
93667754Smsmith		return (CAS_RX_CONF_COMP_32K);
93767754Smsmith	default:
93867754Smsmith		printf("%s: invalid dcompletion ring size %d\n", __func__, sz);
93967754Smsmith		return (CAS_RX_CONF_COMP_128);
94067754Smsmith	}
94167754Smsmith}
94267754Smsmith
943193267Sjkimstatic void
944193267Sjkimcas_init(void *xsc)
945193267Sjkim{
946193267Sjkim	struct cas_softc *sc = xsc;
947193267Sjkim
948193267Sjkim	CAS_LOCK(sc);
949193267Sjkim	cas_init_locked(sc);
950193267Sjkim	CAS_UNLOCK(sc);
951193267Sjkim}
952193267Sjkim
953193267Sjkim/*
954193267Sjkim * Initialization of interface; set up initialization block
95567754Smsmith * and transmit/receive descriptor rings.
95667754Smsmith */
95791116Smsmithstatic void
95891116Smsmithcas_init_locked(struct cas_softc *sc)
95991116Smsmith{
96091116Smsmith	struct ifnet *ifp = sc->sc_ifp;
96167754Smsmith	uint32_t v;
96267754Smsmith
96367754Smsmith	CAS_LOCK_ASSERT(sc, MA_OWNED);
96467754Smsmith
96567754Smsmith	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
966114237Snjl		return;
96767754Smsmith
968167802Sjkim#ifdef CAS_DEBUG
969167802Sjkim	CTR2(KTR_CAS, "%s: %s: calling stop", device_get_name(sc->sc_dev),
970167802Sjkim	    __func__);
971167802Sjkim#endif
972167802Sjkim	/*
973167802Sjkim	 * Initialization sequence.  The numbered steps below correspond
974167802Sjkim	 * to the sequence outlined in section 6.3.5.1 in the Ethernet
97567754Smsmith	 * Channel Engine manual (part of the PCIO manual).
97667754Smsmith	 * See also the STP2002-STQ document from Sun Microsystems.
97767754Smsmith	 */
97867754Smsmith
97967754Smsmith	/* step 1 & 2.  Reset the Ethernet Channel. */
980193267Sjkim	cas_stop(ifp);
981193267Sjkim	cas_reset(sc);
982193267Sjkim#ifdef CAS_DEBUG
983193267Sjkim	CTR2(KTR_CAS, "%s: %s: restarting", device_get_name(sc->sc_dev),
984193267Sjkim	    __func__);
985193267Sjkim#endif
986193267Sjkim
987193267Sjkim	if ((sc->sc_flags & CAS_SERDES) == 0)
988193267Sjkim		/* Re-initialize the MIF. */
989193267Sjkim		cas_mifinit(sc);
990193267Sjkim
991193267Sjkim	/* step 3.  Setup data structures in host memory. */
992193267Sjkim	cas_meminit(sc);
993193267Sjkim
994193267Sjkim	/* step 4.  TX MAC registers & counters */
995193267Sjkim	cas_init_regs(sc);
996193267Sjkim
997193267Sjkim	/* step 5.  RX MAC registers & counters */
998193267Sjkim	cas_setladrf(sc);
999193267Sjkim
1000117521Snjl	/* step 6 & 7.  Program Ring Base Addresses. */
1001117521Snjl	CAS_WRITE_4(sc, CAS_TX_DESC3_BASE_HI,
1002117521Snjl	    (((uint64_t)CAS_CDTXDADDR(sc, 0)) >> 32));
1003138287Smarks	CAS_WRITE_4(sc, CAS_TX_DESC3_BASE_LO,
1004167802Sjkim	    CAS_CDTXDADDR(sc, 0) & 0xffffffff);
1005117521Snjl
1006117521Snjl	CAS_WRITE_4(sc, CAS_RX_COMP_BASE_HI,
1007138287Smarks	    (((uint64_t)CAS_CDRXCADDR(sc, 0)) >> 32));
1008167802Sjkim	CAS_WRITE_4(sc, CAS_RX_COMP_BASE_LO,
1009117521Snjl	    CAS_CDRXCADDR(sc, 0) & 0xffffffff);
1010117521Snjl
101167754Smsmith	CAS_WRITE_4(sc, CAS_RX_DESC_BASE_HI,
101267754Smsmith	    (((uint64_t)CAS_CDRXDADDR(sc, 0)) >> 32));
101367754Smsmith	CAS_WRITE_4(sc, CAS_RX_DESC_BASE_LO,
1014254745Sjkim	    CAS_CDRXDADDR(sc, 0) & 0xffffffff);
1015254745Sjkim
1016254745Sjkim	if ((sc->sc_flags & CAS_REG_PLUS) != 0) {
1017254745Sjkim		CAS_WRITE_4(sc, CAS_RX_DESC2_BASE_HI,
1018216471Sjkim		    (((uint64_t)CAS_CDRXD2ADDR(sc, 0)) >> 32));
1019216471Sjkim		CAS_WRITE_4(sc, CAS_RX_DESC2_BASE_LO,
1020216471Sjkim		    CAS_CDRXD2ADDR(sc, 0) & 0xffffffff);
1021216471Sjkim	}
1022216471Sjkim
1023216471Sjkim#ifdef CAS_DEBUG
1024216471Sjkim	CTR5(KTR_CAS,
1025216471Sjkim	    "loading TXDR %lx, RXCR %lx, RXDR %lx, RXD2R %lx, cddma %lx",
1026216471Sjkim	    CAS_CDTXDADDR(sc, 0), CAS_CDRXCADDR(sc, 0), CAS_CDRXDADDR(sc, 0),
1027216471Sjkim	    CAS_CDRXD2ADDR(sc, 0), sc->sc_cddma);
102877424Smsmith#endif
1029167802Sjkim
103067754Smsmith	/* step 8.  Global Configuration & Interrupt Masks */
103167754Smsmith
1032216471Sjkim	/* Disable weighted round robin. */
1033216471Sjkim	CAS_WRITE_4(sc, CAS_CAW, CAS_CAW_RR_DIS);
1034216471Sjkim
1035216471Sjkim	/*
1036216471Sjkim	 * Enable infinite bursts for revisions without PCI issues if
1037216471Sjkim	 * applicable.  Doing so greatly improves the TX performance on
103877424Smsmith	 * !__sparc64__.
1039167802Sjkim	 */
1040167802Sjkim	CAS_WRITE_4(sc, CAS_INF_BURST,
1041167802Sjkim#if !defined(__sparc64__)
104267754Smsmith	    (sc->sc_flags & CAS_TABORT) == 0 ? CAS_INF_BURST_EN :
104387031Smsmith#endif
104487031Smsmith	    0);
1045167802Sjkim
1046167802Sjkim	/* Set up interrupts. */
104767754Smsmith	CAS_WRITE_4(sc, CAS_INTMASK,
104899679Siwasaki	    ~(CAS_INTR_TX_INT_ME | CAS_INTR_TX_TAG_ERR |
104999679Siwasaki	    CAS_INTR_RX_DONE | CAS_INTR_RX_BUF_NA | CAS_INTR_RX_TAG_ERR |
1050167802Sjkim	    CAS_INTR_RX_COMP_FULL | CAS_INTR_RX_BUF_AEMPTY |
1051167802Sjkim	    CAS_INTR_RX_COMP_AFULL | CAS_INTR_RX_LEN_MMATCH |
105287031Smsmith	    CAS_INTR_PCI_ERROR_INT
105399679Siwasaki#ifdef CAS_DEBUG
105499679Siwasaki	    | CAS_INTR_PCS_INT | CAS_INTR_MIF
1055138287Smarks#endif
1056138287Smarks	    ));
1057167802Sjkim	/* Don't clear top level interrupts when CAS_STATUS_ALIAS is read. */
1058167802Sjkim	CAS_WRITE_4(sc, CAS_CLEAR_ALIAS, 0);
1059167802Sjkim	CAS_WRITE_4(sc, CAS_MAC_RX_MASK, ~CAS_MAC_RX_OVERFLOW);
1060167802Sjkim	CAS_WRITE_4(sc, CAS_MAC_TX_MASK,
1061167802Sjkim	    ~(CAS_MAC_TX_UNDERRUN | CAS_MAC_TX_MAX_PKT_ERR));
106299679Siwasaki#ifdef CAS_DEBUG
1063193267Sjkim	CAS_WRITE_4(sc, CAS_MAC_CTRL_MASK,
1064138287Smarks	    ~(CAS_MAC_CTRL_PAUSE_RCVD | CAS_MAC_CTRL_PAUSE |
1065193267Sjkim	    CAS_MAC_CTRL_NON_PAUSE));
1066193267Sjkim#else
1067193267Sjkim	CAS_WRITE_4(sc, CAS_MAC_CTRL_MASK,
1068193267Sjkim	    CAS_MAC_CTRL_PAUSE_RCVD | CAS_MAC_CTRL_PAUSE |
1069193267Sjkim	    CAS_MAC_CTRL_NON_PAUSE);
1070193267Sjkim#endif
1071193267Sjkim
1072193267Sjkim	/* Enable PCI error interrupts. */
1073193267Sjkim	CAS_WRITE_4(sc, CAS_ERROR_MASK,
1074193267Sjkim	    ~(CAS_ERROR_DTRTO | CAS_ERROR_OTHER | CAS_ERROR_DMAW_ZERO |
1075193267Sjkim	    CAS_ERROR_DMAR_ZERO | CAS_ERROR_RTRTO));
1076127175Snjl
107777424Smsmith	/* Enable PCI error interrupts in BIM configuration. */
107867754Smsmith	CAS_WRITE_4(sc, CAS_BIM_CONF,
107977424Smsmith	    CAS_BIM_CONF_DPAR_EN | CAS_BIM_CONF_RMA_EN | CAS_BIM_CONF_RTA_EN);
1080167802Sjkim
1081167802Sjkim	/*
1082167802Sjkim	 * step 9.  ETX Configuration: encode receive descriptor ring size,
1083202771Sjkim	 * enable DMA and disable pre-interrupt writeback completion.
1084167802Sjkim	 */
1085167802Sjkim	v = cas_descsize(CAS_NTXDESC) << CAS_TX_CONF_DESC3_SHFT;
108667754Smsmith	CAS_WRITE_4(sc, CAS_TX_CONF, v | CAS_TX_CONF_TXDMA_EN |
1087167802Sjkim	    CAS_TX_CONF_RDPP_DIS | CAS_TX_CONF_PICWB_DIS);
108867754Smsmith
1089228110Sjkim	/* step 10.  ERX Configuration */
1090228110Sjkim
1091228110Sjkim	/*
1092228110Sjkim	 * Encode receive completion and descriptor ring sizes, set the
1093228110Sjkim	 * swivel offset.
1094228110Sjkim	 */
1095228110Sjkim	v = cas_rxcompsize(CAS_NRXCOMP) << CAS_RX_CONF_COMP_SHFT;
1096228110Sjkim	v |= cas_descsize(CAS_NRXDESC) << CAS_RX_CONF_DESC_SHFT;
1097228110Sjkim	if ((sc->sc_flags & CAS_REG_PLUS) != 0)
1098228110Sjkim		v |= cas_descsize(CAS_NRXDESC2) << CAS_RX_CONF_DESC2_SHFT;
1099228110Sjkim	CAS_WRITE_4(sc, CAS_RX_CONF,
110067754Smsmith	    v | (ETHER_ALIGN << CAS_RX_CONF_SOFF_SHFT));
110177424Smsmith
1102167802Sjkim	/* Set the PAUSE thresholds.  We use the maximum OFF threshold. */
1103167802Sjkim	CAS_WRITE_4(sc, CAS_RX_PTHRS,
1104167802Sjkim	    ((111 * 64) << CAS_RX_PTHRS_XOFF_SHFT) |
1105167802Sjkim	    ((15 * 64) << CAS_RX_PTHRS_XON_SHFT));
110667754Smsmith
110767754Smsmith	/* RX blanking */
110867754Smsmith	CAS_WRITE_4(sc, CAS_RX_BLANK,
110967754Smsmith	    (15 << CAS_RX_BLANK_TIME_SHFT) | (5 << CAS_RX_BLANK_PKTS_SHFT));
111067754Smsmith
111177424Smsmith	/* Set RX_COMP_AFULL threshold to half of the RX completions. */
1112207344Sjkim	CAS_WRITE_4(sc, CAS_RX_AEMPTY_THRS,
1113167802Sjkim	    (CAS_NRXCOMP / 2) << CAS_RX_AEMPTY_COMP_SHFT);
1114167802Sjkim
1115167802Sjkim	/* Initialize the RX page size register as appropriate for 8k. */
111667754Smsmith	CAS_WRITE_4(sc, CAS_RX_PSZ,
1117210976Sjkim	    (CAS_RX_PSZ_8K << CAS_RX_PSZ_SHFT) |
1118210976Sjkim	    (4 << CAS_RX_PSZ_MB_CNT_SHFT) |
1119210976Sjkim	    (CAS_RX_PSZ_MB_STRD_2K << CAS_RX_PSZ_MB_STRD_SHFT) |
1120210976Sjkim	    (CAS_RX_PSZ_MB_OFF_64 << CAS_RX_PSZ_MB_OFF_SHFT));
112167754Smsmith
1122210976Sjkim	/* Disable RX random early detection. */
112367754Smsmith	CAS_WRITE_4(sc,	CAS_RX_RED, 0);
112467754Smsmith
112591116Smsmith	/* Zero the RX reassembly DMA table. */
112691116Smsmith	for (v = 0; v <= CAS_RX_REAS_DMA_ADDR_LC; v++) {
112767754Smsmith		CAS_WRITE_4(sc,	CAS_RX_REAS_DMA_ADDR, v);
1128216471Sjkim		CAS_WRITE_4(sc,	CAS_RX_REAS_DMA_DATA_LO, 0);
1129216471Sjkim		CAS_WRITE_4(sc,	CAS_RX_REAS_DMA_DATA_MD, 0);
1130216471Sjkim		CAS_WRITE_4(sc,	CAS_RX_REAS_DMA_DATA_HI, 0);
1131216471Sjkim	}
1132216471Sjkim
1133197104Sjkim	/* Ensure the RX control FIFO and RX IPP FIFO addresses are zero. */
113467754Smsmith	CAS_WRITE_4(sc, CAS_RX_CTRL_FIFO, 0);
1135197104Sjkim	CAS_WRITE_4(sc, CAS_RX_IPP_ADDR, 0);
1136193267Sjkim
1137197104Sjkim	/* Finally, enable RX DMA. */
1138197104Sjkim	CAS_WRITE_4(sc, CAS_RX_CONF,
1139193267Sjkim	    CAS_READ_4(sc, CAS_RX_CONF) | CAS_RX_CONF_RXDMA_EN);
1140193267Sjkim
114167754Smsmith	/* step 11.  Configure Media. */
1142241973Sjkim
1143197104Sjkim	/* step 12.  RX_MAC Configuration Register */
1144241973Sjkim	v = CAS_READ_4(sc, CAS_MAC_RX_CONF) & ~CAS_MAC_RX_CONF_STRPPAD;
1145117521Snjl	v |= CAS_MAC_RX_CONF_EN | CAS_MAC_RX_CONF_STRPFCS;
1146197104Sjkim	CAS_WRITE_4(sc, CAS_MAC_RX_CONF, 0);
1147197104Sjkim	CAS_BARRIER(sc, CAS_MAC_RX_CONF, 4,
114867754Smsmith	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1149241973Sjkim	if (!cas_bitwait(sc, CAS_MAC_RX_CONF, CAS_MAC_RX_CONF_EN, 0))
115067754Smsmith		device_printf(sc->sc_dev, "cannot configure RX MAC\n");
1151241973Sjkim	CAS_WRITE_4(sc, CAS_MAC_RX_CONF, v);
1152117521Snjl
1153197104Sjkim	/* step 13.  TX_MAC Configuration Register */
1154197104Sjkim	v = CAS_READ_4(sc, CAS_MAC_TX_CONF);
1155241973Sjkim	v |= CAS_MAC_TX_CONF_EN;
1156117521Snjl	CAS_WRITE_4(sc, CAS_MAC_TX_CONF, 0);
1157241973Sjkim	CAS_BARRIER(sc, CAS_MAC_TX_CONF, 4,
1158117521Snjl	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1159197104Sjkim	if (!cas_bitwait(sc, CAS_MAC_TX_CONF, CAS_MAC_TX_CONF_EN, 0))
1160197104Sjkim		device_printf(sc->sc_dev, "cannot configure TX MAC\n");
1161197104Sjkim	CAS_WRITE_4(sc, CAS_MAC_TX_CONF, v);
1162197104Sjkim
1163197104Sjkim	/* step 14.  Issue Transmit Pending command. */
1164117521Snjl
1165197104Sjkim	/* step 15.  Give the reciever a swift kick. */
1166197104Sjkim	CAS_WRITE_4(sc, CAS_RX_KICK, CAS_NRXDESC - 4);
1167197104Sjkim	CAS_WRITE_4(sc, CAS_RX_COMP_TAIL, 0);
1168197104Sjkim	if ((sc->sc_flags & CAS_REG_PLUS) != 0)
1169197104Sjkim		CAS_WRITE_4(sc, CAS_RX_KICK2, CAS_NRXDESC2 - 4);
1170197104Sjkim
1171197104Sjkim	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1172197104Sjkim	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1173197104Sjkim
1174202771Sjkim	mii_mediachg(sc->sc_mii);
1175241973Sjkim
1176241973Sjkim	/* Start the one second timer. */
1177241973Sjkim	sc->sc_wdog_timer = 0;
1178241973Sjkim	callout_reset(&sc->sc_tick_ch, hz, cas_tick, sc);
1179117521Snjl}
1180197104Sjkim
1181117521Snjlstatic int
1182197104Sjkimcas_load_txmbuf(struct cas_softc *sc, struct mbuf **m_head)
1183117521Snjl{
1184197104Sjkim	bus_dma_segment_t txsegs[CAS_NTXSEGS];
1185117521Snjl	struct cas_txsoft *txs;
1186197104Sjkim	struct ip *ip;
1187117521Snjl	struct mbuf *m;
1188197104Sjkim	uint64_t cflags;
1189197104Sjkim	int error, nexttx, nsegs, offset, seg;
1190197104Sjkim
1191197104Sjkim	CAS_LOCK_ASSERT(sc, MA_OWNED);
1192241973Sjkim
1193241973Sjkim	/* Get a work queue entry. */
1194241973Sjkim	if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) {
1195241973Sjkim		/* Ran out of descriptors. */
1196197104Sjkim		return (ENOBUFS);
1197241973Sjkim	}
1198117521Snjl
1199167802Sjkim	cflags = 0;
1200167802Sjkim	if (((*m_head)->m_pkthdr.csum_flags & CAS_CSUM_FEATURES) != 0) {
1201167802Sjkim		if (M_WRITABLE(*m_head) == 0) {
1202167802Sjkim			m = m_dup(*m_head, M_DONTWAIT);
1203167802Sjkim			m_freem(*m_head);
1204167802Sjkim			*m_head = m;
1205167802Sjkim			if (m == NULL)
1206167802Sjkim				return (ENOBUFS);
120767754Smsmith		}
120867754Smsmith		offset = sizeof(struct ether_header);
1209114237Snjl		m = m_pullup(*m_head, offset + sizeof(struct ip));
121067754Smsmith		if (m == NULL) {
1211167802Sjkim			*m_head = NULL;
1212167802Sjkim			return (ENOBUFS);
1213167802Sjkim		}
1214167802Sjkim		ip = (struct ip *)(mtod(m, caddr_t) + offset);
1215114237Snjl		offset += (ip->ip_hl << 2);
121680062Smsmith		cflags = (offset << CAS_TD_CKSUM_START_SHFT) |
121767754Smsmith		    ((offset + m->m_pkthdr.csum_data) <<
1218114237Snjl		    CAS_TD_CKSUM_STUFF_SHFT) | CAS_TD_CKSUM_EN;
121967754Smsmith		*m_head = m;
1220167802Sjkim	}
1221167802Sjkim
1222167802Sjkim	error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap,
1223167802Sjkim	    *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT);
1224167802Sjkim	if (error == EFBIG) {
1225114237Snjl		m = m_collapse(*m_head, M_DONTWAIT, CAS_NTXSEGS);
122677424Smsmith		if (m == NULL) {
122767754Smsmith			m_freem(*m_head);
122867754Smsmith			*m_head = NULL;
122967754Smsmith			return (ENOBUFS);
1230193267Sjkim		}
123167754Smsmith		*m_head = m;
1232193267Sjkim		error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag,
1233193267Sjkim		    txs->txs_dmamap, *m_head, txsegs, &nsegs,
1234193267Sjkim		    BUS_DMA_NOWAIT);
1235193267Sjkim		if (error != 0) {
1236193267Sjkim			m_freem(*m_head);
1237193267Sjkim			*m_head = NULL;
1238193267Sjkim			return (error);
123967754Smsmith		}
1240193267Sjkim	} else if (error != 0)
124167754Smsmith		return (error);
1242193267Sjkim	/* If nsegs is wrong then the stack is corrupt. */
124367754Smsmith	KASSERT(nsegs <= CAS_NTXSEGS,
1244193267Sjkim	    ("%s: too many DMA segments (%d)", __func__, nsegs));
1245193267Sjkim	if (nsegs == 0) {
1246193267Sjkim		m_freem(*m_head);
1247193267Sjkim		*m_head = NULL;
1248193267Sjkim		return (EIO);
1249193267Sjkim	}
1250193267Sjkim
1251151937Sjkim	/*
1252151937Sjkim	 * Ensure we have enough descriptors free to describe
1253193267Sjkim	 * the packet.  Note, we always reserve one descriptor
1254167802Sjkim	 * at the end of the ring as a termination point, in
1255167802Sjkim	 * order to prevent wrap-around.
1256253690Sjkim	 */
1257253690Sjkim	if (nsegs > sc->sc_txfree - 1) {
1258253690Sjkim		txs->txs_ndescs = 0;
1259253690Sjkim		bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap);
1260253690Sjkim		return (ENOBUFS);
1261253690Sjkim	}
1262253690Sjkim
1263253690Sjkim	txs->txs_ndescs = nsegs;
1264253690Sjkim	txs->txs_firstdesc = sc->sc_txnext;
1265253690Sjkim	nexttx = txs->txs_firstdesc;
1266253690Sjkim	for (seg = 0; seg < nsegs; seg++, nexttx = CAS_NEXTTX(nexttx)) {
1267253690Sjkim#ifdef CAS_DEBUG
1268253690Sjkim		CTR6(KTR_CAS,
1269253690Sjkim		    "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)",
1270253690Sjkim		    __func__, seg, nexttx, txsegs[seg].ds_len,
1271253690Sjkim		    txsegs[seg].ds_addr, htole64(txsegs[seg].ds_addr));
1272253690Sjkim#endif
1273253690Sjkim		sc->sc_txdescs[nexttx].cd_buf_ptr =
1274253690Sjkim		    htole64(txsegs[seg].ds_addr);
1275253690Sjkim		KASSERT(txsegs[seg].ds_len <
1276253690Sjkim		    CAS_TD_BUF_LEN_MASK >> CAS_TD_BUF_LEN_SHFT,
1277253690Sjkim		    ("%s: segment size too large!", __func__));
1278253690Sjkim		sc->sc_txdescs[nexttx].cd_flags =
1279253690Sjkim		    htole64(txsegs[seg].ds_len << CAS_TD_BUF_LEN_SHFT);
1280253690Sjkim		txs->txs_lastdesc = nexttx;
1281253690Sjkim	}
1282253690Sjkim
1283253690Sjkim	/* Set EOF on the last descriptor. */
128467754Smsmith#ifdef CAS_DEBUG
1285	CTR3(KTR_CAS, "%s: end of frame at segment %d, TX %d",
1286	    __func__, seg, nexttx);
1287#endif
1288	sc->sc_txdescs[txs->txs_lastdesc].cd_flags |=
1289	    htole64(CAS_TD_END_OF_FRAME);
1290
1291	/* Lastly set SOF on the first descriptor. */
1292#ifdef CAS_DEBUG
1293	CTR3(KTR_CAS, "%s: start of frame at segment %d, TX %d",
1294	    __func__, seg, nexttx);
1295#endif
1296	if (sc->sc_txwin += nsegs > CAS_MAXTXFREE * 2 / 3) {
1297		sc->sc_txwin = 0;
1298		sc->sc_txdescs[txs->txs_firstdesc].cd_flags |=
1299		    htole64(cflags | CAS_TD_START_OF_FRAME | CAS_TD_INT_ME);
1300	} else
1301		sc->sc_txdescs[txs->txs_firstdesc].cd_flags |=
1302		    htole64(cflags | CAS_TD_START_OF_FRAME);
1303
1304	/* Sync the DMA map. */
1305	bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap,
1306	    BUS_DMASYNC_PREWRITE);
1307
1308#ifdef CAS_DEBUG
1309	CTR4(KTR_CAS, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d",
1310	    __func__, txs->txs_firstdesc, txs->txs_lastdesc,
1311	    txs->txs_ndescs);
1312#endif
1313	STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
1314	STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
1315	txs->txs_mbuf = *m_head;
1316
1317	sc->sc_txnext = CAS_NEXTTX(txs->txs_lastdesc);
1318	sc->sc_txfree -= txs->txs_ndescs;
1319
1320	return (0);
1321}
1322
1323static void
1324cas_init_regs(struct cas_softc *sc)
1325{
1326	int i;
1327	const u_char *laddr = IF_LLADDR(sc->sc_ifp);
1328
1329	CAS_LOCK_ASSERT(sc, MA_OWNED);
1330
1331	/* These registers are not cleared on reset. */
1332	if ((sc->sc_flags & CAS_INITED) == 0) {
1333		/* magic values */
1334		CAS_WRITE_4(sc, CAS_MAC_IPG0, 0);
1335		CAS_WRITE_4(sc, CAS_MAC_IPG1, 8);
1336		CAS_WRITE_4(sc, CAS_MAC_IPG2, 4);
1337
1338		/* min frame length */
1339		CAS_WRITE_4(sc, CAS_MAC_MIN_FRAME, ETHER_MIN_LEN);
1340		/* max frame length and max burst size */
1341		CAS_WRITE_4(sc, CAS_MAC_MAX_BF,
1342		    ((ETHER_MAX_LEN_JUMBO + ETHER_VLAN_ENCAP_LEN) <<
1343		    CAS_MAC_MAX_BF_FRM_SHFT) |
1344		    (0x2000 << CAS_MAC_MAX_BF_BST_SHFT));
1345
1346		/* more magic values */
1347		CAS_WRITE_4(sc, CAS_MAC_PREAMBLE_LEN, 0x7);
1348		CAS_WRITE_4(sc, CAS_MAC_JAM_SIZE, 0x4);
1349		CAS_WRITE_4(sc, CAS_MAC_ATTEMPT_LIMIT, 0x10);
1350		CAS_WRITE_4(sc, CAS_MAC_CTRL_TYPE, 0x8088);
1351
1352		/* random number seed */
1353		CAS_WRITE_4(sc, CAS_MAC_RANDOM_SEED,
1354		    ((laddr[5] << 8) | laddr[4]) & 0x3ff);
1355
1356		/* secondary MAC addresses: 0:0:0:0:0:0 */
1357		for (i = CAS_MAC_ADDR3; i <= CAS_MAC_ADDR41;
1358		    i += CAS_MAC_ADDR4 - CAS_MAC_ADDR3)
1359			CAS_WRITE_4(sc, i, 0);
1360
1361		/* MAC control address: 01:80:c2:00:00:01 */
1362		CAS_WRITE_4(sc, CAS_MAC_ADDR42, 0x0001);
1363		CAS_WRITE_4(sc, CAS_MAC_ADDR43, 0xc200);
1364		CAS_WRITE_4(sc, CAS_MAC_ADDR44, 0x0180);
1365
1366		/* MAC filter address: 0:0:0:0:0:0 */
1367		CAS_WRITE_4(sc, CAS_MAC_AFILTER0, 0);
1368		CAS_WRITE_4(sc, CAS_MAC_AFILTER1, 0);
1369		CAS_WRITE_4(sc, CAS_MAC_AFILTER2, 0);
1370		CAS_WRITE_4(sc, CAS_MAC_AFILTER_MASK1_2, 0);
1371		CAS_WRITE_4(sc, CAS_MAC_AFILTER_MASK0, 0);
1372
1373		/* Zero the hash table. */
1374		for (i = CAS_MAC_HASH0; i <= CAS_MAC_HASH15;
1375		    i += CAS_MAC_HASH1 - CAS_MAC_HASH0)
1376			CAS_WRITE_4(sc, i, 0);
1377
1378		sc->sc_flags |= CAS_INITED;
1379	}
1380
1381	/* Counters need to be zeroed. */
1382	CAS_WRITE_4(sc, CAS_MAC_NORM_COLL_CNT, 0);
1383	CAS_WRITE_4(sc, CAS_MAC_FIRST_COLL_CNT, 0);
1384	CAS_WRITE_4(sc, CAS_MAC_EXCESS_COLL_CNT, 0);
1385	CAS_WRITE_4(sc, CAS_MAC_LATE_COLL_CNT, 0);
1386	CAS_WRITE_4(sc, CAS_MAC_DEFER_TMR_CNT, 0);
1387	CAS_WRITE_4(sc, CAS_MAC_PEAK_ATTEMPTS, 0);
1388	CAS_WRITE_4(sc, CAS_MAC_RX_FRAME_COUNT, 0);
1389	CAS_WRITE_4(sc, CAS_MAC_RX_LEN_ERR_CNT, 0);
1390	CAS_WRITE_4(sc, CAS_MAC_RX_ALIGN_ERR, 0);
1391	CAS_WRITE_4(sc, CAS_MAC_RX_CRC_ERR_CNT, 0);
1392	CAS_WRITE_4(sc, CAS_MAC_RX_CODE_VIOL, 0);
1393
1394	/* Set XOFF PAUSE time. */
1395	CAS_WRITE_4(sc, CAS_MAC_SPC, 0x1BF0 << CAS_MAC_SPC_TIME_SHFT);
1396
1397	/* Set the station address. */
1398	CAS_WRITE_4(sc, CAS_MAC_ADDR0, (laddr[4] << 8) | laddr[5]);
1399	CAS_WRITE_4(sc, CAS_MAC_ADDR1, (laddr[2] << 8) | laddr[3]);
1400	CAS_WRITE_4(sc, CAS_MAC_ADDR2, (laddr[0] << 8) | laddr[1]);
1401
1402	/* Enable MII outputs. */
1403	CAS_WRITE_4(sc, CAS_MAC_XIF_CONF, CAS_MAC_XIF_CONF_TX_OE);
1404}
1405
1406static void
1407cas_tx_task(void *arg, int pending __unused)
1408{
1409	struct ifnet *ifp;
1410
1411	ifp = (struct ifnet *)arg;
1412	cas_start(ifp);
1413}
1414
1415static inline void
1416cas_txkick(struct cas_softc *sc)
1417{
1418
1419	/*
1420	 * Update the TX kick register.  This register has to point to the
1421	 * descriptor after the last valid one and for optimum performance
1422	 * should be incremented in multiples of 4 (the DMA engine fetches/
1423	 * updates descriptors in batches of 4).
1424	 */
1425#ifdef CAS_DEBUG
1426	CTR3(KTR_CAS, "%s: %s: kicking TX %d",
1427	    device_get_name(sc->sc_dev), __func__, sc->sc_txnext);
1428#endif
1429	CAS_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1430	CAS_WRITE_4(sc, CAS_TX_KICK3, sc->sc_txnext);
1431}
1432
1433static void
1434cas_start(struct ifnet *ifp)
1435{
1436	struct cas_softc *sc = ifp->if_softc;
1437	struct mbuf *m;
1438	int kicked, ntx;
1439
1440	CAS_LOCK(sc);
1441
1442	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
1443	    IFF_DRV_RUNNING || (sc->sc_flags & CAS_LINK) == 0) {
1444		CAS_UNLOCK(sc);
1445		return;
1446	}
1447
1448	if (sc->sc_txfree < CAS_MAXTXFREE / 4)
1449		cas_tint(sc);
1450
1451#ifdef CAS_DEBUG
1452	CTR4(KTR_CAS, "%s: %s: txfree %d, txnext %d",
1453	    device_get_name(sc->sc_dev), __func__, sc->sc_txfree,
1454	    sc->sc_txnext);
1455#endif
1456	ntx = 0;
1457	kicked = 0;
1458	for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) {
1459		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1460		if (m == NULL)
1461			break;
1462		if (cas_load_txmbuf(sc, &m) != 0) {
1463			if (m == NULL)
1464				break;
1465			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1466			IFQ_DRV_PREPEND(&ifp->if_snd, m);
1467			break;
1468		}
1469		if ((sc->sc_txnext % 4) == 0) {
1470			cas_txkick(sc);
1471			kicked = 1;
1472		} else
1473			kicked = 0;
1474		ntx++;
1475		BPF_MTAP(ifp, m);
1476	}
1477
1478	if (ntx > 0) {
1479		if (kicked == 0)
1480			cas_txkick(sc);
1481#ifdef CAS_DEBUG
1482		CTR2(KTR_CAS, "%s: packets enqueued, OWN on %d",
1483		    device_get_name(sc->sc_dev), sc->sc_txnext);
1484#endif
1485
1486		/* Set a watchdog timer in case the chip flakes out. */
1487		sc->sc_wdog_timer = 5;
1488#ifdef CAS_DEBUG
1489		CTR3(KTR_CAS, "%s: %s: watchdog %d",
1490		    device_get_name(sc->sc_dev), __func__,
1491		    sc->sc_wdog_timer);
1492#endif
1493	}
1494
1495	CAS_UNLOCK(sc);
1496}
1497
1498static void
1499cas_tint(struct cas_softc *sc)
1500{
1501	struct ifnet *ifp = sc->sc_ifp;
1502	struct cas_txsoft *txs;
1503	int progress;
1504	uint32_t txlast;
1505#ifdef CAS_DEBUG
1506	int i;
1507
1508	CAS_LOCK_ASSERT(sc, MA_OWNED);
1509
1510	CTR2(KTR_CAS, "%s: %s", device_get_name(sc->sc_dev), __func__);
1511#endif
1512
1513	/*
1514	 * Go through our TX list and free mbufs for those
1515	 * frames that have been transmitted.
1516	 */
1517	progress = 0;
1518	CAS_CDSYNC(sc, BUS_DMASYNC_POSTREAD);
1519	while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
1520#ifdef CAS_DEBUG
1521		if ((ifp->if_flags & IFF_DEBUG) != 0) {
1522			printf("    txsoft %p transmit chain:\n", txs);
1523			for (i = txs->txs_firstdesc;; i = CAS_NEXTTX(i)) {
1524				printf("descriptor %d: ", i);
1525				printf("cd_flags: 0x%016llx\t",
1526				    (long long)le64toh(
1527				    sc->sc_txdescs[i].cd_flags));
1528				printf("cd_buf_ptr: 0x%016llx\n",
1529				    (long long)le64toh(
1530				    sc->sc_txdescs[i].cd_buf_ptr));
1531				if (i == txs->txs_lastdesc)
1532					break;
1533			}
1534		}
1535#endif
1536
1537		/*
1538		 * In theory, we could harvest some descriptors before
1539		 * the ring is empty, but that's a bit complicated.
1540		 *
1541		 * CAS_TX_COMPn points to the last descriptor
1542		 * processed + 1.
1543		 */
1544		txlast = CAS_READ_4(sc, CAS_TX_COMP3);
1545#ifdef CAS_DEBUG
1546		CTR4(KTR_CAS, "%s: txs->txs_firstdesc = %d, "
1547		    "txs->txs_lastdesc = %d, txlast = %d",
1548		    __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast);
1549#endif
1550		if (txs->txs_firstdesc <= txs->txs_lastdesc) {
1551			if ((txlast >= txs->txs_firstdesc) &&
1552			    (txlast <= txs->txs_lastdesc))
1553				break;
1554		} else {
1555			/* Ick -- this command wraps. */
1556			if ((txlast >= txs->txs_firstdesc) ||
1557			    (txlast <= txs->txs_lastdesc))
1558				break;
1559		}
1560
1561#ifdef CAS_DEBUG
1562		CTR1(KTR_CAS, "%s: releasing a descriptor", __func__);
1563#endif
1564		STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
1565
1566		sc->sc_txfree += txs->txs_ndescs;
1567
1568		bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap,
1569		    BUS_DMASYNC_POSTWRITE);
1570		bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap);
1571		if (txs->txs_mbuf != NULL) {
1572			m_freem(txs->txs_mbuf);
1573			txs->txs_mbuf = NULL;
1574		}
1575
1576		STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
1577
1578		ifp->if_opackets++;
1579		progress = 1;
1580	}
1581
1582#ifdef CAS_DEBUG
1583	CTR4(KTR_CAS, "%s: CAS_TX_STATE_MACHINE %x CAS_TX_DESC_BASE %llx "
1584	    "CAS_TX_COMP3 %x",
1585	    __func__, CAS_READ_4(sc, CAS_TX_STATE_MACHINE),
1586	    ((long long)CAS_READ_4(sc, CAS_TX_DESC_BASE_HI3) << 32) |
1587	    CAS_READ_4(sc, CAS_TX_DESC_BASE_LO3),
1588	    CAS_READ_4(sc, CAS_TX_COMP3));
1589#endif
1590
1591	if (progress) {
1592		/* We freed some descriptors, so reset IFF_DRV_OACTIVE. */
1593		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1594		if (STAILQ_EMPTY(&sc->sc_txdirtyq))
1595			sc->sc_wdog_timer = 0;
1596	}
1597
1598#ifdef CAS_DEBUG
1599	CTR3(KTR_CAS, "%s: %s: watchdog %d",
1600	    device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer);
1601#endif
1602}
1603
1604static void
1605cas_rint_timeout(void *arg)
1606{
1607	struct cas_softc *sc = arg;
1608
1609	CAS_LOCK_ASSERT(sc, MA_NOTOWNED);
1610
1611	cas_rint(sc);
1612}
1613
1614static void
1615cas_rint(struct cas_softc *sc)
1616{
1617	struct cas_rxdsoft *rxds, *rxds2;
1618	struct ifnet *ifp = sc->sc_ifp;
1619	struct mbuf *m, *m2;
1620	uint64_t word1, word2, word3, word4;
1621	uint32_t rxhead;
1622	u_int idx, idx2, len, off, skip;
1623
1624	CAS_LOCK_ASSERT(sc, MA_NOTOWNED);
1625
1626	callout_stop(&sc->sc_rx_ch);
1627
1628#ifdef CAS_DEBUG
1629	CTR2(KTR_CAS, "%s: %s", device_get_name(sc->sc_dev), __func__);
1630#endif
1631
1632#define	PRINTWORD(n, delimiter)						\
1633	printf("word ## n: 0x%016llx%c", (long long)word ## n, delimiter)
1634
1635#define	SKIPASSERT(n)							\
1636	KASSERT(sc->sc_rxcomps[sc->sc_rxcptr].crc_word ## n == 0,	\
1637	    ("%s: word ## n not 0", __func__))
1638
1639#define	WORDTOH(n)							\
1640	word ## n = le64toh(sc->sc_rxcomps[sc->sc_rxcptr].crc_word ## n)
1641
1642	/*
1643	 * Read the completion head register once.  This limits
1644	 * how long the following loop can execute.
1645	 */
1646	rxhead = CAS_READ_4(sc, CAS_RX_COMP_HEAD);
1647#ifdef CAS_DEBUG
1648	CTR4(KTR_CAS, "%s: sc->sc_rxcptr %d, sc->sc_rxdptr %d, head %d",
1649	    __func__, sc->rxcptr, sc->sc_rxdptr, rxhead);
1650#endif
1651	skip = 0;
1652	CAS_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1653	for (; sc->sc_rxcptr != rxhead;
1654	    sc->sc_rxcptr = CAS_NEXTRXCOMP(sc->sc_rxcptr)) {
1655		if (skip != 0) {
1656			SKIPASSERT(1);
1657			SKIPASSERT(2);
1658			SKIPASSERT(3);
1659
1660			--skip;
1661			goto skip;
1662		}
1663
1664		WORDTOH(1);
1665		WORDTOH(2);
1666		WORDTOH(3);
1667		WORDTOH(4);
1668
1669#ifdef CAS_DEBUG
1670		if ((ifp->if_flags & IFF_DEBUG) != 0) {
1671			printf("    completion %d: ", sc->sc_rxcptr);
1672			PRINTWORD(1, '\t');
1673			PRINTWORD(2, '\t');
1674			PRINTWORD(3, '\t');
1675			PRINTWORD(4, '\n');
1676		}
1677#endif
1678
1679		if (__predict_false(
1680		    (word1 & CAS_RC1_TYPE_MASK) == CAS_RC1_TYPE_HW ||
1681		    (word4 & CAS_RC4_ZERO) != 0)) {
1682			/*
1683			 * The descriptor is still marked as owned, although
1684			 * it is supposed to have completed.  This has been
1685			 * observed on some machines.  Just exiting here
1686			 * might leave the packet sitting around until another
1687			 * one arrives to trigger a new interrupt, which is
1688			 * generally undesirable, so set up a timeout.
1689			 */
1690			callout_reset(&sc->sc_rx_ch, CAS_RXOWN_TICKS,
1691			    cas_rint_timeout, sc);
1692			break;
1693		}
1694
1695		if (__predict_false(
1696		    (word4 & (CAS_RC4_BAD | CAS_RC4_LEN_MMATCH)) != 0)) {
1697			ifp->if_ierrors++;
1698			device_printf(sc->sc_dev,
1699			    "receive error: CRC error\n");
1700			continue;
1701		}
1702
1703		KASSERT(CAS_GET(word1, CAS_RC1_DATA_SIZE) == 0 ||
1704		    CAS_GET(word2, CAS_RC2_HDR_SIZE) == 0,
1705		    ("%s: data and header present", __func__));
1706		KASSERT((word1 & CAS_RC1_SPLIT_PKT) == 0 ||
1707		    CAS_GET(word2, CAS_RC2_HDR_SIZE) == 0,
1708		    ("%s: split and header present", __func__));
1709		KASSERT(CAS_GET(word1, CAS_RC1_DATA_SIZE) == 0 ||
1710		    (word1 & CAS_RC1_RELEASE_HDR) == 0,
1711		    ("%s: data present but header release", __func__));
1712		KASSERT(CAS_GET(word2, CAS_RC2_HDR_SIZE) == 0 ||
1713		    (word1 & CAS_RC1_RELEASE_DATA) == 0,
1714		    ("%s: header present but data release", __func__));
1715
1716		if ((len = CAS_GET(word2, CAS_RC2_HDR_SIZE)) != 0) {
1717			idx = CAS_GET(word2, CAS_RC2_HDR_INDEX);
1718			off = CAS_GET(word2, CAS_RC2_HDR_OFF);
1719#ifdef CAS_DEBUG
1720			CTR4(KTR_CAS, "%s: hdr at idx %d, off %d, len %d",
1721			    __func__, idx, off, len);
1722#endif
1723			rxds = &sc->sc_rxdsoft[idx];
1724			MGETHDR(m, M_DONTWAIT, MT_DATA);
1725			if (m != NULL) {
1726				refcount_acquire(&rxds->rxds_refcount);
1727				bus_dmamap_sync(sc->sc_rdmatag,
1728				    rxds->rxds_dmamap, BUS_DMASYNC_POSTREAD);
1729#if __FreeBSD_version < 800016
1730				MEXTADD(m, (caddr_t)rxds->rxds_buf +
1731				    off * 256 + ETHER_ALIGN, len, cas_free,
1732				    rxds, M_RDONLY, EXT_NET_DRV);
1733#else
1734				MEXTADD(m, (caddr_t)rxds->rxds_buf +
1735				    off * 256 + ETHER_ALIGN, len, cas_free,
1736				    sc, (void *)(uintptr_t)idx,
1737				    M_RDONLY, EXT_NET_DRV);
1738#endif
1739				if ((m->m_flags & M_EXT) == 0) {
1740					m_freem(m);
1741					m = NULL;
1742				}
1743			}
1744			if (m != NULL) {
1745				m->m_pkthdr.rcvif = ifp;
1746				m->m_pkthdr.len = m->m_len = len;
1747				ifp->if_ipackets++;
1748				if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
1749					cas_rxcksum(m, CAS_GET(word4,
1750					    CAS_RC4_TCP_CSUM));
1751				/* Pass it on. */
1752				(*ifp->if_input)(ifp, m);
1753			} else
1754				ifp->if_ierrors++;
1755
1756			if ((word1 & CAS_RC1_RELEASE_HDR) != 0 &&
1757			    refcount_release(&rxds->rxds_refcount) != 0)
1758				cas_add_rxdesc(sc, idx);
1759		} else if ((len = CAS_GET(word1, CAS_RC1_DATA_SIZE)) != 0) {
1760			idx = CAS_GET(word1, CAS_RC1_DATA_INDEX);
1761			off = CAS_GET(word1, CAS_RC1_DATA_OFF);
1762#ifdef CAS_DEBUG
1763			CTR4(KTR_CAS, "%s: data at idx %d, off %d, len %d",
1764			    __func__, idx, off, len);
1765#endif
1766			rxds = &sc->sc_rxdsoft[idx];
1767			MGETHDR(m, M_DONTWAIT, MT_DATA);
1768			if (m != NULL) {
1769				refcount_acquire(&rxds->rxds_refcount);
1770				off += ETHER_ALIGN;
1771				m->m_len = min(CAS_PAGE_SIZE - off, len);
1772				bus_dmamap_sync(sc->sc_rdmatag,
1773				    rxds->rxds_dmamap, BUS_DMASYNC_POSTREAD);
1774#if __FreeBSD_version < 800016
1775				MEXTADD(m, (caddr_t)rxds->rxds_buf + off,
1776				    m->m_len, cas_free, rxds, M_RDONLY,
1777				    EXT_NET_DRV);
1778#else
1779				MEXTADD(m, (caddr_t)rxds->rxds_buf + off,
1780				    m->m_len, cas_free, sc,
1781				    (void *)(uintptr_t)idx, M_RDONLY,
1782				    EXT_NET_DRV);
1783#endif
1784				if ((m->m_flags & M_EXT) == 0) {
1785					m_freem(m);
1786					m = NULL;
1787				}
1788			}
1789			idx2 = 0;
1790			m2 = NULL;
1791			rxds2 = NULL;
1792			if ((word1 & CAS_RC1_SPLIT_PKT) != 0) {
1793				KASSERT((word1 & CAS_RC1_RELEASE_NEXT) != 0,
1794				    ("%s: split but no release next",
1795				    __func__));
1796
1797				idx2 = CAS_GET(word2, CAS_RC2_NEXT_INDEX);
1798#ifdef CAS_DEBUG
1799				CTR2(KTR_CAS, "%s: split at idx %d",
1800				    __func__, idx2);
1801#endif
1802				rxds2 = &sc->sc_rxdsoft[idx2];
1803				if (m != NULL) {
1804					MGET(m2, M_DONTWAIT, MT_DATA);
1805					if (m2 != NULL) {
1806						refcount_acquire(
1807						    &rxds2->rxds_refcount);
1808						m2->m_len = len - m->m_len;
1809						bus_dmamap_sync(
1810						    sc->sc_rdmatag,
1811						    rxds2->rxds_dmamap,
1812						    BUS_DMASYNC_POSTREAD);
1813#if __FreeBSD_version < 800016
1814						MEXTADD(m2,
1815						    (caddr_t)rxds2->rxds_buf,
1816						    m2->m_len, cas_free,
1817						    rxds2, M_RDONLY,
1818						    EXT_NET_DRV);
1819#else
1820						MEXTADD(m2,
1821						    (caddr_t)rxds2->rxds_buf,
1822						    m2->m_len, cas_free, sc,
1823						    (void *)(uintptr_t)idx2,
1824						    M_RDONLY, EXT_NET_DRV);
1825#endif
1826						if ((m2->m_flags & M_EXT) ==
1827						    0) {
1828							m_freem(m2);
1829							m2 = NULL;
1830						}
1831					}
1832				}
1833				if (m2 != NULL)
1834					m->m_next = m2;
1835				else if (m != NULL) {
1836					m_freem(m);
1837					m = NULL;
1838				}
1839			}
1840			if (m != NULL) {
1841				m->m_pkthdr.rcvif = ifp;
1842				m->m_pkthdr.len = len;
1843				ifp->if_ipackets++;
1844				if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
1845					cas_rxcksum(m, CAS_GET(word4,
1846					    CAS_RC4_TCP_CSUM));
1847				/* Pass it on. */
1848				(*ifp->if_input)(ifp, m);
1849			} else
1850				ifp->if_ierrors++;
1851
1852			if ((word1 & CAS_RC1_RELEASE_DATA) != 0 &&
1853			    refcount_release(&rxds->rxds_refcount) != 0)
1854				cas_add_rxdesc(sc, idx);
1855			if ((word1 & CAS_RC1_SPLIT_PKT) != 0 &&
1856			    refcount_release(&rxds2->rxds_refcount) != 0)
1857				cas_add_rxdesc(sc, idx2);
1858		}
1859
1860		skip = CAS_GET(word1, CAS_RC1_SKIP);
1861
1862 skip:
1863		cas_rxcompinit(&sc->sc_rxcomps[sc->sc_rxcptr]);
1864		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1865			break;
1866	}
1867	CAS_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1868	CAS_WRITE_4(sc, CAS_RX_COMP_TAIL, sc->sc_rxcptr);
1869
1870#undef PRINTWORD
1871#undef SKIPASSERT
1872#undef WORDTOH
1873
1874#ifdef CAS_DEBUG
1875	CTR4(KTR_CAS, "%s: done sc->sc_rxcptr %d, sc->sc_rxdptr %d, head %d",
1876	    __func__, sc->rxcptr, sc->sc_rxdptr,
1877	    CAS_READ_4(sc, CAS_RX_COMP_HEAD));
1878#endif
1879}
1880
1881static void
1882cas_free(void *arg1, void *arg2)
1883{
1884	struct cas_rxdsoft *rxds;
1885	struct cas_softc *sc;
1886	u_int idx;
1887
1888#if __FreeBSD_version < 800016
1889	rxds = arg2;
1890	sc = rxds->rxds_sc;
1891	idx = rxds->rxds_idx;
1892#else
1893	sc = arg1;
1894	idx = (uintptr_t)arg2;
1895	rxds = &sc->sc_rxdsoft[idx];
1896#endif
1897	if (refcount_release(&rxds->rxds_refcount) == 0)
1898		return;
1899
1900	/*
1901	 * NB: this function can be called via m_freem(9) within
1902	 * this driver!
1903	 */
1904
1905	cas_add_rxdesc(sc, idx);
1906}
1907
1908static inline void
1909cas_add_rxdesc(struct cas_softc *sc, u_int idx)
1910{
1911	u_int locked;
1912
1913	if ((locked = CAS_LOCK_OWNED(sc)) == 0)
1914		CAS_LOCK(sc);
1915
1916	bus_dmamap_sync(sc->sc_rdmatag, sc->sc_rxdsoft[idx].rxds_dmamap,
1917	    BUS_DMASYNC_PREREAD);
1918	CAS_UPDATE_RXDESC(sc, sc->sc_rxdptr, idx);
1919	sc->sc_rxdptr = CAS_NEXTRXDESC(sc->sc_rxdptr);
1920
1921	/*
1922	 * Update the RX kick register.  This register has to point to the
1923	 * descriptor after the last valid one (before the current batch)
1924	 * and for optimum performance should be incremented in multiples
1925	 * of 4 (the DMA engine fetches/updates descriptors in batches of 4).
1926	 */
1927	if ((sc->sc_rxdptr % 4) == 0) {
1928		CAS_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1929		CAS_WRITE_4(sc, CAS_RX_KICK,
1930		    (sc->sc_rxdptr + CAS_NRXDESC - 4) & CAS_NRXDESC_MASK);
1931	}
1932
1933	if (locked == 0)
1934		CAS_UNLOCK(sc);
1935}
1936
1937static void
1938cas_eint(struct cas_softc *sc, u_int status)
1939{
1940	struct ifnet *ifp = sc->sc_ifp;
1941
1942	CAS_LOCK_ASSERT(sc, MA_NOTOWNED);
1943
1944	ifp->if_ierrors++;
1945
1946	device_printf(sc->sc_dev, "%s: status 0x%x", __func__, status);
1947	if ((status & CAS_INTR_PCI_ERROR_INT) != 0) {
1948		status = CAS_READ_4(sc, CAS_ERROR_STATUS);
1949		printf(", PCI bus error 0x%x", status);
1950		if ((status & CAS_ERROR_OTHER) != 0) {
1951			status = pci_read_config(sc->sc_dev, PCIR_STATUS, 2);
1952			printf(", PCI status 0x%x", status);
1953			pci_write_config(sc->sc_dev, PCIR_STATUS, status, 2);
1954		}
1955	}
1956	printf("\n");
1957
1958	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1959	cas_init(sc);
1960	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1961		taskqueue_enqueue(sc->sc_tq, &sc->sc_tx_task);
1962}
1963
1964static int
1965cas_intr(void *v)
1966{
1967	struct cas_softc *sc = v;
1968
1969	if (__predict_false((CAS_READ_4(sc, CAS_STATUS_ALIAS) &
1970	    CAS_INTR_SUMMARY) == 0))
1971		return (FILTER_STRAY);
1972
1973	/* Disable interrupts. */
1974	CAS_WRITE_4(sc, CAS_INTMASK, 0xffffffff);
1975	taskqueue_enqueue(sc->sc_tq, &sc->sc_intr_task);
1976
1977	return (FILTER_HANDLED);
1978}
1979
1980static void
1981cas_intr_task(void *arg, int pending __unused)
1982{
1983	struct cas_softc *sc = arg;
1984	struct ifnet *ifp = sc->sc_ifp;
1985	uint32_t status, status2;
1986
1987	CAS_LOCK_ASSERT(sc, MA_NOTOWNED);
1988
1989	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1990		return;
1991
1992	status = CAS_READ_4(sc, CAS_STATUS);
1993	if (__predict_false((status & CAS_INTR_SUMMARY) == 0))
1994		goto done;
1995
1996#ifdef CAS_DEBUG
1997	CTR4(KTR_CAS, "%s: %s: cplt %x, status %x",
1998	    device_get_name(sc->sc_dev), __func__,
1999	    (status >> CAS_STATUS_TX_COMP3_SHIFT), (u_int)status);
2000
2001	/*
2002	 * PCS interrupts must be cleared, otherwise no traffic is passed!
2003	 */
2004	if ((status & CAS_INTR_PCS_INT) != 0) {
2005		status2 =
2006		    CAS_READ_4(sc, CAS_PCS_INTR_STATUS) |
2007		    CAS_READ_4(sc, CAS_PCS_INTR_STATUS);
2008		if ((status2 & CAS_PCS_INTR_LINK) != 0)
2009			device_printf(sc->sc_dev,
2010			    "%s: PCS link status changed\n", __func__);
2011	}
2012	if ((status & CAS_MAC_CTRL_STATUS) != 0) {
2013		status2 = CAS_READ_4(sc, CAS_MAC_CTRL_STATUS);
2014		if ((status2 & CAS_MAC_CTRL_PAUSE) != 0)
2015			device_printf(sc->sc_dev,
2016			    "%s: PAUSE received (PAUSE time %d slots)\n",
2017			    __func__,
2018			    (status2 & CAS_MAC_CTRL_STATUS_PT_MASK) >>
2019			    CAS_MAC_CTRL_STATUS_PT_SHFT);
2020		if ((status2 & CAS_MAC_CTRL_PAUSE) != 0)
2021			device_printf(sc->sc_dev,
2022			    "%s: transited to PAUSE state\n", __func__);
2023		if ((status2 & CAS_MAC_CTRL_NON_PAUSE) != 0)
2024			device_printf(sc->sc_dev,
2025			    "%s: transited to non-PAUSE state\n", __func__);
2026	}
2027	if ((status & CAS_INTR_MIF) != 0)
2028		device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__);
2029#endif
2030
2031	if (__predict_false((status &
2032	    (CAS_INTR_TX_TAG_ERR | CAS_INTR_RX_TAG_ERR |
2033	    CAS_INTR_RX_LEN_MMATCH | CAS_INTR_PCI_ERROR_INT)) != 0)) {
2034		cas_eint(sc, status);
2035		return;
2036	}
2037
2038	if (__predict_false(status & CAS_INTR_TX_MAC_INT)) {
2039		status2 = CAS_READ_4(sc, CAS_MAC_TX_STATUS);
2040		if ((status2 &
2041		    (CAS_MAC_TX_UNDERRUN | CAS_MAC_TX_MAX_PKT_ERR)) != 0)
2042			sc->sc_ifp->if_oerrors++;
2043		else if ((status2 & ~CAS_MAC_TX_FRAME_XMTD) != 0)
2044			device_printf(sc->sc_dev,
2045			    "MAC TX fault, status %x\n", status2);
2046	}
2047
2048	if (__predict_false(status & CAS_INTR_RX_MAC_INT)) {
2049		status2 = CAS_READ_4(sc, CAS_MAC_RX_STATUS);
2050		if ((status2 & CAS_MAC_RX_OVERFLOW) != 0)
2051			sc->sc_ifp->if_ierrors++;
2052		else if ((status2 & ~CAS_MAC_RX_FRAME_RCVD) != 0)
2053			device_printf(sc->sc_dev,
2054			    "MAC RX fault, status %x\n", status2);
2055	}
2056
2057	if ((status &
2058	    (CAS_INTR_RX_DONE | CAS_INTR_RX_BUF_NA | CAS_INTR_RX_COMP_FULL |
2059	    CAS_INTR_RX_BUF_AEMPTY | CAS_INTR_RX_COMP_AFULL)) != 0) {
2060		cas_rint(sc);
2061#ifdef CAS_DEBUG
2062		if (__predict_false((status &
2063		    (CAS_INTR_RX_BUF_NA | CAS_INTR_RX_COMP_FULL |
2064		    CAS_INTR_RX_BUF_AEMPTY | CAS_INTR_RX_COMP_AFULL)) != 0))
2065			device_printf(sc->sc_dev,
2066			    "RX fault, status %x\n", status);
2067#endif
2068	}
2069
2070	if ((status &
2071	    (CAS_INTR_TX_INT_ME | CAS_INTR_TX_ALL | CAS_INTR_TX_DONE)) != 0) {
2072		CAS_LOCK(sc);
2073		cas_tint(sc);
2074		CAS_UNLOCK(sc);
2075	}
2076
2077	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
2078		return;
2079	else if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
2080		taskqueue_enqueue(sc->sc_tq, &sc->sc_tx_task);
2081
2082	status = CAS_READ_4(sc, CAS_STATUS_ALIAS);
2083	if (__predict_false((status & CAS_INTR_SUMMARY) != 0)) {
2084		taskqueue_enqueue(sc->sc_tq, &sc->sc_intr_task);
2085		return;
2086	}
2087
2088 done:
2089	/* Re-enable interrupts. */
2090	CAS_WRITE_4(sc, CAS_INTMASK,
2091	    ~(CAS_INTR_TX_INT_ME | CAS_INTR_TX_TAG_ERR |
2092	    CAS_INTR_RX_DONE | CAS_INTR_RX_BUF_NA | CAS_INTR_RX_TAG_ERR |
2093	    CAS_INTR_RX_COMP_FULL | CAS_INTR_RX_BUF_AEMPTY |
2094	    CAS_INTR_RX_COMP_AFULL | CAS_INTR_RX_LEN_MMATCH |
2095	    CAS_INTR_PCI_ERROR_INT
2096#ifdef CAS_DEBUG
2097	    | CAS_INTR_PCS_INT | CAS_INTR_MIF
2098#endif
2099	));
2100}
2101
2102static void
2103cas_watchdog(struct cas_softc *sc)
2104{
2105	struct ifnet *ifp = sc->sc_ifp;
2106
2107	CAS_LOCK_ASSERT(sc, MA_OWNED);
2108
2109#ifdef CAS_DEBUG
2110	CTR4(KTR_CAS,
2111	    "%s: CAS_RX_CONFIG %x CAS_MAC_RX_STATUS %x CAS_MAC_RX_CONFIG %x",
2112	    __func__, CAS_READ_4(sc, CAS_RX_CONFIG),
2113	    CAS_READ_4(sc, CAS_MAC_RX_STATUS),
2114	    CAS_READ_4(sc, CAS_MAC_RX_CONFIG));
2115	CTR4(KTR_CAS,
2116	    "%s: CAS_TX_CONFIG %x CAS_MAC_TX_STATUS %x CAS_MAC_TX_CONFIG %x",
2117	    __func__, CAS_READ_4(sc, CAS_TX_CONFIG),
2118	    CAS_READ_4(sc, CAS_MAC_TX_STATUS),
2119	    CAS_READ_4(sc, CAS_MAC_TX_CONFIG));
2120#endif
2121
2122	if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0)
2123		return;
2124
2125	if ((sc->sc_flags & CAS_LINK) != 0)
2126		device_printf(sc->sc_dev, "device timeout\n");
2127	else if (bootverbose)
2128		device_printf(sc->sc_dev, "device timeout (no link)\n");
2129	++ifp->if_oerrors;
2130
2131	/* Try to get more packets going. */
2132	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
2133	cas_init_locked(sc);
2134	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
2135		taskqueue_enqueue(sc->sc_tq, &sc->sc_tx_task);
2136}
2137
2138static void
2139cas_mifinit(struct cas_softc *sc)
2140{
2141
2142	/* Configure the MIF in frame mode. */
2143	CAS_WRITE_4(sc, CAS_MIF_CONF,
2144	    CAS_READ_4(sc, CAS_MIF_CONF) & ~CAS_MIF_CONF_BB_MODE);
2145	CAS_BARRIER(sc, CAS_MIF_CONF, 4,
2146	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2147}
2148
2149/*
2150 * MII interface
2151 *
2152 * The MII interface supports at least three different operating modes:
2153 *
2154 * Bitbang mode is implemented using data, clock and output enable registers.
2155 *
2156 * Frame mode is implemented by loading a complete frame into the frame
2157 * register and polling the valid bit for completion.
2158 *
2159 * Polling mode uses the frame register but completion is indicated by
2160 * an interrupt.
2161 *
2162 */
2163static int
2164cas_mii_readreg(device_t dev, int phy, int reg)
2165{
2166	struct cas_softc *sc;
2167	int n;
2168	uint32_t v;
2169
2170#ifdef CAS_DEBUG_PHY
2171	printf("%s: phy %d reg %d\n", __func__, phy, reg);
2172#endif
2173
2174	sc = device_get_softc(dev);
2175	if (sc->sc_phyad != -1 && phy != sc->sc_phyad)
2176		return (0);
2177
2178	if ((sc->sc_flags & CAS_SERDES) != 0) {
2179		switch (reg) {
2180		case MII_BMCR:
2181			reg = CAS_PCS_CTRL;
2182			break;
2183		case MII_BMSR:
2184			reg = CAS_PCS_STATUS;
2185			break;
2186		case MII_PHYIDR1:
2187		case MII_PHYIDR2:
2188			return (0);
2189		case MII_ANAR:
2190			reg = CAS_PCS_ANAR;
2191			break;
2192		case MII_ANLPAR:
2193			reg = CAS_PCS_ANLPAR;
2194			break;
2195		case MII_EXTSR:
2196			return (EXTSR_1000XFDX | EXTSR_1000XHDX);
2197		default:
2198			device_printf(sc->sc_dev,
2199			    "%s: unhandled register %d\n", __func__, reg);
2200			return (0);
2201		}
2202		return (CAS_READ_4(sc, reg));
2203	}
2204
2205	/* Construct the frame command. */
2206	v = CAS_MIF_FRAME_READ |
2207	    (phy << CAS_MIF_FRAME_PHY_SHFT) |
2208	    (reg << CAS_MIF_FRAME_REG_SHFT);
2209
2210	CAS_WRITE_4(sc, CAS_MIF_FRAME, v);
2211	CAS_BARRIER(sc, CAS_MIF_FRAME, 4,
2212	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2213	for (n = 0; n < 100; n++) {
2214		DELAY(1);
2215		v = CAS_READ_4(sc, CAS_MIF_FRAME);
2216		if (v & CAS_MIF_FRAME_TA_LSB)
2217			return (v & CAS_MIF_FRAME_DATA);
2218	}
2219
2220	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
2221	return (0);
2222}
2223
2224static int
2225cas_mii_writereg(device_t dev, int phy, int reg, int val)
2226{
2227	struct cas_softc *sc;
2228	int n;
2229	uint32_t v;
2230
2231#ifdef CAS_DEBUG_PHY
2232	printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__);
2233#endif
2234
2235	sc = device_get_softc(dev);
2236	if (sc->sc_phyad != -1 && phy != sc->sc_phyad)
2237		return (0);
2238
2239	if ((sc->sc_flags & CAS_SERDES) != 0) {
2240		switch (reg) {
2241		case MII_BMSR:
2242			reg = CAS_PCS_STATUS;
2243			break;
2244		case MII_BMCR:
2245			reg = CAS_PCS_CTRL;
2246			if ((val & CAS_PCS_CTRL_RESET) == 0)
2247				break;
2248			CAS_WRITE_4(sc, CAS_PCS_CTRL, val);
2249			CAS_BARRIER(sc, CAS_PCS_CTRL, 4,
2250			    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2251			if (!cas_bitwait(sc, CAS_PCS_CTRL,
2252			    CAS_PCS_CTRL_RESET, 0))
2253				device_printf(sc->sc_dev,
2254				    "cannot reset PCS\n");
2255			/* FALLTHROUGH */
2256		case MII_ANAR:
2257			CAS_WRITE_4(sc, CAS_PCS_CONF, 0);
2258			CAS_BARRIER(sc, CAS_PCS_CONF, 4,
2259			    BUS_SPACE_BARRIER_WRITE);
2260			CAS_WRITE_4(sc, CAS_PCS_ANAR, val);
2261			CAS_BARRIER(sc, CAS_PCS_ANAR, 4,
2262			    BUS_SPACE_BARRIER_WRITE);
2263			CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL,
2264			    CAS_PCS_SERDES_CTRL_ESD);
2265			CAS_BARRIER(sc, CAS_PCS_CONF, 4,
2266			    BUS_SPACE_BARRIER_WRITE);
2267			CAS_WRITE_4(sc, CAS_PCS_CONF,
2268			    CAS_PCS_CONF_EN);
2269			CAS_BARRIER(sc, CAS_PCS_CONF, 4,
2270			    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2271			return (0);
2272		case MII_ANLPAR:
2273			reg = CAS_PCS_ANLPAR;
2274			break;
2275		default:
2276			device_printf(sc->sc_dev,
2277			    "%s: unhandled register %d\n", __func__, reg);
2278			return (0);
2279		}
2280		CAS_WRITE_4(sc, reg, val);
2281		CAS_BARRIER(sc, reg, 4,
2282		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2283		return (0);
2284	}
2285
2286	/* Construct the frame command. */
2287	v = CAS_MIF_FRAME_WRITE |
2288	    (phy << CAS_MIF_FRAME_PHY_SHFT) |
2289	    (reg << CAS_MIF_FRAME_REG_SHFT) |
2290	    (val & CAS_MIF_FRAME_DATA);
2291
2292	CAS_WRITE_4(sc, CAS_MIF_FRAME, v);
2293	CAS_BARRIER(sc, CAS_MIF_FRAME, 4,
2294	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2295	for (n = 0; n < 100; n++) {
2296		DELAY(1);
2297		v = CAS_READ_4(sc, CAS_MIF_FRAME);
2298		if (v & CAS_MIF_FRAME_TA_LSB)
2299			return (1);
2300	}
2301
2302	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
2303	return (0);
2304}
2305
2306static void
2307cas_mii_statchg(device_t dev)
2308{
2309	struct cas_softc *sc;
2310	struct ifnet *ifp;
2311	int gigabit;
2312	uint32_t rxcfg, txcfg, v;
2313
2314	sc = device_get_softc(dev);
2315	ifp = sc->sc_ifp;
2316
2317	CAS_LOCK_ASSERT(sc, MA_OWNED);
2318
2319#ifdef CAS_DEBUG
2320	if ((ifp->if_flags & IFF_DEBUG) != 0)
2321		device_printf(sc->sc_dev, "%s: status change: PHY = %d\n",
2322		    __func__, sc->sc_phyad);
2323#endif
2324
2325	if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 &&
2326	    IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE)
2327		sc->sc_flags |= CAS_LINK;
2328	else
2329		sc->sc_flags &= ~CAS_LINK;
2330
2331	switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) {
2332	case IFM_1000_SX:
2333	case IFM_1000_LX:
2334	case IFM_1000_CX:
2335	case IFM_1000_T:
2336		gigabit = 1;
2337		break;
2338	default:
2339		gigabit = 0;
2340	}
2341
2342	/*
2343	 * The configuration done here corresponds to the steps F) and
2344	 * G) and as far as enabling of RX and TX MAC goes also step H)
2345	 * of the initialization sequence outlined in section 11.2.1 of
2346	 * the Cassini+ ASIC Specification.
2347	 */
2348
2349	rxcfg = CAS_READ_4(sc, CAS_MAC_RX_CONF);
2350	rxcfg &= ~(CAS_MAC_RX_CONF_EN | CAS_MAC_RX_CONF_CARR);
2351	txcfg = CAS_MAC_TX_CONF_EN_IPG0 | CAS_MAC_TX_CONF_NGU |
2352	    CAS_MAC_TX_CONF_NGUL;
2353	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0)
2354		txcfg |= CAS_MAC_TX_CONF_ICARR | CAS_MAC_TX_CONF_ICOLLIS;
2355	else if (gigabit != 0) {
2356		rxcfg |= CAS_MAC_RX_CONF_CARR;
2357		txcfg |= CAS_MAC_TX_CONF_CARR;
2358	}
2359	CAS_WRITE_4(sc, CAS_MAC_TX_CONF, 0);
2360	CAS_BARRIER(sc, CAS_MAC_TX_CONF, 4,
2361	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2362	if (!cas_bitwait(sc, CAS_MAC_TX_CONF, CAS_MAC_TX_CONF_EN, 0))
2363		device_printf(sc->sc_dev, "cannot disable TX MAC\n");
2364	CAS_WRITE_4(sc, CAS_MAC_TX_CONF, txcfg);
2365	CAS_WRITE_4(sc, CAS_MAC_RX_CONF, 0);
2366	CAS_BARRIER(sc, CAS_MAC_RX_CONF, 4,
2367	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2368	if (!cas_bitwait(sc, CAS_MAC_RX_CONF, CAS_MAC_RX_CONF_EN, 0))
2369		device_printf(sc->sc_dev, "cannot disable RX MAC\n");
2370	CAS_WRITE_4(sc, CAS_MAC_RX_CONF, rxcfg);
2371
2372	v = CAS_READ_4(sc, CAS_MAC_CTRL_CONF) &
2373	    ~(CAS_MAC_CTRL_CONF_TXP | CAS_MAC_CTRL_CONF_RXP);
2374#ifdef notyet
2375	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) &
2376	    IFM_ETH_RXPAUSE) != 0)
2377		v |= CAS_MAC_CTRL_CONF_RXP;
2378	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) &
2379	    IFM_ETH_TXPAUSE) != 0)
2380		v |= CAS_MAC_CTRL_CONF_TXP;
2381#endif
2382	CAS_WRITE_4(sc, CAS_MAC_CTRL_CONF, v);
2383
2384	/*
2385	 * All supported chips have a bug causing incorrect checksum
2386	 * to be calculated when letting them strip the FCS in half-
2387	 * duplex mode.  In theory we could disable FCS stripping and
2388	 * manually adjust the checksum accordingly.  It seems to make
2389	 * more sense to optimze for the common case and just disable
2390	 * hardware checksumming in half-duplex mode though.
2391	 */
2392	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0) {
2393		ifp->if_capenable &= ~IFCAP_HWCSUM;
2394		ifp->if_hwassist = 0;
2395	} else if ((sc->sc_flags & CAS_NO_CSUM) == 0) {
2396		ifp->if_capenable = ifp->if_capabilities;
2397		ifp->if_hwassist = CAS_CSUM_FEATURES;
2398	}
2399
2400	if (sc->sc_variant == CAS_SATURN) {
2401		if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0)
2402			/* silicon bug workaround */
2403			CAS_WRITE_4(sc, CAS_MAC_PREAMBLE_LEN, 0x41);
2404		else
2405			CAS_WRITE_4(sc, CAS_MAC_PREAMBLE_LEN, 0x7);
2406	}
2407
2408	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 &&
2409	    gigabit != 0)
2410		CAS_WRITE_4(sc, CAS_MAC_SLOT_TIME,
2411		    CAS_MAC_SLOT_TIME_CARR);
2412	else
2413		CAS_WRITE_4(sc, CAS_MAC_SLOT_TIME,
2414		    CAS_MAC_SLOT_TIME_NORM);
2415
2416	/* XIF Configuration */
2417	v = CAS_MAC_XIF_CONF_TX_OE | CAS_MAC_XIF_CONF_LNKLED;
2418	if ((sc->sc_flags & CAS_SERDES) == 0) {
2419		if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0)
2420			v |= CAS_MAC_XIF_CONF_NOECHO;
2421		v |= CAS_MAC_XIF_CONF_BUF_OE;
2422	}
2423	if (gigabit != 0)
2424		v |= CAS_MAC_XIF_CONF_GMII;
2425	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0)
2426		v |= CAS_MAC_XIF_CONF_FDXLED;
2427	CAS_WRITE_4(sc, CAS_MAC_XIF_CONF, v);
2428
2429	if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
2430	    (sc->sc_flags & CAS_LINK) != 0) {
2431		CAS_WRITE_4(sc, CAS_MAC_TX_CONF,
2432		    txcfg | CAS_MAC_TX_CONF_EN);
2433		CAS_WRITE_4(sc, CAS_MAC_RX_CONF,
2434		    rxcfg | CAS_MAC_RX_CONF_EN);
2435	}
2436}
2437
2438static int
2439cas_mediachange(struct ifnet *ifp)
2440{
2441	struct cas_softc *sc = ifp->if_softc;
2442	int error;
2443
2444	/* XXX add support for serial media. */
2445
2446	CAS_LOCK(sc);
2447	error = mii_mediachg(sc->sc_mii);
2448	CAS_UNLOCK(sc);
2449	return (error);
2450}
2451
2452static void
2453cas_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
2454{
2455	struct cas_softc *sc = ifp->if_softc;
2456
2457	CAS_LOCK(sc);
2458	if ((ifp->if_flags & IFF_UP) == 0) {
2459		CAS_UNLOCK(sc);
2460		return;
2461	}
2462
2463	mii_pollstat(sc->sc_mii);
2464	ifmr->ifm_active = sc->sc_mii->mii_media_active;
2465	ifmr->ifm_status = sc->sc_mii->mii_media_status;
2466	CAS_UNLOCK(sc);
2467}
2468
2469static int
2470cas_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2471{
2472	struct cas_softc *sc = ifp->if_softc;
2473	struct ifreq *ifr = (struct ifreq *)data;
2474	int error;
2475
2476	error = 0;
2477	switch (cmd) {
2478	case SIOCSIFFLAGS:
2479		CAS_LOCK(sc);
2480		if ((ifp->if_flags & IFF_UP) != 0) {
2481			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
2482			    ((ifp->if_flags ^ sc->sc_ifflags) &
2483			    (IFF_ALLMULTI | IFF_PROMISC)) != 0)
2484				cas_setladrf(sc);
2485			else
2486				cas_init_locked(sc);
2487		} else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
2488			cas_stop(ifp);
2489		sc->sc_ifflags = ifp->if_flags;
2490		CAS_UNLOCK(sc);
2491		break;
2492	case SIOCSIFCAP:
2493		CAS_LOCK(sc);
2494		if ((sc->sc_flags & CAS_NO_CSUM) != 0) {
2495			error = EINVAL;
2496			CAS_UNLOCK(sc);
2497			break;
2498		}
2499		ifp->if_capenable = ifr->ifr_reqcap;
2500		if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
2501			ifp->if_hwassist = CAS_CSUM_FEATURES;
2502		else
2503			ifp->if_hwassist = 0;
2504		CAS_UNLOCK(sc);
2505		break;
2506	case SIOCADDMULTI:
2507	case SIOCDELMULTI:
2508		CAS_LOCK(sc);
2509		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
2510			cas_setladrf(sc);
2511		CAS_UNLOCK(sc);
2512		break;
2513	case SIOCSIFMTU:
2514		if ((ifr->ifr_mtu < ETHERMIN) ||
2515		    (ifr->ifr_mtu > ETHERMTU_JUMBO))
2516			error = EINVAL;
2517		else
2518			ifp->if_mtu = ifr->ifr_mtu;
2519		break;
2520	case SIOCGIFMEDIA:
2521	case SIOCSIFMEDIA:
2522		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd);
2523		break;
2524	default:
2525		error = ether_ioctl(ifp, cmd, data);
2526		break;
2527	}
2528
2529	return (error);
2530}
2531
2532static void
2533cas_setladrf(struct cas_softc *sc)
2534{
2535	struct ifnet *ifp = sc->sc_ifp;
2536	struct ifmultiaddr *inm;
2537	int i;
2538	uint32_t hash[16];
2539	uint32_t crc, v;
2540
2541	CAS_LOCK_ASSERT(sc, MA_OWNED);
2542
2543	/* Get the current RX configuration. */
2544	v = CAS_READ_4(sc, CAS_MAC_RX_CONF);
2545
2546	/*
2547	 * Turn off promiscuous mode, promiscuous group mode (all multicast),
2548	 * and hash filter.  Depending on the case, the right bit will be
2549	 * enabled.
2550	 */
2551	v &= ~(CAS_MAC_RX_CONF_PROMISC | CAS_MAC_RX_CONF_HFILTER |
2552	    CAS_MAC_RX_CONF_PGRP);
2553
2554	CAS_WRITE_4(sc, CAS_MAC_RX_CONF, v);
2555	CAS_BARRIER(sc, CAS_MAC_RX_CONF, 4,
2556	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
2557	if (!cas_bitwait(sc, CAS_MAC_RX_CONF, CAS_MAC_RX_CONF_HFILTER, 0))
2558		device_printf(sc->sc_dev, "cannot disable RX hash filter\n");
2559
2560	if ((ifp->if_flags & IFF_PROMISC) != 0) {
2561		v |= CAS_MAC_RX_CONF_PROMISC;
2562		goto chipit;
2563	}
2564	if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
2565		v |= CAS_MAC_RX_CONF_PGRP;
2566		goto chipit;
2567	}
2568
2569	/*
2570	 * Set up multicast address filter by passing all multicast
2571	 * addresses through a crc generator, and then using the high
2572	 * order 8 bits as an index into the 256 bit logical address
2573	 * filter.  The high order 4 bits selects the word, while the
2574	 * other 4 bits select the bit within the word (where bit 0
2575	 * is the MSB).
2576	 */
2577
2578	/* Clear the hash table. */
2579	memset(hash, 0, sizeof(hash));
2580
2581	if_maddr_rlock(ifp);
2582	TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
2583		if (inm->ifma_addr->sa_family != AF_LINK)
2584			continue;
2585		crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
2586		    inm->ifma_addr), ETHER_ADDR_LEN);
2587
2588		/* We just want the 8 most significant bits. */
2589		crc >>= 24;
2590
2591		/* Set the corresponding bit in the filter. */
2592		hash[crc >> 4] |= 1 << (15 - (crc & 15));
2593	}
2594	if_maddr_runlock(ifp);
2595
2596	v |= CAS_MAC_RX_CONF_HFILTER;
2597
2598	/* Now load the hash table into the chip (if we are using it). */
2599	for (i = 0; i < 16; i++)
2600		CAS_WRITE_4(sc,
2601		    CAS_MAC_HASH0 + i * (CAS_MAC_HASH1 - CAS_MAC_HASH0),
2602		    hash[i]);
2603
2604 chipit:
2605	CAS_WRITE_4(sc, CAS_MAC_RX_CONF, v);
2606}
2607
2608static int	cas_pci_attach(device_t dev);
2609static int	cas_pci_detach(device_t dev);
2610static int	cas_pci_probe(device_t dev);
2611static int	cas_pci_resume(device_t dev);
2612static int	cas_pci_suspend(device_t dev);
2613
2614static device_method_t cas_pci_methods[] = {
2615	/* Device interface */
2616	DEVMETHOD(device_probe,		cas_pci_probe),
2617	DEVMETHOD(device_attach,	cas_pci_attach),
2618	DEVMETHOD(device_detach,	cas_pci_detach),
2619	DEVMETHOD(device_suspend,	cas_pci_suspend),
2620	DEVMETHOD(device_resume,	cas_pci_resume),
2621	/* Use the suspend handler here, it is all that is required. */
2622	DEVMETHOD(device_shutdown,	cas_pci_suspend),
2623
2624	/* bus interface */
2625	DEVMETHOD(bus_print_child,	bus_generic_print_child),
2626	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
2627
2628	/* MII interface */
2629	DEVMETHOD(miibus_readreg,	cas_mii_readreg),
2630	DEVMETHOD(miibus_writereg,	cas_mii_writereg),
2631	DEVMETHOD(miibus_statchg,	cas_mii_statchg),
2632
2633	KOBJMETHOD_END
2634};
2635
2636static driver_t cas_pci_driver = {
2637	"cas",
2638	cas_pci_methods,
2639	sizeof(struct cas_softc)
2640};
2641
2642DRIVER_MODULE(cas, pci, cas_pci_driver, cas_devclass, 0, 0);
2643DRIVER_MODULE(miibus, cas, miibus_driver, miibus_devclass, 0, 0);
2644MODULE_DEPEND(cas, pci, 1, 1, 1);
2645
2646static const struct cas_pci_dev {
2647	uint32_t	cpd_devid;
2648	uint8_t		cpd_revid;
2649	int		cpd_variant;
2650	const char	*cpd_desc;
2651} const cas_pci_devlist[] = {
2652	{ 0x0035100b, 0x0, CAS_SATURN, "NS DP83065 Saturn Gigabit Ethernet" },
2653	{ 0xabba108e, 0x10, CAS_CASPLUS, "Sun Cassini+ Gigabit Ethernet" },
2654	{ 0xabba108e, 0x0, CAS_CAS, "Sun Cassini Gigabit Ethernet" },
2655	{ 0, 0, 0, NULL }
2656};
2657
2658static int
2659cas_pci_probe(device_t dev)
2660{
2661	int i;
2662
2663	for (i = 0; cas_pci_devlist[i].cpd_desc != NULL; i++) {
2664		if (pci_get_devid(dev) == cas_pci_devlist[i].cpd_devid &&
2665		    pci_get_revid(dev) >= cas_pci_devlist[i].cpd_revid) {
2666			device_set_desc(dev, cas_pci_devlist[i].cpd_desc);
2667			return (BUS_PROBE_DEFAULT);
2668		}
2669	}
2670
2671	return (ENXIO);
2672}
2673
2674static struct resource_spec cas_pci_res_spec[] = {
2675	{ SYS_RES_IRQ, 0, RF_SHAREABLE | RF_ACTIVE },	/* CAS_RES_INTR */
2676	{ SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE },	/* CAS_RES_MEM */
2677	{ -1, 0 }
2678};
2679
2680#define	CAS_LOCAL_MAC_ADDRESS	"local-mac-address"
2681#define	CAS_PHY_INTERFACE	"phy-interface"
2682#define	CAS_PHY_TYPE		"phy-type"
2683#define	CAS_PHY_TYPE_PCS	"pcs"
2684
2685static int
2686cas_pci_attach(device_t dev)
2687{
2688	char buf[sizeof(CAS_LOCAL_MAC_ADDRESS)];
2689	struct cas_softc *sc;
2690	int i;
2691#if !(defined(__powerpc__) || defined(__sparc64__))
2692	u_char enaddr[4][ETHER_ADDR_LEN];
2693	u_int j, k, lma, pcs[4], phy;
2694#endif
2695
2696	sc = device_get_softc(dev);
2697	sc->sc_variant = CAS_UNKNOWN;
2698	for (i = 0; cas_pci_devlist[i].cpd_desc != NULL; i++) {
2699		if (pci_get_devid(dev) == cas_pci_devlist[i].cpd_devid &&
2700		    pci_get_revid(dev) >= cas_pci_devlist[i].cpd_revid) {
2701			sc->sc_variant = cas_pci_devlist[i].cpd_variant;
2702			break;
2703		}
2704	}
2705	if (sc->sc_variant == CAS_UNKNOWN) {
2706		device_printf(dev, "unknown adaptor\n");
2707		return (ENXIO);
2708	}
2709
2710	pci_enable_busmaster(dev);
2711
2712	sc->sc_dev = dev;
2713	if (sc->sc_variant == CAS_CAS && pci_get_devid(dev) < 0x02)
2714		/* Hardware checksumming may hang TX. */
2715		sc->sc_flags |= CAS_NO_CSUM;
2716	if (sc->sc_variant == CAS_CASPLUS || sc->sc_variant == CAS_SATURN)
2717		sc->sc_flags |= CAS_REG_PLUS;
2718	if (sc->sc_variant == CAS_CAS ||
2719	    (sc->sc_variant == CAS_CASPLUS && pci_get_revid(dev) < 0x11))
2720		sc->sc_flags |= CAS_TABORT;
2721	if (bootverbose)
2722		device_printf(dev, "flags=0x%x\n", sc->sc_flags);
2723
2724	if (bus_alloc_resources(dev, cas_pci_res_spec, sc->sc_res)) {
2725		device_printf(dev, "failed to allocate resources\n");
2726		bus_release_resources(dev, cas_pci_res_spec, sc->sc_res);
2727		return (ENXIO);
2728	}
2729
2730	CAS_LOCK_INIT(sc, device_get_nameunit(dev));
2731
2732#if defined(__powerpc__) || defined(__sparc64__)
2733	OF_getetheraddr(dev, sc->sc_enaddr);
2734	if (OF_getprop(ofw_bus_get_node(dev), CAS_PHY_INTERFACE, buf,
2735	    sizeof(buf)) > 0 || OF_getprop(ofw_bus_get_node(dev),
2736	    CAS_PHY_TYPE, buf, sizeof(buf)) > 0) {
2737		buf[sizeof(buf) - 1] = '\0';
2738		if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0)
2739			sc->sc_flags |= CAS_SERDES;
2740	}
2741#else
2742	/*
2743	 * Dig out VPD (vital product data) and read the MAC address as well
2744	 * as the PHY type.  The VPD resides in the PCI Expansion ROM (PCI
2745	 * FCode) and can't be accessed via the PCI capability pointer.
2746	 * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format described
2747	 * in the free US Patent 7149820.
2748	 */
2749
2750#define	PCI_ROMHDR_SIZE			0x1c
2751#define	PCI_ROMHDR_SIG			0x00
2752#define	PCI_ROMHDR_SIG_MAGIC		0xaa55		/* little endian */
2753#define	PCI_ROMHDR_PTR_DATA		0x18
2754#define	PCI_ROM_SIZE			0x18
2755#define	PCI_ROM_SIG			0x00
2756#define	PCI_ROM_SIG_MAGIC		0x52494350	/* "PCIR", endian */
2757							/* reversed */
2758#define	PCI_ROM_VENDOR			0x04
2759#define	PCI_ROM_DEVICE			0x06
2760#define	PCI_ROM_PTR_VPD			0x08
2761#define	PCI_VPDRES_BYTE0		0x00
2762#define	PCI_VPDRES_ISLARGE(x)		((x) & 0x80)
2763#define	PCI_VPDRES_LARGE_NAME(x)	((x) & 0x7f)
2764#define	PCI_VPDRES_LARGE_LEN_LSB	0x01
2765#define	PCI_VPDRES_LARGE_LEN_MSB	0x02
2766#define	PCI_VPDRES_LARGE_SIZE		0x03
2767#define	PCI_VPDRES_TYPE_ID_STRING	0x02		/* large */
2768#define	PCI_VPDRES_TYPE_VPD		0x10		/* large */
2769#define	PCI_VPD_KEY0			0x00
2770#define	PCI_VPD_KEY1			0x01
2771#define	PCI_VPD_LEN			0x02
2772#define	PCI_VPD_SIZE			0x03
2773
2774#define	CAS_ROM_READ_1(sc, offs)					\
2775	CAS_READ_1((sc), CAS_PCI_ROM_OFFSET + (offs))
2776#define	CAS_ROM_READ_2(sc, offs)					\
2777	CAS_READ_2((sc), CAS_PCI_ROM_OFFSET + (offs))
2778#define	CAS_ROM_READ_4(sc, offs)					\
2779	CAS_READ_4((sc), CAS_PCI_ROM_OFFSET + (offs))
2780
2781	lma = phy = 0;
2782	memset(enaddr, 0, sizeof(enaddr));
2783	memset(pcs, 0, sizeof(pcs));
2784
2785	/* Enable PCI Expansion ROM access. */
2786	CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN,
2787	    CAS_BIM_LDEV_OEN_PAD | CAS_BIM_LDEV_OEN_PROM);
2788
2789	/* Read PCI Expansion ROM header. */
2790	if (CAS_ROM_READ_2(sc, PCI_ROMHDR_SIG) != PCI_ROMHDR_SIG_MAGIC ||
2791	    (i = CAS_ROM_READ_2(sc, PCI_ROMHDR_PTR_DATA)) <
2792	    PCI_ROMHDR_SIZE) {
2793		device_printf(dev, "unexpected PCI Expansion ROM header\n");
2794		goto fail_prom;
2795	}
2796
2797	/* Read PCI Expansion ROM data. */
2798	if (CAS_ROM_READ_4(sc, i + PCI_ROM_SIG) != PCI_ROM_SIG_MAGIC ||
2799	    CAS_ROM_READ_2(sc, i + PCI_ROM_VENDOR) != pci_get_vendor(dev) ||
2800	    CAS_ROM_READ_2(sc, i + PCI_ROM_DEVICE) != pci_get_device(dev) ||
2801	    (j = CAS_ROM_READ_2(sc, i + PCI_ROM_PTR_VPD)) <
2802	    i + PCI_ROM_SIZE) {
2803		device_printf(dev, "unexpected PCI Expansion ROM data\n");
2804		goto fail_prom;
2805	}
2806
2807	/* Read PCI VPD. */
2808 next:
2809	if (PCI_VPDRES_ISLARGE(CAS_ROM_READ_1(sc,
2810	    j + PCI_VPDRES_BYTE0)) == 0) {
2811		device_printf(dev, "no large PCI VPD\n");
2812		goto fail_prom;
2813	}
2814
2815	i = (CAS_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_MSB) << 8) |
2816	    CAS_ROM_READ_1(sc, j + PCI_VPDRES_LARGE_LEN_LSB);
2817	switch (PCI_VPDRES_LARGE_NAME(CAS_ROM_READ_1(sc,
2818	    j + PCI_VPDRES_BYTE0))) {
2819	case PCI_VPDRES_TYPE_ID_STRING:
2820		/* Skip identifier string. */
2821		j += PCI_VPDRES_LARGE_SIZE + i;
2822		goto next;
2823	case PCI_VPDRES_TYPE_VPD:
2824		for (j += PCI_VPDRES_LARGE_SIZE; i > 0;
2825		    i -= PCI_VPD_SIZE + CAS_ROM_READ_1(sc, j + PCI_VPD_LEN),
2826		    j += PCI_VPD_SIZE + CAS_ROM_READ_1(sc, j + PCI_VPD_LEN)) {
2827			if (CAS_ROM_READ_1(sc, j + PCI_VPD_KEY0) != 'Z')
2828				/* no Enhanced VPD */
2829				continue;
2830			if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE) != 'I')
2831				/* no instance property */
2832				continue;
2833			if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) == 'B') {
2834				/* byte array */
2835				if (CAS_ROM_READ_1(sc,
2836				    j + PCI_VPD_SIZE + 4) != ETHER_ADDR_LEN)
2837					continue;
2838				bus_read_region_1(sc->sc_res[CAS_RES_MEM],
2839				    CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5,
2840				    buf, sizeof(buf));
2841				buf[sizeof(buf) - 1] = '\0';
2842				if (strcmp(buf, CAS_LOCAL_MAC_ADDRESS) != 0)
2843					continue;
2844				bus_read_region_1(sc->sc_res[CAS_RES_MEM],
2845				    CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE +
2846				    5 + sizeof(CAS_LOCAL_MAC_ADDRESS),
2847				    enaddr[lma], sizeof(enaddr[lma]));
2848				lma++;
2849				if (lma == 4 && phy == 4)
2850					break;
2851			} else if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) ==
2852			   'S') {
2853				/* string */
2854				if (CAS_ROM_READ_1(sc,
2855				    j + PCI_VPD_SIZE + 4) !=
2856				    sizeof(CAS_PHY_TYPE_PCS))
2857					continue;
2858				bus_read_region_1(sc->sc_res[CAS_RES_MEM],
2859				    CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5,
2860				    buf, sizeof(buf));
2861				buf[sizeof(buf) - 1] = '\0';
2862				if (strcmp(buf, CAS_PHY_INTERFACE) == 0)
2863					k = sizeof(CAS_PHY_INTERFACE);
2864				else if (strcmp(buf, CAS_PHY_TYPE) == 0)
2865					k = sizeof(CAS_PHY_TYPE);
2866				else
2867					continue;
2868				bus_read_region_1(sc->sc_res[CAS_RES_MEM],
2869				    CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE +
2870				    5 + k, buf, sizeof(buf));
2871				buf[sizeof(buf) - 1] = '\0';
2872				if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0)
2873					pcs[phy] = 1;
2874				phy++;
2875				if (lma == 4 && phy == 4)
2876					break;
2877			}
2878		}
2879		break;
2880	default:
2881		device_printf(dev, "unexpected PCI VPD\n");
2882		goto fail_prom;
2883	}
2884
2885 fail_prom:
2886	CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN, 0);
2887
2888	if (lma == 0) {
2889		device_printf(dev, "could not determine Ethernet address\n");
2890		goto fail;
2891	}
2892	i = 0;
2893	if (lma > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr))
2894		i = pci_get_slot(dev);
2895	memcpy(sc->sc_enaddr, enaddr[i], ETHER_ADDR_LEN);
2896
2897	if (phy == 0) {
2898		device_printf(dev, "could not determine PHY type\n");
2899		goto fail;
2900	}
2901	i = 0;
2902	if (phy > 1 && pci_get_slot(dev) < sizeof(pcs) / sizeof(*pcs))
2903		i = pci_get_slot(dev);
2904	if (pcs[i] != 0)
2905		sc->sc_flags |= CAS_SERDES;
2906#endif
2907
2908	if (cas_attach(sc) != 0) {
2909		device_printf(dev, "could not be attached\n");
2910		goto fail;
2911	}
2912
2913	if (bus_setup_intr(dev, sc->sc_res[CAS_RES_INTR], INTR_TYPE_NET |
2914	    INTR_MPSAFE, cas_intr, NULL, sc, &sc->sc_ih) != 0) {
2915		device_printf(dev, "failed to set up interrupt\n");
2916		cas_detach(sc);
2917		goto fail;
2918	}
2919	return (0);
2920
2921 fail:
2922	CAS_LOCK_DESTROY(sc);
2923	bus_release_resources(dev, cas_pci_res_spec, sc->sc_res);
2924	return (ENXIO);
2925}
2926
2927static int
2928cas_pci_detach(device_t dev)
2929{
2930	struct cas_softc *sc;
2931
2932	sc = device_get_softc(dev);
2933	bus_teardown_intr(dev, sc->sc_res[CAS_RES_INTR], sc->sc_ih);
2934	cas_detach(sc);
2935	CAS_LOCK_DESTROY(sc);
2936	bus_release_resources(dev, cas_pci_res_spec, sc->sc_res);
2937	return (0);
2938}
2939
2940static int
2941cas_pci_suspend(device_t dev)
2942{
2943
2944	cas_suspend(device_get_softc(dev));
2945	return (0);
2946}
2947
2948static int
2949cas_pci_resume(device_t dev)
2950{
2951
2952	cas_resume(device_get_softc(dev));
2953	return (0);
2954}
2955