if_stge.c revision 215297
1160641Syongari/*	$NetBSD: if_stge.c,v 1.32 2005/12/11 12:22:49 christos Exp $	*/
2160641Syongari
3160641Syongari/*-
4160641Syongari * Copyright (c) 2001 The NetBSD Foundation, Inc.
5160641Syongari * All rights reserved.
6160641Syongari *
7160641Syongari * This code is derived from software contributed to The NetBSD Foundation
8160641Syongari * by Jason R. Thorpe.
9160641Syongari *
10160641Syongari * Redistribution and use in source and binary forms, with or without
11160641Syongari * modification, are permitted provided that the following conditions
12160641Syongari * are met:
13160641Syongari * 1. Redistributions of source code must retain the above copyright
14160641Syongari *    notice, this list of conditions and the following disclaimer.
15160641Syongari * 2. Redistributions in binary form must reproduce the above copyright
16160641Syongari *    notice, this list of conditions and the following disclaimer in the
17160641Syongari *    documentation and/or other materials provided with the distribution.
18160641Syongari *
19160641Syongari * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20160641Syongari * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21160641Syongari * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22160641Syongari * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23160641Syongari * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24160641Syongari * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25160641Syongari * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26160641Syongari * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27160641Syongari * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28160641Syongari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29160641Syongari * POSSIBILITY OF SUCH DAMAGE.
30160641Syongari */
31160641Syongari
32160641Syongari/*
33160641Syongari * Device driver for the Sundance Tech. TC9021 10/100/1000
34160641Syongari * Ethernet controller.
35160641Syongari */
36160641Syongari
37160641Syongari#include <sys/cdefs.h>
38160641Syongari__FBSDID("$FreeBSD: head/sys/dev/stge/if_stge.c 215297 2010-11-14 13:26:10Z marius $");
39160641Syongari
40160641Syongari#ifdef HAVE_KERNEL_OPTION_HEADERS
41160641Syongari#include "opt_device_polling.h"
42160641Syongari#endif
43160641Syongari
44160641Syongari#include <sys/param.h>
45160641Syongari#include <sys/systm.h>
46160641Syongari#include <sys/endian.h>
47160641Syongari#include <sys/mbuf.h>
48160641Syongari#include <sys/malloc.h>
49160641Syongari#include <sys/kernel.h>
50160641Syongari#include <sys/module.h>
51160641Syongari#include <sys/socket.h>
52160641Syongari#include <sys/sockio.h>
53160641Syongari#include <sys/sysctl.h>
54160641Syongari#include <sys/taskqueue.h>
55160641Syongari
56160641Syongari#include <net/bpf.h>
57160641Syongari#include <net/ethernet.h>
58160641Syongari#include <net/if.h>
59160641Syongari#include <net/if_dl.h>
60160641Syongari#include <net/if_media.h>
61160641Syongari#include <net/if_types.h>
62160641Syongari#include <net/if_vlan_var.h>
63160641Syongari
64160641Syongari#include <machine/bus.h>
65160641Syongari#include <machine/resource.h>
66160641Syongari#include <sys/bus.h>
67160641Syongari#include <sys/rman.h>
68160641Syongari
69160641Syongari#include <dev/mii/mii.h>
70160641Syongari#include <dev/mii/miivar.h>
71160641Syongari
72160641Syongari#include <dev/pci/pcireg.h>
73160641Syongari#include <dev/pci/pcivar.h>
74160641Syongari
75160641Syongari#include <dev/stge/if_stgereg.h>
76160641Syongari
77160641Syongari#define	STGE_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
78160641Syongari
79160641SyongariMODULE_DEPEND(stge, pci, 1, 1, 1);
80160641SyongariMODULE_DEPEND(stge, ether, 1, 1, 1);
81160641SyongariMODULE_DEPEND(stge, miibus, 1, 1, 1);
82160641Syongari
83160641Syongari/* "device miibus" required.  See GENERIC if you get errors here. */
84160641Syongari#include "miibus_if.h"
85160641Syongari
86160641Syongari/*
87160641Syongari * Devices supported by this driver.
88160641Syongari */
89160641Syongaristatic struct stge_product {
90160641Syongari	uint16_t	stge_vendorid;
91160641Syongari	uint16_t	stge_deviceid;
92160641Syongari	const char	*stge_name;
93160641Syongari} stge_products[] = {
94160641Syongari	{ VENDOR_SUNDANCETI,	DEVICEID_SUNDANCETI_ST1023,
95160641Syongari	  "Sundance ST-1023 Gigabit Ethernet" },
96160641Syongari
97160641Syongari	{ VENDOR_SUNDANCETI,	DEVICEID_SUNDANCETI_ST2021,
98160641Syongari	  "Sundance ST-2021 Gigabit Ethernet" },
99160641Syongari
100160641Syongari	{ VENDOR_TAMARACK,	DEVICEID_TAMARACK_TC9021,
101160641Syongari	  "Tamarack TC9021 Gigabit Ethernet" },
102160641Syongari
103160641Syongari	{ VENDOR_TAMARACK,	DEVICEID_TAMARACK_TC9021_ALT,
104160641Syongari	  "Tamarack TC9021 Gigabit Ethernet" },
105160641Syongari
106160641Syongari	/*
107160641Syongari	 * The Sundance sample boards use the Sundance vendor ID,
108160641Syongari	 * but the Tamarack product ID.
109160641Syongari	 */
110160641Syongari	{ VENDOR_SUNDANCETI,	DEVICEID_TAMARACK_TC9021,
111160641Syongari	  "Sundance TC9021 Gigabit Ethernet" },
112160641Syongari
113160641Syongari	{ VENDOR_SUNDANCETI,	DEVICEID_TAMARACK_TC9021_ALT,
114160641Syongari	  "Sundance TC9021 Gigabit Ethernet" },
115160641Syongari
116160641Syongari	{ VENDOR_DLINK,		DEVICEID_DLINK_DL4000,
117160641Syongari	  "D-Link DL-4000 Gigabit Ethernet" },
118160641Syongari
119160641Syongari	{ VENDOR_ANTARES,	DEVICEID_ANTARES_TC9021,
120160641Syongari	  "Antares Gigabit Ethernet" }
121160641Syongari};
122160641Syongari
123160641Syongaristatic int	stge_probe(device_t);
124160641Syongaristatic int	stge_attach(device_t);
125160641Syongaristatic int	stge_detach(device_t);
126173839Syongaristatic int	stge_shutdown(device_t);
127160641Syongaristatic int	stge_suspend(device_t);
128160641Syongaristatic int	stge_resume(device_t);
129160641Syongari
130160641Syongaristatic int	stge_encap(struct stge_softc *, struct mbuf **);
131160641Syongaristatic void	stge_start(struct ifnet *);
132160641Syongaristatic void	stge_start_locked(struct ifnet *);
133169157Syongaristatic void	stge_watchdog(struct stge_softc *);
134160641Syongaristatic int	stge_ioctl(struct ifnet *, u_long, caddr_t);
135160641Syongaristatic void	stge_init(void *);
136160641Syongaristatic void	stge_init_locked(struct stge_softc *);
137160641Syongaristatic void	stge_vlan_setup(struct stge_softc *);
138160641Syongaristatic void	stge_stop(struct stge_softc *);
139160641Syongaristatic void	stge_start_tx(struct stge_softc *);
140160641Syongaristatic void	stge_start_rx(struct stge_softc *);
141160641Syongaristatic void	stge_stop_tx(struct stge_softc *);
142160641Syongaristatic void	stge_stop_rx(struct stge_softc *);
143160641Syongari
144160641Syongaristatic void	stge_reset(struct stge_softc *, uint32_t);
145160641Syongaristatic int	stge_eeprom_wait(struct stge_softc *);
146160641Syongaristatic void	stge_read_eeprom(struct stge_softc *, int, uint16_t *);
147160641Syongaristatic void	stge_tick(void *);
148160641Syongaristatic void	stge_stats_update(struct stge_softc *);
149160641Syongaristatic void	stge_set_filter(struct stge_softc *);
150160641Syongaristatic void	stge_set_multi(struct stge_softc *);
151160641Syongari
152160641Syongaristatic void	stge_link_task(void *, int);
153160641Syongaristatic void	stge_intr(void *);
154160641Syongaristatic __inline int stge_tx_error(struct stge_softc *);
155160641Syongaristatic void	stge_txeof(struct stge_softc *);
156193096Sattiliostatic int	stge_rxeof(struct stge_softc *);
157160641Syongaristatic __inline void stge_discard_rxbuf(struct stge_softc *, int);
158160641Syongaristatic int	stge_newbuf(struct stge_softc *, int);
159160641Syongari#ifndef __NO_STRICT_ALIGNMENT
160160641Syongaristatic __inline struct mbuf *stge_fixup_rx(struct stge_softc *, struct mbuf *);
161160641Syongari#endif
162160641Syongari
163160641Syongaristatic void	stge_mii_sync(struct stge_softc *);
164160641Syongaristatic void	stge_mii_send(struct stge_softc *, uint32_t, int);
165160641Syongaristatic int	stge_mii_readreg(struct stge_softc *, struct stge_mii_frame *);
166160641Syongaristatic int	stge_mii_writereg(struct stge_softc *, struct stge_mii_frame *);
167160641Syongaristatic int	stge_miibus_readreg(device_t, int, int);
168160641Syongaristatic int	stge_miibus_writereg(device_t, int, int, int);
169160641Syongaristatic void	stge_miibus_statchg(device_t);
170160641Syongaristatic int	stge_mediachange(struct ifnet *);
171160641Syongaristatic void	stge_mediastatus(struct ifnet *, struct ifmediareq *);
172160641Syongari
173160641Syongaristatic void	stge_dmamap_cb(void *, bus_dma_segment_t *, int, int);
174160641Syongaristatic int	stge_dma_alloc(struct stge_softc *);
175160641Syongaristatic void	stge_dma_free(struct stge_softc *);
176160641Syongaristatic void	stge_dma_wait(struct stge_softc *);
177160641Syongaristatic void	stge_init_tx_ring(struct stge_softc *);
178160641Syongaristatic int	stge_init_rx_ring(struct stge_softc *);
179160641Syongari#ifdef DEVICE_POLLING
180193096Sattiliostatic int	stge_poll(struct ifnet *, enum poll_cmd, int);
181160641Syongari#endif
182160641Syongari
183175315Syongaristatic void	stge_setwol(struct stge_softc *);
184160641Syongaristatic int	sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
185160641Syongaristatic int	sysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS);
186160641Syongaristatic int	sysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS);
187160641Syongari
188160641Syongaristatic device_method_t stge_methods[] = {
189160641Syongari	/* Device interface */
190160641Syongari	DEVMETHOD(device_probe,		stge_probe),
191160641Syongari	DEVMETHOD(device_attach,	stge_attach),
192160641Syongari	DEVMETHOD(device_detach,	stge_detach),
193160641Syongari	DEVMETHOD(device_shutdown,	stge_shutdown),
194160641Syongari	DEVMETHOD(device_suspend,	stge_suspend),
195160641Syongari	DEVMETHOD(device_resume,	stge_resume),
196160641Syongari
197160641Syongari	/* MII interface */
198160641Syongari	DEVMETHOD(miibus_readreg,	stge_miibus_readreg),
199160641Syongari	DEVMETHOD(miibus_writereg,	stge_miibus_writereg),
200160641Syongari	DEVMETHOD(miibus_statchg,	stge_miibus_statchg),
201160641Syongari
202160641Syongari	{ 0, 0 }
203160641Syongari
204160641Syongari};
205160641Syongari
206160641Syongaristatic driver_t stge_driver = {
207160641Syongari	"stge",
208160641Syongari	stge_methods,
209160641Syongari	sizeof(struct stge_softc)
210160641Syongari};
211160641Syongari
212160641Syongaristatic devclass_t stge_devclass;
213160641Syongari
214160641SyongariDRIVER_MODULE(stge, pci, stge_driver, stge_devclass, 0, 0);
215160641SyongariDRIVER_MODULE(miibus, stge, miibus_driver, miibus_devclass, 0, 0);
216160641Syongari
217160641Syongaristatic struct resource_spec stge_res_spec_io[] = {
218160641Syongari	{ SYS_RES_IOPORT,	PCIR_BAR(0),	RF_ACTIVE },
219160641Syongari	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
220160641Syongari	{ -1,			0,		0 }
221160641Syongari};
222160641Syongari
223160641Syongaristatic struct resource_spec stge_res_spec_mem[] = {
224160641Syongari	{ SYS_RES_MEMORY,	PCIR_BAR(1),	RF_ACTIVE },
225160641Syongari	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
226160641Syongari	{ -1,			0,		0 }
227160641Syongari};
228160641Syongari
229160641Syongari#define	MII_SET(x)	\
230160641Syongari	CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) | (x))
231160641Syongari#define	MII_CLR(x)	\
232160641Syongari	CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) & ~(x))
233160641Syongari
234160641Syongari/*
235160641Syongari * Sync the PHYs by setting data bit and strobing the clock 32 times.
236160641Syongari */
237160641Syongaristatic void
238160641Syongaristge_mii_sync(struct stge_softc	*sc)
239160641Syongari{
240160641Syongari	int i;
241160641Syongari
242160641Syongari	MII_SET(PC_MgmtDir | PC_MgmtData);
243160641Syongari
244160641Syongari	for (i = 0; i < 32; i++) {
245160641Syongari		MII_SET(PC_MgmtClk);
246160641Syongari		DELAY(1);
247160641Syongari		MII_CLR(PC_MgmtClk);
248160641Syongari		DELAY(1);
249160641Syongari	}
250160641Syongari}
251160641Syongari
252160641Syongari/*
253160641Syongari * Clock a series of bits through the MII.
254160641Syongari */
255160641Syongaristatic void
256160641Syongaristge_mii_send(struct stge_softc *sc, uint32_t bits, int cnt)
257160641Syongari{
258160641Syongari	int i;
259160641Syongari
260160641Syongari	MII_CLR(PC_MgmtClk);
261160641Syongari
262160641Syongari	for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
263160641Syongari		if (bits & i)
264160641Syongari			MII_SET(PC_MgmtData);
265160641Syongari                else
266160641Syongari			MII_CLR(PC_MgmtData);
267160641Syongari		DELAY(1);
268160641Syongari		MII_CLR(PC_MgmtClk);
269160641Syongari		DELAY(1);
270160641Syongari		MII_SET(PC_MgmtClk);
271160641Syongari	}
272160641Syongari}
273160641Syongari
274160641Syongari/*
275160641Syongari * Read an PHY register through the MII.
276160641Syongari */
277160641Syongaristatic int
278160641Syongaristge_mii_readreg(struct stge_softc *sc, struct stge_mii_frame *frame)
279160641Syongari{
280160641Syongari	int i, ack;
281160641Syongari
282160641Syongari	/*
283160641Syongari	 * Set up frame for RX.
284160641Syongari	 */
285160641Syongari	frame->mii_stdelim = STGE_MII_STARTDELIM;
286160641Syongari	frame->mii_opcode = STGE_MII_READOP;
287160641Syongari	frame->mii_turnaround = 0;
288160641Syongari	frame->mii_data = 0;
289160641Syongari
290160641Syongari	CSR_WRITE_1(sc, STGE_PhyCtrl, 0 | sc->sc_PhyCtrl);
291160641Syongari	/*
292160641Syongari 	 * Turn on data xmit.
293160641Syongari	 */
294160641Syongari	MII_SET(PC_MgmtDir);
295160641Syongari
296160641Syongari	stge_mii_sync(sc);
297160641Syongari
298160641Syongari	/*
299160641Syongari	 * Send command/address info.
300160641Syongari	 */
301160641Syongari	stge_mii_send(sc, frame->mii_stdelim, 2);
302160641Syongari	stge_mii_send(sc, frame->mii_opcode, 2);
303160641Syongari	stge_mii_send(sc, frame->mii_phyaddr, 5);
304160641Syongari	stge_mii_send(sc, frame->mii_regaddr, 5);
305160641Syongari
306160641Syongari	/* Turn off xmit. */
307160641Syongari	MII_CLR(PC_MgmtDir);
308160641Syongari
309160641Syongari	/* Idle bit */
310160641Syongari	MII_CLR((PC_MgmtClk | PC_MgmtData));
311160641Syongari	DELAY(1);
312160641Syongari	MII_SET(PC_MgmtClk);
313160641Syongari	DELAY(1);
314160641Syongari
315160641Syongari	/* Check for ack */
316160641Syongari	MII_CLR(PC_MgmtClk);
317160641Syongari	DELAY(1);
318160641Syongari	ack = CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData;
319160641Syongari	MII_SET(PC_MgmtClk);
320160641Syongari	DELAY(1);
321160641Syongari
322160641Syongari	/*
323160641Syongari	 * Now try reading data bits. If the ack failed, we still
324160641Syongari	 * need to clock through 16 cycles to keep the PHY(s) in sync.
325160641Syongari	 */
326160641Syongari	if (ack) {
327160641Syongari		for(i = 0; i < 16; i++) {
328160641Syongari			MII_CLR(PC_MgmtClk);
329160641Syongari			DELAY(1);
330160641Syongari			MII_SET(PC_MgmtClk);
331160641Syongari			DELAY(1);
332160641Syongari		}
333160641Syongari		goto fail;
334160641Syongari	}
335160641Syongari
336160641Syongari	for (i = 0x8000; i; i >>= 1) {
337160641Syongari		MII_CLR(PC_MgmtClk);
338160641Syongari		DELAY(1);
339160641Syongari		if (!ack) {
340160641Syongari			if (CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData)
341160641Syongari				frame->mii_data |= i;
342160641Syongari			DELAY(1);
343160641Syongari		}
344160641Syongari		MII_SET(PC_MgmtClk);
345160641Syongari		DELAY(1);
346160641Syongari	}
347160641Syongari
348160641Syongarifail:
349160641Syongari	MII_CLR(PC_MgmtClk);
350160641Syongari	DELAY(1);
351160641Syongari	MII_SET(PC_MgmtClk);
352160641Syongari	DELAY(1);
353160641Syongari
354160641Syongari	if (ack)
355160641Syongari		return(1);
356160641Syongari	return(0);
357160641Syongari}
358160641Syongari
359160641Syongari/*
360160641Syongari * Write to a PHY register through the MII.
361160641Syongari */
362160641Syongaristatic int
363160641Syongaristge_mii_writereg(struct stge_softc *sc, struct stge_mii_frame *frame)
364160641Syongari{
365160641Syongari
366160641Syongari	/*
367160641Syongari	 * Set up frame for TX.
368160641Syongari	 */
369160641Syongari	frame->mii_stdelim = STGE_MII_STARTDELIM;
370160641Syongari	frame->mii_opcode = STGE_MII_WRITEOP;
371160641Syongari	frame->mii_turnaround = STGE_MII_TURNAROUND;
372160641Syongari
373160641Syongari	/*
374160641Syongari 	 * Turn on data output.
375160641Syongari	 */
376160641Syongari	MII_SET(PC_MgmtDir);
377160641Syongari
378160641Syongari	stge_mii_sync(sc);
379160641Syongari
380160641Syongari	stge_mii_send(sc, frame->mii_stdelim, 2);
381160641Syongari	stge_mii_send(sc, frame->mii_opcode, 2);
382160641Syongari	stge_mii_send(sc, frame->mii_phyaddr, 5);
383160641Syongari	stge_mii_send(sc, frame->mii_regaddr, 5);
384160641Syongari	stge_mii_send(sc, frame->mii_turnaround, 2);
385160641Syongari	stge_mii_send(sc, frame->mii_data, 16);
386160641Syongari
387160641Syongari	/* Idle bit. */
388160641Syongari	MII_SET(PC_MgmtClk);
389160641Syongari	DELAY(1);
390160641Syongari	MII_CLR(PC_MgmtClk);
391160641Syongari	DELAY(1);
392160641Syongari
393160641Syongari	/*
394160641Syongari	 * Turn off xmit.
395160641Syongari	 */
396160641Syongari	MII_CLR(PC_MgmtDir);
397160641Syongari
398160641Syongari	return(0);
399160641Syongari}
400160641Syongari
401160641Syongari/*
402160641Syongari * sc_miibus_readreg:	[mii interface function]
403160641Syongari *
404160641Syongari *	Read a PHY register on the MII of the TC9021.
405160641Syongari */
406160641Syongaristatic int
407160641Syongaristge_miibus_readreg(device_t dev, int phy, int reg)
408160641Syongari{
409160641Syongari	struct stge_softc *sc;
410160641Syongari	struct stge_mii_frame frame;
411160641Syongari	int error;
412160641Syongari
413160641Syongari	sc = device_get_softc(dev);
414160641Syongari
415160641Syongari	if (reg == STGE_PhyCtrl) {
416160641Syongari		/* XXX allow ip1000phy read STGE_PhyCtrl register. */
417160641Syongari		STGE_MII_LOCK(sc);
418160641Syongari		error = CSR_READ_1(sc, STGE_PhyCtrl);
419160641Syongari		STGE_MII_UNLOCK(sc);
420160641Syongari		return (error);
421160641Syongari	}
422160641Syongari	bzero(&frame, sizeof(frame));
423160641Syongari	frame.mii_phyaddr = phy;
424160641Syongari	frame.mii_regaddr = reg;
425160641Syongari
426160641Syongari	STGE_MII_LOCK(sc);
427160641Syongari	error = stge_mii_readreg(sc, &frame);
428160641Syongari	STGE_MII_UNLOCK(sc);
429160641Syongari
430160641Syongari	if (error != 0) {
431160641Syongari		/* Don't show errors for PHY probe request */
432160641Syongari		if (reg != 1)
433160641Syongari			device_printf(sc->sc_dev, "phy read fail\n");
434160641Syongari		return (0);
435160641Syongari	}
436160641Syongari	return (frame.mii_data);
437160641Syongari}
438160641Syongari
439160641Syongari/*
440160641Syongari * stge_miibus_writereg:	[mii interface function]
441160641Syongari *
442160641Syongari *	Write a PHY register on the MII of the TC9021.
443160641Syongari */
444160641Syongaristatic int
445160641Syongaristge_miibus_writereg(device_t dev, int phy, int reg, int val)
446160641Syongari{
447160641Syongari	struct stge_softc *sc;
448160641Syongari	struct stge_mii_frame frame;
449160641Syongari	int error;
450160641Syongari
451160641Syongari	sc = device_get_softc(dev);
452160641Syongari
453160641Syongari	bzero(&frame, sizeof(frame));
454160641Syongari	frame.mii_phyaddr = phy;
455160641Syongari	frame.mii_regaddr = reg;
456160641Syongari	frame.mii_data = val;
457160641Syongari
458160641Syongari	STGE_MII_LOCK(sc);
459160641Syongari	error = stge_mii_writereg(sc, &frame);
460160641Syongari	STGE_MII_UNLOCK(sc);
461160641Syongari
462160641Syongari	if (error != 0)
463160641Syongari		device_printf(sc->sc_dev, "phy write fail\n");
464160641Syongari	return (0);
465160641Syongari}
466160641Syongari
467160641Syongari/*
468160641Syongari * stge_miibus_statchg:	[mii interface function]
469160641Syongari *
470160641Syongari *	Callback from MII layer when media changes.
471160641Syongari */
472160641Syongaristatic void
473160641Syongaristge_miibus_statchg(device_t dev)
474160641Syongari{
475160641Syongari	struct stge_softc *sc;
476160641Syongari
477160641Syongari	sc = device_get_softc(dev);
478160641Syongari	taskqueue_enqueue(taskqueue_swi, &sc->sc_link_task);
479160641Syongari}
480160641Syongari
481160641Syongari/*
482160641Syongari * stge_mediastatus:	[ifmedia interface function]
483160641Syongari *
484160641Syongari *	Get the current interface media status.
485160641Syongari */
486160641Syongaristatic void
487160641Syongaristge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
488160641Syongari{
489160641Syongari	struct stge_softc *sc;
490160641Syongari	struct mii_data *mii;
491160641Syongari
492160641Syongari	sc = ifp->if_softc;
493160641Syongari	mii = device_get_softc(sc->sc_miibus);
494160641Syongari
495160641Syongari	mii_pollstat(mii);
496160641Syongari	ifmr->ifm_status = mii->mii_media_status;
497160641Syongari	ifmr->ifm_active = mii->mii_media_active;
498160641Syongari}
499160641Syongari
500160641Syongari/*
501160641Syongari * stge_mediachange:	[ifmedia interface function]
502160641Syongari *
503160641Syongari *	Set hardware to newly-selected media.
504160641Syongari */
505160641Syongaristatic int
506160641Syongaristge_mediachange(struct ifnet *ifp)
507160641Syongari{
508160641Syongari	struct stge_softc *sc;
509160641Syongari	struct mii_data *mii;
510160641Syongari
511160641Syongari	sc = ifp->if_softc;
512160641Syongari	mii = device_get_softc(sc->sc_miibus);
513160641Syongari	mii_mediachg(mii);
514160641Syongari
515160641Syongari	return (0);
516160641Syongari}
517160641Syongari
518160641Syongaristatic int
519160641Syongaristge_eeprom_wait(struct stge_softc *sc)
520160641Syongari{
521160641Syongari	int i;
522160641Syongari
523160641Syongari	for (i = 0; i < STGE_TIMEOUT; i++) {
524160641Syongari		DELAY(1000);
525160641Syongari		if ((CSR_READ_2(sc, STGE_EepromCtrl) & EC_EepromBusy) == 0)
526160641Syongari			return (0);
527160641Syongari	}
528160641Syongari	return (1);
529160641Syongari}
530160641Syongari
531160641Syongari/*
532160641Syongari * stge_read_eeprom:
533160641Syongari *
534160641Syongari *	Read data from the serial EEPROM.
535160641Syongari */
536160641Syongaristatic void
537160641Syongaristge_read_eeprom(struct stge_softc *sc, int offset, uint16_t *data)
538160641Syongari{
539160641Syongari
540160641Syongari	if (stge_eeprom_wait(sc))
541160641Syongari		device_printf(sc->sc_dev, "EEPROM failed to come ready\n");
542160641Syongari
543160641Syongari	CSR_WRITE_2(sc, STGE_EepromCtrl,
544160641Syongari	    EC_EepromAddress(offset) | EC_EepromOpcode(EC_OP_RR));
545160641Syongari	if (stge_eeprom_wait(sc))
546160641Syongari		device_printf(sc->sc_dev, "EEPROM read timed out\n");
547160641Syongari	*data = CSR_READ_2(sc, STGE_EepromData);
548160641Syongari}
549160641Syongari
550160641Syongari
551160641Syongaristatic int
552160641Syongaristge_probe(device_t dev)
553160641Syongari{
554160641Syongari	struct stge_product *sp;
555160641Syongari	int i;
556160641Syongari	uint16_t vendor, devid;
557160641Syongari
558160641Syongari	vendor = pci_get_vendor(dev);
559160641Syongari	devid = pci_get_device(dev);
560160641Syongari	sp = stge_products;
561160641Syongari	for (i = 0; i < sizeof(stge_products)/sizeof(stge_products[0]);
562160641Syongari	    i++, sp++) {
563160641Syongari		if (vendor == sp->stge_vendorid &&
564160641Syongari		    devid == sp->stge_deviceid) {
565160641Syongari			device_set_desc(dev, sp->stge_name);
566160641Syongari			return (BUS_PROBE_DEFAULT);
567160641Syongari		}
568160641Syongari	}
569160641Syongari
570160641Syongari	return (ENXIO);
571160641Syongari}
572160641Syongari
573160641Syongaristatic int
574160641Syongaristge_attach(device_t dev)
575160641Syongari{
576160641Syongari	struct stge_softc *sc;
577160641Syongari	struct ifnet *ifp;
578160641Syongari	uint8_t enaddr[ETHER_ADDR_LEN];
579213893Smarius	int error, flags, i;
580160641Syongari	uint16_t cmd;
581160641Syongari	uint32_t val;
582160641Syongari
583160641Syongari	error = 0;
584160641Syongari	sc = device_get_softc(dev);
585160641Syongari	sc->sc_dev = dev;
586160641Syongari
587160641Syongari	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
588160641Syongari	    MTX_DEF);
589160641Syongari	mtx_init(&sc->sc_mii_mtx, "stge_mii_mutex", NULL, MTX_DEF);
590160641Syongari	callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0);
591160641Syongari	TASK_INIT(&sc->sc_link_task, 0, stge_link_task, sc);
592160641Syongari
593160641Syongari	/*
594160641Syongari	 * Map the device.
595160641Syongari	 */
596160641Syongari	pci_enable_busmaster(dev);
597160641Syongari	cmd = pci_read_config(dev, PCIR_COMMAND, 2);
598160641Syongari	val = pci_read_config(dev, PCIR_BAR(1), 4);
599160641Syongari	if ((val & 0x01) != 0)
600160641Syongari		sc->sc_spec = stge_res_spec_mem;
601160641Syongari	else {
602160641Syongari		val = pci_read_config(dev, PCIR_BAR(0), 4);
603160641Syongari		if ((val & 0x01) == 0) {
604160641Syongari			device_printf(sc->sc_dev, "couldn't locate IO BAR\n");
605160641Syongari			error = ENXIO;
606160641Syongari			goto fail;
607160641Syongari		}
608160641Syongari		sc->sc_spec = stge_res_spec_io;
609160641Syongari	}
610160641Syongari	error = bus_alloc_resources(dev, sc->sc_spec, sc->sc_res);
611160641Syongari	if (error != 0) {
612160641Syongari		device_printf(dev, "couldn't allocate %s resources\n",
613160641Syongari		    sc->sc_spec == stge_res_spec_mem ? "memory" : "I/O");
614160641Syongari		goto fail;
615160641Syongari	}
616160641Syongari	sc->sc_rev = pci_get_revid(dev);
617160641Syongari
618160641Syongari	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
619160641Syongari	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
620160641Syongari	    "rxint_nframe", CTLTYPE_INT|CTLFLAG_RW, &sc->sc_rxint_nframe, 0,
621160641Syongari	    sysctl_hw_stge_rxint_nframe, "I", "stge rx interrupt nframe");
622160641Syongari
623160641Syongari	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
624160641Syongari	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
625160641Syongari	    "rxint_dmawait", CTLTYPE_INT|CTLFLAG_RW, &sc->sc_rxint_dmawait, 0,
626160641Syongari	    sysctl_hw_stge_rxint_dmawait, "I", "stge rx interrupt dmawait");
627160641Syongari
628160641Syongari	/* Pull in device tunables. */
629160641Syongari	sc->sc_rxint_nframe = STGE_RXINT_NFRAME_DEFAULT;
630160641Syongari	error = resource_int_value(device_get_name(dev), device_get_unit(dev),
631160641Syongari	    "rxint_nframe", &sc->sc_rxint_nframe);
632160641Syongari	if (error == 0) {
633160641Syongari		if (sc->sc_rxint_nframe < STGE_RXINT_NFRAME_MIN ||
634160641Syongari		    sc->sc_rxint_nframe > STGE_RXINT_NFRAME_MAX) {
635160641Syongari			device_printf(dev, "rxint_nframe value out of range; "
636160641Syongari			    "using default: %d\n", STGE_RXINT_NFRAME_DEFAULT);
637160641Syongari			sc->sc_rxint_nframe = STGE_RXINT_NFRAME_DEFAULT;
638160641Syongari		}
639160641Syongari	}
640160641Syongari
641160641Syongari	sc->sc_rxint_dmawait = STGE_RXINT_DMAWAIT_DEFAULT;
642160641Syongari	error = resource_int_value(device_get_name(dev), device_get_unit(dev),
643160641Syongari	    "rxint_dmawait", &sc->sc_rxint_dmawait);
644160641Syongari	if (error == 0) {
645160641Syongari		if (sc->sc_rxint_dmawait < STGE_RXINT_DMAWAIT_MIN ||
646160641Syongari		    sc->sc_rxint_dmawait > STGE_RXINT_DMAWAIT_MAX) {
647160641Syongari			device_printf(dev, "rxint_dmawait value out of range; "
648160641Syongari			    "using default: %d\n", STGE_RXINT_DMAWAIT_DEFAULT);
649160641Syongari			sc->sc_rxint_dmawait = STGE_RXINT_DMAWAIT_DEFAULT;
650160641Syongari		}
651160641Syongari	}
652160641Syongari
653160641Syongari	if ((error = stge_dma_alloc(sc) != 0))
654160641Syongari		goto fail;
655160641Syongari
656160641Syongari	/*
657160641Syongari	 * Determine if we're copper or fiber.  It affects how we
658160641Syongari	 * reset the card.
659160641Syongari	 */
660160641Syongari	if (CSR_READ_4(sc, STGE_AsicCtrl) & AC_PhyMedia)
661160641Syongari		sc->sc_usefiber = 1;
662160641Syongari	else
663160641Syongari		sc->sc_usefiber = 0;
664160641Syongari
665160641Syongari	/* Load LED configuration from EEPROM. */
666160641Syongari	stge_read_eeprom(sc, STGE_EEPROM_LEDMode, &sc->sc_led);
667160641Syongari
668160641Syongari	/*
669160641Syongari	 * Reset the chip to a known state.
670160641Syongari	 */
671160641Syongari	STGE_LOCK(sc);
672160641Syongari	stge_reset(sc, STGE_RESET_FULL);
673160641Syongari	STGE_UNLOCK(sc);
674160641Syongari
675160641Syongari	/*
676160641Syongari	 * Reading the station address from the EEPROM doesn't seem
677160641Syongari	 * to work, at least on my sample boards.  Instead, since
678160641Syongari	 * the reset sequence does AutoInit, read it from the station
679160641Syongari	 * address registers. For Sundance 1023 you can only read it
680160641Syongari	 * from EEPROM.
681160641Syongari	 */
682160641Syongari	if (pci_get_device(dev) != DEVICEID_SUNDANCETI_ST1023) {
683160641Syongari		uint16_t v;
684160641Syongari
685160641Syongari		v = CSR_READ_2(sc, STGE_StationAddress0);
686160641Syongari		enaddr[0] = v & 0xff;
687160641Syongari		enaddr[1] = v >> 8;
688160641Syongari		v = CSR_READ_2(sc, STGE_StationAddress1);
689160641Syongari		enaddr[2] = v & 0xff;
690160641Syongari		enaddr[3] = v >> 8;
691160641Syongari		v = CSR_READ_2(sc, STGE_StationAddress2);
692160641Syongari		enaddr[4] = v & 0xff;
693160641Syongari		enaddr[5] = v >> 8;
694160641Syongari		sc->sc_stge1023 = 0;
695160641Syongari	} else {
696160641Syongari		uint16_t myaddr[ETHER_ADDR_LEN / 2];
697160641Syongari		for (i = 0; i <ETHER_ADDR_LEN / 2; i++) {
698160641Syongari			stge_read_eeprom(sc, STGE_EEPROM_StationAddress0 + i,
699160641Syongari			    &myaddr[i]);
700160641Syongari			myaddr[i] = le16toh(myaddr[i]);
701160641Syongari		}
702160641Syongari		bcopy(myaddr, enaddr, sizeof(enaddr));
703160641Syongari		sc->sc_stge1023 = 1;
704160641Syongari	}
705160641Syongari
706160641Syongari	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
707160641Syongari	if (ifp == NULL) {
708160641Syongari		device_printf(sc->sc_dev, "failed to if_alloc()\n");
709160641Syongari		error = ENXIO;
710160641Syongari		goto fail;
711160641Syongari	}
712160641Syongari
713160641Syongari	ifp->if_softc = sc;
714160641Syongari	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
715160641Syongari	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
716160641Syongari	ifp->if_ioctl = stge_ioctl;
717160641Syongari	ifp->if_start = stge_start;
718160641Syongari	ifp->if_init = stge_init;
719160641Syongari	ifp->if_mtu = ETHERMTU;
720160641Syongari	ifp->if_snd.ifq_drv_maxlen = STGE_TX_RING_CNT - 1;
721160641Syongari	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
722160641Syongari	IFQ_SET_READY(&ifp->if_snd);
723160641Syongari	/* Revision B3 and earlier chips have checksum bug. */
724160641Syongari	if (sc->sc_rev >= 0x0c) {
725160641Syongari		ifp->if_hwassist = STGE_CSUM_FEATURES;
726160641Syongari		ifp->if_capabilities = IFCAP_HWCSUM;
727160641Syongari	} else {
728160641Syongari		ifp->if_hwassist = 0;
729160641Syongari		ifp->if_capabilities = 0;
730160641Syongari	}
731175315Syongari	ifp->if_capabilities |= IFCAP_WOL_MAGIC;
732160641Syongari	ifp->if_capenable = ifp->if_capabilities;
733160641Syongari
734160641Syongari	/*
735160641Syongari	 * Read some important bits from the PhyCtrl register.
736160641Syongari	 */
737160641Syongari	sc->sc_PhyCtrl = CSR_READ_1(sc, STGE_PhyCtrl) &
738160641Syongari	    (PC_PhyDuplexPolarity | PC_PhyLnkPolarity);
739160641Syongari
740160641Syongari	/* Set up MII bus. */
741215297Smarius	flags = MIIF_DOPAUSE;
742213893Smarius	if (sc->sc_rev >= 0x40 && sc->sc_rev <= 0x4e)
743213893Smarius		flags |= MIIF_MACPRIV0;
744213893Smarius	error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, stge_mediachange,
745213893Smarius	    stge_mediastatus, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY,
746213893Smarius	    flags);
747213893Smarius	if (error != 0) {
748213893Smarius		device_printf(sc->sc_dev, "attaching PHYs failed\n");
749160641Syongari		goto fail;
750160641Syongari	}
751160641Syongari
752160641Syongari	ether_ifattach(ifp, enaddr);
753160641Syongari
754160641Syongari	/* VLAN capability setup */
755160641Syongari	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
756160641Syongari	if (sc->sc_rev >= 0x0c)
757160641Syongari		ifp->if_capabilities |= IFCAP_VLAN_HWCSUM;
758160641Syongari	ifp->if_capenable = ifp->if_capabilities;
759160641Syongari#ifdef DEVICE_POLLING
760160641Syongari	ifp->if_capabilities |= IFCAP_POLLING;
761160641Syongari#endif
762160641Syongari	/*
763160641Syongari	 * Tell the upper layer(s) we support long frames.
764160641Syongari	 * Must appear after the call to ether_ifattach() because
765160641Syongari	 * ether_ifattach() sets ifi_hdrlen to the default value.
766160641Syongari	 */
767160641Syongari	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
768160641Syongari
769160641Syongari	/*
770160641Syongari	 * The manual recommends disabling early transmit, so we
771160641Syongari	 * do.  It's disabled anyway, if using IP checksumming,
772160641Syongari	 * since the entire packet must be in the FIFO in order
773160641Syongari	 * for the chip to perform the checksum.
774160641Syongari	 */
775160641Syongari	sc->sc_txthresh = 0x0fff;
776160641Syongari
777160641Syongari	/*
778160641Syongari	 * Disable MWI if the PCI layer tells us to.
779160641Syongari	 */
780160641Syongari	sc->sc_DMACtrl = 0;
781160641Syongari	if ((cmd & PCIM_CMD_MWRICEN) == 0)
782160641Syongari		sc->sc_DMACtrl |= DMAC_MWIDisable;
783160641Syongari
784160641Syongari	/*
785160641Syongari	 * Hookup IRQ
786160641Syongari	 */
787160641Syongari	error = bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_NET | INTR_MPSAFE,
788166901Spiso	    NULL, stge_intr, sc, &sc->sc_ih);
789160641Syongari	if (error != 0) {
790160641Syongari		ether_ifdetach(ifp);
791160641Syongari		device_printf(sc->sc_dev, "couldn't set up IRQ\n");
792160641Syongari		sc->sc_ifp = NULL;
793160641Syongari		goto fail;
794160641Syongari	}
795160641Syongari
796160641Syongarifail:
797160641Syongari	if (error != 0)
798160641Syongari		stge_detach(dev);
799160641Syongari
800160641Syongari	return (error);
801160641Syongari}
802160641Syongari
803160641Syongaristatic int
804160641Syongaristge_detach(device_t dev)
805160641Syongari{
806160641Syongari	struct stge_softc *sc;
807160641Syongari	struct ifnet *ifp;
808160641Syongari
809160641Syongari	sc = device_get_softc(dev);
810160641Syongari
811160641Syongari	ifp = sc->sc_ifp;
812160641Syongari#ifdef DEVICE_POLLING
813160641Syongari	if (ifp && ifp->if_capenable & IFCAP_POLLING)
814160641Syongari		ether_poll_deregister(ifp);
815160641Syongari#endif
816160641Syongari	if (device_is_attached(dev)) {
817160641Syongari		STGE_LOCK(sc);
818160641Syongari		/* XXX */
819160641Syongari		sc->sc_detach = 1;
820160641Syongari		stge_stop(sc);
821160641Syongari		STGE_UNLOCK(sc);
822160641Syongari		callout_drain(&sc->sc_tick_ch);
823160641Syongari		taskqueue_drain(taskqueue_swi, &sc->sc_link_task);
824160641Syongari		ether_ifdetach(ifp);
825160641Syongari	}
826160641Syongari
827160641Syongari	if (sc->sc_miibus != NULL) {
828160641Syongari		device_delete_child(dev, sc->sc_miibus);
829160641Syongari		sc->sc_miibus = NULL;
830160641Syongari	}
831160641Syongari	bus_generic_detach(dev);
832160641Syongari	stge_dma_free(sc);
833160641Syongari
834160641Syongari	if (ifp != NULL) {
835160641Syongari		if_free(ifp);
836160641Syongari		sc->sc_ifp = NULL;
837160641Syongari	}
838160641Syongari
839160641Syongari	if (sc->sc_ih) {
840160641Syongari		bus_teardown_intr(dev, sc->sc_res[1], sc->sc_ih);
841160641Syongari		sc->sc_ih = NULL;
842160641Syongari	}
843160641Syongari	bus_release_resources(dev, sc->sc_spec, sc->sc_res);
844160641Syongari
845160641Syongari	mtx_destroy(&sc->sc_mii_mtx);
846160641Syongari	mtx_destroy(&sc->sc_mtx);
847160641Syongari
848160641Syongari	return (0);
849160641Syongari}
850160641Syongari
851160641Syongaristruct stge_dmamap_arg {
852160641Syongari	bus_addr_t	stge_busaddr;
853160641Syongari};
854160641Syongari
855160641Syongaristatic void
856160641Syongaristge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
857160641Syongari{
858160641Syongari	struct stge_dmamap_arg *ctx;
859160641Syongari
860160641Syongari	if (error != 0)
861160641Syongari		return;
862160641Syongari
863160641Syongari	ctx = (struct stge_dmamap_arg *)arg;
864160641Syongari	ctx->stge_busaddr = segs[0].ds_addr;
865160641Syongari}
866160641Syongari
867160641Syongaristatic int
868160641Syongaristge_dma_alloc(struct stge_softc *sc)
869160641Syongari{
870160641Syongari	struct stge_dmamap_arg ctx;
871160641Syongari	struct stge_txdesc *txd;
872160641Syongari	struct stge_rxdesc *rxd;
873160641Syongari	int error, i;
874160641Syongari
875160641Syongari	/* create parent tag. */
876166165Smarius	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),/* parent */
877160641Syongari		    1, 0,			/* algnmnt, boundary */
878160641Syongari		    STGE_DMA_MAXADDR,		/* lowaddr */
879160641Syongari		    BUS_SPACE_MAXADDR,		/* highaddr */
880160641Syongari		    NULL, NULL,			/* filter, filterarg */
881160641Syongari		    BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
882160641Syongari		    0,				/* nsegments */
883160641Syongari		    BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
884160641Syongari		    0,				/* flags */
885160641Syongari		    NULL, NULL,			/* lockfunc, lockarg */
886160641Syongari		    &sc->sc_cdata.stge_parent_tag);
887160641Syongari	if (error != 0) {
888160641Syongari		device_printf(sc->sc_dev, "failed to create parent DMA tag\n");
889160641Syongari		goto fail;
890160641Syongari	}
891160641Syongari	/* create tag for Tx ring. */
892160641Syongari	error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */
893160641Syongari		    STGE_RING_ALIGN, 0,		/* algnmnt, boundary */
894160641Syongari		    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
895160641Syongari		    BUS_SPACE_MAXADDR,		/* highaddr */
896160641Syongari		    NULL, NULL,			/* filter, filterarg */
897160641Syongari		    STGE_TX_RING_SZ,		/* maxsize */
898160641Syongari		    1,				/* nsegments */
899160641Syongari		    STGE_TX_RING_SZ,		/* maxsegsize */
900160641Syongari		    0,				/* flags */
901160641Syongari		    NULL, NULL,			/* lockfunc, lockarg */
902160641Syongari		    &sc->sc_cdata.stge_tx_ring_tag);
903160641Syongari	if (error != 0) {
904160641Syongari		device_printf(sc->sc_dev,
905160641Syongari		    "failed to allocate Tx ring DMA tag\n");
906160641Syongari		goto fail;
907160641Syongari	}
908160641Syongari
909160641Syongari	/* create tag for Rx ring. */
910160641Syongari	error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */
911160641Syongari		    STGE_RING_ALIGN, 0,		/* algnmnt, boundary */
912160641Syongari		    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
913160641Syongari		    BUS_SPACE_MAXADDR,		/* highaddr */
914160641Syongari		    NULL, NULL,			/* filter, filterarg */
915160641Syongari		    STGE_RX_RING_SZ,		/* maxsize */
916160641Syongari		    1,				/* nsegments */
917160641Syongari		    STGE_RX_RING_SZ,		/* maxsegsize */
918160641Syongari		    0,				/* flags */
919160641Syongari		    NULL, NULL,			/* lockfunc, lockarg */
920160641Syongari		    &sc->sc_cdata.stge_rx_ring_tag);
921160641Syongari	if (error != 0) {
922160641Syongari		device_printf(sc->sc_dev,
923160641Syongari		    "failed to allocate Rx ring DMA tag\n");
924160641Syongari		goto fail;
925160641Syongari	}
926160641Syongari
927160641Syongari	/* create tag for Tx buffers. */
928160641Syongari	error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */
929160641Syongari		    1, 0,			/* algnmnt, boundary */
930160641Syongari		    BUS_SPACE_MAXADDR,		/* lowaddr */
931160641Syongari		    BUS_SPACE_MAXADDR,		/* highaddr */
932160641Syongari		    NULL, NULL,			/* filter, filterarg */
933160641Syongari		    MCLBYTES * STGE_MAXTXSEGS,	/* maxsize */
934160641Syongari		    STGE_MAXTXSEGS,		/* nsegments */
935160641Syongari		    MCLBYTES,			/* maxsegsize */
936160641Syongari		    0,				/* flags */
937160641Syongari		    NULL, NULL,			/* lockfunc, lockarg */
938160641Syongari		    &sc->sc_cdata.stge_tx_tag);
939160641Syongari	if (error != 0) {
940160641Syongari		device_printf(sc->sc_dev, "failed to allocate Tx DMA tag\n");
941160641Syongari		goto fail;
942160641Syongari	}
943160641Syongari
944160641Syongari	/* create tag for Rx buffers. */
945160641Syongari	error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */
946160641Syongari		    1, 0,			/* algnmnt, boundary */
947160641Syongari		    BUS_SPACE_MAXADDR,		/* lowaddr */
948160641Syongari		    BUS_SPACE_MAXADDR,		/* highaddr */
949160641Syongari		    NULL, NULL,			/* filter, filterarg */
950160641Syongari		    MCLBYTES,			/* maxsize */
951160641Syongari		    1,				/* nsegments */
952160641Syongari		    MCLBYTES,			/* maxsegsize */
953160641Syongari		    0,				/* flags */
954160641Syongari		    NULL, NULL,			/* lockfunc, lockarg */
955160641Syongari		    &sc->sc_cdata.stge_rx_tag);
956160641Syongari	if (error != 0) {
957160641Syongari		device_printf(sc->sc_dev, "failed to allocate Rx DMA tag\n");
958160641Syongari		goto fail;
959160641Syongari	}
960160641Syongari
961160641Syongari	/* allocate DMA'able memory and load the DMA map for Tx ring. */
962160641Syongari	error = bus_dmamem_alloc(sc->sc_cdata.stge_tx_ring_tag,
963160641Syongari	    (void **)&sc->sc_rdata.stge_tx_ring, BUS_DMA_NOWAIT | BUS_DMA_ZERO,
964160641Syongari	    &sc->sc_cdata.stge_tx_ring_map);
965160641Syongari	if (error != 0) {
966160641Syongari		device_printf(sc->sc_dev,
967160641Syongari		    "failed to allocate DMA'able memory for Tx ring\n");
968160641Syongari		goto fail;
969160641Syongari	}
970160641Syongari
971160641Syongari	ctx.stge_busaddr = 0;
972160641Syongari	error = bus_dmamap_load(sc->sc_cdata.stge_tx_ring_tag,
973160641Syongari	    sc->sc_cdata.stge_tx_ring_map, sc->sc_rdata.stge_tx_ring,
974160641Syongari	    STGE_TX_RING_SZ, stge_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
975160641Syongari	if (error != 0 || ctx.stge_busaddr == 0) {
976160641Syongari		device_printf(sc->sc_dev,
977160641Syongari		    "failed to load DMA'able memory for Tx ring\n");
978160641Syongari		goto fail;
979160641Syongari	}
980160641Syongari	sc->sc_rdata.stge_tx_ring_paddr = ctx.stge_busaddr;
981160641Syongari
982160641Syongari	/* allocate DMA'able memory and load the DMA map for Rx ring. */
983160641Syongari	error = bus_dmamem_alloc(sc->sc_cdata.stge_rx_ring_tag,
984160641Syongari	    (void **)&sc->sc_rdata.stge_rx_ring, BUS_DMA_NOWAIT | BUS_DMA_ZERO,
985160641Syongari	    &sc->sc_cdata.stge_rx_ring_map);
986160641Syongari	if (error != 0) {
987160641Syongari		device_printf(sc->sc_dev,
988160641Syongari		    "failed to allocate DMA'able memory for Rx ring\n");
989160641Syongari		goto fail;
990160641Syongari	}
991160641Syongari
992160641Syongari	ctx.stge_busaddr = 0;
993160641Syongari	error = bus_dmamap_load(sc->sc_cdata.stge_rx_ring_tag,
994160641Syongari	    sc->sc_cdata.stge_rx_ring_map, sc->sc_rdata.stge_rx_ring,
995160641Syongari	    STGE_RX_RING_SZ, stge_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
996160641Syongari	if (error != 0 || ctx.stge_busaddr == 0) {
997160641Syongari		device_printf(sc->sc_dev,
998160641Syongari		    "failed to load DMA'able memory for Rx ring\n");
999160641Syongari		goto fail;
1000160641Syongari	}
1001160641Syongari	sc->sc_rdata.stge_rx_ring_paddr = ctx.stge_busaddr;
1002160641Syongari
1003160641Syongari	/* create DMA maps for Tx buffers. */
1004160641Syongari	for (i = 0; i < STGE_TX_RING_CNT; i++) {
1005160641Syongari		txd = &sc->sc_cdata.stge_txdesc[i];
1006160641Syongari		txd->tx_m = NULL;
1007160641Syongari		txd->tx_dmamap = 0;
1008160641Syongari		error = bus_dmamap_create(sc->sc_cdata.stge_tx_tag, 0,
1009160641Syongari		    &txd->tx_dmamap);
1010160641Syongari		if (error != 0) {
1011160641Syongari			device_printf(sc->sc_dev,
1012160641Syongari			    "failed to create Tx dmamap\n");
1013160641Syongari			goto fail;
1014160641Syongari		}
1015160641Syongari	}
1016160641Syongari	/* create DMA maps for Rx buffers. */
1017160641Syongari	if ((error = bus_dmamap_create(sc->sc_cdata.stge_rx_tag, 0,
1018160641Syongari	    &sc->sc_cdata.stge_rx_sparemap)) != 0) {
1019160641Syongari		device_printf(sc->sc_dev, "failed to create spare Rx dmamap\n");
1020160641Syongari		goto fail;
1021160641Syongari	}
1022160641Syongari	for (i = 0; i < STGE_RX_RING_CNT; i++) {
1023160641Syongari		rxd = &sc->sc_cdata.stge_rxdesc[i];
1024160641Syongari		rxd->rx_m = NULL;
1025160641Syongari		rxd->rx_dmamap = 0;
1026160641Syongari		error = bus_dmamap_create(sc->sc_cdata.stge_rx_tag, 0,
1027160641Syongari		    &rxd->rx_dmamap);
1028160641Syongari		if (error != 0) {
1029160641Syongari			device_printf(sc->sc_dev,
1030160641Syongari			    "failed to create Rx dmamap\n");
1031160641Syongari			goto fail;
1032160641Syongari		}
1033160641Syongari	}
1034160641Syongari
1035160641Syongarifail:
1036160641Syongari	return (error);
1037160641Syongari}
1038160641Syongari
1039160641Syongaristatic void
1040160641Syongaristge_dma_free(struct stge_softc *sc)
1041160641Syongari{
1042160641Syongari	struct stge_txdesc *txd;
1043160641Syongari	struct stge_rxdesc *rxd;
1044160641Syongari	int i;
1045160641Syongari
1046160641Syongari	/* Tx ring */
1047160641Syongari	if (sc->sc_cdata.stge_tx_ring_tag) {
1048160641Syongari		if (sc->sc_cdata.stge_tx_ring_map)
1049160641Syongari			bus_dmamap_unload(sc->sc_cdata.stge_tx_ring_tag,
1050160641Syongari			    sc->sc_cdata.stge_tx_ring_map);
1051160641Syongari		if (sc->sc_cdata.stge_tx_ring_map &&
1052160641Syongari		    sc->sc_rdata.stge_tx_ring)
1053160641Syongari			bus_dmamem_free(sc->sc_cdata.stge_tx_ring_tag,
1054160641Syongari			    sc->sc_rdata.stge_tx_ring,
1055160641Syongari			    sc->sc_cdata.stge_tx_ring_map);
1056160641Syongari		sc->sc_rdata.stge_tx_ring = NULL;
1057160641Syongari		sc->sc_cdata.stge_tx_ring_map = 0;
1058160641Syongari		bus_dma_tag_destroy(sc->sc_cdata.stge_tx_ring_tag);
1059160641Syongari		sc->sc_cdata.stge_tx_ring_tag = NULL;
1060160641Syongari	}
1061160641Syongari	/* Rx ring */
1062160641Syongari	if (sc->sc_cdata.stge_rx_ring_tag) {
1063160641Syongari		if (sc->sc_cdata.stge_rx_ring_map)
1064160641Syongari			bus_dmamap_unload(sc->sc_cdata.stge_rx_ring_tag,
1065160641Syongari			    sc->sc_cdata.stge_rx_ring_map);
1066160641Syongari		if (sc->sc_cdata.stge_rx_ring_map &&
1067160641Syongari		    sc->sc_rdata.stge_rx_ring)
1068160641Syongari			bus_dmamem_free(sc->sc_cdata.stge_rx_ring_tag,
1069160641Syongari			    sc->sc_rdata.stge_rx_ring,
1070160641Syongari			    sc->sc_cdata.stge_rx_ring_map);
1071160641Syongari		sc->sc_rdata.stge_rx_ring = NULL;
1072160641Syongari		sc->sc_cdata.stge_rx_ring_map = 0;
1073160641Syongari		bus_dma_tag_destroy(sc->sc_cdata.stge_rx_ring_tag);
1074160641Syongari		sc->sc_cdata.stge_rx_ring_tag = NULL;
1075160641Syongari	}
1076160641Syongari	/* Tx buffers */
1077160641Syongari	if (sc->sc_cdata.stge_tx_tag) {
1078160641Syongari		for (i = 0; i < STGE_TX_RING_CNT; i++) {
1079160641Syongari			txd = &sc->sc_cdata.stge_txdesc[i];
1080160641Syongari			if (txd->tx_dmamap) {
1081160641Syongari				bus_dmamap_destroy(sc->sc_cdata.stge_tx_tag,
1082160641Syongari				    txd->tx_dmamap);
1083160641Syongari				txd->tx_dmamap = 0;
1084160641Syongari			}
1085160641Syongari		}
1086160641Syongari		bus_dma_tag_destroy(sc->sc_cdata.stge_tx_tag);
1087160641Syongari		sc->sc_cdata.stge_tx_tag = NULL;
1088160641Syongari	}
1089160641Syongari	/* Rx buffers */
1090160641Syongari	if (sc->sc_cdata.stge_rx_tag) {
1091160641Syongari		for (i = 0; i < STGE_RX_RING_CNT; i++) {
1092160641Syongari			rxd = &sc->sc_cdata.stge_rxdesc[i];
1093160641Syongari			if (rxd->rx_dmamap) {
1094160641Syongari				bus_dmamap_destroy(sc->sc_cdata.stge_rx_tag,
1095160641Syongari				    rxd->rx_dmamap);
1096160641Syongari				rxd->rx_dmamap = 0;
1097160641Syongari			}
1098160641Syongari		}
1099160641Syongari		if (sc->sc_cdata.stge_rx_sparemap) {
1100160641Syongari			bus_dmamap_destroy(sc->sc_cdata.stge_rx_tag,
1101160641Syongari			    sc->sc_cdata.stge_rx_sparemap);
1102160641Syongari			sc->sc_cdata.stge_rx_sparemap = 0;
1103160641Syongari		}
1104160641Syongari		bus_dma_tag_destroy(sc->sc_cdata.stge_rx_tag);
1105160641Syongari		sc->sc_cdata.stge_rx_tag = NULL;
1106160641Syongari	}
1107160641Syongari
1108160641Syongari	if (sc->sc_cdata.stge_parent_tag) {
1109160641Syongari		bus_dma_tag_destroy(sc->sc_cdata.stge_parent_tag);
1110160641Syongari		sc->sc_cdata.stge_parent_tag = NULL;
1111160641Syongari	}
1112160641Syongari}
1113160641Syongari
1114160641Syongari/*
1115160641Syongari * stge_shutdown:
1116160641Syongari *
1117160641Syongari *	Make sure the interface is stopped at reboot time.
1118160641Syongari */
1119173839Syongaristatic int
1120160641Syongaristge_shutdown(device_t dev)
1121160641Syongari{
1122160641Syongari
1123175315Syongari	return (stge_suspend(dev));
1124175315Syongari}
1125160641Syongari
1126175315Syongaristatic void
1127175315Syongaristge_setwol(struct stge_softc *sc)
1128175315Syongari{
1129175315Syongari	struct ifnet *ifp;
1130175315Syongari	uint8_t v;
1131173839Syongari
1132175315Syongari	STGE_LOCK_ASSERT(sc);
1133175315Syongari
1134175315Syongari	ifp = sc->sc_ifp;
1135175315Syongari	v = CSR_READ_1(sc, STGE_WakeEvent);
1136175315Syongari	/* Disable all WOL bits. */
1137175315Syongari	v &= ~(WE_WakePktEnable | WE_MagicPktEnable | WE_LinkEventEnable |
1138175315Syongari	    WE_WakeOnLanEnable);
1139175315Syongari	if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0)
1140175315Syongari		v |= WE_MagicPktEnable | WE_WakeOnLanEnable;
1141175315Syongari	CSR_WRITE_1(sc, STGE_WakeEvent, v);
1142175315Syongari	/* Reset Tx and prevent transmission. */
1143175315Syongari	CSR_WRITE_4(sc, STGE_AsicCtrl,
1144175315Syongari	    CSR_READ_4(sc, STGE_AsicCtrl) | AC_TxReset);
1145175315Syongari	/*
1146175315Syongari	 * TC9021 automatically reset link speed to 100Mbps when it's put
1147175315Syongari	 * into sleep so there is no need to try to resetting link speed.
1148175315Syongari	 */
1149160641Syongari}
1150160641Syongari
1151160641Syongaristatic int
1152160641Syongaristge_suspend(device_t dev)
1153160641Syongari{
1154160641Syongari	struct stge_softc *sc;
1155160641Syongari
1156160641Syongari	sc = device_get_softc(dev);
1157160641Syongari
1158160641Syongari	STGE_LOCK(sc);
1159160641Syongari	stge_stop(sc);
1160160641Syongari	sc->sc_suspended = 1;
1161175315Syongari	stge_setwol(sc);
1162160641Syongari	STGE_UNLOCK(sc);
1163160641Syongari
1164160641Syongari	return (0);
1165160641Syongari}
1166160641Syongari
1167160641Syongaristatic int
1168160641Syongaristge_resume(device_t dev)
1169160641Syongari{
1170160641Syongari	struct stge_softc *sc;
1171160641Syongari	struct ifnet *ifp;
1172175315Syongari	uint8_t v;
1173160641Syongari
1174160641Syongari	sc = device_get_softc(dev);
1175160641Syongari
1176160641Syongari	STGE_LOCK(sc);
1177175315Syongari	/*
1178175315Syongari	 * Clear WOL bits, so special frames wouldn't interfere
1179175315Syongari	 * normal Rx operation anymore.
1180175315Syongari	 */
1181175315Syongari	v = CSR_READ_1(sc, STGE_WakeEvent);
1182175315Syongari	v &= ~(WE_WakePktEnable | WE_MagicPktEnable | WE_LinkEventEnable |
1183175315Syongari	    WE_WakeOnLanEnable);
1184175315Syongari	CSR_WRITE_1(sc, STGE_WakeEvent, v);
1185160641Syongari	ifp = sc->sc_ifp;
1186160641Syongari	if (ifp->if_flags & IFF_UP)
1187160641Syongari		stge_init_locked(sc);
1188160641Syongari
1189160641Syongari	sc->sc_suspended = 0;
1190160641Syongari	STGE_UNLOCK(sc);
1191160641Syongari
1192160641Syongari	return (0);
1193160641Syongari}
1194160641Syongari
1195160641Syongaristatic void
1196160641Syongaristge_dma_wait(struct stge_softc *sc)
1197160641Syongari{
1198160641Syongari	int i;
1199160641Syongari
1200160641Syongari	for (i = 0; i < STGE_TIMEOUT; i++) {
1201160641Syongari		DELAY(2);
1202160641Syongari		if ((CSR_READ_4(sc, STGE_DMACtrl) & DMAC_TxDMAInProg) == 0)
1203160641Syongari			break;
1204160641Syongari	}
1205160641Syongari
1206160641Syongari	if (i == STGE_TIMEOUT)
1207160641Syongari		device_printf(sc->sc_dev, "DMA wait timed out\n");
1208160641Syongari}
1209160641Syongari
1210160641Syongaristatic int
1211160641Syongaristge_encap(struct stge_softc *sc, struct mbuf **m_head)
1212160641Syongari{
1213160641Syongari	struct stge_txdesc *txd;
1214160641Syongari	struct stge_tfd *tfd;
1215161235Syongari	struct mbuf *m;
1216160641Syongari	bus_dma_segment_t txsegs[STGE_MAXTXSEGS];
1217160641Syongari	int error, i, nsegs, si;
1218160641Syongari	uint64_t csum_flags, tfc;
1219160641Syongari
1220160641Syongari	STGE_LOCK_ASSERT(sc);
1221160641Syongari
1222160641Syongari	if ((txd = STAILQ_FIRST(&sc->sc_cdata.stge_txfreeq)) == NULL)
1223160641Syongari		return (ENOBUFS);
1224160641Syongari
1225160641Syongari	error =  bus_dmamap_load_mbuf_sg(sc->sc_cdata.stge_tx_tag,
1226161235Syongari	    txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
1227160641Syongari	if (error == EFBIG) {
1228175430Syongari		m = m_collapse(*m_head, M_DONTWAIT, STGE_MAXTXSEGS);
1229161235Syongari		if (m == NULL) {
1230161235Syongari			m_freem(*m_head);
1231161235Syongari			*m_head = NULL;
1232160641Syongari			return (ENOMEM);
1233160641Syongari		}
1234161235Syongari		*m_head = m;
1235160641Syongari		error = bus_dmamap_load_mbuf_sg(sc->sc_cdata.stge_tx_tag,
1236161235Syongari		    txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
1237160641Syongari		if (error != 0) {
1238161235Syongari			m_freem(*m_head);
1239161235Syongari			*m_head = NULL;
1240160641Syongari			return (error);
1241160641Syongari		}
1242160641Syongari	} else if (error != 0)
1243160641Syongari		return (error);
1244160641Syongari	if (nsegs == 0) {
1245161235Syongari		m_freem(*m_head);
1246161235Syongari		*m_head = NULL;
1247160641Syongari		return (EIO);
1248160641Syongari	}
1249160641Syongari
1250161235Syongari	m = *m_head;
1251160641Syongari	csum_flags = 0;
1252160641Syongari	if ((m->m_pkthdr.csum_flags & STGE_CSUM_FEATURES) != 0) {
1253160641Syongari		if (m->m_pkthdr.csum_flags & CSUM_IP)
1254160641Syongari			csum_flags |= TFD_IPChecksumEnable;
1255160641Syongari		if (m->m_pkthdr.csum_flags & CSUM_TCP)
1256160641Syongari			csum_flags |= TFD_TCPChecksumEnable;
1257160641Syongari		else if (m->m_pkthdr.csum_flags & CSUM_UDP)
1258160641Syongari			csum_flags |= TFD_UDPChecksumEnable;
1259160641Syongari	}
1260160641Syongari
1261160641Syongari	si = sc->sc_cdata.stge_tx_prod;
1262160641Syongari	tfd = &sc->sc_rdata.stge_tx_ring[si];
1263160641Syongari	for (i = 0; i < nsegs; i++)
1264160641Syongari		tfd->tfd_frags[i].frag_word0 =
1265160641Syongari		    htole64(FRAG_ADDR(txsegs[i].ds_addr) |
1266160641Syongari		    FRAG_LEN(txsegs[i].ds_len));
1267160641Syongari	sc->sc_cdata.stge_tx_cnt++;
1268160641Syongari
1269160641Syongari	tfc = TFD_FrameId(si) | TFD_WordAlign(TFD_WordAlign_disable) |
1270160641Syongari	    TFD_FragCount(nsegs) | csum_flags;
1271160641Syongari	if (sc->sc_cdata.stge_tx_cnt >= STGE_TX_HIWAT)
1272160641Syongari		tfc |= TFD_TxDMAIndicate;
1273160641Syongari
1274160641Syongari	/* Update producer index. */
1275160641Syongari	sc->sc_cdata.stge_tx_prod = (si + 1) % STGE_TX_RING_CNT;
1276160641Syongari
1277160641Syongari	/* Check if we have a VLAN tag to insert. */
1278162375Sandre	if (m->m_flags & M_VLANTAG)
1279162375Sandre		tfc |= (TFD_VLANTagInsert | TFD_VID(m->m_pkthdr.ether_vtag));
1280160641Syongari	tfd->tfd_control = htole64(tfc);
1281160641Syongari
1282160641Syongari	/* Update Tx Queue. */
1283160641Syongari	STAILQ_REMOVE_HEAD(&sc->sc_cdata.stge_txfreeq, tx_q);
1284160641Syongari	STAILQ_INSERT_TAIL(&sc->sc_cdata.stge_txbusyq, txd, tx_q);
1285160641Syongari	txd->tx_m = m;
1286160641Syongari
1287160641Syongari	/* Sync descriptors. */
1288160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_tx_tag, txd->tx_dmamap,
1289160641Syongari	    BUS_DMASYNC_PREWRITE);
1290160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag,
1291160641Syongari	    sc->sc_cdata.stge_tx_ring_map,
1292160641Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1293160641Syongari
1294160641Syongari	return (0);
1295160641Syongari}
1296160641Syongari
1297160641Syongari/*
1298160641Syongari * stge_start:		[ifnet interface function]
1299160641Syongari *
1300160641Syongari *	Start packet transmission on the interface.
1301160641Syongari */
1302160641Syongaristatic void
1303160641Syongaristge_start(struct ifnet *ifp)
1304160641Syongari{
1305160641Syongari	struct stge_softc *sc;
1306160641Syongari
1307160641Syongari	sc = ifp->if_softc;
1308160641Syongari	STGE_LOCK(sc);
1309160641Syongari	stge_start_locked(ifp);
1310160641Syongari	STGE_UNLOCK(sc);
1311160641Syongari}
1312160641Syongari
1313160641Syongaristatic void
1314160641Syongaristge_start_locked(struct ifnet *ifp)
1315160641Syongari{
1316160641Syongari        struct stge_softc *sc;
1317160641Syongari        struct mbuf *m_head;
1318160641Syongari	int enq;
1319160641Syongari
1320160641Syongari	sc = ifp->if_softc;
1321160641Syongari
1322160641Syongari	STGE_LOCK_ASSERT(sc);
1323160641Syongari
1324160641Syongari	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
1325169158Syongari	    IFF_DRV_RUNNING || sc->sc_link == 0)
1326160641Syongari		return;
1327160641Syongari
1328160641Syongari	for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
1329160641Syongari		if (sc->sc_cdata.stge_tx_cnt >= STGE_TX_HIWAT) {
1330160641Syongari			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1331160641Syongari			break;
1332160641Syongari		}
1333160641Syongari
1334160641Syongari		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
1335160641Syongari		if (m_head == NULL)
1336160641Syongari			break;
1337160641Syongari		/*
1338160641Syongari		 * Pack the data into the transmit ring. If we
1339160641Syongari		 * don't have room, set the OACTIVE flag and wait
1340160641Syongari		 * for the NIC to drain the ring.
1341160641Syongari		 */
1342160641Syongari		if (stge_encap(sc, &m_head)) {
1343160641Syongari			if (m_head == NULL)
1344160641Syongari				break;
1345160641Syongari			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
1346160641Syongari			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1347160641Syongari			break;
1348160641Syongari		}
1349160641Syongari
1350160641Syongari		enq++;
1351160641Syongari		/*
1352160641Syongari		 * If there's a BPF listener, bounce a copy of this frame
1353160641Syongari		 * to him.
1354160641Syongari		 */
1355167190Scsjp		ETHER_BPF_MTAP(ifp, m_head);
1356160641Syongari	}
1357160641Syongari
1358160641Syongari	if (enq > 0) {
1359160641Syongari		/* Transmit */
1360160641Syongari		CSR_WRITE_4(sc, STGE_DMACtrl, DMAC_TxDMAPollNow);
1361160641Syongari
1362160641Syongari		/* Set a timeout in case the chip goes out to lunch. */
1363169157Syongari		sc->sc_watchdog_timer = 5;
1364160641Syongari	}
1365160641Syongari}
1366160641Syongari
1367160641Syongari/*
1368169157Syongari * stge_watchdog:
1369160641Syongari *
1370160641Syongari *	Watchdog timer handler.
1371160641Syongari */
1372160641Syongaristatic void
1373169157Syongaristge_watchdog(struct stge_softc *sc)
1374160641Syongari{
1375169157Syongari	struct ifnet *ifp;
1376160641Syongari
1377169157Syongari	STGE_LOCK_ASSERT(sc);
1378160641Syongari
1379169157Syongari	if (sc->sc_watchdog_timer == 0 || --sc->sc_watchdog_timer)
1380169157Syongari		return;
1381169157Syongari
1382169157Syongari	ifp = sc->sc_ifp;
1383160641Syongari	if_printf(sc->sc_ifp, "device timeout\n");
1384160641Syongari	ifp->if_oerrors++;
1385212972Syongari	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1386160641Syongari	stge_init_locked(sc);
1387169159Syongari	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1388169159Syongari		stge_start_locked(ifp);
1389160641Syongari}
1390160641Syongari
1391160641Syongari/*
1392160641Syongari * stge_ioctl:		[ifnet interface function]
1393160641Syongari *
1394160641Syongari *	Handle control requests from the operator.
1395160641Syongari */
1396160641Syongaristatic int
1397160641Syongaristge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1398160641Syongari{
1399160641Syongari	struct stge_softc *sc;
1400160641Syongari	struct ifreq *ifr;
1401160641Syongari	struct mii_data *mii;
1402160641Syongari	int error, mask;
1403160641Syongari
1404160641Syongari	sc = ifp->if_softc;
1405160641Syongari	ifr = (struct ifreq *)data;
1406160641Syongari	error = 0;
1407160641Syongari	switch (cmd) {
1408160641Syongari	case SIOCSIFMTU:
1409160641Syongari		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > STGE_JUMBO_MTU)
1410160641Syongari			error = EINVAL;
1411160641Syongari		else if (ifp->if_mtu != ifr->ifr_mtu) {
1412160641Syongari			ifp->if_mtu = ifr->ifr_mtu;
1413160641Syongari			STGE_LOCK(sc);
1414212972Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
1415212972Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1416212972Syongari				stge_init_locked(sc);
1417212972Syongari			}
1418160641Syongari			STGE_UNLOCK(sc);
1419160641Syongari		}
1420160641Syongari		break;
1421160641Syongari	case SIOCSIFFLAGS:
1422160641Syongari		STGE_LOCK(sc);
1423160641Syongari		if ((ifp->if_flags & IFF_UP) != 0) {
1424160641Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
1425160641Syongari				if (((ifp->if_flags ^ sc->sc_if_flags)
1426160641Syongari				    & IFF_PROMISC) != 0)
1427160641Syongari					stge_set_filter(sc);
1428160641Syongari			} else {
1429160641Syongari				if (sc->sc_detach == 0)
1430160641Syongari					stge_init_locked(sc);
1431160641Syongari			}
1432160641Syongari		} else {
1433160641Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1434160641Syongari				stge_stop(sc);
1435160641Syongari		}
1436160641Syongari		sc->sc_if_flags = ifp->if_flags;
1437160641Syongari		STGE_UNLOCK(sc);
1438160641Syongari		break;
1439160641Syongari	case SIOCADDMULTI:
1440160641Syongari	case SIOCDELMULTI:
1441160641Syongari		STGE_LOCK(sc);
1442160641Syongari		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1443160641Syongari			stge_set_multi(sc);
1444160641Syongari		STGE_UNLOCK(sc);
1445160641Syongari		break;
1446160641Syongari	case SIOCSIFMEDIA:
1447160641Syongari	case SIOCGIFMEDIA:
1448160641Syongari		mii = device_get_softc(sc->sc_miibus);
1449160641Syongari		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1450160641Syongari		break;
1451160641Syongari	case SIOCSIFCAP:
1452160641Syongari		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
1453160641Syongari#ifdef DEVICE_POLLING
1454160641Syongari		if ((mask & IFCAP_POLLING) != 0) {
1455160641Syongari			if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) {
1456160641Syongari				error = ether_poll_register(stge_poll, ifp);
1457160641Syongari				if (error != 0)
1458160641Syongari					break;
1459160641Syongari				STGE_LOCK(sc);
1460160641Syongari				CSR_WRITE_2(sc, STGE_IntEnable, 0);
1461160641Syongari				ifp->if_capenable |= IFCAP_POLLING;
1462160641Syongari				STGE_UNLOCK(sc);
1463160641Syongari			} else {
1464160641Syongari				error = ether_poll_deregister(ifp);
1465160641Syongari				if (error != 0)
1466160641Syongari					break;
1467160641Syongari				STGE_LOCK(sc);
1468160641Syongari				CSR_WRITE_2(sc, STGE_IntEnable,
1469160641Syongari				    sc->sc_IntEnable);
1470160641Syongari				ifp->if_capenable &= ~IFCAP_POLLING;
1471160641Syongari				STGE_UNLOCK(sc);
1472160641Syongari			}
1473160641Syongari		}
1474160641Syongari#endif
1475160641Syongari		if ((mask & IFCAP_HWCSUM) != 0) {
1476160641Syongari			ifp->if_capenable ^= IFCAP_HWCSUM;
1477160641Syongari			if ((IFCAP_HWCSUM & ifp->if_capenable) != 0 &&
1478160641Syongari			    (IFCAP_HWCSUM & ifp->if_capabilities) != 0)
1479160641Syongari				ifp->if_hwassist = STGE_CSUM_FEATURES;
1480160641Syongari			else
1481160641Syongari				ifp->if_hwassist = 0;
1482160641Syongari		}
1483175315Syongari		if ((mask & IFCAP_WOL) != 0 &&
1484175315Syongari		    (ifp->if_capabilities & IFCAP_WOL) != 0) {
1485175315Syongari			if ((mask & IFCAP_WOL_MAGIC) != 0)
1486175315Syongari				ifp->if_capenable ^= IFCAP_WOL_MAGIC;
1487175315Syongari		}
1488160641Syongari		if ((mask & IFCAP_VLAN_HWTAGGING) != 0) {
1489160641Syongari			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
1490160641Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
1491160641Syongari				STGE_LOCK(sc);
1492160641Syongari				stge_vlan_setup(sc);
1493160641Syongari				STGE_UNLOCK(sc);
1494160641Syongari			}
1495160641Syongari		}
1496160641Syongari		VLAN_CAPABILITIES(ifp);
1497160641Syongari		break;
1498160641Syongari	default:
1499160641Syongari		error = ether_ioctl(ifp, cmd, data);
1500160641Syongari		break;
1501160641Syongari	}
1502160641Syongari
1503160641Syongari	return (error);
1504160641Syongari}
1505160641Syongari
1506160641Syongaristatic void
1507160641Syongaristge_link_task(void *arg, int pending)
1508160641Syongari{
1509160641Syongari	struct stge_softc *sc;
1510169158Syongari	struct mii_data *mii;
1511160641Syongari	uint32_t v, ac;
1512160641Syongari	int i;
1513160641Syongari
1514160641Syongari	sc = (struct stge_softc *)arg;
1515160641Syongari	STGE_LOCK(sc);
1516169158Syongari
1517169158Syongari	mii = device_get_softc(sc->sc_miibus);
1518169158Syongari	if (mii->mii_media_status & IFM_ACTIVE) {
1519169158Syongari		if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
1520169158Syongari			sc->sc_link = 1;
1521169158Syongari	} else
1522169158Syongari		sc->sc_link = 0;
1523169158Syongari
1524169158Syongari	sc->sc_MACCtrl = 0;
1525169158Syongari	if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0)
1526169158Syongari		sc->sc_MACCtrl |= MC_DuplexSelect;
1527215297Smarius	if (((mii->mii_media_active & IFM_GMASK) & IFM_ETH_RXPAUSE) != 0)
1528169158Syongari		sc->sc_MACCtrl |= MC_RxFlowControlEnable;
1529215297Smarius	if (((mii->mii_media_active & IFM_GMASK) & IFM_ETH_TXPAUSE) != 0)
1530169158Syongari		sc->sc_MACCtrl |= MC_TxFlowControlEnable;
1531160641Syongari	/*
1532160641Syongari	 * Update STGE_MACCtrl register depending on link status.
1533160641Syongari	 * (duplex, flow control etc)
1534160641Syongari	 */
1535160641Syongari	v = ac = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
1536160641Syongari	v &= ~(MC_DuplexSelect|MC_RxFlowControlEnable|MC_TxFlowControlEnable);
1537160641Syongari	v |= sc->sc_MACCtrl;
1538160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
1539160641Syongari	if (((ac ^ sc->sc_MACCtrl) & MC_DuplexSelect) != 0) {
1540160641Syongari		/* Duplex setting changed, reset Tx/Rx functions. */
1541160641Syongari		ac = CSR_READ_4(sc, STGE_AsicCtrl);
1542160641Syongari		ac |= AC_TxReset | AC_RxReset;
1543160641Syongari		CSR_WRITE_4(sc, STGE_AsicCtrl, ac);
1544160641Syongari		for (i = 0; i < STGE_TIMEOUT; i++) {
1545160641Syongari			DELAY(100);
1546160641Syongari			if ((CSR_READ_4(sc, STGE_AsicCtrl) & AC_ResetBusy) == 0)
1547160641Syongari				break;
1548160641Syongari		}
1549160641Syongari		if (i == STGE_TIMEOUT)
1550160641Syongari			device_printf(sc->sc_dev, "reset failed to complete\n");
1551160641Syongari	}
1552160641Syongari	STGE_UNLOCK(sc);
1553160641Syongari}
1554160641Syongari
1555160641Syongaristatic __inline int
1556160641Syongaristge_tx_error(struct stge_softc *sc)
1557160641Syongari{
1558160641Syongari	uint32_t txstat;
1559160641Syongari	int error;
1560160641Syongari
1561160641Syongari	for (error = 0;;) {
1562160641Syongari		txstat = CSR_READ_4(sc, STGE_TxStatus);
1563160641Syongari		if ((txstat & TS_TxComplete) == 0)
1564160641Syongari			break;
1565160641Syongari		/* Tx underrun */
1566160641Syongari		if ((txstat & TS_TxUnderrun) != 0) {
1567160641Syongari			/*
1568160641Syongari			 * XXX
1569160641Syongari			 * There should be a more better way to recover
1570160641Syongari			 * from Tx underrun instead of a full reset.
1571160641Syongari			 */
1572160641Syongari			if (sc->sc_nerr++ < STGE_MAXERR)
1573160641Syongari				device_printf(sc->sc_dev, "Tx underrun, "
1574160641Syongari				    "resetting...\n");
1575160641Syongari			if (sc->sc_nerr == STGE_MAXERR)
1576160641Syongari				device_printf(sc->sc_dev, "too many errors; "
1577160641Syongari				    "not reporting any more\n");
1578160641Syongari			error = -1;
1579160641Syongari			break;
1580160641Syongari		}
1581160641Syongari		/* Maximum/Late collisions, Re-enable Tx MAC. */
1582160641Syongari		if ((txstat & (TS_MaxCollisions|TS_LateCollision)) != 0)
1583160641Syongari			CSR_WRITE_4(sc, STGE_MACCtrl,
1584160641Syongari			    (CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK) |
1585160641Syongari			    MC_TxEnable);
1586160641Syongari	}
1587160641Syongari
1588160641Syongari	return (error);
1589160641Syongari}
1590160641Syongari
1591160641Syongari/*
1592160641Syongari * stge_intr:
1593160641Syongari *
1594160641Syongari *	Interrupt service routine.
1595160641Syongari */
1596160641Syongaristatic void
1597160641Syongaristge_intr(void *arg)
1598160641Syongari{
1599160641Syongari	struct stge_softc *sc;
1600160641Syongari	struct ifnet *ifp;
1601160641Syongari	int reinit;
1602160641Syongari	uint16_t status;
1603160641Syongari
1604160641Syongari	sc = (struct stge_softc *)arg;
1605160641Syongari	ifp = sc->sc_ifp;
1606160641Syongari
1607160641Syongari	STGE_LOCK(sc);
1608160641Syongari
1609160641Syongari#ifdef DEVICE_POLLING
1610160641Syongari	if ((ifp->if_capenable & IFCAP_POLLING) != 0)
1611160641Syongari		goto done_locked;
1612160641Syongari#endif
1613160641Syongari	status = CSR_READ_2(sc, STGE_IntStatus);
1614160641Syongari	if (sc->sc_suspended || (status & IS_InterruptStatus) == 0)
1615160641Syongari		goto done_locked;
1616160641Syongari
1617160641Syongari	/* Disable interrupts. */
1618160641Syongari	for (reinit = 0;;) {
1619160641Syongari		status = CSR_READ_2(sc, STGE_IntStatusAck);
1620160641Syongari		status &= sc->sc_IntEnable;
1621160641Syongari		if (status == 0)
1622160641Syongari			break;
1623160641Syongari		/* Host interface errors. */
1624160641Syongari		if ((status & IS_HostError) != 0) {
1625160641Syongari			device_printf(sc->sc_dev,
1626160641Syongari			    "Host interface error, resetting...\n");
1627160641Syongari			reinit = 1;
1628160641Syongari			goto force_init;
1629160641Syongari		}
1630160641Syongari
1631160641Syongari		/* Receive interrupts. */
1632160641Syongari		if ((status & IS_RxDMAComplete) != 0) {
1633160641Syongari			stge_rxeof(sc);
1634160641Syongari			if ((status & IS_RFDListEnd) != 0)
1635160641Syongari				CSR_WRITE_4(sc, STGE_DMACtrl,
1636160641Syongari				    DMAC_RxDMAPollNow);
1637160641Syongari		}
1638160641Syongari
1639160641Syongari		/* Transmit interrupts. */
1640160641Syongari		if ((status & (IS_TxDMAComplete | IS_TxComplete)) != 0)
1641160641Syongari			stge_txeof(sc);
1642160641Syongari
1643160641Syongari		/* Transmission errors.*/
1644160641Syongari		if ((status & IS_TxComplete) != 0) {
1645160641Syongari			if ((reinit = stge_tx_error(sc)) != 0)
1646160641Syongari				break;
1647160641Syongari		}
1648160641Syongari	}
1649160641Syongari
1650160641Syongariforce_init:
1651212972Syongari	if (reinit != 0) {
1652212972Syongari		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1653160641Syongari		stge_init_locked(sc);
1654212972Syongari	}
1655160641Syongari
1656160641Syongari	/* Re-enable interrupts. */
1657160641Syongari	CSR_WRITE_2(sc, STGE_IntEnable, sc->sc_IntEnable);
1658160641Syongari
1659160641Syongari	/* Try to get more packets going. */
1660160641Syongari	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1661160641Syongari		stge_start_locked(ifp);
1662160641Syongari
1663160641Syongaridone_locked:
1664160641Syongari	STGE_UNLOCK(sc);
1665160641Syongari}
1666160641Syongari
1667160641Syongari/*
1668160641Syongari * stge_txeof:
1669160641Syongari *
1670160641Syongari *	Helper; handle transmit interrupts.
1671160641Syongari */
1672160641Syongaristatic void
1673160641Syongaristge_txeof(struct stge_softc *sc)
1674160641Syongari{
1675160641Syongari	struct ifnet *ifp;
1676160641Syongari	struct stge_txdesc *txd;
1677160641Syongari	uint64_t control;
1678160641Syongari	int cons;
1679160641Syongari
1680160641Syongari	STGE_LOCK_ASSERT(sc);
1681160641Syongari
1682160641Syongari	ifp = sc->sc_ifp;
1683160641Syongari
1684160641Syongari	txd = STAILQ_FIRST(&sc->sc_cdata.stge_txbusyq);
1685160641Syongari	if (txd == NULL)
1686160641Syongari		return;
1687160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag,
1688160641Syongari	    sc->sc_cdata.stge_tx_ring_map, BUS_DMASYNC_POSTREAD);
1689160641Syongari
1690160641Syongari	/*
1691160641Syongari	 * Go through our Tx list and free mbufs for those
1692160641Syongari	 * frames which have been transmitted.
1693160641Syongari	 */
1694160641Syongari	for (cons = sc->sc_cdata.stge_tx_cons;;
1695160641Syongari	    cons = (cons + 1) % STGE_TX_RING_CNT) {
1696160641Syongari		if (sc->sc_cdata.stge_tx_cnt <= 0)
1697160641Syongari			break;
1698160641Syongari		control = le64toh(sc->sc_rdata.stge_tx_ring[cons].tfd_control);
1699160641Syongari		if ((control & TFD_TFDDone) == 0)
1700160641Syongari			break;
1701160641Syongari		sc->sc_cdata.stge_tx_cnt--;
1702160641Syongari		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1703160641Syongari
1704160641Syongari		bus_dmamap_sync(sc->sc_cdata.stge_tx_tag, txd->tx_dmamap,
1705160641Syongari		    BUS_DMASYNC_POSTWRITE);
1706160641Syongari		bus_dmamap_unload(sc->sc_cdata.stge_tx_tag, txd->tx_dmamap);
1707160641Syongari
1708160641Syongari		/* Output counter is updated with statistics register */
1709160641Syongari		m_freem(txd->tx_m);
1710160641Syongari		txd->tx_m = NULL;
1711160641Syongari		STAILQ_REMOVE_HEAD(&sc->sc_cdata.stge_txbusyq, tx_q);
1712160641Syongari		STAILQ_INSERT_TAIL(&sc->sc_cdata.stge_txfreeq, txd, tx_q);
1713160641Syongari		txd = STAILQ_FIRST(&sc->sc_cdata.stge_txbusyq);
1714160641Syongari	}
1715160641Syongari	sc->sc_cdata.stge_tx_cons = cons;
1716160641Syongari	if (sc->sc_cdata.stge_tx_cnt == 0)
1717169157Syongari		sc->sc_watchdog_timer = 0;
1718160641Syongari
1719160641Syongari        bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag,
1720160641Syongari	    sc->sc_cdata.stge_tx_ring_map,
1721160641Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1722160641Syongari}
1723160641Syongari
1724160641Syongaristatic __inline void
1725160641Syongaristge_discard_rxbuf(struct stge_softc *sc, int idx)
1726160641Syongari{
1727160641Syongari	struct stge_rfd *rfd;
1728160641Syongari
1729160641Syongari	rfd = &sc->sc_rdata.stge_rx_ring[idx];
1730160641Syongari	rfd->rfd_status = 0;
1731160641Syongari}
1732160641Syongari
1733160641Syongari#ifndef __NO_STRICT_ALIGNMENT
1734160641Syongari/*
1735160641Syongari * It seems that TC9021's DMA engine has alignment restrictions in
1736160641Syongari * DMA scatter operations. The first DMA segment has no address
1737160641Syongari * alignment restrictins but the rest should be aligned on 4(?) bytes
1738160641Syongari * boundary. Otherwise it would corrupt random memory. Since we don't
1739160641Syongari * know which one is used for the first segment in advance we simply
1740160641Syongari * don't align at all.
1741160641Syongari * To avoid copying over an entire frame to align, we allocate a new
1742160641Syongari * mbuf and copy ethernet header to the new mbuf. The new mbuf is
1743160641Syongari * prepended into the existing mbuf chain.
1744160641Syongari */
1745160641Syongaristatic __inline struct mbuf *
1746160641Syongaristge_fixup_rx(struct stge_softc *sc, struct mbuf *m)
1747160641Syongari{
1748160641Syongari	struct mbuf *n;
1749160641Syongari
1750160641Syongari	n = NULL;
1751160641Syongari	if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) {
1752160641Syongari		bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len);
1753160641Syongari		m->m_data += ETHER_HDR_LEN;
1754160641Syongari		n = m;
1755160641Syongari	} else {
1756160641Syongari		MGETHDR(n, M_DONTWAIT, MT_DATA);
1757160641Syongari		if (n != NULL) {
1758160641Syongari			bcopy(m->m_data, n->m_data, ETHER_HDR_LEN);
1759160641Syongari			m->m_data += ETHER_HDR_LEN;
1760160641Syongari			m->m_len -= ETHER_HDR_LEN;
1761160641Syongari			n->m_len = ETHER_HDR_LEN;
1762160641Syongari			M_MOVE_PKTHDR(n, m);
1763160641Syongari			n->m_next = m;
1764160641Syongari		} else
1765160641Syongari			m_freem(m);
1766160641Syongari	}
1767160641Syongari
1768160641Syongari	return (n);
1769160641Syongari}
1770160641Syongari#endif
1771160641Syongari
1772160641Syongari/*
1773160641Syongari * stge_rxeof:
1774160641Syongari *
1775160641Syongari *	Helper; handle receive interrupts.
1776160641Syongari */
1777193096Sattiliostatic int
1778160641Syongaristge_rxeof(struct stge_softc *sc)
1779160641Syongari{
1780160641Syongari	struct ifnet *ifp;
1781160641Syongari	struct stge_rxdesc *rxd;
1782160641Syongari	struct mbuf *mp, *m;
1783160641Syongari	uint64_t status64;
1784160641Syongari	uint32_t status;
1785193096Sattilio	int cons, prog, rx_npkts;
1786160641Syongari
1787160641Syongari	STGE_LOCK_ASSERT(sc);
1788160641Syongari
1789193096Sattilio	rx_npkts = 0;
1790160641Syongari	ifp = sc->sc_ifp;
1791160641Syongari
1792160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_rx_ring_tag,
1793160641Syongari	    sc->sc_cdata.stge_rx_ring_map, BUS_DMASYNC_POSTREAD);
1794160641Syongari
1795160641Syongari	prog = 0;
1796160641Syongari	for (cons = sc->sc_cdata.stge_rx_cons; prog < STGE_RX_RING_CNT;
1797160641Syongari	    prog++, cons = (cons + 1) % STGE_RX_RING_CNT) {
1798160641Syongari		status64 = le64toh(sc->sc_rdata.stge_rx_ring[cons].rfd_status);
1799160641Syongari		status = RFD_RxStatus(status64);
1800160641Syongari		if ((status & RFD_RFDDone) == 0)
1801160641Syongari			break;
1802160641Syongari#ifdef DEVICE_POLLING
1803160641Syongari		if (ifp->if_capenable & IFCAP_POLLING) {
1804160641Syongari			if (sc->sc_cdata.stge_rxcycles <= 0)
1805160641Syongari				break;
1806160641Syongari			sc->sc_cdata.stge_rxcycles--;
1807160641Syongari		}
1808160641Syongari#endif
1809160641Syongari		prog++;
1810160641Syongari		rxd = &sc->sc_cdata.stge_rxdesc[cons];
1811160641Syongari		mp = rxd->rx_m;
1812160641Syongari
1813160641Syongari		/*
1814160641Syongari		 * If the packet had an error, drop it.  Note we count
1815160641Syongari		 * the error later in the periodic stats update.
1816160641Syongari		 */
1817160641Syongari		if ((status & RFD_FrameEnd) != 0 && (status &
1818160641Syongari		    (RFD_RxFIFOOverrun | RFD_RxRuntFrame |
1819160641Syongari		    RFD_RxAlignmentError | RFD_RxFCSError |
1820160641Syongari		    RFD_RxLengthError)) != 0) {
1821160641Syongari			stge_discard_rxbuf(sc, cons);
1822160641Syongari			if (sc->sc_cdata.stge_rxhead != NULL) {
1823160641Syongari				m_freem(sc->sc_cdata.stge_rxhead);
1824160641Syongari				STGE_RXCHAIN_RESET(sc);
1825160641Syongari			}
1826160641Syongari			continue;
1827160641Syongari		}
1828160641Syongari		/*
1829160641Syongari		 * Add a new receive buffer to the ring.
1830160641Syongari		 */
1831160641Syongari		if (stge_newbuf(sc, cons) != 0) {
1832160641Syongari			ifp->if_iqdrops++;
1833160641Syongari			stge_discard_rxbuf(sc, cons);
1834160641Syongari			if (sc->sc_cdata.stge_rxhead != NULL) {
1835160641Syongari				m_freem(sc->sc_cdata.stge_rxhead);
1836160641Syongari				STGE_RXCHAIN_RESET(sc);
1837160641Syongari			}
1838160641Syongari			continue;
1839160641Syongari		}
1840160641Syongari
1841160641Syongari		if ((status & RFD_FrameEnd) != 0)
1842160641Syongari			mp->m_len = RFD_RxDMAFrameLen(status) -
1843160641Syongari			    sc->sc_cdata.stge_rxlen;
1844160641Syongari		sc->sc_cdata.stge_rxlen += mp->m_len;
1845160641Syongari
1846160641Syongari		/* Chain mbufs. */
1847160641Syongari		if (sc->sc_cdata.stge_rxhead == NULL) {
1848160641Syongari			sc->sc_cdata.stge_rxhead = mp;
1849160641Syongari			sc->sc_cdata.stge_rxtail = mp;
1850160641Syongari		} else {
1851160641Syongari			mp->m_flags &= ~M_PKTHDR;
1852160641Syongari			sc->sc_cdata.stge_rxtail->m_next = mp;
1853160641Syongari			sc->sc_cdata.stge_rxtail = mp;
1854160641Syongari		}
1855160641Syongari
1856160641Syongari		if ((status & RFD_FrameEnd) != 0) {
1857160641Syongari			m = sc->sc_cdata.stge_rxhead;
1858160641Syongari			m->m_pkthdr.rcvif = ifp;
1859160641Syongari			m->m_pkthdr.len = sc->sc_cdata.stge_rxlen;
1860160641Syongari
1861160641Syongari			if (m->m_pkthdr.len > sc->sc_if_framesize) {
1862160641Syongari				m_freem(m);
1863160641Syongari				STGE_RXCHAIN_RESET(sc);
1864160641Syongari				continue;
1865160641Syongari			}
1866160641Syongari			/*
1867160641Syongari			 * Set the incoming checksum information for
1868160641Syongari			 * the packet.
1869160641Syongari			 */
1870160641Syongari			if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
1871160641Syongari				if ((status & RFD_IPDetected) != 0) {
1872160641Syongari					m->m_pkthdr.csum_flags |=
1873160641Syongari						CSUM_IP_CHECKED;
1874160641Syongari					if ((status & RFD_IPError) == 0)
1875160641Syongari						m->m_pkthdr.csum_flags |=
1876160641Syongari						    CSUM_IP_VALID;
1877160641Syongari				}
1878160641Syongari				if (((status & RFD_TCPDetected) != 0 &&
1879160641Syongari				    (status & RFD_TCPError) == 0) ||
1880160641Syongari				    ((status & RFD_UDPDetected) != 0 &&
1881160641Syongari				    (status & RFD_UDPError) == 0)) {
1882160641Syongari					m->m_pkthdr.csum_flags |=
1883160641Syongari					    (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
1884160641Syongari					m->m_pkthdr.csum_data = 0xffff;
1885160641Syongari				}
1886160641Syongari			}
1887160641Syongari
1888160641Syongari#ifndef __NO_STRICT_ALIGNMENT
1889160641Syongari			if (sc->sc_if_framesize > (MCLBYTES - ETHER_ALIGN)) {
1890160641Syongari				if ((m = stge_fixup_rx(sc, m)) == NULL) {
1891160641Syongari					STGE_RXCHAIN_RESET(sc);
1892160641Syongari					continue;
1893160641Syongari				}
1894160641Syongari			}
1895160641Syongari#endif
1896160641Syongari			/* Check for VLAN tagged packets. */
1897160641Syongari			if ((status & RFD_VLANDetected) != 0 &&
1898162375Sandre			    (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) {
1899162375Sandre				m->m_pkthdr.ether_vtag = RFD_TCI(status64);
1900162375Sandre				m->m_flags |= M_VLANTAG;
1901162375Sandre			}
1902160641Syongari
1903160641Syongari			STGE_UNLOCK(sc);
1904160641Syongari			/* Pass it on. */
1905160641Syongari			(*ifp->if_input)(ifp, m);
1906160641Syongari			STGE_LOCK(sc);
1907193096Sattilio			rx_npkts++;
1908160641Syongari
1909160641Syongari			STGE_RXCHAIN_RESET(sc);
1910160641Syongari		}
1911160641Syongari	}
1912160641Syongari
1913160641Syongari	if (prog > 0) {
1914160641Syongari		/* Update the consumer index. */
1915160641Syongari		sc->sc_cdata.stge_rx_cons = cons;
1916160641Syongari		bus_dmamap_sync(sc->sc_cdata.stge_rx_ring_tag,
1917160641Syongari		    sc->sc_cdata.stge_rx_ring_map,
1918160641Syongari		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1919160641Syongari	}
1920193096Sattilio	return (rx_npkts);
1921160641Syongari}
1922160641Syongari
1923160641Syongari#ifdef DEVICE_POLLING
1924193096Sattiliostatic int
1925160641Syongaristge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
1926160641Syongari{
1927160641Syongari	struct stge_softc *sc;
1928160641Syongari	uint16_t status;
1929193096Sattilio	int rx_npkts;
1930160641Syongari
1931193096Sattilio	rx_npkts = 0;
1932160641Syongari	sc = ifp->if_softc;
1933160641Syongari	STGE_LOCK(sc);
1934160641Syongari	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1935160641Syongari		STGE_UNLOCK(sc);
1936193096Sattilio		return (rx_npkts);
1937160641Syongari	}
1938160641Syongari
1939160641Syongari	sc->sc_cdata.stge_rxcycles = count;
1940193096Sattilio	rx_npkts = stge_rxeof(sc);
1941160641Syongari	stge_txeof(sc);
1942160641Syongari
1943160641Syongari	if (cmd == POLL_AND_CHECK_STATUS) {
1944160641Syongari		status = CSR_READ_2(sc, STGE_IntStatus);
1945160641Syongari		status &= sc->sc_IntEnable;
1946160641Syongari		if (status != 0) {
1947160641Syongari			if ((status & IS_HostError) != 0) {
1948160641Syongari				device_printf(sc->sc_dev,
1949160641Syongari				    "Host interface error, resetting...\n");
1950212972Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1951160641Syongari				stge_init_locked(sc);
1952160641Syongari			}
1953160641Syongari			if ((status & IS_TxComplete) != 0) {
1954212972Syongari				if (stge_tx_error(sc) != 0) {
1955212972Syongari					ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1956160641Syongari					stge_init_locked(sc);
1957212972Syongari				}
1958160641Syongari			}
1959160641Syongari		}
1960160641Syongari
1961160641Syongari	}
1962160641Syongari
1963160641Syongari	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1964160641Syongari		stge_start_locked(ifp);
1965160641Syongari
1966160641Syongari	STGE_UNLOCK(sc);
1967193096Sattilio	return (rx_npkts);
1968160641Syongari}
1969160641Syongari#endif	/* DEVICE_POLLING */
1970160641Syongari
1971160641Syongari/*
1972160641Syongari * stge_tick:
1973160641Syongari *
1974160641Syongari *	One second timer, used to tick the MII.
1975160641Syongari */
1976160641Syongaristatic void
1977160641Syongaristge_tick(void *arg)
1978160641Syongari{
1979160641Syongari	struct stge_softc *sc;
1980160641Syongari	struct mii_data *mii;
1981160641Syongari
1982160641Syongari	sc = (struct stge_softc *)arg;
1983160641Syongari
1984160641Syongari	STGE_LOCK_ASSERT(sc);
1985160641Syongari
1986160641Syongari	mii = device_get_softc(sc->sc_miibus);
1987160641Syongari	mii_tick(mii);
1988160641Syongari
1989160641Syongari	/* Update statistics counters. */
1990160641Syongari	stge_stats_update(sc);
1991160641Syongari
1992160641Syongari	/*
1993160641Syongari	 * Relcaim any pending Tx descriptors to release mbufs in a
1994160641Syongari	 * timely manner as we don't generate Tx completion interrupts
1995160641Syongari	 * for every frame. This limits the delay to a maximum of one
1996160641Syongari	 * second.
1997160641Syongari	 */
1998160641Syongari	if (sc->sc_cdata.stge_tx_cnt != 0)
1999160641Syongari		stge_txeof(sc);
2000160641Syongari
2001169157Syongari	stge_watchdog(sc);
2002169157Syongari
2003160641Syongari	callout_reset(&sc->sc_tick_ch, hz, stge_tick, sc);
2004160641Syongari}
2005160641Syongari
2006160641Syongari/*
2007160641Syongari * stge_stats_update:
2008160641Syongari *
2009160641Syongari *	Read the TC9021 statistics counters.
2010160641Syongari */
2011160641Syongaristatic void
2012160641Syongaristge_stats_update(struct stge_softc *sc)
2013160641Syongari{
2014160641Syongari	struct ifnet *ifp;
2015160641Syongari
2016160641Syongari	STGE_LOCK_ASSERT(sc);
2017160641Syongari
2018160641Syongari	ifp = sc->sc_ifp;
2019160641Syongari
2020160641Syongari	CSR_READ_4(sc,STGE_OctetRcvOk);
2021160641Syongari
2022160641Syongari	ifp->if_ipackets += CSR_READ_4(sc, STGE_FramesRcvdOk);
2023160641Syongari
2024160641Syongari	ifp->if_ierrors += CSR_READ_2(sc, STGE_FramesLostRxErrors);
2025160641Syongari
2026160641Syongari	CSR_READ_4(sc, STGE_OctetXmtdOk);
2027160641Syongari
2028160641Syongari	ifp->if_opackets += CSR_READ_4(sc, STGE_FramesXmtdOk);
2029160641Syongari
2030160641Syongari	ifp->if_collisions +=
2031160641Syongari	    CSR_READ_4(sc, STGE_LateCollisions) +
2032160641Syongari	    CSR_READ_4(sc, STGE_MultiColFrames) +
2033160641Syongari	    CSR_READ_4(sc, STGE_SingleColFrames);
2034160641Syongari
2035160641Syongari	ifp->if_oerrors +=
2036160641Syongari	    CSR_READ_2(sc, STGE_FramesAbortXSColls) +
2037160641Syongari	    CSR_READ_2(sc, STGE_FramesWEXDeferal);
2038160641Syongari}
2039160641Syongari
2040160641Syongari/*
2041160641Syongari * stge_reset:
2042160641Syongari *
2043160641Syongari *	Perform a soft reset on the TC9021.
2044160641Syongari */
2045160641Syongaristatic void
2046160641Syongaristge_reset(struct stge_softc *sc, uint32_t how)
2047160641Syongari{
2048160641Syongari	uint32_t ac;
2049160641Syongari	uint8_t v;
2050160641Syongari	int i, dv;
2051160641Syongari
2052160641Syongari	STGE_LOCK_ASSERT(sc);
2053160641Syongari
2054160641Syongari	dv = 5000;
2055160641Syongari	ac = CSR_READ_4(sc, STGE_AsicCtrl);
2056160641Syongari	switch (how) {
2057160641Syongari	case STGE_RESET_TX:
2058160641Syongari		ac |= AC_TxReset | AC_FIFO;
2059160641Syongari		dv = 100;
2060160641Syongari		break;
2061160641Syongari	case STGE_RESET_RX:
2062160641Syongari		ac |= AC_RxReset | AC_FIFO;
2063160641Syongari		dv = 100;
2064160641Syongari		break;
2065160641Syongari	case STGE_RESET_FULL:
2066160641Syongari	default:
2067160641Syongari		/*
2068160641Syongari		 * Only assert RstOut if we're fiber.  We need GMII clocks
2069160641Syongari		 * to be present in order for the reset to complete on fiber
2070160641Syongari		 * cards.
2071160641Syongari		 */
2072160641Syongari		ac |= AC_GlobalReset | AC_RxReset | AC_TxReset |
2073160641Syongari		    AC_DMA | AC_FIFO | AC_Network | AC_Host | AC_AutoInit |
2074160641Syongari		    (sc->sc_usefiber ? AC_RstOut : 0);
2075160641Syongari		break;
2076160641Syongari	}
2077160641Syongari
2078160641Syongari	CSR_WRITE_4(sc, STGE_AsicCtrl, ac);
2079160641Syongari
2080160641Syongari	/* Account for reset problem at 10Mbps. */
2081160641Syongari	DELAY(dv);
2082160641Syongari
2083160641Syongari	for (i = 0; i < STGE_TIMEOUT; i++) {
2084160641Syongari		if ((CSR_READ_4(sc, STGE_AsicCtrl) & AC_ResetBusy) == 0)
2085160641Syongari			break;
2086160641Syongari		DELAY(dv);
2087160641Syongari	}
2088160641Syongari
2089160641Syongari	if (i == STGE_TIMEOUT)
2090160641Syongari		device_printf(sc->sc_dev, "reset failed to complete\n");
2091160641Syongari
2092160641Syongari	/* Set LED, from Linux IPG driver. */
2093160641Syongari	ac = CSR_READ_4(sc, STGE_AsicCtrl);
2094160641Syongari	ac &= ~(AC_LEDMode | AC_LEDSpeed | AC_LEDModeBit1);
2095160641Syongari	if ((sc->sc_led & 0x01) != 0)
2096160641Syongari		ac |= AC_LEDMode;
2097160641Syongari	if ((sc->sc_led & 0x03) != 0)
2098160641Syongari		ac |= AC_LEDModeBit1;
2099160641Syongari	if ((sc->sc_led & 0x08) != 0)
2100160641Syongari		ac |= AC_LEDSpeed;
2101160641Syongari	CSR_WRITE_4(sc, STGE_AsicCtrl, ac);
2102160641Syongari
2103160641Syongari	/* Set PHY, from Linux IPG driver */
2104160641Syongari	v = CSR_READ_1(sc, STGE_PhySet);
2105160641Syongari	v &= ~(PS_MemLenb9b | PS_MemLen | PS_NonCompdet);
2106160641Syongari	v |= ((sc->sc_led & 0x70) >> 4);
2107160641Syongari	CSR_WRITE_1(sc, STGE_PhySet, v);
2108160641Syongari}
2109160641Syongari
2110160641Syongari/*
2111160641Syongari * stge_init:		[ ifnet interface function ]
2112160641Syongari *
2113160641Syongari *	Initialize the interface.
2114160641Syongari */
2115160641Syongaristatic void
2116160641Syongaristge_init(void *xsc)
2117160641Syongari{
2118160641Syongari	struct stge_softc *sc;
2119160641Syongari
2120160641Syongari	sc = (struct stge_softc *)xsc;
2121160641Syongari	STGE_LOCK(sc);
2122160641Syongari	stge_init_locked(sc);
2123160641Syongari	STGE_UNLOCK(sc);
2124160641Syongari}
2125160641Syongari
2126160641Syongaristatic void
2127160641Syongaristge_init_locked(struct stge_softc *sc)
2128160641Syongari{
2129160641Syongari	struct ifnet *ifp;
2130160641Syongari	struct mii_data *mii;
2131160641Syongari	uint16_t eaddr[3];
2132160641Syongari	uint32_t v;
2133160641Syongari	int error;
2134160641Syongari
2135160641Syongari	STGE_LOCK_ASSERT(sc);
2136160641Syongari
2137160641Syongari	ifp = sc->sc_ifp;
2138212972Syongari	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
2139212972Syongari		return;
2140160641Syongari	mii = device_get_softc(sc->sc_miibus);
2141160641Syongari
2142160641Syongari	/*
2143160641Syongari	 * Cancel any pending I/O.
2144160641Syongari	 */
2145160641Syongari	stge_stop(sc);
2146160641Syongari
2147175315Syongari	/*
2148175315Syongari	 * Reset the chip to a known state.
2149175315Syongari	 */
2150175315Syongari	stge_reset(sc, STGE_RESET_FULL);
2151175315Syongari
2152160641Syongari	/* Init descriptors. */
2153160641Syongari	error = stge_init_rx_ring(sc);
2154160641Syongari        if (error != 0) {
2155160641Syongari                device_printf(sc->sc_dev,
2156160641Syongari                    "initialization failed: no memory for rx buffers\n");
2157160641Syongari                stge_stop(sc);
2158160641Syongari		goto out;
2159160641Syongari        }
2160160641Syongari	stge_init_tx_ring(sc);
2161160641Syongari
2162160641Syongari	/* Set the station address. */
2163160641Syongari	bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN);
2164160641Syongari	CSR_WRITE_2(sc, STGE_StationAddress0, htole16(eaddr[0]));
2165160641Syongari	CSR_WRITE_2(sc, STGE_StationAddress1, htole16(eaddr[1]));
2166160641Syongari	CSR_WRITE_2(sc, STGE_StationAddress2, htole16(eaddr[2]));
2167160641Syongari
2168160641Syongari	/*
2169160641Syongari	 * Set the statistics masks.  Disable all the RMON stats,
2170160641Syongari	 * and disable selected stats in the non-RMON stats registers.
2171160641Syongari	 */
2172160641Syongari	CSR_WRITE_4(sc, STGE_RMONStatisticsMask, 0xffffffff);
2173160641Syongari	CSR_WRITE_4(sc, STGE_StatisticsMask,
2174160641Syongari	    (1U << 1) | (1U << 2) | (1U << 3) | (1U << 4) | (1U << 5) |
2175160641Syongari	    (1U << 6) | (1U << 7) | (1U << 8) | (1U << 9) | (1U << 10) |
2176160641Syongari	    (1U << 13) | (1U << 14) | (1U << 15) | (1U << 19) | (1U << 20) |
2177160641Syongari	    (1U << 21));
2178160641Syongari
2179160641Syongari	/* Set up the receive filter. */
2180160641Syongari	stge_set_filter(sc);
2181160641Syongari	/* Program multicast filter. */
2182160641Syongari	stge_set_multi(sc);
2183160641Syongari
2184160641Syongari	/*
2185160641Syongari	 * Give the transmit and receive ring to the chip.
2186160641Syongari	 */
2187160641Syongari	CSR_WRITE_4(sc, STGE_TFDListPtrHi,
2188160641Syongari	    STGE_ADDR_HI(STGE_TX_RING_ADDR(sc, 0)));
2189160641Syongari	CSR_WRITE_4(sc, STGE_TFDListPtrLo,
2190160641Syongari	    STGE_ADDR_LO(STGE_TX_RING_ADDR(sc, 0)));
2191160641Syongari
2192160641Syongari	CSR_WRITE_4(sc, STGE_RFDListPtrHi,
2193160641Syongari	    STGE_ADDR_HI(STGE_RX_RING_ADDR(sc, 0)));
2194160641Syongari	CSR_WRITE_4(sc, STGE_RFDListPtrLo,
2195160641Syongari	    STGE_ADDR_LO(STGE_RX_RING_ADDR(sc, 0)));
2196160641Syongari
2197160641Syongari	/*
2198160641Syongari	 * Initialize the Tx auto-poll period.  It's OK to make this number
2199160641Syongari	 * large (255 is the max, but we use 127) -- we explicitly kick the
2200160641Syongari	 * transmit engine when there's actually a packet.
2201160641Syongari	 */
2202160641Syongari	CSR_WRITE_1(sc, STGE_TxDMAPollPeriod, 127);
2203160641Syongari
2204160641Syongari	/* ..and the Rx auto-poll period. */
2205160641Syongari	CSR_WRITE_1(sc, STGE_RxDMAPollPeriod, 1);
2206160641Syongari
2207160641Syongari	/* Initialize the Tx start threshold. */
2208160641Syongari	CSR_WRITE_2(sc, STGE_TxStartThresh, sc->sc_txthresh);
2209160641Syongari
2210160641Syongari	/* Rx DMA thresholds, from Linux */
2211160641Syongari	CSR_WRITE_1(sc, STGE_RxDMABurstThresh, 0x30);
2212160641Syongari	CSR_WRITE_1(sc, STGE_RxDMAUrgentThresh, 0x30);
2213160641Syongari
2214160641Syongari	/* Rx early threhold, from Linux */
2215160641Syongari	CSR_WRITE_2(sc, STGE_RxEarlyThresh, 0x7ff);
2216160641Syongari
2217160641Syongari	/* Tx DMA thresholds, from Linux */
2218160641Syongari	CSR_WRITE_1(sc, STGE_TxDMABurstThresh, 0x30);
2219160641Syongari	CSR_WRITE_1(sc, STGE_TxDMAUrgentThresh, 0x04);
2220160641Syongari
2221160641Syongari	/*
2222160641Syongari	 * Initialize the Rx DMA interrupt control register.  We
2223160641Syongari	 * request an interrupt after every incoming packet, but
2224160641Syongari	 * defer it for sc_rxint_dmawait us. When the number of
2225160641Syongari	 * interrupts pending reaches STGE_RXINT_NFRAME, we stop
2226160641Syongari	 * deferring the interrupt, and signal it immediately.
2227160641Syongari	 */
2228160641Syongari	CSR_WRITE_4(sc, STGE_RxDMAIntCtrl,
2229160641Syongari	    RDIC_RxFrameCount(sc->sc_rxint_nframe) |
2230160641Syongari	    RDIC_RxDMAWaitTime(STGE_RXINT_USECS2TICK(sc->sc_rxint_dmawait)));
2231160641Syongari
2232160641Syongari	/*
2233160641Syongari	 * Initialize the interrupt mask.
2234160641Syongari	 */
2235160641Syongari	sc->sc_IntEnable = IS_HostError | IS_TxComplete |
2236160641Syongari	    IS_TxDMAComplete | IS_RxDMAComplete | IS_RFDListEnd;
2237160641Syongari#ifdef DEVICE_POLLING
2238160641Syongari	/* Disable interrupts if we are polling. */
2239160641Syongari	if ((ifp->if_capenable & IFCAP_POLLING) != 0)
2240160641Syongari		CSR_WRITE_2(sc, STGE_IntEnable, 0);
2241160641Syongari	else
2242160641Syongari#endif
2243160641Syongari	CSR_WRITE_2(sc, STGE_IntEnable, sc->sc_IntEnable);
2244160641Syongari
2245160641Syongari	/*
2246160641Syongari	 * Configure the DMA engine.
2247160641Syongari	 * XXX Should auto-tune TxBurstLimit.
2248160641Syongari	 */
2249160641Syongari	CSR_WRITE_4(sc, STGE_DMACtrl, sc->sc_DMACtrl | DMAC_TxBurstLimit(3));
2250160641Syongari
2251160641Syongari	/*
2252160641Syongari	 * Send a PAUSE frame when we reach 29,696 bytes in the Rx
2253160641Syongari	 * FIFO, and send an un-PAUSE frame when we reach 3056 bytes
2254160641Syongari	 * in the Rx FIFO.
2255160641Syongari	 */
2256160641Syongari	CSR_WRITE_2(sc, STGE_FlowOnTresh, 29696 / 16);
2257160641Syongari	CSR_WRITE_2(sc, STGE_FlowOffThresh, 3056 / 16);
2258160641Syongari
2259160641Syongari	/*
2260160641Syongari	 * Set the maximum frame size.
2261160641Syongari	 */
2262160641Syongari	sc->sc_if_framesize = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
2263160641Syongari	CSR_WRITE_2(sc, STGE_MaxFrameSize, sc->sc_if_framesize);
2264160641Syongari
2265160641Syongari	/*
2266160641Syongari	 * Initialize MacCtrl -- do it before setting the media,
2267160641Syongari	 * as setting the media will actually program the register.
2268160641Syongari	 *
2269160641Syongari	 * Note: We have to poke the IFS value before poking
2270160641Syongari	 * anything else.
2271160641Syongari	 */
2272160641Syongari	/* Tx/Rx MAC should be disabled before programming IFS.*/
2273160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, MC_IFSSelect(MC_IFS96bit));
2274160641Syongari
2275160641Syongari	stge_vlan_setup(sc);
2276160641Syongari
2277160641Syongari	if (sc->sc_rev >= 6) {		/* >= B.2 */
2278160641Syongari		/* Multi-frag frame bug work-around. */
2279160641Syongari		CSR_WRITE_2(sc, STGE_DebugCtrl,
2280160641Syongari		    CSR_READ_2(sc, STGE_DebugCtrl) | 0x0200);
2281160641Syongari
2282160641Syongari		/* Tx Poll Now bug work-around. */
2283160641Syongari		CSR_WRITE_2(sc, STGE_DebugCtrl,
2284160641Syongari		    CSR_READ_2(sc, STGE_DebugCtrl) | 0x0010);
2285160641Syongari		/* Tx Poll Now bug work-around. */
2286160641Syongari		CSR_WRITE_2(sc, STGE_DebugCtrl,
2287160641Syongari		    CSR_READ_2(sc, STGE_DebugCtrl) | 0x0020);
2288160641Syongari	}
2289160641Syongari
2290160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2291160641Syongari	v |= MC_StatisticsEnable | MC_TxEnable | MC_RxEnable;
2292160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2293160641Syongari	/*
2294160641Syongari	 * It seems that transmitting frames without checking the state of
2295160641Syongari	 * Rx/Tx MAC wedge the hardware.
2296160641Syongari	 */
2297160641Syongari	stge_start_tx(sc);
2298160641Syongari	stge_start_rx(sc);
2299160641Syongari
2300169158Syongari	sc->sc_link = 0;
2301160641Syongari	/*
2302160641Syongari	 * Set the current media.
2303160641Syongari	 */
2304160641Syongari	mii_mediachg(mii);
2305160641Syongari
2306160641Syongari	/*
2307160641Syongari	 * Start the one second MII clock.
2308160641Syongari	 */
2309160641Syongari	callout_reset(&sc->sc_tick_ch, hz, stge_tick, sc);
2310160641Syongari
2311160641Syongari	/*
2312160641Syongari	 * ...all done!
2313160641Syongari	 */
2314160641Syongari	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2315160641Syongari	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2316160641Syongari
2317160641Syongari out:
2318160641Syongari	if (error != 0)
2319160641Syongari		device_printf(sc->sc_dev, "interface not running\n");
2320160641Syongari}
2321160641Syongari
2322160641Syongaristatic void
2323160641Syongaristge_vlan_setup(struct stge_softc *sc)
2324160641Syongari{
2325160641Syongari	struct ifnet *ifp;
2326160641Syongari	uint32_t v;
2327160641Syongari
2328160641Syongari	ifp = sc->sc_ifp;
2329160641Syongari	/*
2330160641Syongari	 * The NIC always copy a VLAN tag regardless of STGE_MACCtrl
2331160641Syongari	 * MC_AutoVLANuntagging bit.
2332160641Syongari	 * MC_AutoVLANtagging bit selects which VLAN source to use
2333160641Syongari	 * between STGE_VLANTag and TFC. However TFC TFD_VLANTagInsert
2334160641Syongari	 * bit has priority over MC_AutoVLANtagging bit. So we always
2335160641Syongari	 * use TFC instead of STGE_VLANTag register.
2336160641Syongari	 */
2337160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2338160641Syongari	if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
2339160641Syongari		v |= MC_AutoVLANuntagging;
2340160641Syongari	else
2341160641Syongari		v &= ~MC_AutoVLANuntagging;
2342160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2343160641Syongari}
2344160641Syongari
2345160641Syongari/*
2346160641Syongari *	Stop transmission on the interface.
2347160641Syongari */
2348160641Syongaristatic void
2349160641Syongaristge_stop(struct stge_softc *sc)
2350160641Syongari{
2351160641Syongari	struct ifnet *ifp;
2352160641Syongari	struct stge_txdesc *txd;
2353160641Syongari	struct stge_rxdesc *rxd;
2354160641Syongari	uint32_t v;
2355160641Syongari	int i;
2356160641Syongari
2357160641Syongari	STGE_LOCK_ASSERT(sc);
2358160641Syongari	/*
2359160641Syongari	 * Stop the one second clock.
2360160641Syongari	 */
2361160641Syongari	callout_stop(&sc->sc_tick_ch);
2362169157Syongari	sc->sc_watchdog_timer = 0;
2363160641Syongari
2364160641Syongari	/*
2365160641Syongari	 * Disable interrupts.
2366160641Syongari	 */
2367160641Syongari	CSR_WRITE_2(sc, STGE_IntEnable, 0);
2368160641Syongari
2369160641Syongari	/*
2370160641Syongari	 * Stop receiver, transmitter, and stats update.
2371160641Syongari	 */
2372160641Syongari	stge_stop_rx(sc);
2373160641Syongari	stge_stop_tx(sc);
2374160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2375160641Syongari	v |= MC_StatisticsDisable;
2376160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2377160641Syongari
2378160641Syongari	/*
2379160641Syongari	 * Stop the transmit and receive DMA.
2380160641Syongari	 */
2381160641Syongari	stge_dma_wait(sc);
2382160641Syongari	CSR_WRITE_4(sc, STGE_TFDListPtrHi, 0);
2383160641Syongari	CSR_WRITE_4(sc, STGE_TFDListPtrLo, 0);
2384160641Syongari	CSR_WRITE_4(sc, STGE_RFDListPtrHi, 0);
2385160641Syongari	CSR_WRITE_4(sc, STGE_RFDListPtrLo, 0);
2386160641Syongari
2387160641Syongari	/*
2388160641Syongari	 * Free RX and TX mbufs still in the queues.
2389160641Syongari	 */
2390160641Syongari	for (i = 0; i < STGE_RX_RING_CNT; i++) {
2391160641Syongari		rxd = &sc->sc_cdata.stge_rxdesc[i];
2392160641Syongari		if (rxd->rx_m != NULL) {
2393160641Syongari			bus_dmamap_sync(sc->sc_cdata.stge_rx_tag,
2394160641Syongari			    rxd->rx_dmamap, BUS_DMASYNC_POSTREAD);
2395160641Syongari			bus_dmamap_unload(sc->sc_cdata.stge_rx_tag,
2396160641Syongari			    rxd->rx_dmamap);
2397160641Syongari			m_freem(rxd->rx_m);
2398160641Syongari			rxd->rx_m = NULL;
2399160641Syongari		}
2400160641Syongari        }
2401160641Syongari	for (i = 0; i < STGE_TX_RING_CNT; i++) {
2402160641Syongari		txd = &sc->sc_cdata.stge_txdesc[i];
2403160641Syongari		if (txd->tx_m != NULL) {
2404160641Syongari			bus_dmamap_sync(sc->sc_cdata.stge_tx_tag,
2405160641Syongari			    txd->tx_dmamap, BUS_DMASYNC_POSTWRITE);
2406160641Syongari			bus_dmamap_unload(sc->sc_cdata.stge_tx_tag,
2407160641Syongari			    txd->tx_dmamap);
2408160641Syongari			m_freem(txd->tx_m);
2409160641Syongari			txd->tx_m = NULL;
2410160641Syongari		}
2411160641Syongari        }
2412160641Syongari
2413160641Syongari	/*
2414160641Syongari	 * Mark the interface down and cancel the watchdog timer.
2415160641Syongari	 */
2416160641Syongari	ifp = sc->sc_ifp;
2417160641Syongari	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
2418169158Syongari	sc->sc_link = 0;
2419160641Syongari}
2420160641Syongari
2421160641Syongaristatic void
2422160641Syongaristge_start_tx(struct stge_softc *sc)
2423160641Syongari{
2424160641Syongari	uint32_t v;
2425160641Syongari	int i;
2426160641Syongari
2427160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2428160641Syongari	if ((v & MC_TxEnabled) != 0)
2429160641Syongari		return;
2430160641Syongari	v |= MC_TxEnable;
2431160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2432160641Syongari	CSR_WRITE_1(sc, STGE_TxDMAPollPeriod, 127);
2433160641Syongari	for (i = STGE_TIMEOUT; i > 0; i--) {
2434160641Syongari		DELAY(10);
2435160641Syongari		v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2436160641Syongari		if ((v & MC_TxEnabled) != 0)
2437160641Syongari			break;
2438160641Syongari	}
2439160641Syongari	if (i == 0)
2440160641Syongari		device_printf(sc->sc_dev, "Starting Tx MAC timed out\n");
2441160641Syongari}
2442160641Syongari
2443160641Syongaristatic void
2444160641Syongaristge_start_rx(struct stge_softc *sc)
2445160641Syongari{
2446160641Syongari	uint32_t v;
2447160641Syongari	int i;
2448160641Syongari
2449160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2450160641Syongari	if ((v & MC_RxEnabled) != 0)
2451160641Syongari		return;
2452160641Syongari	v |= MC_RxEnable;
2453160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2454160641Syongari	CSR_WRITE_1(sc, STGE_RxDMAPollPeriod, 1);
2455160641Syongari	for (i = STGE_TIMEOUT; i > 0; i--) {
2456160641Syongari		DELAY(10);
2457160641Syongari		v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2458160641Syongari		if ((v & MC_RxEnabled) != 0)
2459160641Syongari			break;
2460160641Syongari	}
2461160641Syongari	if (i == 0)
2462160641Syongari		device_printf(sc->sc_dev, "Starting Rx MAC timed out\n");
2463160641Syongari}
2464160641Syongari
2465160641Syongaristatic void
2466160641Syongaristge_stop_tx(struct stge_softc *sc)
2467160641Syongari{
2468160641Syongari	uint32_t v;
2469160641Syongari	int i;
2470160641Syongari
2471160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2472160641Syongari	if ((v & MC_TxEnabled) == 0)
2473160641Syongari		return;
2474160641Syongari	v |= MC_TxDisable;
2475160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2476160641Syongari	for (i = STGE_TIMEOUT; i > 0; i--) {
2477160641Syongari		DELAY(10);
2478160641Syongari		v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2479160641Syongari		if ((v & MC_TxEnabled) == 0)
2480160641Syongari			break;
2481160641Syongari	}
2482160641Syongari	if (i == 0)
2483160641Syongari		device_printf(sc->sc_dev, "Stopping Tx MAC timed out\n");
2484160641Syongari}
2485160641Syongari
2486160641Syongaristatic void
2487160641Syongaristge_stop_rx(struct stge_softc *sc)
2488160641Syongari{
2489160641Syongari	uint32_t v;
2490160641Syongari	int i;
2491160641Syongari
2492160641Syongari	v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2493160641Syongari	if ((v & MC_RxEnabled) == 0)
2494160641Syongari		return;
2495160641Syongari	v |= MC_RxDisable;
2496160641Syongari	CSR_WRITE_4(sc, STGE_MACCtrl, v);
2497160641Syongari	for (i = STGE_TIMEOUT; i > 0; i--) {
2498160641Syongari		DELAY(10);
2499160641Syongari		v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK;
2500160641Syongari		if ((v & MC_RxEnabled) == 0)
2501160641Syongari			break;
2502160641Syongari	}
2503160641Syongari	if (i == 0)
2504160641Syongari		device_printf(sc->sc_dev, "Stopping Rx MAC timed out\n");
2505160641Syongari}
2506160641Syongari
2507160641Syongaristatic void
2508160641Syongaristge_init_tx_ring(struct stge_softc *sc)
2509160641Syongari{
2510160641Syongari	struct stge_ring_data *rd;
2511160641Syongari	struct stge_txdesc *txd;
2512160641Syongari	bus_addr_t addr;
2513160641Syongari	int i;
2514160641Syongari
2515160641Syongari	STAILQ_INIT(&sc->sc_cdata.stge_txfreeq);
2516160641Syongari	STAILQ_INIT(&sc->sc_cdata.stge_txbusyq);
2517160641Syongari
2518160641Syongari	sc->sc_cdata.stge_tx_prod = 0;
2519160641Syongari	sc->sc_cdata.stge_tx_cons = 0;
2520160641Syongari	sc->sc_cdata.stge_tx_cnt = 0;
2521160641Syongari
2522160641Syongari	rd = &sc->sc_rdata;
2523160641Syongari	bzero(rd->stge_tx_ring, STGE_TX_RING_SZ);
2524160641Syongari	for (i = 0; i < STGE_TX_RING_CNT; i++) {
2525160641Syongari		if (i == (STGE_TX_RING_CNT - 1))
2526160641Syongari			addr = STGE_TX_RING_ADDR(sc, 0);
2527160641Syongari		else
2528160641Syongari			addr = STGE_TX_RING_ADDR(sc, i + 1);
2529160641Syongari		rd->stge_tx_ring[i].tfd_next = htole64(addr);
2530160641Syongari		rd->stge_tx_ring[i].tfd_control = htole64(TFD_TFDDone);
2531160641Syongari		txd = &sc->sc_cdata.stge_txdesc[i];
2532160641Syongari		STAILQ_INSERT_TAIL(&sc->sc_cdata.stge_txfreeq, txd, tx_q);
2533160641Syongari	}
2534160641Syongari
2535160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag,
2536160641Syongari	    sc->sc_cdata.stge_tx_ring_map,
2537160641Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2538160641Syongari
2539160641Syongari}
2540160641Syongari
2541160641Syongaristatic int
2542160641Syongaristge_init_rx_ring(struct stge_softc *sc)
2543160641Syongari{
2544160641Syongari	struct stge_ring_data *rd;
2545160641Syongari	bus_addr_t addr;
2546160641Syongari	int i;
2547160641Syongari
2548160641Syongari	sc->sc_cdata.stge_rx_cons = 0;
2549160641Syongari	STGE_RXCHAIN_RESET(sc);
2550160641Syongari
2551160641Syongari	rd = &sc->sc_rdata;
2552160641Syongari	bzero(rd->stge_rx_ring, STGE_RX_RING_SZ);
2553160641Syongari	for (i = 0; i < STGE_RX_RING_CNT; i++) {
2554160641Syongari		if (stge_newbuf(sc, i) != 0)
2555160641Syongari			return (ENOBUFS);
2556160641Syongari		if (i == (STGE_RX_RING_CNT - 1))
2557160641Syongari			addr = STGE_RX_RING_ADDR(sc, 0);
2558160641Syongari		else
2559160641Syongari			addr = STGE_RX_RING_ADDR(sc, i + 1);
2560160641Syongari		rd->stge_rx_ring[i].rfd_next = htole64(addr);
2561160641Syongari		rd->stge_rx_ring[i].rfd_status = 0;
2562160641Syongari	}
2563160641Syongari
2564160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_rx_ring_tag,
2565160641Syongari	    sc->sc_cdata.stge_rx_ring_map,
2566160641Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2567160641Syongari
2568160641Syongari	return (0);
2569160641Syongari}
2570160641Syongari
2571160641Syongari/*
2572160641Syongari * stge_newbuf:
2573160641Syongari *
2574160641Syongari *	Add a receive buffer to the indicated descriptor.
2575160641Syongari */
2576160641Syongaristatic int
2577160641Syongaristge_newbuf(struct stge_softc *sc, int idx)
2578160641Syongari{
2579160641Syongari	struct stge_rxdesc *rxd;
2580160641Syongari	struct stge_rfd *rfd;
2581160641Syongari	struct mbuf *m;
2582160641Syongari	bus_dma_segment_t segs[1];
2583160641Syongari	bus_dmamap_t map;
2584160641Syongari	int nsegs;
2585160641Syongari
2586160641Syongari	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
2587160641Syongari	if (m == NULL)
2588160641Syongari		return (ENOBUFS);
2589160641Syongari	m->m_len = m->m_pkthdr.len = MCLBYTES;
2590160641Syongari	/*
2591160641Syongari	 * The hardware requires 4bytes aligned DMA address when JUMBO
2592160641Syongari	 * frame is used.
2593160641Syongari	 */
2594160641Syongari	if (sc->sc_if_framesize <= (MCLBYTES - ETHER_ALIGN))
2595160641Syongari		m_adj(m, ETHER_ALIGN);
2596160641Syongari
2597160641Syongari	if (bus_dmamap_load_mbuf_sg(sc->sc_cdata.stge_rx_tag,
2598160641Syongari	    sc->sc_cdata.stge_rx_sparemap, m, segs, &nsegs, 0) != 0) {
2599160641Syongari		m_freem(m);
2600160641Syongari		return (ENOBUFS);
2601160641Syongari	}
2602160641Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
2603160641Syongari
2604160641Syongari	rxd = &sc->sc_cdata.stge_rxdesc[idx];
2605160641Syongari	if (rxd->rx_m != NULL) {
2606160641Syongari		bus_dmamap_sync(sc->sc_cdata.stge_rx_tag, rxd->rx_dmamap,
2607160641Syongari		    BUS_DMASYNC_POSTREAD);
2608160641Syongari		bus_dmamap_unload(sc->sc_cdata.stge_rx_tag, rxd->rx_dmamap);
2609160641Syongari	}
2610160641Syongari	map = rxd->rx_dmamap;
2611160641Syongari	rxd->rx_dmamap = sc->sc_cdata.stge_rx_sparemap;
2612160641Syongari	sc->sc_cdata.stge_rx_sparemap = map;
2613160641Syongari	bus_dmamap_sync(sc->sc_cdata.stge_rx_tag, rxd->rx_dmamap,
2614160641Syongari	    BUS_DMASYNC_PREREAD);
2615160641Syongari	rxd->rx_m = m;
2616160641Syongari
2617160641Syongari	rfd = &sc->sc_rdata.stge_rx_ring[idx];
2618160641Syongari	rfd->rfd_frag.frag_word0 =
2619160641Syongari	    htole64(FRAG_ADDR(segs[0].ds_addr) | FRAG_LEN(segs[0].ds_len));
2620160641Syongari	rfd->rfd_status = 0;
2621160641Syongari
2622160641Syongari	return (0);
2623160641Syongari}
2624160641Syongari
2625160641Syongari/*
2626160641Syongari * stge_set_filter:
2627160641Syongari *
2628160641Syongari *	Set up the receive filter.
2629160641Syongari */
2630160641Syongaristatic void
2631160641Syongaristge_set_filter(struct stge_softc *sc)
2632160641Syongari{
2633160641Syongari	struct ifnet *ifp;
2634160641Syongari	uint16_t mode;
2635160641Syongari
2636160641Syongari	STGE_LOCK_ASSERT(sc);
2637160641Syongari
2638160641Syongari	ifp = sc->sc_ifp;
2639160641Syongari
2640160641Syongari	mode = CSR_READ_2(sc, STGE_ReceiveMode);
2641160641Syongari	mode |= RM_ReceiveUnicast;
2642160641Syongari	if ((ifp->if_flags & IFF_BROADCAST) != 0)
2643160641Syongari		mode |= RM_ReceiveBroadcast;
2644160641Syongari	else
2645160641Syongari		mode &= ~RM_ReceiveBroadcast;
2646160641Syongari	if ((ifp->if_flags & IFF_PROMISC) != 0)
2647160641Syongari		mode |= RM_ReceiveAllFrames;
2648160641Syongari	else
2649160641Syongari		mode &= ~RM_ReceiveAllFrames;
2650160641Syongari
2651160641Syongari	CSR_WRITE_2(sc, STGE_ReceiveMode, mode);
2652160641Syongari}
2653160641Syongari
2654160641Syongaristatic void
2655160641Syongaristge_set_multi(struct stge_softc *sc)
2656160641Syongari{
2657160641Syongari	struct ifnet *ifp;
2658160641Syongari	struct ifmultiaddr *ifma;
2659160641Syongari	uint32_t crc;
2660160641Syongari	uint32_t mchash[2];
2661160641Syongari	uint16_t mode;
2662160641Syongari	int count;
2663160641Syongari
2664160641Syongari	STGE_LOCK_ASSERT(sc);
2665160641Syongari
2666160641Syongari	ifp = sc->sc_ifp;
2667160641Syongari
2668160641Syongari	mode = CSR_READ_2(sc, STGE_ReceiveMode);
2669160641Syongari	if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
2670160641Syongari		if ((ifp->if_flags & IFF_PROMISC) != 0)
2671160641Syongari			mode |= RM_ReceiveAllFrames;
2672160641Syongari		else if ((ifp->if_flags & IFF_ALLMULTI) != 0)
2673160641Syongari			mode |= RM_ReceiveMulticast;
2674160641Syongari		CSR_WRITE_2(sc, STGE_ReceiveMode, mode);
2675160641Syongari		return;
2676160641Syongari	}
2677160641Syongari
2678160641Syongari	/* clear existing filters. */
2679160641Syongari	CSR_WRITE_4(sc, STGE_HashTable0, 0);
2680160641Syongari	CSR_WRITE_4(sc, STGE_HashTable1, 0);
2681160641Syongari
2682160641Syongari	/*
2683160641Syongari	 * Set up the multicast address filter by passing all multicast
2684160641Syongari	 * addresses through a CRC generator, and then using the low-order
2685160641Syongari	 * 6 bits as an index into the 64 bit multicast hash table.  The
2686160641Syongari	 * high order bits select the register, while the rest of the bits
2687160641Syongari	 * select the bit within the register.
2688160641Syongari	 */
2689160641Syongari
2690160641Syongari	bzero(mchash, sizeof(mchash));
2691160641Syongari
2692160641Syongari	count = 0;
2693195049Srwatson	if_maddr_rlock(sc->sc_ifp);
2694160641Syongari	TAILQ_FOREACH(ifma, &sc->sc_ifp->if_multiaddrs, ifma_link) {
2695160641Syongari		if (ifma->ifma_addr->sa_family != AF_LINK)
2696160641Syongari			continue;
2697160641Syongari		crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
2698160641Syongari		    ifma->ifma_addr), ETHER_ADDR_LEN);
2699160641Syongari
2700160641Syongari		/* Just want the 6 least significant bits. */
2701160641Syongari		crc &= 0x3f;
2702160641Syongari
2703160641Syongari		/* Set the corresponding bit in the hash table. */
2704160641Syongari		mchash[crc >> 5] |= 1 << (crc & 0x1f);
2705160641Syongari		count++;
2706160641Syongari	}
2707195049Srwatson	if_maddr_runlock(ifp);
2708160641Syongari
2709160641Syongari	mode &= ~(RM_ReceiveMulticast | RM_ReceiveAllFrames);
2710160641Syongari	if (count > 0)
2711160641Syongari		mode |= RM_ReceiveMulticastHash;
2712160641Syongari	else
2713160641Syongari		mode &= ~RM_ReceiveMulticastHash;
2714160641Syongari
2715160641Syongari	CSR_WRITE_4(sc, STGE_HashTable0, mchash[0]);
2716160641Syongari	CSR_WRITE_4(sc, STGE_HashTable1, mchash[1]);
2717160641Syongari	CSR_WRITE_2(sc, STGE_ReceiveMode, mode);
2718160641Syongari}
2719160641Syongari
2720160641Syongaristatic int
2721160641Syongarisysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
2722160641Syongari{
2723160641Syongari	int error, value;
2724160641Syongari
2725160641Syongari	if (!arg1)
2726160641Syongari		return (EINVAL);
2727160641Syongari	value = *(int *)arg1;
2728160641Syongari	error = sysctl_handle_int(oidp, &value, 0, req);
2729160641Syongari	if (error || !req->newptr)
2730160641Syongari		return (error);
2731160641Syongari	if (value < low || value > high)
2732160641Syongari		return (EINVAL);
2733160641Syongari        *(int *)arg1 = value;
2734160641Syongari
2735160641Syongari        return (0);
2736160641Syongari}
2737160641Syongari
2738160641Syongaristatic int
2739160641Syongarisysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS)
2740160641Syongari{
2741160641Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
2742160641Syongari	    STGE_RXINT_NFRAME_MIN, STGE_RXINT_NFRAME_MAX));
2743160641Syongari}
2744160641Syongari
2745160641Syongaristatic int
2746160641Syongarisysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS)
2747160641Syongari{
2748160641Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
2749160641Syongari	    STGE_RXINT_DMAWAIT_MIN, STGE_RXINT_DMAWAIT_MAX));
2750160641Syongari}
2751