if_ste.c revision 51455
1194676Sthompsa/*
2194676Sthompsa * Copyright (c) 1997, 1998, 1999
3194676Sthompsa *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4195957Salfred *
5194676Sthompsa * Redistribution and use in source and binary forms, with or without
6194676Sthompsa * modification, are permitted provided that the following conditions
7194676Sthompsa * are met:
8194676Sthompsa * 1. Redistributions of source code must retain the above copyright
9194676Sthompsa *    notice, this list of conditions and the following disclaimer.
10194676Sthompsa * 2. Redistributions in binary form must reproduce the above copyright
11194676Sthompsa *    notice, this list of conditions and the following disclaimer in the
12194676Sthompsa *    documentation and/or other materials provided with the distribution.
13194676Sthompsa * 3. All advertising materials mentioning features or use of this software
14194676Sthompsa *    must display the following acknowledgement:
15194676Sthompsa *	This product includes software developed by Bill Paul.
16194676Sthompsa * 4. Neither the name of the author nor the names of any co-contributors
17194676Sthompsa *    may be used to endorse or promote products derived from this software
18194676Sthompsa *    without specific prior written permission.
19194676Sthompsa *
20194676Sthompsa * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21194676Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22194676Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23194676Sthompsa * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24194676Sthompsa * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25194676Sthompsa * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26194676Sthompsa * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27194676Sthompsa * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28194676Sthompsa * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29194676Sthompsa * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30194676Sthompsa * THE POSSIBILITY OF SUCH DAMAGE.
31194676Sthompsa *
32194676Sthompsa * $FreeBSD: head/sys/pci/if_ste.c 51455 1999-09-20 08:47:11Z wpaul $
33194676Sthompsa */
34194676Sthompsa
35195957Salfred
36195957Salfred#include "bpf.h"
37195957Salfred
38199055Sthompsa#include <sys/param.h>
39194676Sthompsa#include <sys/systm.h>
40194676Sthompsa#include <sys/sockio.h>
41194676Sthompsa#include <sys/mbuf.h>
42194676Sthompsa#include <sys/malloc.h>
43194676Sthompsa#include <sys/kernel.h>
44194676Sthompsa#include <sys/socket.h>
45194676Sthompsa
46194676Sthompsa#include <net/if.h>
47194676Sthompsa#include <net/if_arp.h>
48194676Sthompsa#include <net/ethernet.h>
49195957Salfred#include <net/if_dl.h>
50195957Salfred#include <net/if_media.h>
51195957Salfred
52195957Salfred#if NBPF > 0
53195957Salfred#include <net/bpf.h>
54195957Salfred#endif
55195957Salfred
56195957Salfred#include "opt_bdg.h"
57195957Salfred#ifdef BRIDGE
58195957Salfred#include <net/bridge.h>
59195957Salfred#endif
60195957Salfred
61194676Sthompsa#include <vm/vm.h>              /* for vtophys */
62194676Sthompsa#include <vm/pmap.h>            /* for vtophys */
63194676Sthompsa#include <machine/clock.h>      /* for DELAY */
64195957Salfred#include <machine/bus_memio.h>
65194676Sthompsa#include <machine/bus_pio.h>
66195957Salfred#include <machine/bus.h>
67194676Sthompsa#include <machine/resource.h>
68194676Sthompsa#include <sys/bus.h>
69194676Sthompsa#include <sys/rman.h>
70194676Sthompsa
71194676Sthompsa#include <dev/mii/mii.h>
72195957Salfred#include <dev/mii/miivar.h>
73194676Sthompsa
74194676Sthompsa#include <pci/pcireg.h>
75195957Salfred#include <pci/pcivar.h>
76194676Sthompsa
77194676Sthompsa/* "controller miibus0" required.  See GENERIC if you get errors here. */
78194676Sthompsa#include "miibus_if.h"
79194676Sthompsa
80194676Sthompsa#define STE_USEIOSPACE
81194676Sthompsa
82194676Sthompsa#include <pci/if_stereg.h>
83194676Sthompsa
84194676Sthompsa#if !defined(lint)
85194676Sthompsastatic const char rcsid[] =
86194676Sthompsa  "$FreeBSD: head/sys/pci/if_ste.c 51455 1999-09-20 08:47:11Z wpaul $";
87194676Sthompsa#endif
88194676Sthompsa
89194676Sthompsa/*
90195957Salfred * Various supported device vendors/types and their names.
91195957Salfred */
92194676Sthompsastatic struct ste_type ste_devs[] = {
93195957Salfred	{ ST_VENDORID, ST_DEVICEID_ST201, "Sundance ST201 10/100BaseTX" },
94195957Salfred	{ DL_VENDORID, DL_DEVICEID_550TX, "D-Link DFE-550TX 10/100BaseTX" },
95194676Sthompsa	{ 0, 0, NULL }
96195957Salfred};
97194676Sthompsa
98194676Sthompsastatic int ste_probe		__P((device_t));
99194676Sthompsastatic int ste_attach		__P((device_t));
100195957Salfredstatic int ste_detach		__P((device_t));
101195957Salfredstatic void ste_init		__P((void *));
102194676Sthompsastatic void ste_intr		__P((void *));
103194676Sthompsastatic void ste_rxeof		__P((struct ste_softc *));
104194676Sthompsastatic void ste_txeoc		__P((struct ste_softc *));
105195957Salfredstatic void ste_txeof		__P((struct ste_softc *));
106195957Salfredstatic void ste_stats_update	__P((void *));
107195957Salfredstatic void ste_stop		__P((struct ste_softc *));
108195957Salfredstatic void ste_reset		__P((struct ste_softc *));
109195957Salfredstatic int ste_ioctl		__P((struct ifnet *, u_long, caddr_t));
110194676Sthompsastatic int ste_encap		__P((struct ste_softc *, struct ste_chain *,
111195957Salfred					struct mbuf *));
112194676Sthompsastatic void ste_start		__P((struct ifnet *));
113194676Sthompsastatic void ste_watchdog	__P((struct ifnet *));
114194676Sthompsastatic void ste_shutdown	__P((device_t));
115194676Sthompsastatic int ste_newbuf		__P((struct ste_softc *,
116194676Sthompsa					struct ste_chain_onefrag *,
117194676Sthompsa					struct mbuf *));
118194676Sthompsastatic int ste_ifmedia_upd	__P((struct ifnet *));
119194676Sthompsastatic void ste_ifmedia_sts	__P((struct ifnet *, struct ifmediareq *));
120194676Sthompsa
121194676Sthompsastatic void ste_mii_sync	__P((struct ste_softc *));
122195957Salfredstatic void ste_mii_send	__P((struct ste_softc *, u_int32_t, int));
123195957Salfredstatic int ste_mii_readreg	__P((struct ste_softc *,
124194676Sthompsa					struct ste_mii_frame *));
125194676Sthompsastatic int ste_mii_writereg	__P((struct ste_softc *,
126194676Sthompsa					struct ste_mii_frame *));
127194676Sthompsastatic int ste_miibus_readreg	__P((device_t, int, int));
128195957Salfredstatic int ste_miibus_writereg	__P((device_t, int, int, int));
129194676Sthompsastatic void ste_miibus_statchg	__P((device_t));
130195957Salfred
131194676Sthompsastatic int ste_eeprom_wait	__P((struct ste_softc *));
132195957Salfredstatic int ste_read_eeprom	__P((struct ste_softc *, caddr_t, int,
133195957Salfred							int, int));
134195957Salfredstatic void ste_wait		__P((struct ste_softc *));
135195957Salfredstatic u_int8_t ste_calchash	__P((caddr_t));
136195957Salfredstatic void ste_setmulti	__P((struct ste_softc *));
137195957Salfredstatic int ste_init_rx_list	__P((struct ste_softc *));
138194676Sthompsastatic void ste_init_tx_list	__P((struct ste_softc *));
139194676Sthompsa
140195957Salfred#ifdef STE_USEIOSPACE
141195957Salfred#define STE_RES			SYS_RES_IOPORT
142194676Sthompsa#define STE_RID			STE_PCI_LOIO
143194676Sthompsa#else
144194676Sthompsa#define STE_RES			SYS_RES_MEMORY
145194676Sthompsa#define STE_RID			STE_PCI_LOMEM
146194676Sthompsa#endif
147194676Sthompsa
148194676Sthompsastatic device_method_t ste_methods[] = {
149194676Sthompsa	/* Device interface */
150194676Sthompsa	DEVMETHOD(device_probe,		ste_probe),
151194676Sthompsa	DEVMETHOD(device_attach,	ste_attach),
152194676Sthompsa	DEVMETHOD(device_detach,	ste_detach),
153194676Sthompsa	DEVMETHOD(device_shutdown,	ste_shutdown),
154194676Sthompsa
155195957Salfred	/* bus interface */
156194676Sthompsa	DEVMETHOD(bus_print_child,	bus_generic_print_child),
157195957Salfred	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
158194676Sthompsa
159194676Sthompsa	/* MII interface */
160194676Sthompsa	DEVMETHOD(miibus_readreg,	ste_miibus_readreg),
161194676Sthompsa	DEVMETHOD(miibus_writereg,	ste_miibus_writereg),
162195957Salfred	DEVMETHOD(miibus_statchg,	ste_miibus_statchg),
163194676Sthompsa
164195957Salfred	{ 0, 0 }
165195957Salfred};
166195957Salfred
167195957Salfredstatic driver_t ste_driver = {
168195957Salfred	"ste",
169195957Salfred	ste_methods,
170194676Sthompsa	sizeof(struct ste_softc)
171194676Sthompsa};
172195957Salfred
173194676Sthompsastatic devclass_t ste_devclass;
174195957Salfred
175194676SthompsaDRIVER_MODULE(if_ste, pci, ste_driver, ste_devclass, 0, 0);
176194676SthompsaDRIVER_MODULE(miibus, if_ste, miibus_driver, miibus_devclass, 0, 0);
177194676Sthompsa
178194676Sthompsa#define STE_SETBIT4(sc, reg, x)				\
179194676Sthompsa	CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | x)
180195957Salfred
181194676Sthompsa#define STE_CLRBIT4(sc, reg, x)				\
182194676Sthompsa	CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~x)
183194676Sthompsa
184194676Sthompsa#define STE_SETBIT2(sc, reg, x)				\
185194676Sthompsa	CSR_WRITE_2(sc, reg, CSR_READ_2(sc, reg) | x)
186195957Salfred
187194676Sthompsa#define STE_CLRBIT2(sc, reg, x)				\
188194676Sthompsa	CSR_WRITE_2(sc, reg, CSR_READ_2(sc, reg) & ~x)
189194676Sthompsa
190194676Sthompsa#define STE_SETBIT1(sc, reg, x)				\
191194676Sthompsa	CSR_WRITE_1(sc, reg, CSR_READ_1(sc, reg) | x)
192195560Sthompsa
193195560Sthompsa#define STE_CLRBIT1(sc, reg, x)				\
194195560Sthompsa	CSR_WRITE_1(sc, reg, CSR_READ_1(sc, reg) & ~x)
195195560Sthompsa
196194676Sthompsa
197195957Salfred#define MII_SET(x)		STE_SETBIT1(sc, STE_PHYCTL, x)
198194676Sthompsa#define MII_CLR(x)		STE_CLRBIT1(sc, STE_PHYCTL, x)
199194676Sthompsa
200194676Sthompsa/*
201199055Sthompsa * Sync the PHYs by setting data bit and strobing the clock 32 times.
202199055Sthompsa */
203199055Sthompsastatic void ste_mii_sync(sc)
204199055Sthompsa	struct ste_softc		*sc;
205194676Sthompsa{
206194676Sthompsa	register int		i;
207195957Salfred
208195957Salfred	MII_SET(STE_PHYCTL_MDIR|STE_PHYCTL_MDATA);
209195957Salfred
210195957Salfred	for (i = 0; i < 32; i++) {
211194676Sthompsa		MII_SET(STE_PHYCTL_MCLK);
212194676Sthompsa		DELAY(1);
213194676Sthompsa		MII_CLR(STE_PHYCTL_MCLK);
214194676Sthompsa		DELAY(1);
215195957Salfred	}
216194676Sthompsa
217194676Sthompsa	return;
218194676Sthompsa}
219194676Sthompsa
220194676Sthompsa/*
221194676Sthompsa * Clock a series of bits through the MII.
222194676Sthompsa */
223194676Sthompsastatic void ste_mii_send(sc, bits, cnt)
224194676Sthompsa	struct ste_softc		*sc;
225194676Sthompsa	u_int32_t		bits;
226194676Sthompsa	int			cnt;
227194676Sthompsa{
228194676Sthompsa	int			i;
229194676Sthompsa
230194676Sthompsa	MII_CLR(STE_PHYCTL_MCLK);
231194676Sthompsa
232195957Salfred	for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
233194676Sthompsa                if (bits & i) {
234194676Sthompsa			MII_SET(STE_PHYCTL_MDATA);
235194676Sthompsa                } else {
236194676Sthompsa			MII_CLR(STE_PHYCTL_MDATA);
237194676Sthompsa                }
238194676Sthompsa		DELAY(1);
239194676Sthompsa		MII_CLR(STE_PHYCTL_MCLK);
240194676Sthompsa		DELAY(1);
241194676Sthompsa		MII_SET(STE_PHYCTL_MCLK);
242195957Salfred	}
243194676Sthompsa}
244194676Sthompsa
245195957Salfred/*
246195957Salfred * Read an PHY register through the MII.
247194676Sthompsa */
248194676Sthompsastatic int ste_mii_readreg(sc, frame)
249194676Sthompsa	struct ste_softc		*sc;
250195957Salfred	struct ste_mii_frame	*frame;
251194676Sthompsa
252194676Sthompsa{
253195957Salfred	int			i, ack, s;
254195957Salfred
255194676Sthompsa	s = splimp();
256194676Sthompsa
257194676Sthompsa	/*
258195957Salfred	 * Set up frame for RX.
259194676Sthompsa	 */
260194676Sthompsa	frame->mii_stdelim = STE_MII_STARTDELIM;
261194676Sthompsa	frame->mii_opcode = STE_MII_READOP;
262194676Sthompsa	frame->mii_turnaround = 0;
263194676Sthompsa	frame->mii_data = 0;
264195957Salfred
265195957Salfred	CSR_WRITE_2(sc, STE_PHYCTL, 0);
266195957Salfred	/*
267195957Salfred 	 * Turn on data xmit.
268194676Sthompsa	 */
269194676Sthompsa	MII_SET(STE_PHYCTL_MDIR);
270194676Sthompsa
271194676Sthompsa	ste_mii_sync(sc);
272195957Salfred
273195957Salfred	/*
274195957Salfred	 * Send command/address info.
275195957Salfred	 */
276194676Sthompsa	ste_mii_send(sc, frame->mii_stdelim, 2);
277195957Salfred	ste_mii_send(sc, frame->mii_opcode, 2);
278194676Sthompsa	ste_mii_send(sc, frame->mii_phyaddr, 5);
279195957Salfred	ste_mii_send(sc, frame->mii_regaddr, 5);
280194676Sthompsa
281195957Salfred	/* Turn off xmit. */
282194676Sthompsa	MII_CLR(STE_PHYCTL_MDIR);
283194676Sthompsa
284194676Sthompsa	/* Idle bit */
285194676Sthompsa	MII_CLR((STE_PHYCTL_MCLK|STE_PHYCTL_MDATA));
286194676Sthompsa	DELAY(1);
287194676Sthompsa	MII_SET(STE_PHYCTL_MCLK);
288194676Sthompsa	DELAY(1);
289194676Sthompsa
290194676Sthompsa	/* Check for ack */
291194676Sthompsa	MII_CLR(STE_PHYCTL_MCLK);
292194676Sthompsa	DELAY(1);
293194676Sthompsa	MII_SET(STE_PHYCTL_MCLK);
294194676Sthompsa	DELAY(1);
295194676Sthompsa	ack = CSR_READ_2(sc, STE_PHYCTL) & STE_PHYCTL_MDATA;
296194676Sthompsa
297195957Salfred	/*
298194676Sthompsa	 * Now try reading data bits. If the ack failed, we still
299194676Sthompsa	 * need to clock through 16 cycles to keep the PHY(s) in sync.
300195957Salfred	 */
301194676Sthompsa	if (ack) {
302195957Salfred		for(i = 0; i < 16; i++) {
303194676Sthompsa			MII_CLR(STE_PHYCTL_MCLK);
304195957Salfred			DELAY(1);
305194676Sthompsa			MII_SET(STE_PHYCTL_MCLK);
306194676Sthompsa			DELAY(1);
307194676Sthompsa		}
308194676Sthompsa		goto fail;
309194676Sthompsa	}
310195957Salfred
311194676Sthompsa	for (i = 0x8000; i; i >>= 1) {
312194676Sthompsa		MII_CLR(STE_PHYCTL_MCLK);
313195957Salfred		DELAY(1);
314194676Sthompsa		if (!ack) {
315195957Salfred			if (CSR_READ_2(sc, STE_PHYCTL) & STE_PHYCTL_MDATA)
316194676Sthompsa				frame->mii_data |= i;
317195957Salfred			DELAY(1);
318194676Sthompsa		}
319194676Sthompsa		MII_SET(STE_PHYCTL_MCLK);
320194676Sthompsa		DELAY(1);
321194676Sthompsa	}
322194676Sthompsa
323194676Sthompsafail:
324194676Sthompsa
325194676Sthompsa	MII_CLR(STE_PHYCTL_MCLK);
326195957Salfred	DELAY(1);
327194676Sthompsa	MII_SET(STE_PHYCTL_MCLK);
328194676Sthompsa	DELAY(1);
329194676Sthompsa
330195957Salfred	splx(s);
331194676Sthompsa
332194676Sthompsa	if (ack)
333194676Sthompsa		return(1);
334194676Sthompsa	return(0);
335194676Sthompsa}
336195957Salfred
337195957Salfred/*
338194676Sthompsa * Write to a PHY register through the MII.
339195957Salfred */
340195957Salfredstatic int ste_mii_writereg(sc, frame)
341195957Salfred	struct ste_softc		*sc;
342195957Salfred	struct ste_mii_frame	*frame;
343194676Sthompsa
344194676Sthompsa{
345195957Salfred	int			s;
346194676Sthompsa
347194676Sthompsa	s = splimp();
348195957Salfred	/*
349194676Sthompsa	 * Set up frame for TX.
350194676Sthompsa	 */
351195957Salfred
352195957Salfred	frame->mii_stdelim = STE_MII_STARTDELIM;
353194676Sthompsa	frame->mii_opcode = STE_MII_WRITEOP;
354195957Salfred	frame->mii_turnaround = STE_MII_TURNAROUND;
355195957Salfred
356195957Salfred	/*
357194676Sthompsa 	 * Turn on data output.
358195957Salfred	 */
359194676Sthompsa	MII_SET(STE_PHYCTL_MDIR);
360194676Sthompsa
361194676Sthompsa	ste_mii_sync(sc);
362194676Sthompsa
363194676Sthompsa	ste_mii_send(sc, frame->mii_stdelim, 2);
364195957Salfred	ste_mii_send(sc, frame->mii_opcode, 2);
365194676Sthompsa	ste_mii_send(sc, frame->mii_phyaddr, 5);
366194676Sthompsa	ste_mii_send(sc, frame->mii_regaddr, 5);
367194676Sthompsa	ste_mii_send(sc, frame->mii_turnaround, 2);
368194676Sthompsa	ste_mii_send(sc, frame->mii_data, 16);
369194676Sthompsa
370195957Salfred	/* Idle bit. */
371195957Salfred	MII_SET(STE_PHYCTL_MCLK);
372194676Sthompsa	DELAY(1);
373195957Salfred	MII_CLR(STE_PHYCTL_MCLK);
374195957Salfred	DELAY(1);
375195957Salfred
376195957Salfred	/*
377195560Sthompsa	 * Turn off xmit.
378194676Sthompsa	 */
379194676Sthompsa	MII_CLR(STE_PHYCTL_MDIR);
380194676Sthompsa
381194676Sthompsa	splx(s);
382195957Salfred
383195957Salfred	return(0);
384194676Sthompsa}
385195957Salfred
386194676Sthompsastatic int ste_miibus_readreg(dev, phy, reg)
387195957Salfred	device_t		dev;
388195957Salfred	int			phy, reg;
389195957Salfred{
390195957Salfred	struct ste_softc	*sc;
391195957Salfred	struct ste_mii_frame	frame;
392194676Sthompsa
393195560Sthompsa	sc = device_get_softc(dev);
394195957Salfred
395195957Salfred	bzero((char *)&frame, sizeof(frame));
396195957Salfred
397195560Sthompsa	frame.mii_phyaddr = phy;
398194676Sthompsa	frame.mii_regaddr = reg;
399194676Sthompsa	ste_mii_readreg(sc, &frame);
400194676Sthompsa
401195560Sthompsa	return(frame.mii_data);
402195957Salfred}
403194676Sthompsa
404194676Sthompsastatic int ste_miibus_writereg(dev, phy, reg, data)
405194676Sthompsa	device_t		dev;
406195957Salfred	int			phy, reg, data;
407194676Sthompsa{
408194676Sthompsa	struct ste_softc	*sc;
409195957Salfred	struct ste_mii_frame	frame;
410195957Salfred
411194676Sthompsa	sc = device_get_softc(dev);
412194676Sthompsa	bzero((char *)&frame, sizeof(frame));
413195957Salfred
414195957Salfred	frame.mii_phyaddr = phy;
415194676Sthompsa	frame.mii_regaddr = reg;
416195957Salfred	frame.mii_data = data;
417195957Salfred
418194676Sthompsa	ste_mii_writereg(sc, &frame);
419195957Salfred
420194676Sthompsa	return(0);
421195957Salfred}
422199055Sthompsa
423199055Sthompsastatic void ste_miibus_statchg(dev)
424195957Salfred	device_t		dev;
425194676Sthompsa{
426195957Salfred	struct ste_softc	*sc;
427195957Salfred	struct mii_data		*mii;
428194676Sthompsa
429195957Salfred	sc = device_get_softc(dev);
430195957Salfred	mii = device_get_softc(sc->ste_miibus);
431195957Salfred
432194676Sthompsa	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
433194676Sthompsa		STE_SETBIT2(sc, STE_MACCTL0, STE_MACCTL0_FULLDUPLEX);
434194676Sthompsa	} else {
435194676Sthompsa		STE_CLRBIT2(sc, STE_MACCTL0, STE_MACCTL0_FULLDUPLEX);
436195957Salfred	}
437194676Sthompsa
438195957Salfred	return;
439194676Sthompsa}
440195957Salfred
441194676Sthompsastatic int ste_ifmedia_upd(ifp)
442194676Sthompsa	struct ifnet		*ifp;
443194676Sthompsa{
444195957Salfred	struct ste_softc	*sc;
445194676Sthompsa	struct mii_data		*mii;
446195957Salfred
447194676Sthompsa	sc = ifp->if_softc;
448195957Salfred	mii = device_get_softc(sc->ste_miibus);
449194676Sthompsa	mii_mediachg(mii);
450194676Sthompsa
451195957Salfred	return(0);
452195957Salfred}
453195957Salfred
454194676Sthompsastatic void ste_ifmedia_sts(ifp, ifmr)
455195957Salfred	struct ifnet		*ifp;
456195957Salfred	struct ifmediareq	*ifmr;
457195957Salfred{
458195957Salfred	struct ste_softc	*sc;
459194676Sthompsa	struct mii_data		*mii;
460194676Sthompsa
461194676Sthompsa	sc = ifp->if_softc;
462194676Sthompsa	mii = device_get_softc(sc->ste_miibus);
463195957Salfred
464194676Sthompsa	mii_pollstat(mii);
465195957Salfred	ifmr->ifm_active = mii->mii_media_active;
466195957Salfred	ifmr->ifm_status = mii->mii_media_status;
467195957Salfred
468195957Salfred	return;
469194676Sthompsa}
470195957Salfred
471194676Sthompsastatic void ste_wait(sc)
472195957Salfred	struct ste_softc		*sc;
473194676Sthompsa{
474194676Sthompsa	register int		i;
475195957Salfred
476195957Salfred	for (i = 0; i < STE_TIMEOUT; i++) {
477195957Salfred		if (!(CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_DMA_HALTINPROG))
478195957Salfred			break;
479195957Salfred	}
480195957Salfred
481194676Sthompsa	if (i == STE_TIMEOUT)
482195957Salfred		printf("ste%d: command never completed!\n", sc->ste_unit);
483195957Salfred
484195957Salfred	return;
485195957Salfred}
486195957Salfred
487195957Salfred/*
488195957Salfred * The EEPROM is slow: give it time to come ready after issuing
489195957Salfred * it a command.
490195957Salfred */
491195957Salfredstatic int ste_eeprom_wait(sc)
492195957Salfred	struct ste_softc		*sc;
493195957Salfred{
494195957Salfred	int			i;
495195957Salfred
496195957Salfred	DELAY(1000);
497195957Salfred
498195957Salfred	for (i = 0; i < 100; i++) {
499195957Salfred		if (CSR_READ_2(sc, STE_EEPROM_CTL) & STE_EECTL_BUSY)
500195957Salfred			DELAY(1000);
501195957Salfred		else
502195957Salfred			break;
503195957Salfred	}
504195957Salfred
505195957Salfred	if (i == 100) {
506195957Salfred		printf("ste%d: eeprom failed to come ready\n", sc->ste_unit);
507194676Sthompsa		return(1);
508194676Sthompsa	}
509194676Sthompsa
510195957Salfred	return(0);
511194676Sthompsa}
512195957Salfred
513195957Salfred/*
514194676Sthompsa * Read a sequence of words from the EEPROM. Note that ethernet address
515195957Salfred * data is stored in the EEPROM in network byte order.
516194676Sthompsa */
517194676Sthompsastatic int ste_read_eeprom(sc, dest, off, cnt, swap)
518194676Sthompsa	struct ste_softc		*sc;
519195957Salfred	caddr_t			dest;
520194676Sthompsa	int			off;
521194676Sthompsa	int			cnt;
522195957Salfred	int			swap;
523194676Sthompsa{
524195957Salfred	int			err = 0, i;
525194676Sthompsa	u_int16_t		word = 0, *ptr;
526195957Salfred
527194676Sthompsa	if (ste_eeprom_wait(sc))
528195957Salfred		return(1);
529195957Salfred
530194676Sthompsa	for (i = 0; i < cnt; i++) {
531194676Sthompsa		CSR_WRITE_2(sc, STE_EEPROM_CTL, STE_EEOPCODE_READ | (off + i));
532194676Sthompsa		err = ste_eeprom_wait(sc);
533195957Salfred		if (err)
534194676Sthompsa			break;
535195957Salfred		word = CSR_READ_2(sc, STE_EEPROM_DATA);
536195957Salfred		ptr = (u_int16_t *)(dest + (i * 2));
537194676Sthompsa		if (swap)
538195957Salfred			*ptr = ntohs(word);
539194676Sthompsa		else
540194676Sthompsa			*ptr = word;
541194676Sthompsa	}
542195957Salfred
543194676Sthompsa	return(err ? 1 : 0);
544194676Sthompsa}
545195957Salfred
546194676Sthompsastatic u_int8_t ste_calchash(addr)
547195957Salfred	caddr_t			addr;
548194676Sthompsa{
549195957Salfred
550194676Sthompsa	u_int32_t		crc, carry;
551195957Salfred	int			i, j;
552195957Salfred	u_int8_t		c;
553194676Sthompsa
554194676Sthompsa	/* Compute CRC for the address value. */
555194676Sthompsa	crc = 0xFFFFFFFF; /* initial value */
556195957Salfred
557194676Sthompsa	for (i = 0; i < 6; i++) {
558194676Sthompsa		c = *(addr + i);
559195957Salfred		for (j = 0; j < 8; j++) {
560195957Salfred			carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01);
561194676Sthompsa			crc <<= 1;
562195957Salfred			c >>= 1;
563194676Sthompsa			if (carry)
564194676Sthompsa				crc = (crc ^ 0x04c11db6) | carry;
565194676Sthompsa		}
566195957Salfred	}
567194676Sthompsa
568194676Sthompsa	/* return the filter bit position */
569195957Salfred	return(crc & 0x0000003F);
570195957Salfred}
571195957Salfred
572195957Salfredstatic void ste_setmulti(sc)
573194676Sthompsa	struct ste_softc	*sc;
574195957Salfred{
575195957Salfred	struct ifnet		*ifp;
576195957Salfred	int			h = 0;
577195957Salfred	u_int32_t		hashes[2] = { 0, 0 };
578195957Salfred	struct ifmultiaddr	*ifma;
579195957Salfred
580195957Salfred	ifp = &sc->arpcom.ac_if;
581195957Salfred	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
582195957Salfred		STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI);
583195957Salfred		STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH);
584195957Salfred		return;
585195957Salfred	}
586195957Salfred
587195957Salfred	/* first, zot all the existing hash bits */
588195957Salfred	CSR_WRITE_4(sc, STE_MAR0, 0);
589194676Sthompsa	CSR_WRITE_4(sc, STE_MAR1, 0);
590194676Sthompsa
591195957Salfred	/* now program new ones */
592195957Salfred	for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
593195957Salfred	    ifma = ifma->ifma_link.le_next) {
594195957Salfred		if (ifma->ifma_addr->sa_family != AF_LINK)
595195957Salfred			continue;
596195957Salfred		h = ste_calchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
597195957Salfred		if (h < 32)
598195957Salfred			hashes[0] |= (1 << h);
599195957Salfred		else
600195957Salfred			hashes[1] |= (1 << (h - 32));
601195957Salfred	}
602195957Salfred
603195957Salfred	CSR_WRITE_4(sc, STE_MAR0, hashes[0]);
604195957Salfred	CSR_WRITE_4(sc, STE_MAR1, hashes[1]);
605195957Salfred	STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI);
606194676Sthompsa	STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH);
607195957Salfred
608194676Sthompsa	return;
609194676Sthompsa}
610195957Salfred
611195957Salfredstatic void ste_intr(xsc)
612194676Sthompsa	void			*xsc;
613195957Salfred{
614195560Sthompsa	struct ste_softc	*sc;
615195957Salfred	struct ifnet		*ifp;
616194676Sthompsa	u_int16_t		status;
617195957Salfred
618195957Salfred	sc = xsc;
619195957Salfred	ifp = &sc->arpcom.ac_if;
620195957Salfred
621195957Salfred	/* See if this is really our interrupt. */
622195957Salfred	if (!(CSR_READ_2(sc, STE_ISR) & STE_ISR_INTLATCH))
623195957Salfred		return;
624194676Sthompsa
625194676Sthompsa	for (;;) {
626194676Sthompsa		status = CSR_READ_2(sc, STE_ISR_ACK);
627195957Salfred
628195957Salfred		if (!(status & STE_INTRS))
629195957Salfred			break;
630195957Salfred
631194676Sthompsa		if (status & STE_ISR_RX_DMADONE)
632195957Salfred			ste_rxeof(sc);
633195957Salfred
634195957Salfred		if (status & STE_ISR_TX_DMADONE)
635194676Sthompsa			ste_txeof(sc);
636194676Sthompsa
637194676Sthompsa		if (status & STE_ISR_TX_DONE)
638195957Salfred			ste_txeoc(sc);
639194676Sthompsa
640195957Salfred		if (status & STE_ISR_STATS_OFLOW) {
641195957Salfred			untimeout(ste_stats_update, sc, sc->ste_stat_ch);
642194676Sthompsa			ste_stats_update(sc);
643195957Salfred		}
644194676Sthompsa
645194676Sthompsa		if (status & STE_ISR_HOSTERR) {
646194676Sthompsa			ste_reset(sc);
647195957Salfred			ste_init(sc);
648195957Salfred		}
649195957Salfred	}
650195957Salfred
651195957Salfred	/* Re-enable interrupts */
652195957Salfred	CSR_WRITE_2(sc, STE_IMR, STE_INTRS);
653195957Salfred
654195957Salfred	if (ifp->if_snd.ifq_head != NULL)
655195957Salfred		ste_start(ifp);
656195957Salfred
657195957Salfred	return;
658194676Sthompsa}
659194676Sthompsa
660194676Sthompsa/*
661195957Salfred * A frame has been uploaded: pass the resulting mbuf chain up to
662194676Sthompsa * the higher level protocols.
663195957Salfred */
664194676Sthompsastatic void ste_rxeof(sc)
665194676Sthompsa	struct ste_softc		*sc;
666195957Salfred{
667195957Salfred        struct ether_header	*eh;
668194676Sthompsa        struct mbuf		*m;
669194676Sthompsa        struct ifnet		*ifp;
670194676Sthompsa	struct ste_chain_onefrag	*cur_rx;
671195957Salfred	int			total_len = 0;
672194676Sthompsa	u_int32_t		rxstat;
673195957Salfred
674194676Sthompsa	ifp = &sc->arpcom.ac_if;
675195957Salfred
676194676Sthompsaagain:
677194676Sthompsa
678195957Salfred	while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status)) {
679195957Salfred		cur_rx = sc->ste_cdata.ste_rx_head;
680194676Sthompsa		sc->ste_cdata.ste_rx_head = cur_rx->ste_next;
681195957Salfred
682194676Sthompsa		/*
683194676Sthompsa		 * If an error occurs, update stats, clear the
684194676Sthompsa		 * status word and leave the mbuf cluster in place:
685195957Salfred		 * it should simply get re-used next time this descriptor
686194676Sthompsa	 	 * comes up in the ring.
687195957Salfred		 */
688194676Sthompsa		if (rxstat & STE_RXSTAT_FRAME_ERR) {
689195957Salfred			ifp->if_ierrors++;
690194676Sthompsa			cur_rx->ste_ptr->ste_status = 0;
691194676Sthompsa			continue;
692194676Sthompsa		}
693194676Sthompsa
694194676Sthompsa		/*
695194676Sthompsa		 * If there error bit was not set, the upload complete
696194676Sthompsa		 * bit should be set which means we have a valid packet.
697194676Sthompsa		 * If not, something truly strange has happened.
698195957Salfred		 */
699195957Salfred		if (!(rxstat & STE_RXSTAT_DMADONE)) {
700194676Sthompsa			printf("ste%d: bad receive status -- packet dropped",
701194676Sthompsa							sc->ste_unit);
702194676Sthompsa			ifp->if_ierrors++;
703195957Salfred			cur_rx->ste_ptr->ste_status = 0;
704194676Sthompsa			continue;
705194676Sthompsa		}
706195957Salfred
707195957Salfred		/* No errors; receive the packet. */
708194676Sthompsa		m = cur_rx->ste_mbuf;
709194676Sthompsa		total_len = cur_rx->ste_ptr->ste_status & STE_RXSTAT_FRAMELEN;
710195957Salfred
711194676Sthompsa		/*
712195957Salfred		 * Try to conjure up a new mbuf cluster. If that
713195957Salfred		 * fails, it means we have an out of memory condition and
714194676Sthompsa		 * should leave the buffer in place and continue. This will
715195957Salfred		 * result in a lost packet, but there's little else we
716195957Salfred		 * can do in this situation.
717195957Salfred		 */
718195957Salfred		if (ste_newbuf(sc, cur_rx, NULL) == ENOBUFS) {
719194676Sthompsa			ifp->if_ierrors++;
720194676Sthompsa			cur_rx->ste_ptr->ste_status = 0;
721194676Sthompsa			continue;
722195957Salfred		}
723194676Sthompsa
724195957Salfred		ifp->if_ipackets++;
725194676Sthompsa		eh = mtod(m, struct ether_header *);
726195957Salfred		m->m_pkthdr.rcvif = ifp;
727195957Salfred		m->m_pkthdr.len = m->m_len = total_len;
728194676Sthompsa
729195957Salfred#if NBPF > 0
730195957Salfred		/* Handle BPF listeners. Let the BPF user see the packet. */
731194676Sthompsa		if (ifp->if_bpf)
732195957Salfred			bpf_mtap(ifp, m);
733194676Sthompsa#endif
734194676Sthompsa
735195560Sthompsa#ifdef BRIDGE
736195957Salfred		if (do_bridge) {
737195560Sthompsa			struct ifnet *bdg_ifp ;
738195560Sthompsa			bdg_ifp = bridge_in(m);
739195560Sthompsa			if (bdg_ifp != BDG_LOCAL && bdg_ifp != BDG_DROP)
740195560Sthompsa				bdg_forward(&m, bdg_ifp);
741195560Sthompsa			if (((bdg_ifp != BDG_LOCAL) && (bdg_ifp != BDG_BCAST) &&
742195560Sthompsa			    (bdg_ifp != BDG_MCAST)) || bdg_ifp == BDG_DROP) {
743195560Sthompsa				m_freem(m);
744195560Sthompsa				continue;
745195560Sthompsa			}
746195560Sthompsa		}
747195560Sthompsa#endif
748195560Sthompsa
749195957Salfred#if NBPF > 0
750195957Salfred		/*
751195560Sthompsa		 * Don't pass packet up to the ether_input() layer unless it's
752195957Salfred		 * a broadcast packet, multicast packet, matches our ethernet
753195560Sthompsa		 * address or the interface is in promiscuous mode.
754195957Salfred		 */
755195560Sthompsa		if (ifp->if_bpf) {
756195560Sthompsa			if (ifp->if_flags & IFF_PROMISC &&
757195957Salfred			    (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
758195560Sthompsa			    ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)){
759195560Sthompsa				m_freem(m);
760195957Salfred				continue;
761195560Sthompsa			}
762195957Salfred		}
763195560Sthompsa#endif
764195560Sthompsa
765195560Sthompsa		/* Remove header from mbuf and pass it on. */
766195957Salfred		m_adj(m, sizeof(struct ether_header));
767195560Sthompsa		ether_input(ifp, eh, m);
768195560Sthompsa	}
769195560Sthompsa
770195560Sthompsa	/*
771195560Sthompsa	 * Handle the 'end of channel' condition. When the upload
772195560Sthompsa	 * engine hits the end of the RX ring, it will stall. This
773195560Sthompsa	 * is our cue to flush the RX ring, reload the uplist pointer
774195560Sthompsa	 * register and unstall the engine.
775195957Salfred	 * XXX This is actually a little goofy. With the ThunderLAN
776195957Salfred	 * chip, you get an interrupt when the receiver hits the end
777195560Sthompsa	 * of the receive ring, which tells you exactly when you
778195957Salfred	 * you need to reload the ring pointer. Here we have to
779195957Salfred	 * fake it. I'm mad at myself for not being clever enough
780195957Salfred	 * to avoid the use of a goto here.
781195560Sthompsa	 */
782195957Salfred	if (CSR_READ_4(sc, STE_RX_DMALIST_PTR) == 0 ||
783195957Salfred		CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_RXDMA_STOPPED) {
784195957Salfred		STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL);
785195957Salfred		ste_wait(sc);
786195957Salfred		CSR_WRITE_4(sc, STE_RX_DMALIST_PTR,
787195957Salfred			vtophys(&sc->ste_ldata->ste_rx_list[0]));
788195957Salfred		sc->ste_cdata.ste_rx_head = &sc->ste_cdata.ste_rx_chain[0];
789195957Salfred		STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL);
790195957Salfred		goto again;
791195560Sthompsa	}
792195957Salfred
793195560Sthompsa	return;
794195957Salfred}
795195560Sthompsa
796195560Sthompsastatic void ste_txeoc(sc)
797195957Salfred	struct ste_softc	*sc;
798195957Salfred{
799195957Salfred	u_int8_t		txstat;
800195957Salfred	struct ifnet		*ifp;
801195957Salfred
802195957Salfred	ifp = &sc->arpcom.ac_if;
803195957Salfred
804195957Salfred	while ((txstat = CSR_READ_1(sc, STE_TX_STATUS)) &
805195957Salfred	    STE_TXSTATUS_TXDONE) {
806195957Salfred		if (txstat & STE_TXSTATUS_UNDERRUN ||
807195957Salfred		    txstat & STE_TXSTATUS_EXCESSCOLLS ||
808195957Salfred		    txstat & STE_TXSTATUS_RECLAIMERR) {
809195957Salfred			ifp->if_oerrors++;
810195957Salfred			printf("ste%d: transmission error: %x\n",
811195957Salfred			    sc->ste_unit, txstat);
812195957Salfred			STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_TX_RESET);
813195957Salfred
814195957Salfred			if (sc->ste_cdata.ste_tx_head != NULL)
815195957Salfred				CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
816195957Salfred				    vtophys(sc->ste_cdata.ste_tx_head->ste_ptr));
817195957Salfred			if (txstat & STE_TXSTATUS_UNDERRUN &&
818195957Salfred			    sc->ste_tx_thresh < STE_PACKET_SIZE) {
819195957Salfred				sc->ste_tx_thresh += STE_MIN_FRAMELEN;
820195957Salfred				printf("ste%d: tx underrun, increasing tx"
821195957Salfred				    " start threshold to %d bytes\n",
822195957Salfred				    sc->ste_unit, sc->ste_tx_thresh);
823194676Sthompsa			}
824195957Salfred			CSR_WRITE_2(sc, STE_TX_STARTTHRESH, sc->ste_tx_thresh);
825195957Salfred			CSR_WRITE_2(sc, STE_TX_RECLAIM_THRESH,
826194676Sthompsa			    (STE_PACKET_SIZE >> 4));
827195957Salfred		}
828195957Salfred		ste_init(sc);
829195957Salfred		CSR_WRITE_2(sc, STE_TX_STATUS, txstat);
830195957Salfred	}
831195957Salfred
832195957Salfred	return;
833195957Salfred}
834195957Salfred
835195957Salfredstatic void ste_txeof(sc)
836199575Sthompsa	struct ste_softc	*sc;
837195957Salfred{
838195957Salfred	struct ste_chain	*cur_tx;
839199575Sthompsa	struct ifnet		*ifp;
840199575Sthompsa
841199575Sthompsa	ifp = &sc->arpcom.ac_if;
842195957Salfred
843195957Salfred	/* Clear the timeout timer. */
844195957Salfred	ifp->if_timer = 0;
845195957Salfred
846195957Salfred	while(sc->ste_cdata.ste_tx_head != NULL) {
847195957Salfred		cur_tx = sc->ste_cdata.ste_tx_head;
848195957Salfred		if (!(cur_tx->ste_ptr->ste_ctl & STE_TXCTL_DMADONE))
849195957Salfred			break;
850195957Salfred		sc->ste_cdata.ste_tx_head = cur_tx->ste_next;
851195957Salfred
852195957Salfred		m_freem(cur_tx->ste_mbuf);
853195957Salfred		cur_tx->ste_mbuf = NULL;
854195957Salfred		ifp->if_opackets++;
855195957Salfred
856195957Salfred		cur_tx->ste_next = sc->ste_cdata.ste_tx_free;
857194676Sthompsa		sc->ste_cdata.ste_tx_free = cur_tx;
858195957Salfred	}
859194676Sthompsa
860195957Salfred	if (sc->ste_cdata.ste_tx_head == NULL) {
861195957Salfred		ifp->if_flags &= ~IFF_OACTIVE;
862195957Salfred		sc->ste_cdata.ste_tx_tail = NULL;
863195957Salfred	} else {
864194676Sthompsa		if (CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_TXDMA_STOPPED ||
865195957Salfred		    !CSR_READ_4(sc, STE_TX_DMALIST_PTR)) {
866195957Salfred			CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
867195957Salfred			    vtophys(sc->ste_cdata.ste_tx_head->ste_ptr));
868195957Salfred			CSR_WRITE_4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL);
869195957Salfred		}
870195957Salfred	}
871195957Salfred
872195957Salfred	return;
873195957Salfred}
874195957Salfred
875195957Salfredstatic void ste_stats_update(xsc)
876195957Salfred	void			*xsc;
877195957Salfred{
878195957Salfred	struct ste_softc	*sc;
879195957Salfred	struct ste_stats	stats;
880195957Salfred	struct ifnet		*ifp;
881195957Salfred	struct mii_data		*mii;
882194676Sthompsa	int			i, s;
883194676Sthompsa	u_int8_t		*p;
884195560Sthompsa
885195957Salfred	s = splimp();
886195957Salfred
887195957Salfred	sc = xsc;
888195957Salfred	ifp = &sc->arpcom.ac_if;
889195957Salfred	mii = device_get_softc(sc->ste_miibus);
890195957Salfred
891195957Salfred	p = (u_int8_t *)&stats;
892195957Salfred
893195560Sthompsa	for (i = 0; i < sizeof(stats); i++) {
894194676Sthompsa		*p = CSR_READ_1(sc, STE_STATS + i);
895195957Salfred		p++;
896195957Salfred	}
897195957Salfred
898195957Salfred	ifp->if_collisions += stats.ste_single_colls +
899195957Salfred	    stats.ste_multi_colls + stats.ste_late_colls;
900195957Salfred
901195957Salfred	mii_tick(mii);
902195957Salfred
903194676Sthompsa	sc->ste_stat_ch = timeout(ste_stats_update, sc, hz);
904195957Salfred	splx(s);
905195957Salfred
906195957Salfred	return;
907195957Salfred}
908195957Salfred
909195957Salfred
910195957Salfred/*
911195957Salfred * Probe for a Sundance ST201 chip. Check the PCI vendor and device
912195957Salfred * IDs against our list and return a device name if we find a match.
913195957Salfred */
914195957Salfredstatic int ste_probe(dev)
915194676Sthompsa	device_t		dev;
916195957Salfred{
917195957Salfred	struct ste_type		*t;
918194676Sthompsa
919195957Salfred	t = ste_devs;
920194676Sthompsa
921195957Salfred	while(t->ste_name != NULL) {
922195957Salfred		if ((pci_get_vendor(dev) == t->ste_vid) &&
923195957Salfred		    (pci_get_device(dev) == t->ste_did)) {
924195957Salfred			device_set_desc(dev, t->ste_name);
925195957Salfred			return(0);
926195957Salfred		}
927195957Salfred		t++;
928195957Salfred	}
929195957Salfred
930195957Salfred	return(ENXIO);
931195957Salfred}
932195957Salfred
933195957Salfred/*
934195957Salfred * Attach the interface. Allocate softc structures, do ifmedia
935195957Salfred * setup and ethernet/BPF attach.
936195957Salfred */
937195957Salfredstatic int ste_attach(dev)
938195957Salfred	device_t		dev;
939195957Salfred{
940195957Salfred	int			s;
941195957Salfred	u_int32_t		command;
942195957Salfred	struct ste_softc	*sc;
943195957Salfred	struct ifnet		*ifp;
944195957Salfred	int			unit, error = 0, rid;
945195957Salfred
946194676Sthompsa	s = splimp();
947194676Sthompsa
948195957Salfred	sc = device_get_softc(dev);
949195957Salfred	unit = device_get_unit(dev);
950195957Salfred	bzero(sc, sizeof(struct ste_softc));
951195957Salfred
952195957Salfred	/*
953195957Salfred	 * Handle power management nonsense.
954195957Salfred	 */
955195957Salfred	command = pci_read_config(dev, STE_PCI_CAPID, 4) & 0x000000FF;
956195957Salfred	if (command == 0x01) {
957195957Salfred
958195957Salfred		command = pci_read_config(dev, STE_PCI_PWRMGMTCTRL, 4);
959195957Salfred		if (command & STE_PSTATE_MASK) {
960195957Salfred			u_int32_t		iobase, membase, irq;
961195957Salfred
962195957Salfred			/* Save important PCI config data. */
963195957Salfred			iobase = pci_read_config(dev, STE_PCI_LOIO, 4);
964195957Salfred			membase = pci_read_config(dev, STE_PCI_LOMEM, 4);
965195957Salfred			irq = pci_read_config(dev, STE_PCI_INTLINE, 4);
966195957Salfred
967195957Salfred			/* Reset the power state. */
968195957Salfred			printf("ste%d: chip is in D%d power mode "
969195957Salfred			"-- setting to D0\n", unit, command & STE_PSTATE_MASK);
970195957Salfred			command &= 0xFFFFFFFC;
971195957Salfred			pci_write_config(dev, STE_PCI_PWRMGMTCTRL, command, 4);
972195957Salfred
973195957Salfred			/* Restore PCI config data. */
974195957Salfred			pci_write_config(dev, STE_PCI_LOIO, iobase, 4);
975195957Salfred			pci_write_config(dev, STE_PCI_LOMEM, membase, 4);
976195957Salfred			pci_write_config(dev, STE_PCI_INTLINE, irq, 4);
977195957Salfred		}
978195957Salfred	}
979195957Salfred
980195957Salfred	/*
981195957Salfred	 * Map control/status registers.
982195957Salfred	 */
983195957Salfred	command = pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4);
984195957Salfred	command |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
985195957Salfred	pci_write_config(dev, PCI_COMMAND_STATUS_REG, command, 4);
986195957Salfred	command = pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4);
987195957Salfred
988195957Salfred#ifdef STE_USEIOSPACE
989195957Salfred	if (!(command & PCIM_CMD_PORTEN)) {
990194676Sthompsa		printf("ste%d: failed to enable I/O ports!\n", unit);
991194676Sthompsa		error = ENXIO;
992194676Sthompsa		goto fail;
993195957Salfred	}
994195957Salfred#else
995195957Salfred	if (!(command & PCIM_CMD_MEMEN)) {
996195957Salfred		printf("ste%d: failed to enable memory mapping!\n", unit);
997194676Sthompsa		error = ENXIO;
998195957Salfred		goto fail;
999195957Salfred	}
1000195957Salfred#endif
1001195957Salfred
1002195957Salfred	rid = STE_RID;
1003195957Salfred	sc->ste_res = bus_alloc_resource(dev, STE_RES, &rid,
1004194676Sthompsa	    0, ~0, 1, RF_ACTIVE);
1005195957Salfred
1006195957Salfred	if (sc->ste_res == NULL) {
1007195957Salfred		printf ("ste%d: couldn't map ports/memory\n", unit);
1008195957Salfred		error = ENXIO;
1009194676Sthompsa		goto fail;
1010195957Salfred	}
1011195957Salfred
1012194676Sthompsa	sc->ste_btag = rman_get_bustag(sc->ste_res);
1013195957Salfred	sc->ste_bhandle = rman_get_bushandle(sc->ste_res);
1014195957Salfred
1015194676Sthompsa	rid = 0;
1016195957Salfred	sc->ste_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
1017194676Sthompsa	    RF_SHAREABLE | RF_ACTIVE);
1018195957Salfred
1019195957Salfred	if (sc->ste_irq == NULL) {
1020194676Sthompsa		printf("ste%d: couldn't map interrupt\n", unit);
1021195957Salfred		bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
1022195957Salfred		error = ENXIO;
1023195957Salfred		goto fail;
1024195957Salfred	}
1025195957Salfred
1026195957Salfred	error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET,
1027195957Salfred	    ste_intr, sc, &sc->ste_intrhand);
1028195957Salfred
1029195957Salfred	if (error) {
1030195957Salfred		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
1031195957Salfred		bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
1032195957Salfred		printf("ste%d: couldn't set up irq\n", unit);
1033195957Salfred		goto fail;
1034194676Sthompsa	}
1035195957Salfred
1036195957Salfred	callout_handle_init(&sc->ste_stat_ch);
1037195957Salfred
1038195957Salfred	/* Reset the adapter. */
1039195957Salfred	ste_reset(sc);
1040195957Salfred
1041194676Sthompsa	/*
1042195957Salfred	 * Get station address from the EEPROM.
1043195957Salfred	 */
1044195957Salfred	if (ste_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr,
1045195957Salfred	    STE_EEADDR_NODE0, 3, 0)) {
1046195957Salfred		printf("ste%d: failed to read station address\n", unit);
1047195957Salfred		bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand);
1048195957Salfred		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
1049195957Salfred		bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
1050195957Salfred		error = ENXIO;;
1051195957Salfred		goto fail;
1052195957Salfred	}
1053195957Salfred
1054195957Salfred	/*
1055195957Salfred	 * A Sundance chip was detected. Inform the world.
1056195957Salfred	 */
1057195957Salfred	printf("ste%d: Ethernet address: %6D\n", unit,
1058195957Salfred	    sc->arpcom.ac_enaddr, ":");
1059195957Salfred
1060195957Salfred	sc->ste_unit = unit;
1061195957Salfred
1062195957Salfred	/* Allocate the descriptor queues. */
1063195957Salfred	sc->ste_ldata = contigmalloc(sizeof(struct ste_list_data), M_DEVBUF,
1064195957Salfred	    M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
1065195957Salfred
1066195957Salfred	if (sc->ste_ldata == NULL) {
1067195957Salfred		printf("ste%d: no memory for list buffers!\n", unit);
1068195957Salfred		bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand);
1069195957Salfred		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
1070195957Salfred		bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
1071195957Salfred		error = ENXIO;
1072195957Salfred		goto fail;
1073195957Salfred	}
1074195957Salfred
1075195957Salfred	bzero(sc->ste_ldata, sizeof(struct ste_list_data));
1076195957Salfred
1077195957Salfred	/* Do MII setup. */
1078195957Salfred	if (mii_phy_probe(dev, &sc->ste_miibus,
1079194676Sthompsa		ste_ifmedia_upd, ste_ifmedia_sts)) {
1080195957Salfred		printf("ste%d: MII without any phy!\n", sc->ste_unit);
1081195957Salfred		bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand);
1082195957Salfred		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
1083195957Salfred		bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
1084195957Salfred		free(sc->ste_ldata, M_DEVBUF);
1085195957Salfred		error = ENXIO;
1086195957Salfred		goto fail;
1087195957Salfred	}
1088195957Salfred
1089195957Salfred	ifp = &sc->arpcom.ac_if;
1090195957Salfred	ifp->if_softc = sc;
1091195957Salfred	ifp->if_unit = unit;
1092195957Salfred	ifp->if_name = "ste";
1093195957Salfred	ifp->if_mtu = ETHERMTU;
1094195957Salfred	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1095195957Salfred	ifp->if_ioctl = ste_ioctl;
1096195957Salfred	ifp->if_output = ether_output;
1097195957Salfred	ifp->if_start = ste_start;
1098195957Salfred	ifp->if_watchdog = ste_watchdog;
1099195957Salfred	ifp->if_init = ste_init;
1100195957Salfred	ifp->if_baudrate = 10000000;
1101195957Salfred	ifp->if_snd.ifq_maxlen = STE_TX_LIST_CNT - 1;
1102195957Salfred
1103195957Salfred	/*
1104195957Salfred	 * Call MI attach routines.
1105195957Salfred	 */
1106195957Salfred
1107195957Salfred	if_attach(ifp);
1108195957Salfred	ether_ifattach(ifp);
1109195957Salfred
1110195957Salfred#if NBPF > 0
1111195957Salfred	bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
1112195957Salfred#endif
1113195957Salfred
1114195957Salfredfail:
1115195957Salfred	splx(s);
1116195957Salfred	return(error);
1117195957Salfred}
1118199575Sthompsa
1119199575Sthompsastatic int ste_detach(dev)
1120195957Salfred	device_t		dev;
1121195957Salfred{
1122195957Salfred	struct ste_softc	*sc;
1123195957Salfred	struct ifnet		*ifp;
1124195957Salfred	int			s;
1125195957Salfred
1126195957Salfred	s = splimp();
1127199575Sthompsa
1128199575Sthompsa	sc = device_get_softc(dev);
1129195957Salfred	ifp = &sc->arpcom.ac_if;
1130195957Salfred
1131195957Salfred	ste_stop(sc);
1132195957Salfred	if_detach(ifp);
1133195957Salfred
1134195957Salfred	bus_generic_detach(dev);
1135195957Salfred	device_delete_child(dev, sc->ste_miibus);
1136194676Sthompsa
1137195957Salfred	bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand);
1138195957Salfred	bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
1139195957Salfred	bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
1140195957Salfred
1141195957Salfred	free(sc->ste_ldata, M_DEVBUF);
1142195957Salfred
1143195957Salfred	splx(s);
1144195957Salfred
1145195957Salfred	return(0);
1146195957Salfred}
1147195957Salfred
1148194676Sthompsastatic int ste_newbuf(sc, c, m)
1149195957Salfred	struct ste_softc	*sc;
1150195957Salfred	struct ste_chain_onefrag	*c;
1151194676Sthompsa	struct mbuf		*m;
1152195957Salfred{
1153194676Sthompsa	struct mbuf		*m_new = NULL;
1154195957Salfred
1155195957Salfred	if (m == NULL) {
1156194676Sthompsa		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
1157195957Salfred		if (m_new == NULL) {
1158195957Salfred			printf("ste%d: no memory for rx list -- "
1159195957Salfred			    "packet dropped\n", sc->ste_unit);
1160195957Salfred			return(ENOBUFS);
1161194676Sthompsa		}
1162195957Salfred		MCLGET(m_new, M_DONTWAIT);
1163195957Salfred		if (!(m_new->m_flags & M_EXT)) {
1164195957Salfred			printf("ste%d: no memory for rx list -- "
1165195957Salfred			    "packet dropped\n", sc->ste_unit);
1166195957Salfred			m_freem(m_new);
1167195957Salfred			return(ENOBUFS);
1168195957Salfred		}
1169195957Salfred		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
1170195957Salfred	} else {
1171195957Salfred		m_new = m;
1172195957Salfred		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
1173195957Salfred		m_new->m_data = m_new->m_ext.ext_buf;
1174194676Sthompsa	}
1175195957Salfred
1176195957Salfred	m_adj(m_new, ETHER_ALIGN);
1177195957Salfred
1178195957Salfred	c->ste_mbuf = m_new;
1179195957Salfred	c->ste_ptr->ste_status = 0;
1180195957Salfred	c->ste_ptr->ste_frag.ste_addr = vtophys(mtod(m_new, caddr_t));
1181195560Sthompsa	c->ste_ptr->ste_frag.ste_len = 1536 | STE_FRAG_LAST;
1182195957Salfred
1183195957Salfred	return(0);
1184195957Salfred}
1185195957Salfred
1186195957Salfredstatic int ste_init_rx_list(sc)
1187195957Salfred	struct ste_softc	*sc;
1188195957Salfred{
1189195957Salfred	struct ste_chain_data	*cd;
1190194676Sthompsa	struct ste_list_data	*ld;
1191195957Salfred	int			i;
1192195957Salfred
1193194676Sthompsa	cd = &sc->ste_cdata;
1194195957Salfred	ld = sc->ste_ldata;
1195195957Salfred
1196194676Sthompsa	for (i = 0; i < STE_RX_LIST_CNT; i++) {
1197195957Salfred		cd->ste_rx_chain[i].ste_ptr = &ld->ste_rx_list[i];
1198195957Salfred		if (ste_newbuf(sc, &cd->ste_rx_chain[i], NULL) == ENOBUFS)
1199195957Salfred			return(ENOBUFS);
1200195957Salfred		if (i == (STE_RX_LIST_CNT - 1)) {
1201194676Sthompsa			cd->ste_rx_chain[i].ste_next =
1202195957Salfred			    &cd->ste_rx_chain[0];
1203194676Sthompsa			ld->ste_rx_list[i].ste_next =
1204195957Salfred			    vtophys(&ld->ste_rx_list[0]);
1205195957Salfred		} else {
1206195957Salfred			cd->ste_rx_chain[i].ste_next =
1207195957Salfred			    &cd->ste_rx_chain[i + 1];
1208195957Salfred			ld->ste_rx_list[i].ste_next =
1209195957Salfred			    vtophys(&ld->ste_rx_list[i + 1]);
1210195957Salfred		}
1211199055Sthompsa
1212195957Salfred	}
1213195957Salfred
1214195957Salfred	cd->ste_rx_head = &cd->ste_rx_chain[0];
1215195957Salfred
1216195957Salfred	return(0);
1217195957Salfred}
1218195957Salfred
1219195957Salfredstatic void ste_init_tx_list(sc)
1220195957Salfred	struct ste_softc	*sc;
1221195957Salfred{
1222195957Salfred	struct ste_chain_data	*cd;
1223195957Salfred	struct ste_list_data	*ld;
1224195957Salfred	int			i;
1225195957Salfred
1226195957Salfred	cd = &sc->ste_cdata;
1227195957Salfred	ld = sc->ste_ldata;
1228195957Salfred	for (i = 0; i < STE_TX_LIST_CNT; i++) {
1229195957Salfred		cd->ste_tx_chain[i].ste_ptr = &ld->ste_tx_list[i];
1230195957Salfred		if (i == (STE_TX_LIST_CNT - 1))
1231195957Salfred			cd->ste_tx_chain[i].ste_next = NULL;
1232195957Salfred		else
1233195957Salfred			cd->ste_tx_chain[i].ste_next =
1234195957Salfred			    &cd->ste_tx_chain[i + 1];
1235195957Salfred	}
1236195957Salfred
1237195957Salfred	cd->ste_tx_free = &cd->ste_tx_chain[0];
1238195957Salfred	cd->ste_tx_tail = cd->ste_tx_head = NULL;
1239195957Salfred
1240199575Sthompsa	return;
1241195957Salfred}
1242195957Salfred
1243195957Salfredstatic void ste_init(xsc)
1244199575Sthompsa	void			*xsc;
1245199575Sthompsa{
1246199575Sthompsa	struct ste_softc	*sc;
1247199575Sthompsa	int			i, s;
1248199575Sthompsa	struct ifnet		*ifp;
1249195957Salfred	struct mii_data		*mii;
1250195957Salfred
1251199575Sthompsa	s = splimp();
1252195957Salfred
1253195957Salfred	sc = xsc;
1254195957Salfred	ifp = &sc->arpcom.ac_if;
1255195957Salfred	mii = device_get_softc(sc->ste_miibus);
1256195957Salfred
1257195957Salfred	ste_stop(sc);
1258195957Salfred
1259195957Salfred	/* Init our MAC address */
1260195957Salfred	for (i = 0; i < ETHER_ADDR_LEN; i++) {
1261195957Salfred		CSR_WRITE_1(sc, STE_PAR0 + i, sc->arpcom.ac_enaddr[i]);
1262195957Salfred	}
1263194676Sthompsa
1264194676Sthompsa	/* Init RX list */
1265195957Salfred	if (ste_init_rx_list(sc) == ENOBUFS) {
1266195957Salfred		printf("ste%d: initialization failed: no "
1267194676Sthompsa		    "memory for RX buffers\n", sc->ste_unit);
1268195957Salfred		ste_stop(sc);
1269194676Sthompsa		splx(s);
1270195957Salfred		return;
1271195957Salfred	}
1272195957Salfred
1273195957Salfred	/* Init TX descriptors */
1274199055Sthompsa	ste_init_tx_list(sc);
1275199575Sthompsa
1276194676Sthompsa	/* Set the TX freethresh value */
1277195957Salfred	CSR_WRITE_1(sc, STE_TX_DMABURST_THRESH, STE_PACKET_SIZE >> 8);
1278195957Salfred
1279194676Sthompsa	/* Set the TX start threshold for best performance. */
1280199575Sthompsa	sc->ste_tx_thresh = STE_MIN_FRAMELEN;
1281195957Salfred	CSR_WRITE_2(sc, STE_TX_STARTTHRESH, sc->ste_tx_thresh);
1282199575Sthompsa
1283194676Sthompsa	/* Set the TX reclaim threshold. */
1284195957Salfred	CSR_WRITE_1(sc, STE_TX_RECLAIM_THRESH, (STE_PACKET_SIZE >> 4));
1285194676Sthompsa
1286195957Salfred	/* Set up the RX filter. */
1287195957Salfred	CSR_WRITE_1(sc, STE_RX_MODE, STE_RXMODE_UNICAST);
1288195957Salfred
1289195957Salfred	/* If we want promiscuous mode, set the allframes bit. */
1290195957Salfred	if (ifp->if_flags & IFF_PROMISC) {
1291195957Salfred		STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC);
1292195957Salfred	} else {
1293195957Salfred		STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC);
1294195957Salfred	}
1295195957Salfred
1296199575Sthompsa	/* Set capture broadcast bit to accept broadcast frames. */
1297199575Sthompsa	if (ifp->if_flags & IFF_BROADCAST) {
1298195957Salfred		STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST);
1299195957Salfred	} else {
1300195957Salfred		STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST);
1301195957Salfred	}
1302195957Salfred
1303199575Sthompsa	ste_setmulti(sc);
1304199575Sthompsa
1305199575Sthompsa	/* Load the address of the RX list. */
1306199575Sthompsa	STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL);
1307199575Sthompsa	ste_wait(sc);
1308195957Salfred	CSR_WRITE_4(sc, STE_RX_DMALIST_PTR,
1309195957Salfred	    vtophys(&sc->ste_ldata->ste_rx_list[0]));
1310195957Salfred	STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL);
1311199575Sthompsa	STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL);
1312199575Sthompsa
1313195957Salfred	/* Enable receiver and transmitter */
1314195957Salfred	CSR_WRITE_2(sc, STE_MACCTL0, 0);
1315199575Sthompsa	STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_ENABLE);
1316195957Salfred	STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_RX_ENABLE);
1317199575Sthompsa
1318199575Sthompsa	/* Enable stats counters. */
1319195957Salfred	STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_STATS_ENABLE);
1320195957Salfred
1321195957Salfred	/* Enable interrupts. */
1322195957Salfred	CSR_WRITE_2(sc, STE_ISR, 0xFFFF);
1323195957Salfred	CSR_WRITE_2(sc, STE_IMR, STE_INTRS);
1324199575Sthompsa
1325199575Sthompsa	mii_mediachg(mii);
1326195957Salfred
1327195957Salfred	ifp->if_flags |= IFF_RUNNING;
1328195957Salfred	ifp->if_flags &= ~IFF_OACTIVE;
1329195957Salfred
1330195957Salfred	splx(s);
1331195957Salfred
1332199575Sthompsa	sc->ste_stat_ch = timeout(ste_stats_update, sc, hz);
1333195957Salfred
1334195957Salfred	return;
1335195957Salfred}
1336195957Salfred
1337195957Salfredstatic void ste_stop(sc)
1338195957Salfred	struct ste_softc	*sc;
1339199575Sthompsa{
1340194676Sthompsa	int			i;
1341194676Sthompsa	struct ifnet		*ifp;
1342195957Salfred
1343195957Salfred	ifp = &sc->arpcom.ac_if;
1344195957Salfred
1345195957Salfred	untimeout(ste_stats_update, sc, sc->ste_stat_ch);
1346195957Salfred
1347199055Sthompsa	CSR_WRITE_2(sc, STE_IMR, 0);
1348199055Sthompsa	STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_DISABLE);
1349199055Sthompsa	STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_RX_DISABLE);
1350199055Sthompsa	STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_STATS_DISABLE);
1351199055Sthompsa	STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL);
1352199055Sthompsa	STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL);
1353199055Sthompsa	ste_wait(sc);
1354199055Sthompsa
1355199055Sthompsa	for (i = 0; i < STE_RX_LIST_CNT; i++) {
1356199055Sthompsa		if (sc->ste_cdata.ste_rx_chain[i].ste_mbuf != NULL) {
1357199055Sthompsa			m_freem(sc->ste_cdata.ste_rx_chain[i].ste_mbuf);
1358199055Sthompsa			sc->ste_cdata.ste_rx_chain[i].ste_mbuf = NULL;
1359199055Sthompsa		}
1360	}
1361
1362	for (i = 0; i < STE_TX_LIST_CNT; i++) {
1363		if (sc->ste_cdata.ste_tx_chain[i].ste_mbuf != NULL) {
1364			m_freem(sc->ste_cdata.ste_tx_chain[i].ste_mbuf);
1365			sc->ste_cdata.ste_tx_chain[i].ste_mbuf = NULL;
1366		}
1367	}
1368
1369	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1370
1371	return;
1372}
1373
1374static void ste_reset(sc)
1375	struct ste_softc	*sc;
1376{
1377	int			i;
1378
1379	STE_SETBIT4(sc, STE_ASICCTL,
1380	    STE_ASICCTL_GLOBAL_RESET|STE_ASICCTL_RX_RESET|
1381	    STE_ASICCTL_TX_RESET|STE_ASICCTL_DMA_RESET|
1382	    STE_ASICCTL_FIFO_RESET|STE_ASICCTL_NETWORK_RESET|
1383	    STE_ASICCTL_AUTOINIT_RESET|STE_ASICCTL_HOST_RESET|
1384	    STE_ASICCTL_EXTRESET_RESET);
1385
1386	DELAY(100000);
1387
1388	for (i = 0; i < STE_TIMEOUT; i++) {
1389		if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RESET_BUSY))
1390			break;
1391	}
1392
1393	if (i == STE_TIMEOUT)
1394		printf("ste%d: global reset never completed\n", sc->ste_unit);
1395
1396#ifdef foo
1397	STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_RX_RESET);
1398	for (i = 0; i < STE_TIMEOUT; i++) {
1399		if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RX_RESET))
1400			break;
1401	}
1402
1403	if (i == STE_TIMEOUT)
1404		printf("ste%d: RX reset never completed\n", sc->ste_unit);
1405
1406	DELAY(100000);
1407
1408	STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_TX_RESET);
1409	for (i = 0; i < STE_TIMEOUT; i++) {
1410		if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_TX_RESET))
1411			break;
1412	}
1413
1414	if (i == STE_TIMEOUT)
1415		printf("ste%d: TX reset never completed\n", sc->ste_unit);
1416
1417	DELAY(100000);
1418#endif
1419
1420	return;
1421}
1422
1423static int ste_ioctl(ifp, command, data)
1424	struct ifnet		*ifp;
1425	u_long			command;
1426	caddr_t			data;
1427{
1428	struct ste_softc	*sc;
1429	struct ifreq		*ifr;
1430	struct mii_data		*mii;
1431	int			error = 0, s;
1432
1433	s = splimp();
1434
1435	sc = ifp->if_softc;
1436	ifr = (struct ifreq *)data;
1437
1438	switch(command) {
1439	case SIOCSIFADDR:
1440	case SIOCGIFADDR:
1441	case SIOCSIFMTU:
1442		error = ether_ioctl(ifp, command, data);
1443		break;
1444	case SIOCSIFFLAGS:
1445		if (ifp->if_flags & IFF_UP) {
1446			ste_init(sc);
1447		} else {
1448			if (ifp->if_flags & IFF_RUNNING)
1449				ste_stop(sc);
1450		}
1451		error = 0;
1452		break;
1453	case SIOCADDMULTI:
1454	case SIOCDELMULTI:
1455		ste_setmulti(sc);
1456		error = 0;
1457		break;
1458	case SIOCGIFMEDIA:
1459	case SIOCSIFMEDIA:
1460		mii = device_get_softc(sc->ste_miibus);
1461		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
1462		break;
1463	default:
1464		error = EINVAL;
1465		break;
1466	}
1467
1468	splx(s);
1469
1470	return(error);
1471}
1472
1473static int ste_encap(sc, c, m_head)
1474	struct ste_softc	*sc;
1475	struct ste_chain	*c;
1476	struct mbuf		*m_head;
1477{
1478	int			frag = 0;
1479	struct ste_frag		*f = NULL;
1480	int			total_len;
1481	struct mbuf		*m;
1482
1483	m = m_head;
1484	total_len = 0;
1485
1486	for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
1487		if (m->m_len != 0) {
1488			if (frag == STE_MAXFRAGS)
1489				break;
1490			total_len += m->m_len;
1491			f = &c->ste_ptr->ste_frags[frag];
1492			f->ste_addr = vtophys(mtod(m, vm_offset_t));
1493			f->ste_len = m->m_len;
1494			frag++;
1495		}
1496	}
1497
1498	if (m != NULL) {
1499		struct mbuf		*m_new = NULL;
1500
1501		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
1502		if (m_new == NULL) {
1503			printf("ste%d: no memory for "
1504			   "tx list", sc->ste_unit);
1505			return(1);
1506		}
1507		if (m_head->m_pkthdr.len > MHLEN) {
1508			MCLGET(m_new, M_DONTWAIT);
1509			if (!(m_new->m_flags & M_EXT)) {
1510				m_freem(m_new);
1511				printf("ste%d: no memory for "
1512			   	    "tx list", sc->ste_unit);
1513				return(1);
1514			}
1515		}
1516		m_copydata(m_head, 0, m_head->m_pkthdr.len,
1517		    mtod(m_new, caddr_t));
1518		m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
1519		m_freem(m_head);
1520		m_head = m_new;
1521		f = &c->ste_ptr->ste_frags[0];
1522		f->ste_addr = vtophys(mtod(m_new, caddr_t));
1523		f->ste_len = total_len = m_new->m_len;
1524		frag = 1;
1525	}
1526
1527	c->ste_mbuf = m_head;
1528	c->ste_ptr->ste_frags[frag - 1].ste_len |= STE_FRAG_LAST;
1529	c->ste_ptr->ste_ctl = total_len;
1530	c->ste_ptr->ste_next = 0;
1531
1532	return(0);
1533}
1534
1535static void ste_start(ifp)
1536	struct ifnet		*ifp;
1537{
1538	struct ste_softc	*sc;
1539	struct mbuf		*m_head = NULL;
1540	struct ste_chain	*prev = NULL, *cur_tx = NULL, *start_tx;
1541
1542	sc = ifp->if_softc;
1543
1544	if (sc->ste_cdata.ste_tx_free == NULL) {
1545		ifp->if_flags |= IFF_OACTIVE;
1546		return;
1547	}
1548
1549	start_tx = sc->ste_cdata.ste_tx_free;
1550
1551	while(sc->ste_cdata.ste_tx_free != NULL) {
1552		IF_DEQUEUE(&ifp->if_snd, m_head);
1553		if (m_head == NULL)
1554			break;
1555
1556		cur_tx = sc->ste_cdata.ste_tx_free;
1557		sc->ste_cdata.ste_tx_free = cur_tx->ste_next;
1558
1559		cur_tx->ste_next = NULL;
1560
1561		ste_encap(sc, cur_tx, m_head);
1562
1563		if (prev != NULL) {
1564			prev->ste_next = cur_tx;
1565			prev->ste_ptr->ste_next = vtophys(cur_tx->ste_ptr);
1566		}
1567		prev = cur_tx;
1568
1569#if NBPF > 0
1570		/*
1571		 * If there's a BPF listener, bounce a copt of this frame
1572		 * to him.
1573	 	 */
1574		if (ifp->if_bpf)
1575			bpf_mtap(ifp, cur_tx->ste_mbuf);
1576#endif
1577	}
1578
1579	if (cur_tx == NULL)
1580		return;
1581
1582	cur_tx->ste_ptr->ste_ctl |= STE_TXCTL_DMAINTR;
1583
1584	STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL);
1585	ste_wait(sc);
1586
1587	if (sc->ste_cdata.ste_tx_head != NULL) {
1588		sc->ste_cdata.ste_tx_tail->ste_next = start_tx;
1589		sc->ste_cdata.ste_tx_tail->ste_ptr->ste_next =
1590		    vtophys(start_tx->ste_ptr);
1591		sc->ste_cdata.ste_tx_tail->ste_ptr->ste_ctl &=
1592		    ~STE_TXCTL_DMAINTR;
1593		sc->ste_cdata.ste_tx_tail = cur_tx;
1594	} else {
1595		sc->ste_cdata.ste_tx_head = start_tx;
1596		sc->ste_cdata.ste_tx_tail = cur_tx;
1597	}
1598
1599	if (!CSR_READ_4(sc, STE_TX_DMALIST_PTR))
1600		CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
1601		    vtophys(start_tx->ste_ptr));
1602	STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL);
1603
1604	ifp->if_timer = 5;
1605
1606	return;
1607}
1608
1609static void ste_watchdog(ifp)
1610	struct ifnet		*ifp;
1611{
1612	struct ste_softc	*sc;
1613
1614	sc = ifp->if_softc;
1615
1616	ifp->if_oerrors++;
1617	printf("ste%d: watchdog timeout\n", sc->ste_unit);
1618
1619#ifdef foo
1620	if (sc->ste_pinfo != NULL) {
1621		if (!(ste_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
1622			printf("ste%d: no carrier - transceiver "
1623			    "cable problem?\n", sc->ste_unit);
1624	}
1625#endif
1626
1627	ste_txeoc(sc);
1628	ste_txeof(sc);
1629	ste_rxeof(sc);
1630	ste_reset(sc);
1631	ste_init(sc);
1632
1633	if (ifp->if_snd.ifq_head != NULL)
1634		ste_start(ifp);
1635
1636	return;
1637}
1638
1639static void ste_shutdown(dev)
1640	device_t		dev;
1641{
1642	struct ste_softc	*sc;
1643
1644	sc = device_get_softc(dev);
1645
1646	ste_stop(sc);
1647
1648	return;
1649}
1650