if_bfe.c revision 119919
1185573Srwatson/*
2191273Srwatson * Copyright (c) 2003 Stuart Walsh<stu@ipng.org.uk>
3162503Srwatson * and Duncan Barclay<dmlb@dmlb.org>
4155131Srwatson */
5155131Srwatson
6155131Srwatson/*
7155131Srwatson * Redistribution and use in source and binary forms, with or without
8155131Srwatson * modification, are permitted provided that the following conditions
9155131Srwatson * are met:
10155131Srwatson * 1. Redistributions of source code must retain the above copyright
11155131Srwatson *    notice, this list of conditions and the following disclaimer.
12155131Srwatson * 2. Redistributions in binary form must reproduce the above copyright
13155131Srwatson *    notice, this list of conditions and the following disclaimer in the
14185573Srwatson *    documentation and/or other materials provided with the distribution.
15155131Srwatson *
16155131Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 'AS IS' AND
17155131Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18155131Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19155131Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20155131Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21155131Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22155131Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23155131Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24155131Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25155131Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26155131Srwatson * SUCH DAMAGE.
27155131Srwatson */
28155131Srwatson
29155131Srwatson
30155131Srwatson#include <sys/cdefs.h>
31185573Srwatson__FBSDID("$FreeBSD: head/sys/dev/bfe/if_bfe.c 119919 2003-09-09 18:21:17Z wpaul $");
32185573Srwatson
33155131Srwatson#include <sys/param.h>
34155131Srwatson#include <sys/systm.h>
35189279Srwatson#include <sys/sockio.h>
36155131Srwatson#include <sys/mbuf.h>
37155131Srwatson#include <sys/malloc.h>
38243750Srwatson#include <sys/kernel.h>
39186647Srwatson#include <sys/socket.h>
40155131Srwatson#include <sys/queue.h>
41186647Srwatson
42155131Srwatson#include <net/if.h>
43155131Srwatson#include <net/if_arp.h>
44155131Srwatson#include <net/ethernet.h>
45162503Srwatson#include <net/if_dl.h>
46162503Srwatson#include <net/if_media.h>
47162503Srwatson
48185573Srwatson#include <net/bpf.h>
49185573Srwatson
50185573Srwatson#include <net/if_types.h>
51162503Srwatson#include <net/if_vlan_var.h>
52191273Srwatson
53191273Srwatson#include <netinet/in_systm.h>
54155131Srwatson#include <netinet/in.h>
55155131Srwatson#include <netinet/ip.h>
56162503Srwatson
57155131Srwatson#include <machine/clock.h>      /* for DELAY */
58155131Srwatson#include <machine/bus_memio.h>
59155131Srwatson#include <machine/bus.h>
60155131Srwatson#include <machine/resource.h>
61155131Srwatson#include <sys/bus.h>
62155131Srwatson#include <sys/rman.h>
63155131Srwatson
64155131Srwatson#include <dev/mii/mii.h>
65186647Srwatson#include <dev/mii/miivar.h>
66155131Srwatson#include "miidevs.h"
67186647Srwatson
68155131Srwatson#include <dev/pci/pcireg.h>
69155131Srwatson#include <dev/pci/pcivar.h>
70189279Srwatson
71189279Srwatson#include <dev/bfe/if_bfereg.h>
72189279Srwatson
73243750SrwatsonMODULE_DEPEND(bfe, pci, 1, 1, 1);
74243750SrwatsonMODULE_DEPEND(bfe, ether, 1, 1, 1);
75189279SrwatsonMODULE_DEPEND(bfe, miibus, 1, 1, 1);
76189279Srwatson
77189279Srwatson/* "controller miibus0" required.  See GENERIC if you get errors here. */
78189279Srwatson#include "miibus_if.h"
79189279Srwatson
80189279Srwatson#define BFE_DEVDESC_MAX		64	/* Maximum device description length */
81189279Srwatson
82189279Srwatsonstatic struct bfe_type bfe_devs[] = {
83189279Srwatson	{ BCOM_VENDORID, BCOM_DEVICEID_BCM4401,
84189279Srwatson		"Broadcom BCM4401 Fast Ethernet" },
85189279Srwatson		{ 0, 0, NULL }
86189279Srwatson};
87189279Srwatson
88189279Srwatsonstatic int  bfe_probe				(device_t);
89189279Srwatsonstatic int  bfe_attach				(device_t);
90189279Srwatsonstatic int  bfe_detach				(device_t);
91189279Srwatsonstatic void bfe_release_resources	(struct bfe_softc *);
92189279Srwatsonstatic void bfe_intr				(void *);
93189279Srwatsonstatic void bfe_start				(struct ifnet *);
94189279Srwatsonstatic int  bfe_ioctl				(struct ifnet *, u_long, caddr_t);
95189279Srwatsonstatic void bfe_init				(void *);
96155131Srwatsonstatic void bfe_stop				(struct bfe_softc *);
97155131Srwatsonstatic void bfe_watchdog			(struct ifnet *);
98155131Srwatsonstatic void bfe_shutdown			(device_t);
99155131Srwatsonstatic void bfe_tick				(void *);
100155131Srwatsonstatic void bfe_txeof				(struct bfe_softc *);
101155131Srwatsonstatic void bfe_rxeof				(struct bfe_softc *);
102243750Srwatsonstatic void bfe_set_rx_mode			(struct bfe_softc *);
103155131Srwatsonstatic int  bfe_list_rx_init		(struct bfe_softc *);
104155131Srwatsonstatic int  bfe_list_newbuf			(struct bfe_softc *, int, struct mbuf*);
105155131Srwatsonstatic void bfe_rx_ring_free		(struct bfe_softc *);
106155131Srwatson
107155131Srwatsonstatic void bfe_pci_setup			(struct bfe_softc *, u_int32_t);
108155131Srwatsonstatic int  bfe_ifmedia_upd			(struct ifnet *);
109155131Srwatsonstatic void bfe_ifmedia_sts			(struct ifnet *, struct ifmediareq *);
110155131Srwatsonstatic int  bfe_miibus_readreg		(device_t, int, int);
111155131Srwatsonstatic int  bfe_miibus_writereg		(device_t, int, int, int);
112155131Srwatsonstatic void bfe_miibus_statchg		(device_t);
113155131Srwatsonstatic int  bfe_wait_bit			(struct bfe_softc *, u_int32_t, u_int32_t,
114155131Srwatson		u_long, const int);
115155131Srwatsonstatic void bfe_get_config			(struct bfe_softc *sc);
116155131Srwatsonstatic void bfe_read_eeprom			(struct bfe_softc *, u_int8_t *);
117155131Srwatsonstatic void bfe_stats_update		(struct bfe_softc *);
118155131Srwatsonstatic void bfe_clear_stats			(struct bfe_softc *);
119155131Srwatsonstatic int  bfe_readphy				(struct bfe_softc *, u_int32_t, u_int32_t*);
120155131Srwatsonstatic int  bfe_writephy			(struct bfe_softc *, u_int32_t, u_int32_t);
121155131Srwatsonstatic int  bfe_resetphy			(struct bfe_softc *);
122155131Srwatsonstatic int  bfe_setupphy			(struct bfe_softc *);
123195740Srwatsonstatic void bfe_chip_reset			(struct bfe_softc *);
124195740Srwatsonstatic void bfe_chip_halt			(struct bfe_softc *);
125195740Srwatsonstatic void bfe_core_reset			(struct bfe_softc *);
126195740Srwatsonstatic void bfe_core_disable		(struct bfe_softc *);
127155131Srwatsonstatic int  bfe_dma_alloc			(device_t);
128195740Srwatsonstatic void bfe_dma_map_desc		(void *, bus_dma_segment_t *, int, int);
129195740Srwatsonstatic void bfe_dma_map				(void *, bus_dma_segment_t *, int, int);
130155131Srwatsonstatic void bfe_cam_write			(struct bfe_softc *, u_char *, int);
131155131Srwatson
132155131Srwatsonstatic device_method_t bfe_methods[] = {
133155131Srwatson	/* Device interface */
134155131Srwatson	DEVMETHOD(device_probe,		bfe_probe),
135155131Srwatson	DEVMETHOD(device_attach,	bfe_attach),
136155131Srwatson	DEVMETHOD(device_detach,	bfe_detach),
137155131Srwatson	DEVMETHOD(device_shutdown,	bfe_shutdown),
138155131Srwatson
139155131Srwatson	/* bus interface */
140155131Srwatson	DEVMETHOD(bus_print_child,	bus_generic_print_child),
141155131Srwatson	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
142155131Srwatson
143155131Srwatson	/* MII interface */
144155131Srwatson	DEVMETHOD(miibus_readreg,	bfe_miibus_readreg),
145155131Srwatson	DEVMETHOD(miibus_writereg,	bfe_miibus_writereg),
146155131Srwatson	DEVMETHOD(miibus_statchg,	bfe_miibus_statchg),
147189279Srwatson
148189279Srwatson	{ 0, 0 }
149189279Srwatson};
150189279Srwatson
151189279Srwatsonstatic driver_t bfe_driver = {
152189279Srwatson	"bfe",
153189279Srwatson	bfe_methods,
154189279Srwatson	sizeof(struct bfe_softc)
155189279Srwatson};
156189279Srwatson
157189279Srwatsonstatic devclass_t bfe_devclass;
158189279Srwatson
159189279SrwatsonDRIVER_MODULE(bfe, pci, bfe_driver, bfe_devclass, 0, 0);
160189279SrwatsonDRIVER_MODULE(miibus, bfe, miibus_driver, miibus_devclass, 0, 0);
161189279Srwatson
162189279Srwatson/*
163189279Srwatson * Probe for a Broadcom 4401 chip.
164189279Srwatson */
165189279Srwatsonstatic int
166189279Srwatsonbfe_probe(device_t dev)
167189279Srwatson{
168189279Srwatson	struct bfe_type *t;
169189279Srwatson	struct bfe_softc *sc;
170189279Srwatson
171189279Srwatson	t = bfe_devs;
172189279Srwatson
173189279Srwatson	sc = device_get_softc(dev);
174189279Srwatson	bzero(sc, sizeof(struct bfe_softc));
175189279Srwatson	sc->bfe_unit = device_get_unit(dev);
176189279Srwatson	sc->bfe_dev = dev;
177189279Srwatson
178189279Srwatson	while(t->bfe_name != NULL) {
179189279Srwatson		if ((pci_get_vendor(dev) == t->bfe_vid) &&
180189279Srwatson				(pci_get_device(dev) == t->bfe_did)) {
181189279Srwatson			device_set_desc_copy(dev, t->bfe_name);
182189279Srwatson			return(0);
183189279Srwatson		}
184189279Srwatson		t++;
185243750Srwatson	}
186189279Srwatson
187189279Srwatson	return(ENXIO);
188189279Srwatson}
189189279Srwatson
190189279Srwatsonstatic int
191189279Srwatsonbfe_dma_alloc(device_t dev)
192189279Srwatson{
193189279Srwatson	struct bfe_softc *sc;
194189279Srwatson	int error, i;
195189279Srwatson
196189279Srwatson	sc = device_get_softc(dev);
197189279Srwatson
198189279Srwatson	/* parent tag */
199189279Srwatson	error = bus_dma_tag_create(NULL,  /* parent */
200189279Srwatson			PAGE_SIZE, 0,             /* alignment, boundary */
201189279Srwatson			BUS_SPACE_MAXADDR,        /* lowaddr */
202189279Srwatson			BUS_SPACE_MAXADDR_32BIT,  /* highaddr */
203189279Srwatson			NULL, NULL,               /* filter, filterarg */
204189279Srwatson			MAXBSIZE,                 /* maxsize */
205189279Srwatson			BUS_SPACE_UNRESTRICTED,   /* num of segments */
206189279Srwatson			BUS_SPACE_MAXSIZE_32BIT,  /* max segment size */
207189279Srwatson			BUS_DMA_ALLOCNOW,         /* flags */
208189279Srwatson			NULL, NULL,               /* lockfunc, lockarg */
209189279Srwatson			&sc->bfe_parent_tag);
210189279Srwatson
211189279Srwatson	/* tag for TX ring */
212189279Srwatson	error = bus_dma_tag_create(sc->bfe_parent_tag, BFE_TX_LIST_SIZE,
213189279Srwatson			BFE_TX_LIST_SIZE, BUS_SPACE_MAXADDR,  BUS_SPACE_MAXADDR,
214189279Srwatson			NULL, NULL, BFE_TX_LIST_SIZE, 1,  BUS_SPACE_MAXSIZE_32BIT,
215189279Srwatson			0, NULL, NULL, &sc->bfe_tx_tag);
216189279Srwatson
217189279Srwatson	if (error) {
218189279Srwatson		device_printf(dev, "could not allocate dma tag\n");
219189279Srwatson		return(ENOMEM);
220189279Srwatson	}
221189279Srwatson
222189279Srwatson	/* tag for RX ring */
223162503Srwatson	error = bus_dma_tag_create(sc->bfe_parent_tag, BFE_RX_LIST_SIZE,
224162503Srwatson			BFE_RX_LIST_SIZE, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
225162503Srwatson			NULL, NULL, BFE_RX_LIST_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT,
226162503Srwatson			0, NULL, NULL, &sc->bfe_rx_tag);
227162503Srwatson
228191273Srwatson	if (error) {
229162503Srwatson		device_printf(dev, "could not allocate dma tag\n");
230189279Srwatson		return(ENOMEM);
231189279Srwatson	}
232162503Srwatson
233162503Srwatson	/* tag for mbufs */
234162503Srwatson	error = bus_dma_tag_create(sc->bfe_parent_tag, ETHER_ALIGN, 0,
235162503Srwatson			BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
236162503Srwatson			1, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->bfe_tag);
237189279Srwatson
238189279Srwatson	if (error) {
239189279Srwatson		device_printf(dev, "could not allocate dma tag\n");
240162503Srwatson		return(ENOMEM);
241189279Srwatson	}
242189279Srwatson
243162503Srwatson	/* pre allocate dmamaps for RX list */
244189279Srwatson	for (i = 0; i < BFE_RX_LIST_CNT; i++) {
245162503Srwatson		error = bus_dmamap_create(sc->bfe_tag, 0, &sc->bfe_rx_ring[i].bfe_map);
246189279Srwatson		if (error) {
247189279Srwatson			device_printf(dev, "cannot create DMA map for RX\n");
248162503Srwatson			return(ENOMEM);
249162503Srwatson		}
250162503Srwatson	}
251162503Srwatson
252162503Srwatson	/* pre allocate dmamaps for TX list */
253162503Srwatson	for (i = 0; i < BFE_TX_LIST_CNT; i++) {
254162503Srwatson		error = bus_dmamap_create(sc->bfe_tag, 0, &sc->bfe_tx_ring[i].bfe_map);
255162503Srwatson		if (error) {
256191273Srwatson			device_printf(dev, "cannot create DMA map for TX\n");
257162503Srwatson			return(ENOMEM);
258162503Srwatson		}
259162503Srwatson	}
260189279Srwatson
261162503Srwatson	/* Alloc dma for rx ring */
262162503Srwatson	error = bus_dmamem_alloc(sc->bfe_rx_tag, (void *)&sc->bfe_rx_list,
263162503Srwatson			BUS_DMA_NOWAIT, &sc->bfe_rx_map);
264162503Srwatson
265162503Srwatson	if(error)
266162503Srwatson		return(ENOMEM);
267162503Srwatson
268162503Srwatson	bzero(sc->bfe_rx_list, BFE_RX_LIST_SIZE);
269189279Srwatson	error = bus_dmamap_load(sc->bfe_rx_tag, sc->bfe_rx_map,
270189279Srwatson			sc->bfe_rx_list, sizeof(struct bfe_desc),
271189279Srwatson			bfe_dma_map, &sc->bfe_rx_dma, 0);
272189279Srwatson
273189279Srwatson	if(error)
274189279Srwatson		return(ENOMEM);
275189279Srwatson
276189279Srwatson	bus_dmamap_sync(sc->bfe_rx_tag, sc->bfe_rx_map, BUS_DMASYNC_PREREAD);
277189279Srwatson
278189279Srwatson	error = bus_dmamem_alloc(sc->bfe_tx_tag, (void *)&sc->bfe_tx_list,
279189279Srwatson			BUS_DMA_NOWAIT, &sc->bfe_tx_map);
280162503Srwatson	if (error)
281162503Srwatson		return(ENOMEM);
282162503Srwatson
283162503Srwatson
284162503Srwatson	error = bus_dmamap_load(sc->bfe_tx_tag, sc->bfe_tx_map,
285162503Srwatson			sc->bfe_tx_list, sizeof(struct bfe_desc),
286162503Srwatson			bfe_dma_map, &sc->bfe_tx_dma, 0);
287162503Srwatson	if(error)
288162503Srwatson		return(ENOMEM);
289162503Srwatson
290155131Srwatson	bzero(sc->bfe_tx_list, BFE_TX_LIST_SIZE);
291155131Srwatson	bus_dmamap_sync(sc->bfe_tx_tag, sc->bfe_tx_map, BUS_DMASYNC_PREREAD);
292162503Srwatson
293162503Srwatson	return(0);
294162503Srwatson}
295191273Srwatson
296191273Srwatsonstatic int
297162503Srwatsonbfe_attach(device_t dev)
298162503Srwatson{
299191273Srwatson	struct ifnet *ifp;
300191273Srwatson	struct bfe_softc *sc;
301191273Srwatson	int unit, error = 0, rid;
302191273Srwatson
303191273Srwatson	sc = device_get_softc(dev);
304191273Srwatson	mtx_init(&sc->bfe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
305191273Srwatson			MTX_DEF | MTX_RECURSE);
306191273Srwatson
307191273Srwatson	unit = device_get_unit(dev);
308191273Srwatson	sc->bfe_dev = dev;
309191273Srwatson	sc->bfe_unit = unit;
310191273Srwatson
311191273Srwatson	/*
312191273Srwatson	 * Handle power management nonsense.
313191273Srwatson	 */
314162503Srwatson	if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
315191273Srwatson		u_int32_t membase, irq;
316162503Srwatson
317162503Srwatson		/* Save important PCI config data. */
318155131Srwatson		membase = pci_read_config(dev, BFE_PCI_MEMLO, 4);
319155131Srwatson		irq = pci_read_config(dev, BFE_PCI_INTLINE, 4);
320155131Srwatson
321155131Srwatson		/* Reset the power state. */
322186647Srwatson		printf("bfe%d: chip is is in D%d power mode -- setting to D0\n",
323155131Srwatson				sc->bfe_unit, pci_get_powerstate(dev));
324186647Srwatson
325162503Srwatson		pci_set_powerstate(dev, PCI_POWERSTATE_D0);
326186647Srwatson
327155131Srwatson		/* Restore PCI config data. */
328186647Srwatson		pci_write_config(dev, BFE_PCI_MEMLO, membase, 4);
329155131Srwatson		pci_write_config(dev, BFE_PCI_INTLINE, irq, 4);
330155131Srwatson	}
331155131Srwatson
332162503Srwatson	/*
333155131Srwatson	 * Map control/status registers.
334155131Srwatson	 */
335155131Srwatson	pci_enable_busmaster(dev);
336155131Srwatson
337155131Srwatson	rid = BFE_PCI_MEMLO;
338186647Srwatson	sc->bfe_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1,
339155131Srwatson			RF_ACTIVE);
340186647Srwatson	if (sc->bfe_res == NULL) {
341155131Srwatson		printf ("bfe%d: couldn't map memory\n", unit);
342155131Srwatson		error = ENXIO;
343155131Srwatson		goto fail;
344155131Srwatson	}
345155131Srwatson
346186647Srwatson	sc->bfe_btag = rman_get_bustag(sc->bfe_res);
347155131Srwatson	sc->bfe_bhandle = rman_get_bushandle(sc->bfe_res);
348186647Srwatson	sc->bfe_vhandle = (vm_offset_t)rman_get_virtual(sc->bfe_res);
349155131Srwatson
350155131Srwatson	/* Allocate interrupt */
351155131Srwatson	rid = 0;
352155131Srwatson
353155131Srwatson	sc->bfe_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
354155131Srwatson			RF_SHAREABLE | RF_ACTIVE);
355155131Srwatson	if (sc->bfe_irq == NULL) {
356155131Srwatson		printf("bfe%d: couldn't map interrupt\n", unit);
357155131Srwatson		error = ENXIO;
358155131Srwatson		goto fail;
359155131Srwatson	}
360155131Srwatson
361162503Srwatson	if (bfe_dma_alloc(dev)) {
362162503Srwatson		printf("bfe%d: failed to allocate DMA resources\n", sc->bfe_unit);
363155131Srwatson		bfe_release_resources(sc);
364186647Srwatson		error = ENXIO;
365162503Srwatson		goto fail;
366186647Srwatson	}
367155131Srwatson
368155131Srwatson	/* Set up ifnet structure */
369155131Srwatson	ifp = &sc->arpcom.ac_if;
370155131Srwatson	ifp->if_softc = sc;
371155131Srwatson	ifp->if_unit = sc->bfe_unit;
372155131Srwatson	ifp->if_name = "bfe";
373155131Srwatson	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
374186647Srwatson	ifp->if_ioctl = bfe_ioctl;
375155131Srwatson	ifp->if_output = ether_output;
376186647Srwatson	ifp->if_start = bfe_start;
377155131Srwatson	ifp->if_watchdog = bfe_watchdog;
378155131Srwatson	ifp->if_init = bfe_init;
379162503Srwatson	ifp->if_mtu = ETHERMTU;
380186647Srwatson	ifp->if_baudrate = 10000000;
381162503Srwatson	ifp->if_snd.ifq_maxlen = BFE_TX_QLEN;
382186647Srwatson
383155131Srwatson	bfe_get_config(sc);
384162503Srwatson
385185573Srwatson	printf("bfe%d: Ethernet address: %6D\n", unit, sc->arpcom.ac_enaddr, ":");
386186647Srwatson
387162503Srwatson	/* Reset the chip and turn on the PHY */
388186647Srwatson	bfe_chip_reset(sc);
389155131Srwatson
390162503Srwatson	if (mii_phy_probe(dev, &sc->bfe_miibus,
391185573Srwatson				bfe_ifmedia_upd, bfe_ifmedia_sts)) {
392186647Srwatson		printf("bfe%d: MII without any PHY!\n", sc->bfe_unit);
393162503Srwatson		error = ENXIO;
394186647Srwatson		goto fail;
395155131Srwatson	}
396155131Srwatson
397155131Srwatson	ether_ifattach(ifp, sc->arpcom.ac_enaddr);
398155131Srwatson	callout_handle_init(&sc->bfe_stat_ch);
399243750Srwatson
400243750Srwatson	/*
401243750Srwatson	 * Hook interrupt last to avoid having to lock softc
402243750Srwatson	 */
403243750Srwatson	error = bus_setup_intr(dev, sc->bfe_irq, INTR_TYPE_NET,
404243750Srwatson			bfe_intr, sc, &sc->bfe_intrhand);
405243750Srwatson
406243750Srwatson	if (error) {
407243750Srwatson		bfe_release_resources(sc);
408243750Srwatson		printf("bfe%d: couldn't set up irq\n", unit);
409243750Srwatson		goto fail;
410243750Srwatson	}
411243750Srwatsonfail:
412243750Srwatson	if(error)
413243750Srwatson		bfe_release_resources(sc);
414243750Srwatson	return(error);
415243750Srwatson}
416243750Srwatson
417243750Srwatsonstatic int
418243750Srwatsonbfe_detach(device_t dev)
419243750Srwatson{
420243750Srwatson	struct bfe_softc *sc;
421243750Srwatson	struct ifnet *ifp;
422243750Srwatson
423243750Srwatson	sc = device_get_softc(dev);
424243750Srwatson
425243750Srwatson	KASSERT(mtx_initialized(&sc->bfe_mtx), ("bfe mutex not initialized"));
426243750Srwatson	BFE_LOCK(scp);
427243750Srwatson
428243750Srwatson	ifp = &sc->arpcom.ac_if;
429243750Srwatson
430243750Srwatson	if (device_is_attached(dev)) {
431243750Srwatson		bfe_stop(sc);
432243750Srwatson		ether_ifdetach(ifp);
433243750Srwatson	}
434243750Srwatson
435243750Srwatson	bfe_chip_reset(sc);
436162503Srwatson
437155131Srwatson	bus_generic_detach(dev);
438155131Srwatson	if(sc->bfe_miibus != NULL)
439155131Srwatson		device_delete_child(dev, sc->bfe_miibus);
440155131Srwatson
441155131Srwatson	bfe_release_resources(sc);
442155131Srwatson	BFE_UNLOCK(sc);
443186647Srwatson	mtx_destroy(&sc->bfe_mtx);
444155131Srwatson
445186647Srwatson	return(0);
446162503Srwatson}
447155131Srwatson
448186647Srwatson/*
449155131Srwatson * Stop all chip I/O so that the kernel's probe routines don't
450186647Srwatson * get confused by errant DMAs when rebooting.
451155131Srwatson */
452155131Srwatsonstatic void
453162503Srwatsonbfe_shutdown(device_t dev)
454186647Srwatson{
455162503Srwatson	struct bfe_softc *sc;
456186647Srwatson
457243750Srwatson	sc = device_get_softc(dev);
458162503Srwatson	BFE_LOCK(sc);
459155131Srwatson	bfe_stop(sc);
460186647Srwatson
461162503Srwatson	BFE_UNLOCK(sc);
462186647Srwatson	return;
463155131Srwatson}
464155131Srwatson
465155131Srwatsonstatic int
466155131Srwatsonbfe_miibus_readreg(device_t dev, int phy, int reg)
467162621Srwatson{
468162621Srwatson	struct bfe_softc *sc;
469162621Srwatson	u_int32_t ret;
470162621Srwatson
471162621Srwatson	sc = device_get_softc(dev);
472189279Srwatson	if(phy != sc->bfe_phyaddr)
473189279Srwatson		return(0);
474189279Srwatson	bfe_readphy(sc, reg, &ret);
475189279Srwatson
476162621Srwatson	return(ret);
477186647Srwatson}
478162621Srwatson
479186647Srwatsonstatic int
480162621Srwatsonbfe_miibus_writereg(device_t dev, int phy, int reg, int val)
481189279Srwatson{
482186647Srwatson	struct bfe_softc *sc;
483162621Srwatson
484186647Srwatson	sc = device_get_softc(dev);
485162621Srwatson	if(phy != sc->bfe_phyaddr)
486162621Srwatson		return(0);
487189279Srwatson	bfe_writephy(sc, reg, val);
488186647Srwatson
489162621Srwatson	return(0);
490186647Srwatson}
491162621Srwatson
492243750Srwatsonstatic void
493162621Srwatsonbfe_miibus_statchg(device_t dev)
494189279Srwatson{
495189279Srwatson	return;
496189279Srwatson}
497189279Srwatson
498189279Srwatsonstatic void
499189279Srwatsonbfe_tx_ring_free(struct bfe_softc *sc)
500189279Srwatson{
501189279Srwatson    int i;
502189279Srwatson
503189279Srwatson    for(i = 0; i < BFE_TX_LIST_CNT; i++) {
504189279Srwatson        if(sc->bfe_tx_ring[i].bfe_mbuf != NULL) {
505189279Srwatson            m_freem(sc->bfe_tx_ring[i].bfe_mbuf);
506189279Srwatson            sc->bfe_tx_ring[i].bfe_mbuf = NULL;
507189279Srwatson            bus_dmamap_unload(sc->bfe_tag,
508189279Srwatson                    sc->bfe_tx_ring[i].bfe_map);
509189279Srwatson            bus_dmamap_destroy(sc->bfe_tag,
510189279Srwatson                    sc->bfe_tx_ring[i].bfe_map);
511189279Srwatson        }
512186647Srwatson    }
513162621Srwatson    bzero(sc->bfe_tx_list, BFE_TX_LIST_SIZE);
514186647Srwatson    bus_dmamap_sync(sc->bfe_tx_tag, sc->bfe_tx_map, BUS_DMASYNC_PREREAD);
515162621Srwatson}
516162621Srwatson
517189279Srwatsonstatic void
518162621Srwatsonbfe_rx_ring_free(struct bfe_softc *sc)
519162621Srwatson{
520162621Srwatson	int i;
521162621Srwatson
522189279Srwatson	for (i = 0; i < BFE_RX_LIST_CNT; i++) {
523189279Srwatson		if (sc->bfe_rx_ring[i].bfe_mbuf != NULL) {
524186647Srwatson			m_freem(sc->bfe_rx_ring[i].bfe_mbuf);
525162621Srwatson			sc->bfe_rx_ring[i].bfe_mbuf = NULL;
526186647Srwatson			bus_dmamap_unload(sc->bfe_tag,
527189279Srwatson					sc->bfe_rx_ring[i].bfe_map);
528162621Srwatson			bus_dmamap_destroy(sc->bfe_tag,
529162621Srwatson					sc->bfe_rx_ring[i].bfe_map);
530162621Srwatson		}
531186647Srwatson	}
532162621Srwatson	bzero(sc->bfe_rx_list, BFE_RX_LIST_SIZE);
533186647Srwatson	bus_dmamap_sync(sc->bfe_rx_tag, sc->bfe_rx_map, BUS_DMASYNC_PREREAD);
534162621Srwatson}
535162621Srwatson
536162621Srwatson
537243750Srwatsonstatic int
538243750Srwatsonbfe_list_rx_init(struct bfe_softc *sc)
539155131Srwatson{
540155131Srwatson	int i;
541155131Srwatson
542186647Srwatson	for(i = 0; i < BFE_RX_LIST_CNT; i++) {
543155131Srwatson		if(bfe_list_newbuf(sc, i, NULL) == ENOBUFS)
544186647Srwatson			return ENOBUFS;
545162503Srwatson	}
546243750Srwatson
547186647Srwatson	bus_dmamap_sync(sc->bfe_rx_tag, sc->bfe_rx_map, BUS_DMASYNC_PREREAD);
548155131Srwatson	CSR_WRITE_4(sc, BFE_DMARX_PTR, (i * sizeof(struct bfe_desc)));
549186647Srwatson
550155131Srwatson	sc->bfe_rx_cons = 0;
551155131Srwatson
552162503Srwatson	return(0);
553186647Srwatson}
554162503Srwatson
555186647Srwatsonstatic int
556243750Srwatsonbfe_list_newbuf(struct bfe_softc *sc, int c, struct mbuf *m)
557162503Srwatson{
558185573Srwatson	struct bfe_rxheader *rx_header;
559186647Srwatson	struct bfe_desc *d;
560162503Srwatson	struct bfe_data *r;
561186647Srwatson	u_int32_t ctrl;
562155131Srwatson
563162503Srwatson	if ((c < 0) || (c >= BFE_RX_LIST_CNT))
564185573Srwatson		return(EINVAL);
565186647Srwatson
566162503Srwatson	if(m == NULL) {
567186647Srwatson		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
568155131Srwatson		if(m == NULL)
569155131Srwatson			return(ENOBUFS);
570155131Srwatson		m->m_len = m->m_pkthdr.len = MCLBYTES;
571155131Srwatson	}
572243750Srwatson	else
573243750Srwatson		m->m_data = m->m_ext.ext_buf;
574243750Srwatson
575243750Srwatson	rx_header = mtod(m, struct bfe_rxheader *);
576243750Srwatson	rx_header->len = 0;
577243750Srwatson	rx_header->flags = 0;
578243750Srwatson
579243750Srwatson	/* Map the mbuf into DMA */
580243750Srwatson	sc->bfe_rx_cnt = c;
581243750Srwatson	d = &sc->bfe_rx_list[c];
582155131Srwatson	r = &sc->bfe_rx_ring[c];
583155131Srwatson	bus_dmamap_load(sc->bfe_tag, r->bfe_map, mtod(m, void *),
584155131Srwatson			MCLBYTES, bfe_dma_map_desc, d, 0);
585155131Srwatson	bus_dmamap_sync(sc->bfe_tag, r->bfe_map, BUS_DMASYNC_PREWRITE);
586155131Srwatson
587155131Srwatson	ctrl = ETHER_MAX_LEN + 32;
588243750Srwatson
589162503Srwatson	if(c == BFE_RX_LIST_CNT - 1)
590155131Srwatson		ctrl |= BFE_DESC_EOT;
591162503Srwatson
592162503Srwatson	d->bfe_ctrl = ctrl;
593162503Srwatson	r->bfe_mbuf = m;
594162503Srwatson	bus_dmamap_sync(sc->bfe_rx_tag, sc->bfe_rx_map, BUS_DMASYNC_PREREAD);
595162503Srwatson	return(0);
596162503Srwatson}
597162503Srwatson
598243750Srwatsonstatic void
599185573Srwatsonbfe_get_config(struct bfe_softc *sc)
600185573Srwatson{
601185573Srwatson	u_int8_t eeprom[128];
602185573Srwatson
603185573Srwatson	bfe_read_eeprom(sc, eeprom);
604185573Srwatson
605243750Srwatson	sc->arpcom.ac_enaddr[0] = eeprom[79];
606155131Srwatson	sc->arpcom.ac_enaddr[1] = eeprom[78];
607189279Srwatson	sc->arpcom.ac_enaddr[2] = eeprom[81];
608189279Srwatson	sc->arpcom.ac_enaddr[3] = eeprom[80];
609189279Srwatson	sc->arpcom.ac_enaddr[4] = eeprom[83];
610189279Srwatson	sc->arpcom.ac_enaddr[5] = eeprom[82];
611189279Srwatson
612189279Srwatson	sc->bfe_phyaddr = eeprom[90] & 0x1f;
613189279Srwatson	sc->bfe_mdc_port = (eeprom[90] >> 14) & 0x1;
614189279Srwatson
615189279Srwatson	sc->bfe_core_unit = 0;
616189279Srwatson	sc->bfe_dma_offset = BFE_PCI_DMA;
617189279Srwatson}
618189279Srwatson
619189279Srwatsonstatic void
620189279Srwatsonbfe_pci_setup(struct bfe_softc *sc, u_int32_t cores)
621189279Srwatson{
622189279Srwatson	u_int32_t bar_orig, pci_rev, val;
623189279Srwatson
624189279Srwatson	bar_orig = pci_read_config(sc->bfe_dev, BFE_BAR0_WIN, 4);
625189279Srwatson	pci_write_config(sc->bfe_dev, BFE_BAR0_WIN, BFE_REG_PCI, 4);
626189279Srwatson	pci_rev = CSR_READ_4(sc, BFE_SBIDHIGH) & BFE_RC_MASK;
627189279Srwatson
628189279Srwatson	val = CSR_READ_4(sc, BFE_SBINTVEC);
629189279Srwatson	val |= cores;
630189279Srwatson	CSR_WRITE_4(sc, BFE_SBINTVEC, val);
631189279Srwatson
632189279Srwatson	val = CSR_READ_4(sc, BFE_SSB_PCI_TRANS_2);
633189279Srwatson	val |= BFE_SSB_PCI_PREF | BFE_SSB_PCI_BURST;
634189279Srwatson	CSR_WRITE_4(sc, BFE_SSB_PCI_TRANS_2, val);
635189279Srwatson
636189279Srwatson	pci_write_config(sc->bfe_dev, BFE_BAR0_WIN, bar_orig, 4);
637189279Srwatson}
638189279Srwatson
639189279Srwatsonstatic void
640189279Srwatsonbfe_clear_stats(struct bfe_softc *sc)
641189279Srwatson{
642189279Srwatson	u_long reg;
643189279Srwatson
644189279Srwatson	BFE_LOCK(sc);
645189279Srwatson
646189279Srwatson	CSR_WRITE_4(sc, BFE_MIB_CTRL, BFE_MIB_CLR_ON_READ);
647189279Srwatson	for (reg = BFE_TX_GOOD_O; reg <= BFE_TX_PAUSE; reg += 4)
648189279Srwatson		CSR_READ_4(sc, reg);
649189279Srwatson	for (reg = BFE_RX_GOOD_O; reg <= BFE_RX_NPAUSE; reg += 4)
650189279Srwatson		CSR_READ_4(sc, reg);
651243750Srwatson
652189279Srwatson	BFE_UNLOCK(sc);
653189279Srwatson}
654189279Srwatson
655189279Srwatsonstatic int
656243750Srwatsonbfe_resetphy(struct bfe_softc *sc)
657189279Srwatson{
658189279Srwatson	u_int32_t val;
659189279Srwatson
660189279Srwatson	BFE_LOCK(sc);
661189279Srwatson	bfe_writephy(sc, 0, BMCR_RESET);
662189279Srwatson	DELAY(100);
663189279Srwatson	bfe_readphy(sc, 0, &val);
664189279Srwatson	if (val & BMCR_RESET) {
665189279Srwatson		printf("bfe%d: PHY Reset would not complete.\n", sc->bfe_unit);
666189279Srwatson		BFE_UNLOCK(sc);
667189279Srwatson		return ENXIO;
668189279Srwatson	}
669189279Srwatson	BFE_UNLOCK(sc);
670189279Srwatson	return 0;
671189279Srwatson}
672189279Srwatson
673189279Srwatsonstatic void
674189279Srwatsonbfe_chip_halt(struct bfe_softc *sc)
675189279Srwatson{
676189279Srwatson	BFE_LOCK(sc);
677189279Srwatson	/* disable interrupts - not that it actually does..*/
678243750Srwatson	CSR_WRITE_4(sc, BFE_IMASK, 0);
679189279Srwatson	CSR_READ_4(sc, BFE_IMASK);
680189279Srwatson
681189279Srwatson	CSR_WRITE_4(sc, BFE_ENET_CTRL, BFE_ENET_DISABLE);
682189279Srwatson	bfe_wait_bit(sc, BFE_ENET_CTRL, BFE_ENET_DISABLE, 200, 1);
683189279Srwatson
684189279Srwatson	CSR_WRITE_4(sc, BFE_DMARX_CTRL, 0);
685189279Srwatson	CSR_WRITE_4(sc, BFE_DMATX_CTRL, 0);
686189279Srwatson	DELAY(10);
687189279Srwatson
688189279Srwatson	BFE_UNLOCK(sc);
689189279Srwatson}
690189279Srwatson
691189279Srwatsonstatic void
692189279Srwatsonbfe_chip_reset(struct bfe_softc *sc)
693189279Srwatson{
694189279Srwatson	u_int32_t val;
695189279Srwatson
696189279Srwatson	BFE_LOCK(sc);
697189279Srwatson
698189279Srwatson	/* Set the interrupt vector for the enet core */
699189279Srwatson	bfe_pci_setup(sc, BFE_INTVEC_ENET0);
700189279Srwatson
701189279Srwatson	/* is core up? */
702189279Srwatson	val = CSR_READ_4(sc, BFE_SBTMSLOW) & (BFE_RESET | BFE_REJECT | BFE_CLOCK);
703189279Srwatson	if (val == BFE_CLOCK) {
704189279Srwatson		/* It is, so shut it down */
705189279Srwatson		CSR_WRITE_4(sc, BFE_RCV_LAZY, 0);
706189279Srwatson		CSR_WRITE_4(sc, BFE_ENET_CTRL, BFE_ENET_DISABLE);
707189279Srwatson		bfe_wait_bit(sc, BFE_ENET_CTRL, BFE_ENET_DISABLE, 100, 1);
708189279Srwatson		CSR_WRITE_4(sc, BFE_DMATX_CTRL, 0);
709		sc->bfe_tx_cnt = sc->bfe_tx_prod = sc->bfe_tx_cons = 0;
710		if (CSR_READ_4(sc, BFE_DMARX_STAT) & BFE_STAT_EMASK)
711			bfe_wait_bit(sc, BFE_DMARX_STAT, BFE_STAT_SIDLE, 100, 0);
712		CSR_WRITE_4(sc, BFE_DMARX_CTRL, 0);
713		sc->bfe_rx_prod = sc->bfe_rx_cons = 0;
714	}
715
716	bfe_core_reset(sc);
717	bfe_clear_stats(sc);
718
719	/*
720	 * We want the phy registers to be accessible even when
721	 * the driver is "downed" so initialize MDC preamble, frequency,
722	 * and whether internal or external phy here.
723	 */
724
725	/* 4402 has 62.5Mhz SB clock and internal phy */
726	CSR_WRITE_4(sc, BFE_MDIO_CTRL, 0x8d);
727
728	/* Internal or external PHY? */
729	val = CSR_READ_4(sc, BFE_DEVCTRL);
730	if(!(val & BFE_IPP))
731		CSR_WRITE_4(sc, BFE_ENET_CTRL, BFE_ENET_EPSEL);
732	else if(CSR_READ_4(sc, BFE_DEVCTRL) & BFE_EPR) {
733		BFE_AND(sc, BFE_DEVCTRL, ~BFE_EPR);
734		DELAY(100);
735	}
736
737	BFE_OR(sc, BFE_MAC_CTRL, BFE_CTRL_CRC32_ENAB);
738	CSR_WRITE_4(sc, BFE_RCV_LAZY, ((1 << BFE_LAZY_FC_SHIFT) &
739				BFE_LAZY_FC_MASK));
740
741	/*
742	 * We don't want lazy interrupts, so just send them at the end of a frame,
743	 * please
744	 */
745	BFE_OR(sc, BFE_RCV_LAZY, 0);
746
747	/* Set max lengths, accounting for VLAN tags */
748	CSR_WRITE_4(sc, BFE_RXMAXLEN, ETHER_MAX_LEN+32);
749	CSR_WRITE_4(sc, BFE_TXMAXLEN, ETHER_MAX_LEN+32);
750
751	/* Set watermark XXX - magic */
752	CSR_WRITE_4(sc, BFE_TX_WMARK, 56);
753
754	/*
755	 * Initialise DMA channels - not forgetting dma addresses need to be added
756	 * to BFE_PCI_DMA
757	 */
758	CSR_WRITE_4(sc, BFE_DMATX_CTRL, BFE_TX_CTRL_ENABLE);
759	CSR_WRITE_4(sc, BFE_DMATX_ADDR, sc->bfe_tx_dma + BFE_PCI_DMA);
760
761	CSR_WRITE_4(sc, BFE_DMARX_CTRL, (BFE_RX_OFFSET << BFE_RX_CTRL_ROSHIFT) |
762			BFE_RX_CTRL_ENABLE);
763	CSR_WRITE_4(sc, BFE_DMARX_ADDR, sc->bfe_rx_dma + BFE_PCI_DMA);
764
765	bfe_resetphy(sc);
766	bfe_setupphy(sc);
767
768	BFE_UNLOCK(sc);
769}
770
771static void
772bfe_core_disable(struct bfe_softc *sc)
773{
774	if((CSR_READ_4(sc, BFE_SBTMSLOW)) & BFE_RESET)
775		return;
776
777	/*
778	 * Set reject, wait for it set, then wait for the core to stop being busy
779	 * Then set reset and reject and enable the clocks
780	 */
781	CSR_WRITE_4(sc, BFE_SBTMSLOW, (BFE_REJECT | BFE_CLOCK));
782	bfe_wait_bit(sc, BFE_SBTMSLOW, BFE_REJECT, 1000, 0);
783	bfe_wait_bit(sc, BFE_SBTMSHIGH, BFE_BUSY, 1000, 1);
784	CSR_WRITE_4(sc, BFE_SBTMSLOW, (BFE_FGC | BFE_CLOCK | BFE_REJECT |
785				BFE_RESET));
786	CSR_READ_4(sc, BFE_SBTMSLOW);
787	DELAY(10);
788	/* Leave reset and reject set */
789	CSR_WRITE_4(sc, BFE_SBTMSLOW, (BFE_REJECT | BFE_RESET));
790	DELAY(10);
791}
792
793static void
794bfe_core_reset(struct bfe_softc *sc)
795{
796	u_int32_t val;
797
798	/* Disable the core */
799	bfe_core_disable(sc);
800
801	/* and bring it back up */
802	CSR_WRITE_4(sc, BFE_SBTMSLOW, (BFE_RESET | BFE_CLOCK | BFE_FGC));
803	CSR_READ_4(sc, BFE_SBTMSLOW);
804	DELAY(10);
805
806	/* Chip bug, clear SERR, IB and TO if they are set. */
807	if (CSR_READ_4(sc, BFE_SBTMSHIGH) & BFE_SERR)
808		CSR_WRITE_4(sc, BFE_SBTMSHIGH, 0);
809	val = CSR_READ_4(sc, BFE_SBIMSTATE);
810	if (val & (BFE_IBE | BFE_TO))
811		CSR_WRITE_4(sc, BFE_SBIMSTATE, val & ~(BFE_IBE | BFE_TO));
812
813	/* Clear reset and allow it to move through the core */
814	CSR_WRITE_4(sc, BFE_SBTMSLOW, (BFE_CLOCK | BFE_FGC));
815	CSR_READ_4(sc, BFE_SBTMSLOW);
816	DELAY(10);
817
818	/* Leave the clock set */
819	CSR_WRITE_4(sc, BFE_SBTMSLOW, BFE_CLOCK);
820	CSR_READ_4(sc, BFE_SBTMSLOW);
821	DELAY(10);
822}
823
824static void
825bfe_cam_write(struct bfe_softc *sc, u_char *data, int index)
826{
827	u_int32_t val;
828
829	val  = ((u_int32_t) data[2]) << 24;
830	val |= ((u_int32_t) data[3]) << 16;
831	val |= ((u_int32_t) data[4]) <<  8;
832	val |= ((u_int32_t) data[5]);
833	CSR_WRITE_4(sc, BFE_CAM_DATA_LO, val);
834	val = (BFE_CAM_HI_VALID |
835			(((u_int32_t) data[0]) << 8) |
836			(((u_int32_t) data[1])));
837	CSR_WRITE_4(sc, BFE_CAM_DATA_HI, val);
838	CSR_WRITE_4(sc, BFE_CAM_CTRL, (BFE_CAM_WRITE |
839				(index << BFE_CAM_INDEX_SHIFT)));
840	bfe_wait_bit(sc, BFE_CAM_CTRL, BFE_CAM_BUSY, 10000, 1);
841}
842
843static void
844bfe_set_rx_mode(struct bfe_softc *sc)
845{
846	struct ifnet *ifp = &sc->arpcom.ac_if;
847	struct ifmultiaddr  *ifma;
848	u_int32_t val;
849	int i = 0;
850
851	val = CSR_READ_4(sc, BFE_RXCONF);
852
853	if (ifp->if_flags & IFF_PROMISC)
854		val |= BFE_RXCONF_PROMISC;
855	else
856		val &= ~BFE_RXCONF_PROMISC;
857
858	if (ifp->if_flags & IFF_BROADCAST)
859		val &= ~BFE_RXCONF_DBCAST;
860	else
861		val |= BFE_RXCONF_DBCAST;
862
863
864	CSR_WRITE_4(sc, BFE_CAM_CTRL, 0);
865	bfe_cam_write(sc, sc->arpcom.ac_enaddr, i++);
866
867	if (ifp->if_flags & IFF_ALLMULTI)
868		val |= BFE_RXCONF_ALLMULTI;
869	else {
870		val &= ~BFE_RXCONF_ALLMULTI;
871		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
872			if (ifma->ifma_addr->sa_family != AF_LINK)
873				continue;
874			bfe_cam_write(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
875					i++);
876		}
877	}
878
879	CSR_WRITE_4(sc, BFE_RXCONF, val);
880	BFE_OR(sc, BFE_CAM_CTRL, BFE_CAM_ENABLE);
881}
882
883static void
884bfe_dma_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
885{
886	u_int32_t *ptr;
887
888	ptr = arg;
889	*ptr = segs->ds_addr;
890}
891
892static void
893bfe_dma_map_desc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
894{
895	struct bfe_desc *d;
896
897	d = arg;
898	/* The chip needs all addresses to be added to BFE_PCI_DMA */
899	d->bfe_addr = segs->ds_addr + BFE_PCI_DMA;
900}
901
902static void
903bfe_release_resources(struct bfe_softc *sc)
904{
905	device_t dev;
906	int i;
907
908	dev = sc->bfe_dev;
909
910	if (sc->bfe_vpd_prodname != NULL)
911		free(sc->bfe_vpd_prodname, M_DEVBUF);
912
913	if (sc->bfe_vpd_readonly != NULL)
914		free(sc->bfe_vpd_readonly, M_DEVBUF);
915
916	if (sc->bfe_intrhand != NULL)
917		bus_teardown_intr(dev, sc->bfe_irq, sc->bfe_intrhand);
918
919	if (sc->bfe_irq != NULL)
920		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->bfe_irq);
921
922	if (sc->bfe_res != NULL)
923		bus_release_resource(dev, SYS_RES_MEMORY, 0x10, sc->bfe_res);
924
925	if(sc->bfe_tx_tag != NULL) {
926		bus_dmamap_unload(sc->bfe_tx_tag, sc->bfe_tx_map);
927		bus_dmamem_free(sc->bfe_tx_tag, sc->bfe_tx_list, sc->bfe_tx_map);
928		bus_dma_tag_destroy(sc->bfe_tx_tag);
929		sc->bfe_tx_tag = NULL;
930	}
931
932	if(sc->bfe_rx_tag != NULL) {
933		bus_dmamap_unload(sc->bfe_rx_tag, sc->bfe_rx_map);
934		bus_dmamem_free(sc->bfe_rx_tag, sc->bfe_rx_list, sc->bfe_rx_map);
935		bus_dma_tag_destroy(sc->bfe_rx_tag);
936		sc->bfe_rx_tag = NULL;
937	}
938
939	if(sc->bfe_tag != NULL) {
940		for(i = 0; i < BFE_TX_LIST_CNT; i++) {
941			bus_dmamap_destroy(sc->bfe_tag, sc->bfe_tx_ring[i].bfe_map);
942		}
943		bus_dma_tag_destroy(sc->bfe_tag);
944        sc->bfe_tag = NULL;
945	}
946
947	if(sc->bfe_parent_tag != NULL)
948		bus_dma_tag_destroy(sc->bfe_parent_tag);
949
950	return;
951}
952
953static void
954bfe_read_eeprom(struct bfe_softc *sc, u_int8_t *data)
955{
956	long i;
957	u_int16_t *ptr = (u_int16_t *)data;
958
959	for(i = 0; i < 128; i += 2)
960		ptr[i/2] = CSR_READ_4(sc, 4096 + i);
961}
962
963static int
964bfe_wait_bit(struct bfe_softc *sc, u_int32_t reg, u_int32_t bit,
965		u_long timeout, const int clear)
966{
967	u_long i;
968
969	for (i = 0; i < timeout; i++) {
970		u_int32_t val = CSR_READ_4(sc, reg);
971
972		if (clear && !(val & bit))
973			break;
974		if (!clear && (val & bit))
975			break;
976		DELAY(10);
977	}
978	if (i == timeout) {
979		printf("bfe%d: BUG!  Timeout waiting for bit %08x of register "
980				"%x to %s.\n", sc->bfe_unit, bit, reg,
981				(clear ? "clear" : "set"));
982		return -1;
983	}
984	return 0;
985}
986
987static int
988bfe_readphy(struct bfe_softc *sc, u_int32_t reg, u_int32_t *val)
989{
990	int err;
991
992	BFE_LOCK(sc);
993	/* Clear MII ISR */
994	CSR_WRITE_4(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII);
995	CSR_WRITE_4(sc, BFE_MDIO_DATA, (BFE_MDIO_SB_START |
996				(BFE_MDIO_OP_READ << BFE_MDIO_OP_SHIFT) |
997				(sc->bfe_phyaddr << BFE_MDIO_PMD_SHIFT) |
998				(reg << BFE_MDIO_RA_SHIFT) |
999				(BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT)));
1000	err = bfe_wait_bit(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 100, 0);
1001	*val = CSR_READ_4(sc, BFE_MDIO_DATA) & BFE_MDIO_DATA_DATA;
1002
1003	BFE_UNLOCK(sc);
1004	return err;
1005}
1006
1007static int
1008bfe_writephy(struct bfe_softc *sc, u_int32_t reg, u_int32_t val)
1009{
1010	int status;
1011
1012	BFE_LOCK(sc);
1013	CSR_WRITE_4(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII);
1014	CSR_WRITE_4(sc, BFE_MDIO_DATA, (BFE_MDIO_SB_START |
1015				(BFE_MDIO_OP_WRITE << BFE_MDIO_OP_SHIFT) |
1016				(sc->bfe_phyaddr << BFE_MDIO_PMD_SHIFT) |
1017				(reg << BFE_MDIO_RA_SHIFT) |
1018				(BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT) |
1019				(val & BFE_MDIO_DATA_DATA)));
1020	status = bfe_wait_bit(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 100, 0);
1021	BFE_UNLOCK(sc);
1022
1023	return status;
1024}
1025
1026/*
1027 * XXX - I think this is handled by the PHY driver, but it can't hurt to do it
1028 * twice
1029 */
1030static int
1031bfe_setupphy(struct bfe_softc *sc)
1032{
1033	u_int32_t val;
1034	BFE_LOCK(sc);
1035
1036	/* Enable activity LED */
1037	bfe_readphy(sc, 26, &val);
1038	bfe_writephy(sc, 26, val & 0x7fff);
1039	bfe_readphy(sc, 26, &val);
1040
1041	/* Enable traffic meter LED mode */
1042	bfe_readphy(sc, 27, &val);
1043	bfe_writephy(sc, 27, val | (1 << 6));
1044
1045	BFE_UNLOCK(sc);
1046	return 0;
1047}
1048
1049static void
1050bfe_stats_update(struct bfe_softc *sc)
1051{
1052	u_long reg;
1053	u_int32_t *val;
1054
1055	val = &sc->bfe_hwstats.tx_good_octets;
1056	for (reg = BFE_TX_GOOD_O; reg <= BFE_TX_PAUSE; reg += 4) {
1057		*val++ += CSR_READ_4(sc, reg);
1058	}
1059	val = &sc->bfe_hwstats.rx_good_octets;
1060	for (reg = BFE_RX_GOOD_O; reg <= BFE_RX_NPAUSE; reg += 4) {
1061		*val++ += CSR_READ_4(sc, reg);
1062	}
1063}
1064
1065static void
1066bfe_txeof(struct bfe_softc *sc)
1067{
1068	struct ifnet *ifp;
1069	int i, chipidx;
1070
1071	BFE_LOCK(sc);
1072
1073	ifp = &sc->arpcom.ac_if;
1074
1075	chipidx = CSR_READ_4(sc, BFE_DMATX_STAT) & BFE_STAT_CDMASK;
1076	chipidx /= sizeof(struct bfe_desc);
1077
1078    i = sc->bfe_tx_cons;
1079	/* Go through the mbufs and free those that have been transmitted */
1080    while(i != chipidx) {
1081		struct bfe_data *r = &sc->bfe_tx_ring[i];
1082		if(r->bfe_mbuf != NULL) {
1083			ifp->if_opackets++;
1084			m_freem(r->bfe_mbuf);
1085			r->bfe_mbuf = NULL;
1086			bus_dmamap_unload(sc->bfe_tag, r->bfe_map);
1087		}
1088        sc->bfe_tx_cnt--;
1089        BFE_INC(i, BFE_TX_LIST_CNT);
1090	}
1091
1092	if(i != sc->bfe_tx_cons) {
1093		/* we freed up some mbufs */
1094		sc->bfe_tx_cons = i;
1095		ifp->if_flags &= ~IFF_OACTIVE;
1096	}
1097	if(sc->bfe_tx_cnt == 0)
1098		ifp->if_timer = 0;
1099	else
1100		ifp->if_timer = 5;
1101
1102	BFE_UNLOCK(sc);
1103}
1104
1105/* Pass a received packet up the stack */
1106static void
1107bfe_rxeof(struct bfe_softc *sc)
1108{
1109	struct mbuf *m;
1110	struct ifnet *ifp;
1111	struct bfe_rxheader *rxheader;
1112	struct bfe_data *r;
1113	int cons;
1114	u_int32_t status, current, len, flags;
1115
1116	BFE_LOCK(sc);
1117	cons = sc->bfe_rx_cons;
1118	status = CSR_READ_4(sc, BFE_DMARX_STAT);
1119	current = (status & BFE_STAT_CDMASK) / sizeof(struct bfe_desc);
1120
1121	ifp = &sc->arpcom.ac_if;
1122
1123	while(current != cons) {
1124		r = &sc->bfe_rx_ring[cons];
1125		m = r->bfe_mbuf;
1126		rxheader = mtod(m, struct bfe_rxheader*);
1127		bus_dmamap_sync(sc->bfe_tag, r->bfe_map, BUS_DMASYNC_POSTWRITE);
1128		len = rxheader->len;
1129		r->bfe_mbuf = NULL;
1130
1131		bus_dmamap_unload(sc->bfe_tag, r->bfe_map);
1132		flags = rxheader->flags;
1133
1134		len -= ETHER_CRC_LEN;
1135
1136		/* flag an error and try again */
1137		if ((len > ETHER_MAX_LEN+32) || (flags & BFE_RX_FLAG_ERRORS)) {
1138			ifp->if_ierrors++;
1139			if (flags & BFE_RX_FLAG_SERR)
1140				ifp->if_collisions++;
1141			bfe_list_newbuf(sc, cons, m);
1142			continue;
1143		}
1144
1145		/* Go past the rx header */
1146		if (bfe_list_newbuf(sc, cons, NULL) == 0) {
1147			m_adj(m, BFE_RX_OFFSET);
1148			m->m_len = m->m_pkthdr.len = len;
1149		} else {
1150			bfe_list_newbuf(sc, cons, m);
1151			ifp->if_ierrors++;
1152			continue;
1153		}
1154
1155		ifp->if_ipackets++;
1156		m->m_pkthdr.rcvif = ifp;
1157		(*ifp->if_input)(ifp, m);
1158
1159        BFE_INC(cons, BFE_RX_LIST_CNT);
1160	}
1161	sc->bfe_rx_cons = cons;
1162	BFE_UNLOCK(sc);
1163}
1164
1165static void
1166bfe_intr(void *xsc)
1167{
1168	struct bfe_softc *sc = xsc;
1169	struct ifnet *ifp;
1170	u_int32_t istat, imask, flag;
1171
1172	ifp = &sc->arpcom.ac_if;
1173
1174	BFE_LOCK(sc);
1175
1176	istat = CSR_READ_4(sc, BFE_ISTAT);
1177	imask = CSR_READ_4(sc, BFE_IMASK);
1178
1179	/*
1180	 * Defer unsolicited interrupts - This is necessary because setting the
1181	 * chips interrupt mask register to 0 doesn't actually stop the
1182	 * interrupts
1183	 */
1184	istat &= imask;
1185	CSR_WRITE_4(sc, BFE_ISTAT, istat);
1186	CSR_READ_4(sc, BFE_ISTAT);
1187
1188	/* not expecting this interrupt, disregard it */
1189	if(istat == 0) {
1190		BFE_UNLOCK(sc);
1191		return;
1192	}
1193
1194	if(istat & BFE_ISTAT_ERRORS) {
1195		flag = CSR_READ_4(sc, BFE_DMATX_STAT);
1196		if(flag & BFE_STAT_EMASK)
1197			ifp->if_oerrors++;
1198
1199		flag = CSR_READ_4(sc, BFE_DMARX_STAT);
1200		if(flag & BFE_RX_FLAG_ERRORS)
1201			ifp->if_ierrors++;
1202
1203		ifp->if_flags &= ~IFF_RUNNING;
1204		bfe_init(sc);
1205	}
1206
1207	/* A packet was received */
1208	if(istat & BFE_ISTAT_RX)
1209		bfe_rxeof(sc);
1210
1211	/* A packet was sent */
1212	if(istat & BFE_ISTAT_TX)
1213		bfe_txeof(sc);
1214
1215	/* We have packets pending, fire them out */
1216	if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
1217		bfe_start(ifp);
1218
1219	BFE_UNLOCK(sc);
1220}
1221
1222static int
1223bfe_encap(struct bfe_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
1224{
1225	struct bfe_desc *d = NULL;
1226	struct bfe_data *r = NULL;
1227	struct mbuf     *m;
1228	u_int32_t       frag, cur, cnt = 0;
1229	int chainlen = 0;
1230
1231	if(BFE_TX_LIST_CNT - sc->bfe_tx_cnt < 2)
1232		return(ENOBUFS);
1233
1234	/*
1235	 * Count the number of frags in this chain to see if
1236	 * we need to m_defrag.  Since the descriptor list is shared
1237	 * by all packets, we'll m_defrag long chains so that they
1238	 * do not use up the entire list, even if they would fit.
1239	 */
1240	for(m = m_head; m != NULL; m = m->m_next)
1241		chainlen++;
1242
1243
1244	if ((chainlen > BFE_TX_LIST_CNT / 4) ||
1245			((BFE_TX_LIST_CNT - (chainlen + sc->bfe_tx_cnt)) < 2)) {
1246		m = m_defrag(m_head, M_DONTWAIT);
1247		if (m == NULL)
1248			return(ENOBUFS);
1249		m_head = m;
1250	}
1251
1252	/*
1253	 * Start packing the mbufs in this chain into
1254	 * the fragment pointers. Stop when we run out
1255	 * of fragments or hit the end of the mbuf chain.
1256	 */
1257	m = m_head;
1258	cur = frag = *txidx;
1259	cnt = 0;
1260
1261	for(m = m_head; m != NULL; m = m->m_next) {
1262		if(m->m_len != 0) {
1263			if((BFE_TX_LIST_CNT - (sc->bfe_tx_cnt + cnt)) < 2)
1264				return(ENOBUFS);
1265
1266			d = &sc->bfe_tx_list[cur];
1267			r = &sc->bfe_tx_ring[cur];
1268			d->bfe_ctrl = BFE_DESC_LEN & m->m_len;
1269			/* always intterupt on completion */
1270			d->bfe_ctrl |= BFE_DESC_IOC;
1271			if(cnt == 0)
1272				/* Set start of frame */
1273				d->bfe_ctrl |= BFE_DESC_SOF;
1274			if(cur == BFE_TX_LIST_CNT - 1)
1275				/* Tell the chip to wrap to the start of the descriptor list */
1276				d->bfe_ctrl |= BFE_DESC_EOT;
1277
1278			bus_dmamap_load(sc->bfe_tag, r->bfe_map, mtod(m, void*), m->m_len,
1279					bfe_dma_map_desc, d, 0);
1280			bus_dmamap_sync(sc->bfe_tag, r->bfe_map, BUS_DMASYNC_PREREAD);
1281
1282			frag = cur;
1283            BFE_INC(cur, BFE_TX_LIST_CNT);
1284			cnt++;
1285		}
1286	}
1287
1288	if (m != NULL)
1289		return(ENOBUFS);
1290
1291	sc->bfe_tx_list[frag].bfe_ctrl |= BFE_DESC_EOF;
1292	sc->bfe_tx_ring[frag].bfe_mbuf = m_head;
1293	bus_dmamap_sync(sc->bfe_tx_tag, sc->bfe_tx_map, BUS_DMASYNC_PREREAD);
1294
1295	*txidx = cur;
1296	sc->bfe_tx_cnt += cnt;
1297	return (0);
1298}
1299
1300/*
1301 * Set up to transmit a packet
1302 */
1303static void
1304bfe_start(struct ifnet *ifp)
1305{
1306	struct bfe_softc *sc;
1307	struct mbuf *m_head = NULL;
1308	int idx;
1309
1310	sc = ifp->if_softc;
1311	idx = sc->bfe_tx_prod;
1312
1313	BFE_LOCK(sc);
1314
1315	/*
1316	 * not much point trying to send if the link is down or we have nothing to
1317	 * send
1318	 */
1319	if (!sc->bfe_link && ifp->if_snd.ifq_len < 10) {
1320		BFE_UNLOCK(sc);
1321		return;
1322	}
1323
1324	if (ifp->if_flags & IFF_OACTIVE) {
1325		BFE_UNLOCK(sc);
1326		return;
1327	}
1328
1329	while(sc->bfe_tx_ring[idx].bfe_mbuf == NULL) {
1330		IF_DEQUEUE(&ifp->if_snd, m_head);
1331		if(m_head == NULL)
1332			break;
1333
1334		/*
1335		 * Pack the data into the tx ring.  If we dont have enough room, let
1336		 * the chip drain the ring
1337		 */
1338		if(bfe_encap(sc, m_head, &idx)) {
1339			IF_PREPEND(&ifp->if_snd, m_head);
1340			ifp->if_flags |= IFF_OACTIVE;
1341			break;
1342		}
1343
1344		/*
1345		 * If there's a BPF listener, bounce a copy of this frame
1346		 * to him.
1347		 */
1348		BPF_MTAP(ifp, m_head);
1349	}
1350
1351	sc->bfe_tx_prod = idx;
1352	/* Transmit - twice due to apparent hardware bug */
1353	CSR_WRITE_4(sc, BFE_DMATX_PTR, idx * sizeof(struct bfe_desc));
1354	CSR_WRITE_4(sc, BFE_DMATX_PTR, idx * sizeof(struct bfe_desc));
1355
1356	/*
1357	 * Set a timeout in case the chip goes out to lunch.
1358	 */
1359	ifp->if_timer = 5;
1360	BFE_UNLOCK(sc);
1361}
1362
1363static void
1364bfe_init(void *xsc)
1365{
1366	struct bfe_softc *sc = (struct bfe_softc*)xsc;
1367	struct ifnet *ifp = &sc->arpcom.ac_if;
1368
1369	BFE_LOCK(sc);
1370
1371	if (ifp->if_flags & IFF_RUNNING) {
1372		BFE_UNLOCK(sc);
1373		return;
1374	}
1375
1376	bfe_stop(sc);
1377	bfe_chip_reset(sc);
1378
1379	if (bfe_list_rx_init(sc) == ENOBUFS) {
1380		printf("bfe%d: bfe_init failed. Not enough memory for list buffers\n",
1381				sc->bfe_unit);
1382		bfe_stop(sc);
1383		return;
1384	}
1385
1386	bfe_set_rx_mode(sc);
1387
1388	/* Enable the chip and core */
1389	BFE_OR(sc, BFE_ENET_CTRL, BFE_ENET_ENABLE);
1390	/* Enable interrupts */
1391	CSR_WRITE_4(sc, BFE_IMASK, BFE_IMASK_DEF);
1392
1393	bfe_ifmedia_upd(ifp);
1394	ifp->if_flags |= IFF_RUNNING;
1395	ifp->if_flags &= ~IFF_OACTIVE;
1396
1397	sc->bfe_stat_ch = timeout(bfe_tick, sc, hz);
1398	BFE_UNLOCK(sc);
1399}
1400
1401/*
1402 * Set media options.
1403 */
1404static int
1405bfe_ifmedia_upd(struct ifnet *ifp)
1406{
1407	struct bfe_softc *sc;
1408	struct mii_data *mii;
1409
1410	sc = ifp->if_softc;
1411
1412	BFE_LOCK(sc);
1413
1414	mii = device_get_softc(sc->bfe_miibus);
1415	sc->bfe_link = 0;
1416	if (mii->mii_instance) {
1417		struct mii_softc *miisc;
1418		for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
1419				miisc = LIST_NEXT(miisc, mii_list))
1420			mii_phy_reset(miisc);
1421	}
1422	mii_mediachg(mii);
1423
1424	BFE_UNLOCK(sc);
1425	return(0);
1426}
1427
1428/*
1429 * Report current media status.
1430 */
1431static void
1432bfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1433{
1434	struct bfe_softc *sc = ifp->if_softc;
1435	struct mii_data *mii;
1436
1437	BFE_LOCK(sc);
1438
1439	mii = device_get_softc(sc->bfe_miibus);
1440	mii_pollstat(mii);
1441	ifmr->ifm_active = mii->mii_media_active;
1442	ifmr->ifm_status = mii->mii_media_status;
1443
1444	BFE_UNLOCK(sc);
1445}
1446
1447static int
1448bfe_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1449{
1450	struct bfe_softc *sc = ifp->if_softc;
1451	struct ifreq *ifr = (struct ifreq *) data;
1452	struct mii_data *mii;
1453	int error = 0;
1454
1455	BFE_LOCK(sc);
1456
1457	switch(command) {
1458		case SIOCSIFFLAGS:
1459			if(ifp->if_flags & IFF_UP)
1460				if(ifp->if_flags & IFF_RUNNING)
1461					bfe_set_rx_mode(sc);
1462				else
1463					bfe_init(sc);
1464			else if(ifp->if_flags & IFF_RUNNING)
1465				bfe_stop(sc);
1466			break;
1467		case SIOCADDMULTI:
1468		case SIOCDELMULTI:
1469			if(ifp->if_flags & IFF_RUNNING)
1470				bfe_set_rx_mode(sc);
1471			break;
1472		case SIOCGIFMEDIA:
1473		case SIOCSIFMEDIA:
1474			mii = device_get_softc(sc->bfe_miibus);
1475			error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
1476			break;
1477		default:
1478			error = ether_ioctl(ifp, command, data);
1479			break;
1480	}
1481
1482	BFE_UNLOCK(sc);
1483	return error;
1484}
1485
1486static void
1487bfe_watchdog(struct ifnet *ifp)
1488{
1489	struct bfe_softc *sc;
1490
1491	sc = ifp->if_softc;
1492
1493	BFE_LOCK(sc);
1494
1495	printf("bfe%d: watchdog timeout -- resetting\n", sc->bfe_unit);
1496
1497	ifp->if_flags &= ~IFF_RUNNING;
1498	bfe_init(sc);
1499
1500	ifp->if_oerrors++;
1501
1502	BFE_UNLOCK(sc);
1503}
1504
1505static void
1506bfe_tick(void *xsc)
1507{
1508	struct bfe_softc *sc = xsc;
1509	struct mii_data *mii;
1510
1511	if (sc == NULL)
1512		return;
1513
1514	BFE_LOCK(sc);
1515
1516	mii = device_get_softc(sc->bfe_miibus);
1517
1518	bfe_stats_update(sc);
1519	sc->bfe_stat_ch = timeout(bfe_tick, sc, hz);
1520
1521	if(sc->bfe_link) {
1522		BFE_UNLOCK(sc);
1523		return;
1524	}
1525
1526	mii_tick(mii);
1527	if (!sc->bfe_link && mii->mii_media_status & IFM_ACTIVE &&
1528			IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
1529		sc->bfe_link++;
1530
1531	BFE_UNLOCK(sc);
1532}
1533
1534/*
1535 * Stop the adapter and free any mbufs allocated to the
1536 * RX and TX lists.
1537 */
1538static void
1539bfe_stop(struct bfe_softc *sc)
1540{
1541	struct ifnet *ifp;
1542
1543	BFE_LOCK(sc);
1544
1545	untimeout(bfe_tick, sc, sc->bfe_stat_ch);
1546
1547	ifp = &sc->arpcom.ac_if;
1548
1549	bfe_chip_halt(sc);
1550    bfe_tx_ring_free(sc);
1551	bfe_rx_ring_free(sc);
1552
1553	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1554
1555	BFE_UNLOCK(sc);
1556}
1557