1155324Simp/*-
2155324Simp * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
3213496Scognet * Copyright (c) 2009 Greg Ansley.  All rights reserved.
4155324Simp *
5155324Simp * Redistribution and use in source and binary forms, with or without
6155324Simp * modification, are permitted provided that the following conditions
7155324Simp * are met:
8155324Simp * 1. Redistributions of source code must retain the above copyright
9155324Simp *    notice, this list of conditions and the following disclaimer.
10155324Simp * 2. Redistributions in binary form must reproduce the above copyright
11155324Simp *    notice, this list of conditions and the following disclaimer in the
12155324Simp *    documentation and/or other materials provided with the distribution.
13155324Simp *
14185267Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15185267Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16185267Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17185267Simp * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18185267Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19185267Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20185267Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21185267Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22185267Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23185267Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24185267Simp * SUCH DAMAGE.
25155324Simp */
26155324Simp
27192018Sstas/* TODO
28155324Simp *
29192018Sstas * 1) Turn on the clock in pmc?  Turn off?
30192018Sstas * 2) GPIO initializtion in board setup code.
31155324Simp */
32155324Simp
33266196Sian#include "opt_platform.h"
34266196Sian
35155324Simp#include <sys/cdefs.h>
36155324Simp__FBSDID("$FreeBSD$");
37155324Simp
38155324Simp#include <sys/param.h>
39155324Simp#include <sys/systm.h>
40155324Simp#include <sys/bus.h>
41155324Simp#include <sys/kernel.h>
42213496Scognet#include <sys/malloc.h>
43155324Simp#include <sys/mbuf.h>
44155324Simp#include <sys/module.h>
45155324Simp#include <sys/rman.h>
46155324Simp#include <sys/socket.h>
47155324Simp#include <sys/sockio.h>
48163522Simp#include <sys/sysctl.h>
49213496Scognet
50155324Simp#include <machine/bus.h>
51155324Simp
52155324Simp#include <net/ethernet.h>
53155324Simp#include <net/if.h>
54155324Simp#include <net/if_arp.h>
55155324Simp#include <net/if_dl.h>
56155324Simp#include <net/if_media.h>
57155324Simp#include <net/if_mib.h>
58155324Simp#include <net/if_types.h>
59259342Sian#include <net/if_var.h>
60155324Simp
61155324Simp#ifdef INET
62155324Simp#include <netinet/in.h>
63155324Simp#include <netinet/in_systm.h>
64155324Simp#include <netinet/in_var.h>
65155324Simp#include <netinet/ip.h>
66155324Simp#endif
67155324Simp
68155324Simp#include <net/bpf.h>
69155324Simp#include <net/bpfdesc.h>
70155324Simp
71155324Simp#include <dev/mii/mii.h>
72155324Simp#include <dev/mii/miivar.h>
73213496Scognet
74213496Scognet#include "opt_at91.h"
75213496Scognet#include <arm/at91/at91reg.h>
76213496Scognet#include <arm/at91/at91var.h>
77155324Simp#include <arm/at91/if_atereg.h>
78155324Simp
79266196Sian#ifdef FDT
80266196Sian#include <dev/fdt/fdt_common.h>
81266196Sian#include <dev/ofw/ofw_bus.h>
82266196Sian#include <dev/ofw/ofw_bus_subr.h>
83266196Sian#endif
84266196Sian
85155324Simp#include "miibus_if.h"
86155324Simp
87191959Sstas/*
88191959Sstas * Driver-specific flags.
89191959Sstas */
90213496Scognet#define	ATE_FLAG_DETACHING	0x01
91213496Scognet#define	ATE_FLAG_MULTICAST	0x02
92191959Sstas
93213496Scognet/*
94213496Scognet * Old EMAC assumes whole packet fits in one buffer;
95213496Scognet * new EBACB assumes all receive buffers are 128 bytes
96213496Scognet */
97213496Scognet#define	RX_BUF_SIZE(sc)	(sc->is_emacb ? 128 : MCLBYTES)
98213496Scognet
99213496Scognet/*
100213496Scognet * EMACB has an 11 bit counter for Rx/Tx Descriptors
101213496Scognet * for max total of 1024 decriptors each.
102213496Scognet */
103213496Scognet#define	ATE_MAX_RX_DESCR	1024
104213496Scognet#define	ATE_MAX_TX_DESCR	1024
105213496Scognet
106213496Scognet/* How many buffers to allocate */
107213496Scognet#define	ATE_MAX_TX_BUFFERS	4	/* We have ping-pong tx buffers */
108213496Scognet
109213496Scognet/* How much memory to use for rx buffers */
110213496Scognet#define	ATE_RX_MEMORY		(ATE_MAX_RX_DESCR * 128)
111213496Scognet
112213496Scognet/* Actual number of descriptors we allocate */
113213496Scognet#define	ATE_NUM_RX_DESCR	ATE_MAX_RX_DESCR
114213496Scognet#define	ATE_NUM_TX_DESCR	ATE_MAX_TX_BUFFERS
115213496Scognet
116213496Scognet#if ATE_NUM_TX_DESCR > ATE_MAX_TX_DESCR
117213496Scognet#error "Can't have more TX buffers that descriptors"
118213496Scognet#endif
119213496Scognet#if ATE_NUM_RX_DESCR > ATE_MAX_RX_DESCR
120213496Scognet#error "Can't have more RX buffers that descriptors"
121213496Scognet#endif
122213496Scognet
123213496Scognet/* Wrap indexes the same way the hardware does */
124213496Scognet#define	NEXT_RX_IDX(sc, cur)	\
125213496Scognet    ((sc->rx_descs[cur].addr & ETH_WRAP_BIT) ? 0 : (cur + 1))
126213496Scognet
127213496Scognet#define	NEXT_TX_IDX(sc, cur)	\
128213496Scognet    ((sc->tx_descs[cur].status & ETHB_TX_WRAP) ? 0 : (cur + 1))
129213496Scognet
130155324Simpstruct ate_softc
131155324Simp{
132234281Smarius	struct ifnet	*ifp;		/* ifnet pointer */
133234281Smarius	struct mtx	sc_mtx;		/* Basically a perimeter lock */
134234281Smarius	device_t	dev;		/* Myself */
135234281Smarius	device_t	miibus;		/* My child miibus */
136234281Smarius	struct resource *irq_res;	/* IRQ resource */
137234281Smarius	struct resource	*mem_res;	/* Memory resource */
138234281Smarius	struct callout  tick_ch;	/* Tick callout */
139192063Sstas	struct ifmib_iso_8802_3 mibdata; /* Stuff for network mgmt */
140234281Smarius	bus_dma_tag_t   mtag;		/* bus dma tag for mbufs */
141213496Scognet	bus_dma_tag_t   rx_tag;
142213496Scognet	bus_dma_tag_t   rx_desc_tag;
143213496Scognet	bus_dmamap_t    rx_desc_map;
144213496Scognet	bus_dmamap_t    rx_map[ATE_MAX_RX_DESCR];
145234281Smarius	bus_addr_t	rx_desc_phys;   /* PA of rx descriptors */
146234281Smarius	eth_rx_desc_t   *rx_descs;	/* VA of rx descriptors */
147234281Smarius	void		*rx_buf[ATE_NUM_RX_DESCR]; /* RX buffer space */
148234281Smarius	int		rxhead;		/* Current RX map/desc index */
149234281Smarius	uint32_t	rx_buf_size;    /* Size of Rx buffers */
150213496Scognet
151213496Scognet	bus_dma_tag_t   tx_desc_tag;
152213496Scognet	bus_dmamap_t    tx_desc_map;
153213496Scognet	bus_dmamap_t    tx_map[ATE_MAX_TX_BUFFERS];
154234281Smarius	bus_addr_t	tx_desc_phys;   /* PA of tx descriptors */
155234281Smarius	eth_tx_desc_t   *tx_descs;	/* VA of tx descriptors */
156234281Smarius	int		txhead;		/* Current TX map/desc index */
157234281Smarius	int		txtail;		/* Current TX map/desc index */
158234281Smarius	struct mbuf	*sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */
159234281Smarius	void		*intrhand;	/* Interrupt handle */
160234281Smarius	int		flags;
161234281Smarius	int		if_flags;
162234281Smarius	int		use_rmii;
163234281Smarius	int		is_emacb;	/* SAM9x hardware version */
164155324Simp};
165155324Simp
166155324Simpstatic inline uint32_t
167155324SimpRD4(struct ate_softc *sc, bus_size_t off)
168155324Simp{
169192063Sstas
170192063Sstas	return (bus_read_4(sc->mem_res, off));
171155324Simp}
172155324Simp
173155324Simpstatic inline void
174155324SimpWR4(struct ate_softc *sc, bus_size_t off, uint32_t val)
175155324Simp{
176192063Sstas
177155324Simp	bus_write_4(sc->mem_res, off, val);
178155324Simp}
179155324Simp
180192027Sstasstatic inline void
181192027SstasBARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags)
182192027Sstas{
183192027Sstas
184192027Sstas	bus_barrier(sc->mem_res, off, len, flags);
185192027Sstas}
186192027Sstas
187192063Sstas#define	ATE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
188155324Simp#define	ATE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
189192063Sstas#define	ATE_LOCK_INIT(_sc)					\
190192063Sstas	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev),	\
191155324Simp	    MTX_NETWORK_LOCK, MTX_DEF)
192192063Sstas#define	ATE_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
193192063Sstas#define	ATE_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED);
194192063Sstas#define	ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
195155324Simp
196155324Simpstatic devclass_t ate_devclass;
197155324Simp
198192063Sstas/*
199192063Sstas * ifnet entry points.
200192063Sstas */
201192063Sstasstatic void	ateinit_locked(void *);
202192063Sstasstatic void	atestart_locked(struct ifnet *);
203155324Simp
204192063Sstasstatic void	ateinit(void *);
205192063Sstasstatic void	atestart(struct ifnet *);
206192063Sstasstatic void	atestop(struct ate_softc *);
207192063Sstasstatic int	ateioctl(struct ifnet * ifp, u_long, caddr_t);
208155324Simp
209192063Sstas/*
210192063Sstas * Bus entry points.
211192063Sstas */
212192063Sstasstatic int	ate_probe(device_t dev);
213192063Sstasstatic int	ate_attach(device_t dev);
214192063Sstasstatic int	ate_detach(device_t dev);
215192063Sstasstatic void	ate_intr(void *);
216155324Simp
217192063Sstas/*
218192063Sstas * Helper routines.
219192063Sstas */
220192063Sstasstatic int	ate_activate(device_t dev);
221192063Sstasstatic void	ate_deactivate(struct ate_softc *sc);
222192063Sstasstatic int	ate_ifmedia_upd(struct ifnet *ifp);
223192063Sstasstatic void	ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
224192063Sstasstatic int	ate_get_mac(struct ate_softc *sc, u_char *eaddr);
225192063Sstasstatic void	ate_set_mac(struct ate_softc *sc, u_char *eaddr);
226191959Sstasstatic void	ate_rxfilter(struct ate_softc *sc);
227155324Simp
228213496Scognetstatic int	ate_miibus_readreg(device_t dev, int phy, int reg);
229213496Scognet
230213496Scognetstatic int	ate_miibus_writereg(device_t dev, int phy, int reg, int data);
231155324Simp/*
232213496Scognet * The AT91 family of products has the ethernet interface called EMAC.
233213496Scognet * However, it isn't self identifying.  It is anticipated that the parent bus
234155324Simp * code will take care to only add ate devices where they really are.  As
235155324Simp * such, we do nothing here to identify the device and just set its name.
236155324Simp */
237155324Simpstatic int
238155324Simpate_probe(device_t dev)
239155324Simp{
240266196Sian#ifdef FDT
241266196Sian	if (!ofw_bus_is_compatible(dev, "cdns,at32ap7000-macb"))
242266196Sian		return (ENXIO);
243266196Sian#endif
244155324Simp	device_set_desc(dev, "EMAC");
245155324Simp	return (0);
246155324Simp}
247155324Simp
248155324Simpstatic int
249155324Simpate_attach(device_t dev)
250155324Simp{
251192063Sstas	struct ate_softc *sc;
252155324Simp	struct ifnet *ifp = NULL;
253163522Simp	struct sysctl_ctx_list *sctx;
254163522Simp	struct sysctl_oid *soid;
255182477Sstas	u_char eaddr[ETHER_ADDR_LEN];
256182477Sstas	uint32_t rnd;
257192018Sstas	int rid, err;
258155324Simp
259192063Sstas	sc = device_get_softc(dev);
260155324Simp	sc->dev = dev;
261192018Sstas	ATE_LOCK_INIT(sc);
262234281Smarius
263192018Sstas	rid = 0;
264192018Sstas	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
265192018Sstas	    RF_ACTIVE);
266192018Sstas	if (sc->mem_res == NULL) {
267192018Sstas		device_printf(dev, "could not allocate memory resources.\n");
268192018Sstas		err = ENOMEM;
269192018Sstas		goto out;
270192018Sstas	}
271192018Sstas	rid = 0;
272192018Sstas	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
273192018Sstas	    RF_ACTIVE);
274192018Sstas	if (sc->irq_res == NULL) {
275192018Sstas		device_printf(dev, "could not allocate interrupt resources.\n");
276192018Sstas		err = ENOMEM;
277192018Sstas		goto out;
278192018Sstas	}
279192018Sstas
280213496Scognet	/* New or old version, chooses buffer size. */
281234291Smarius	sc->is_emacb = at91_is_sam9() || at91_is_sam9xe();
282213496Scognet	sc->rx_buf_size = RX_BUF_SIZE(sc);
283213496Scognet
284155324Simp	err = ate_activate(dev);
285155324Simp	if (err)
286155324Simp		goto out;
287155324Simp
288213496Scognet	/* Default to what boot rom did */
289213496Scognet	if (!sc->is_emacb)
290213496Scognet		sc->use_rmii =
291213496Scognet		    (RD4(sc, ETH_CFG) & ETH_CFG_RMII) == ETH_CFG_RMII;
292213496Scognet	else
293213496Scognet		sc->use_rmii =
294213496Scognet		    (RD4(sc, ETHB_UIO) & ETHB_UIO_RMII) == ETHB_UIO_RMII;
295159708Simp
296213496Scognet#ifdef AT91_ATE_USE_RMII
297213496Scognet	/* Compile time override */
298213496Scognet	sc->use_rmii = 1;
299213496Scognet#endif
300182476Sstas	/* Sysctls */
301163522Simp	sctx = device_get_sysctl_ctx(dev);
302163522Simp	soid = device_get_sysctl_tree(dev);
303163522Simp	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "rmii",
304213496Scognet	    CTLFLAG_RW, &sc->use_rmii, 0, "rmii in use");
305163522Simp
306192063Sstas	/* Calling atestop before ifp is set is OK. */
307192018Sstas	ATE_LOCK(sc);
308155324Simp	atestop(sc);
309192018Sstas	ATE_UNLOCK(sc);
310213496Scognet	callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
311155324Simp
312166573Simp	if ((err = ate_get_mac(sc, eaddr)) != 0) {
313213496Scognet		/* No MAC address configured. Generate the random one. */
314213496Scognet		if (bootverbose)
315182477Sstas			device_printf(dev,
316182524Sstas			    "Generating random ethernet address.\n");
317182477Sstas		rnd = arc4random();
318182477Sstas
319182477Sstas		/*
320182555Simp		 * Set OUI to convenient locally assigned address.  'b'
321182555Simp		 * is 0x62, which has the locally assigned bit set, and
322182555Simp		 * the broadcast/multicast bit clear.
323182477Sstas		 */
324182555Simp		eaddr[0] = 'b';
325182555Simp		eaddr[1] = 's';
326182555Simp		eaddr[2] = 'd';
327182477Sstas		eaddr[3] = (rnd >> 16) & 0xff;
328213496Scognet		eaddr[4] = (rnd >>  8) & 0xff;
329213496Scognet		eaddr[5] = (rnd >>  0) & 0xff;
330166573Simp	}
331155324Simp
332155405Scognet	sc->ifp = ifp = if_alloc(IFT_ETHER);
333213894Smarius	err = mii_attach(dev, &sc->miibus, ifp, ate_ifmedia_upd,
334213894Smarius	    ate_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
335213894Smarius	if (err != 0) {
336213894Smarius		device_printf(dev, "attaching PHYs failed\n");
337155324Simp		goto out;
338155324Simp	}
339213496Scognet	/*
340234281Smarius	 * XXX: Clear the isolate bit, or we won't get up,
341234281Smarius	 * at least on the HL201
342213496Scognet	 */
343213496Scognet	ate_miibus_writereg(dev, 0, 0, 0x3000);
344155324Simp
345155324Simp	ifp->if_softc = sc;
346155324Simp	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
347155324Simp	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
348165779Sticso	ifp->if_capabilities |= IFCAP_VLAN_MTU;
349192063Sstas	ifp->if_capenable |= IFCAP_VLAN_MTU;	/* The hw bits already set. */
350155324Simp	ifp->if_start = atestart;
351155324Simp	ifp->if_ioctl = ateioctl;
352155324Simp	ifp->if_init = ateinit;
353155324Simp	ifp->if_baudrate = 10000000;
354213496Scognet	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
355213496Scognet	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
356155324Simp	IFQ_SET_READY(&ifp->if_snd);
357155324Simp	ifp->if_linkmib = &sc->mibdata;
358155324Simp	ifp->if_linkmiblen = sizeof(sc->mibdata);
359155324Simp	sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS;
360191959Sstas	sc->if_flags = ifp->if_flags;
361155324Simp
362155324Simp	ether_ifattach(ifp, eaddr);
363155324Simp
364213496Scognet	/* Activate the interrupt. */
365155324Simp	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
366166901Spiso	    NULL, ate_intr, sc, &sc->intrhand);
367155324Simp	if (err) {
368192018Sstas		device_printf(dev, "could not establish interrupt handler.\n");
369155324Simp		ether_ifdetach(ifp);
370192018Sstas		goto out;
371155324Simp	}
372192018Sstas
373192018Sstasout:
374155324Simp	if (err)
375192018Sstas		ate_detach(dev);
376155324Simp	return (err);
377155324Simp}
378155324Simp
379155324Simpstatic int
380155324Simpate_detach(device_t dev)
381155324Simp{
382192018Sstas	struct ate_softc *sc;
383192018Sstas	struct ifnet *ifp;
384192018Sstas
385192018Sstas	sc = device_get_softc(dev);
386192018Sstas	KASSERT(sc != NULL, ("[ate: %d]: sc is NULL", __LINE__));
387192018Sstas	ifp = sc->ifp;
388192018Sstas	if (device_is_attached(dev)) {
389192018Sstas		ATE_LOCK(sc);
390213496Scognet			sc->flags |= ATE_FLAG_DETACHING;
391213496Scognet			atestop(sc);
392192018Sstas		ATE_UNLOCK(sc);
393192018Sstas		callout_drain(&sc->tick_ch);
394213496Scognet		ether_ifdetach(ifp);
395192018Sstas	}
396192018Sstas	if (sc->miibus != NULL) {
397192018Sstas		device_delete_child(dev, sc->miibus);
398192018Sstas		sc->miibus = NULL;
399192018Sstas	}
400192018Sstas	bus_generic_detach(sc->dev);
401192018Sstas	ate_deactivate(sc);
402192018Sstas	if (sc->intrhand != NULL) {
403192018Sstas		bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
404192018Sstas		sc->intrhand = NULL;
405192018Sstas	}
406192018Sstas	if (ifp != NULL) {
407192018Sstas		if_free(ifp);
408192018Sstas		sc->ifp = NULL;
409192018Sstas	}
410192018Sstas	if (sc->mem_res != NULL) {
411192018Sstas		bus_release_resource(dev, SYS_RES_IOPORT,
412192018Sstas		    rman_get_rid(sc->mem_res), sc->mem_res);
413192018Sstas		sc->mem_res = NULL;
414192018Sstas	}
415192018Sstas	if (sc->irq_res != NULL) {
416192018Sstas		bus_release_resource(dev, SYS_RES_IRQ,
417192018Sstas		    rman_get_rid(sc->irq_res), sc->irq_res);
418192018Sstas		sc->irq_res = NULL;
419192018Sstas	}
420192018Sstas	ATE_LOCK_DESTROY(sc);
421192018Sstas	return (0);
422155324Simp}
423155324Simp
424155324Simpstatic void
425155324Simpate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
426155324Simp{
427155324Simp
428155324Simp	if (error != 0)
429155324Simp		return;
430213496Scognet	*(bus_addr_t *)arg = segs[0].ds_addr;
431155324Simp}
432155324Simp
433157562Simpstatic void
434157562Simpate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
435157562Simp{
436157562Simp	struct ate_softc *sc;
437157562Simp
438157562Simp	if (error != 0)
439157562Simp		return;
440157562Simp	sc = (struct ate_softc *)arg;
441157562Simp
442163937Simp	bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
443213496Scognet	sc->rx_descs[sc->rxhead].addr = segs[0].ds_addr;
444213496Scognet	sc->rx_descs[sc->rxhead].status = 0;
445163937Simp	bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_POSTWRITE);
446157562Simp}
447157562Simp
448218387Sticsostatic uint32_t
449218387Sticsoate_mac_hash(const uint8_t *buf)
450218387Sticso{
451218387Sticso	uint32_t index = 0;
452218387Sticso	for (int i = 0; i < 48; i++) {
453218387Sticso		index ^= ((buf[i >> 3] >> (i & 7)) & 1) << (i % 6);
454218387Sticso	}
455218387Sticso	return (index);
456218387Sticso}
457218387Sticso
458155324Simp/*
459213251Sticso * Compute the multicast filter for this device.
460155324Simp */
461191960Sstasstatic int
462155324Simpate_setmcast(struct ate_softc *sc)
463155324Simp{
464155324Simp	uint32_t index;
465155324Simp	uint32_t mcaf[2];
466155324Simp	u_char *af = (u_char *) mcaf;
467155324Simp	struct ifmultiaddr *ifma;
468191960Sstas	struct ifnet *ifp;
469155324Simp
470191960Sstas	ifp = sc->ifp;
471191960Sstas
472191960Sstas	if ((ifp->if_flags & IFF_PROMISC) != 0)
473191960Sstas		return (0);
474191960Sstas	if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
475191960Sstas		WR4(sc, ETH_HSL, 0xffffffff);
476191960Sstas		WR4(sc, ETH_HSH, 0xffffffff);
477191960Sstas		return (1);
478191960Sstas	}
479191960Sstas
480213496Scognet	/* Compute the multicast hash. */
481155324Simp	mcaf[0] = 0;
482155324Simp	mcaf[1] = 0;
483195049Srwatson	if_maddr_rlock(ifp);
484191960Sstas	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
485155324Simp		if (ifma->ifma_addr->sa_family != AF_LINK)
486155324Simp			continue;
487218387Sticso		index = ate_mac_hash(LLADDR((struct sockaddr_dl *)
488218387Sticso		    ifma->ifma_addr));
489155324Simp		af[index >> 3] |= 1 << (index & 7);
490155324Simp	}
491195049Srwatson	if_maddr_runlock(ifp);
492155324Simp
493155324Simp	/*
494155324Simp	 * Write the hash to the hash register.  This card can also
495155324Simp	 * accept unicast packets as well as multicast packets using this
496155324Simp	 * register for easier bridging operations, but we don't take
497155324Simp	 * advantage of that.  Locks here are to avoid LOR with the
498195049Srwatson	 * if_maddr_rlock, but might not be strictly necessary.
499155324Simp	 */
500155324Simp	WR4(sc, ETH_HSL, mcaf[0]);
501155324Simp	WR4(sc, ETH_HSH, mcaf[1]);
502191960Sstas	return (mcaf[0] || mcaf[1]);
503155324Simp}
504155324Simp
505155324Simpstatic int
506155324Simpate_activate(device_t dev)
507155324Simp{
508155324Simp	struct ate_softc *sc;
509213496Scognet	int i;
510155324Simp
511155324Simp	sc = device_get_softc(dev);
512192063Sstas
513213496Scognet	/* Allocate DMA tags and maps for TX mbufs */
514213496Scognet	if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
515183670Simp	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
516213496Scognet	    1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->mtag))
517155324Simp		goto errout;
518155324Simp	for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
519213496Scognet		if ( bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i]))
520155324Simp			goto errout;
521155324Simp	}
522192063Sstas
523155324Simp
524213496Scognet	/* DMA tag and map for the RX descriptors. */
525213496Scognet	if (bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_rx_desc_t),
526183670Simp	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
527213496Scognet	    ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 1,
528213496Scognet	    ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t), 0, busdma_lock_mutex,
529213496Scognet	    &sc->sc_mtx, &sc->rx_desc_tag))
530155324Simp		goto errout;
531156831Simp	if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs,
532156831Simp	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rx_desc_map) != 0)
533155324Simp		goto errout;
534157562Simp	if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map,
535213496Scognet	    sc->rx_descs, ATE_NUM_RX_DESCR * sizeof(eth_rx_desc_t),
536213496Scognet	    ate_getaddr, &sc->rx_desc_phys, 0) != 0)
537155324Simp		goto errout;
538192063Sstas
539213496Scognet	/* Allocate DMA tags and maps for RX. buffers */
540213496Scognet	if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
541213496Scognet	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
542213496Scognet	    sc->rx_buf_size, 1, sc->rx_buf_size, 0,
543213496Scognet	    busdma_lock_mutex, &sc->sc_mtx, &sc->rx_tag))
544213496Scognet		goto errout;
545213496Scognet
546192063Sstas	/*
547213496Scognet	 * Allocate our RX buffers.
548213496Scognet	 * This chip has a RX structure that's filled in.
549213496Scognet	 * XXX On MACB (SAM9 part) we should receive directly into mbuf
550213496Scognet	 * to avoid the copy.  XXX
551192063Sstas	 */
552213496Scognet	sc->rxhead = 0;
553213496Scognet	for (sc->rxhead = 0; sc->rxhead < ATE_RX_MEMORY/sc->rx_buf_size;
554213496Scognet	    sc->rxhead++) {
555213496Scognet		if (bus_dmamem_alloc(sc->rx_tag,
556213496Scognet		    (void **)&sc->rx_buf[sc->rxhead], BUS_DMA_NOWAIT,
557213496Scognet		    &sc->rx_map[sc->rxhead]) != 0)
558155324Simp			goto errout;
559213496Scognet
560213496Scognet		if (bus_dmamap_load(sc->rx_tag, sc->rx_map[sc->rxhead],
561213496Scognet		    sc->rx_buf[sc->rxhead], sc->rx_buf_size,
562213496Scognet		    ate_load_rx_buf, sc, 0) != 0) {
563213496Scognet			printf("bus_dmamem_load\n");
564157562Simp			goto errout;
565213496Scognet		}
566213496Scognet		bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead], BUS_DMASYNC_PREREAD);
567155324Simp	}
568213496Scognet
569213496Scognet	/*
570213496Scognet	 * For the last buffer, set the wrap bit so the controller
571213496Scognet	 * restarts from the first descriptor.
572213496Scognet	 */
573213496Scognet	sc->rx_descs[--sc->rxhead].addr |= ETH_WRAP_BIT;
574213496Scognet	sc->rxhead = 0;
575213496Scognet
576192063Sstas	/* Flush the memory for the EMAC rx descriptor. */
577155324Simp	bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
578213496Scognet
579155324Simp	/* Write the descriptor queue address. */
580155324Simp	WR4(sc, ETH_RBQP, sc->rx_desc_phys);
581213496Scognet
582213496Scognet	/*
583213496Scognet	 * DMA tag and map for the TX descriptors.
584213496Scognet	 */
585213496Scognet	if (bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_tx_desc_t),
586213496Scognet	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
587213496Scognet	    ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 1,
588213496Scognet	    ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t), 0, busdma_lock_mutex,
589213496Scognet	    &sc->sc_mtx, &sc->tx_desc_tag) != 0)
590213496Scognet		goto errout;
591213496Scognet
592213496Scognet	if (bus_dmamem_alloc(sc->tx_desc_tag, (void **)&sc->tx_descs,
593213496Scognet	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->tx_desc_map) != 0)
594213496Scognet		goto errout;
595213496Scognet
596213496Scognet	if (bus_dmamap_load(sc->tx_desc_tag, sc->tx_desc_map,
597213496Scognet	    sc->tx_descs, ATE_MAX_TX_BUFFERS * sizeof(eth_tx_desc_t),
598213496Scognet	    ate_getaddr, &sc->tx_desc_phys, 0) != 0)
599213496Scognet		goto errout;
600213496Scognet
601213496Scognet	/* Initilize descriptors; mark all empty */
602213496Scognet	for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
603213496Scognet		sc->tx_descs[i].addr =0;
604213496Scognet		sc->tx_descs[i].status = ETHB_TX_USED;
605213496Scognet		sc->sent_mbuf[i] = NULL;
606213496Scognet	}
607213496Scognet
608213496Scognet	/* Mark last entry to cause wrap when indexing through */
609213496Scognet	sc->tx_descs[ATE_MAX_TX_BUFFERS - 1].status =
610213496Scognet	    ETHB_TX_WRAP | ETHB_TX_USED;
611213496Scognet
612213496Scognet	/* Flush the memory for the EMAC tx descriptor. */
613213496Scognet	bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE);
614213496Scognet
615213496Scognet	sc->txhead = sc->txtail = 0;
616213496Scognet	if (sc->is_emacb) {
617213496Scognet		/* Write the descriptor queue address. */
618213496Scognet		WR4(sc, ETHB_TBQP, sc->tx_desc_phys);
619213496Scognet
620238895Simp		/* EMACB: Enable transceiver input clock */
621213496Scognet		WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) | ETHB_UIO_CLKE);
622238895Simp	}
623213496Scognet
624155324Simp	return (0);
625192018Sstas
626155324Simperrout:
627155324Simp	return (ENOMEM);
628155324Simp}
629155324Simp
630155324Simpstatic void
631192018Sstasate_deactivate(struct ate_softc *sc)
632155324Simp{
633192018Sstas	int i;
634155324Simp
635192018Sstas	KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
636192018Sstas	if (sc->mtag != NULL) {
637192018Sstas		for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
638192018Sstas			if (sc->sent_mbuf[i] != NULL) {
639192018Sstas				bus_dmamap_sync(sc->mtag, sc->tx_map[i],
640192018Sstas				    BUS_DMASYNC_POSTWRITE);
641192018Sstas				bus_dmamap_unload(sc->mtag, sc->tx_map[i]);
642192018Sstas				m_freem(sc->sent_mbuf[i]);
643155324Simp			}
644192018Sstas			bus_dmamap_destroy(sc->mtag, sc->tx_map[i]);
645192018Sstas			sc->sent_mbuf[i] = NULL;
646192018Sstas			sc->tx_map[i] = NULL;
647155324Simp		}
648192018Sstas		bus_dma_tag_destroy(sc->mtag);
649192018Sstas	}
650192018Sstas	if (sc->rx_desc_tag != NULL) {
651192018Sstas		if (sc->rx_descs != NULL) {
652192018Sstas			if (sc->rx_desc_phys != 0) {
653192018Sstas				bus_dmamap_sync(sc->rx_desc_tag,
654192018Sstas				    sc->rx_desc_map, BUS_DMASYNC_POSTREAD);
655192018Sstas				bus_dmamap_unload(sc->rx_desc_tag,
656192018Sstas				    sc->rx_desc_map);
657192018Sstas				sc->rx_desc_phys = 0;
658155324Simp			}
659155324Simp		}
660155324Simp	}
661213496Scognet	if (sc->rx_tag != NULL) {
662213496Scognet		for (i = 0; sc->rx_buf[i] != NULL; i++) {
663213496Scognet			if (sc->rx_descs[i].addr != 0) {
664213496Scognet				bus_dmamap_sync(sc->rx_tag,
665213496Scognet				    sc->rx_map[i],
666213496Scognet				    BUS_DMASYNC_POSTREAD);
667213496Scognet				bus_dmamap_unload(sc->rx_tag,
668192018Sstas				    sc->rx_map[i]);
669213496Scognet				sc->rx_descs[i].addr = 0;
670192018Sstas			}
671213496Scognet			bus_dmamem_free(sc->rx_tag, sc->rx_buf[i],
672213496Scognet			    sc->rx_map[i]);
673213496Scognet			sc->rx_buf[i] = NULL;
674213496Scognet			sc->rx_map[i] = NULL;
675192018Sstas		}
676213496Scognet		bus_dma_tag_destroy(sc->rx_tag);
677192018Sstas	}
678192018Sstas	if (sc->rx_desc_tag != NULL) {
679192018Sstas		if (sc->rx_descs != NULL)
680192018Sstas			bus_dmamem_free(sc->rx_desc_tag, sc->rx_descs,
681192018Sstas			    sc->rx_desc_map);
682192018Sstas		bus_dma_tag_destroy(sc->rx_desc_tag);
683192018Sstas		sc->rx_descs = NULL;
684192018Sstas		sc->rx_desc_tag = NULL;
685192018Sstas	}
686213496Scognet
687213496Scognet	if (sc->is_emacb)
688238895Simp		WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) & ~ETHB_UIO_CLKE);
689155324Simp}
690155324Simp
691155324Simp/*
692155324Simp * Change media according to request.
693155324Simp */
694155324Simpstatic int
695155324Simpate_ifmedia_upd(struct ifnet *ifp)
696155324Simp{
697155324Simp	struct ate_softc *sc = ifp->if_softc;
698155324Simp	struct mii_data *mii;
699155324Simp
700155324Simp	mii = device_get_softc(sc->miibus);
701155324Simp	ATE_LOCK(sc);
702155324Simp	mii_mediachg(mii);
703155324Simp	ATE_UNLOCK(sc);
704155324Simp	return (0);
705155324Simp}
706155324Simp
707155324Simp/*
708155324Simp * Notify the world which media we're using.
709155324Simp */
710155324Simpstatic void
711155324Simpate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
712155324Simp{
713155324Simp	struct ate_softc *sc = ifp->if_softc;
714155324Simp	struct mii_data *mii;
715155324Simp
716155324Simp	mii = device_get_softc(sc->miibus);
717155324Simp	ATE_LOCK(sc);
718155324Simp	mii_pollstat(mii);
719155324Simp	ifmr->ifm_active = mii->mii_media_active;
720155324Simp	ifmr->ifm_status = mii->mii_media_status;
721155324Simp	ATE_UNLOCK(sc);
722155324Simp}
723155324Simp
724155324Simpstatic void
725163937Simpate_stat_update(struct ate_softc *sc, int active)
726163937Simp{
727192027Sstas	uint32_t reg;
728192027Sstas
729163937Simp	/*
730163937Simp	 * The speed and full/half-duplex state needs to be reflected
731163937Simp	 * in the ETH_CFG register.
732163937Simp	 */
733192027Sstas	reg = RD4(sc, ETH_CFG);
734192027Sstas	reg &= ~(ETH_CFG_SPD | ETH_CFG_FD);
735192027Sstas	if (IFM_SUBTYPE(active) != IFM_10_T)
736192027Sstas		reg |= ETH_CFG_SPD;
737163937Simp	if (active & IFM_FDX)
738192027Sstas		reg |= ETH_CFG_FD;
739192027Sstas	WR4(sc, ETH_CFG, reg);
740163937Simp}
741163937Simp
742163937Simpstatic void
743155324Simpate_tick(void *xsc)
744155324Simp{
745155324Simp	struct ate_softc *sc = xsc;
746163937Simp	struct ifnet *ifp = sc->ifp;
747155324Simp	struct mii_data *mii;
748155324Simp	int active;
749163937Simp	uint32_t c;
750155324Simp
751155324Simp	/*
752155324Simp	 * The KB920x boot loader tests ETH_SR & ETH_SR_LINK and will ask
753155324Simp	 * the MII if there's a link if this bit is clear.  Not sure if we
754155324Simp	 * should do the same thing here or not.
755155324Simp	 */
756155324Simp	ATE_ASSERT_LOCKED(sc);
757155324Simp	if (sc->miibus != NULL) {
758155324Simp		mii = device_get_softc(sc->miibus);
759155324Simp		active = mii->mii_media_active;
760155324Simp		mii_tick(mii);
761155324Simp		if (mii->mii_media_status & IFM_ACTIVE &&
762234281Smarius		    active != mii->mii_media_active)
763163937Simp			ate_stat_update(sc, mii->mii_media_active);
764155324Simp	}
765155324Simp
766155324Simp	/*
767155324Simp	 * Update the stats as best we can.  When we're done, clear
768155324Simp	 * the status counters and start over.  We're supposed to read these
769155324Simp	 * registers often enough that they won't overflow.  Hopefully
770155324Simp	 * once a second is often enough.  Some don't map well to
771155324Simp	 * the dot3Stats mib, so for those we just count them as general
772155324Simp	 * errors.  Stats for iframes, ibutes, oframes and obytes are
773155324Simp	 * collected elsewhere.  These registers zero on a read to prevent
774163937Simp	 * races.  For all the collision stats, also update the collision
775163937Simp	 * stats for the interface.
776155324Simp	 */
777155324Simp	sc->mibdata.dot3StatsAlignmentErrors += RD4(sc, ETH_ALE);
778155324Simp	sc->mibdata.dot3StatsFCSErrors += RD4(sc, ETH_SEQE);
779163937Simp	c = RD4(sc, ETH_SCOL);
780163937Simp	ifp->if_collisions += c;
781163937Simp	sc->mibdata.dot3StatsSingleCollisionFrames += c;
782163937Simp	c = RD4(sc, ETH_MCOL);
783163937Simp	sc->mibdata.dot3StatsMultipleCollisionFrames += c;
784163937Simp	ifp->if_collisions += c;
785155324Simp	sc->mibdata.dot3StatsSQETestErrors += RD4(sc, ETH_SQEE);
786155324Simp	sc->mibdata.dot3StatsDeferredTransmissions += RD4(sc, ETH_DTE);
787163937Simp	c = RD4(sc, ETH_LCOL);
788163937Simp	sc->mibdata.dot3StatsLateCollisions += c;
789163937Simp	ifp->if_collisions += c;
790163937Simp	c = RD4(sc, ETH_ECOL);
791163937Simp	sc->mibdata.dot3StatsExcessiveCollisions += c;
792163937Simp	ifp->if_collisions += c;
793155324Simp	sc->mibdata.dot3StatsCarrierSenseErrors += RD4(sc, ETH_CSE);
794155324Simp	sc->mibdata.dot3StatsFrameTooLongs += RD4(sc, ETH_ELR);
795155324Simp	sc->mibdata.dot3StatsInternalMacReceiveErrors += RD4(sc, ETH_DRFC);
796192063Sstas
797155324Simp	/*
798192063Sstas	 * Not sure where to lump these, so count them against the errors
799155324Simp	 * for the interface.
800155324Simp	 */
801163937Simp	sc->ifp->if_oerrors += RD4(sc, ETH_TUE);
802155324Simp	sc->ifp->if_ierrors += RD4(sc, ETH_CDE) + RD4(sc, ETH_RJB) +
803155324Simp	    RD4(sc, ETH_USF);
804155324Simp
805213496Scognet	/* Schedule another timeout one second from now. */
806155324Simp	callout_reset(&sc->tick_ch, hz, ate_tick, sc);
807155324Simp}
808155324Simp
809155324Simpstatic void
810155445Scognetate_set_mac(struct ate_softc *sc, u_char *eaddr)
811155445Scognet{
812192063Sstas
813155445Scognet	WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) |
814155445Scognet	    (eaddr[1] << 8) | eaddr[0]);
815155445Scognet	WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4]));
816155445Scognet}
817155445Scognet
818166573Simpstatic int
819155324Simpate_get_mac(struct ate_softc *sc, u_char *eaddr)
820155324Simp{
821182477Sstas	bus_size_t sa_low_reg[] = { ETH_SA1L, ETH_SA2L, ETH_SA3L, ETH_SA4L };
822182477Sstas	bus_size_t sa_high_reg[] = { ETH_SA1H, ETH_SA2H, ETH_SA3H, ETH_SA4H };
823166573Simp	uint32_t low, high;
824182477Sstas	int i;
825155324Simp
826166573Simp	/*
827213496Scognet	 * The boot loader may setup the MAC with an address(es), grab the
828213496Scognet	 * first MAC address from the SA[1-4][HL] registers.
829166573Simp	 */
830182477Sstas	for (i = 0; i < 4; i++) {
831182477Sstas		low = RD4(sc, sa_low_reg[i]);
832182477Sstas		high = RD4(sc, sa_high_reg[i]);
833182477Sstas		if ((low | (high & 0xffff)) != 0) {
834182477Sstas			eaddr[0] = low & 0xff;
835182477Sstas			eaddr[1] = (low >> 8) & 0xff;
836182477Sstas			eaddr[2] = (low >> 16) & 0xff;
837182477Sstas			eaddr[3] = (low >> 24) & 0xff;
838182477Sstas			eaddr[4] = high & 0xff;
839182477Sstas			eaddr[5] = (high >> 8) & 0xff;
840182477Sstas			return (0);
841182477Sstas		}
842182477Sstas	}
843182477Sstas	return (ENXIO);
844155324Simp}
845155324Simp
846155324Simpstatic void
847155324Simpate_intr(void *xsc)
848155324Simp{
849155324Simp	struct ate_softc *sc = xsc;
850163937Simp	struct ifnet *ifp = sc->ifp;
851192027Sstas	struct mbuf *mb;
852213496Scognet	eth_rx_desc_t	*rxdhead;
853213496Scognet	uint32_t status, reg, idx;
854213496Scognet	int remain, count, done;
855156831Simp
856155324Simp	status = RD4(sc, ETH_ISR);
857155324Simp	if (status == 0)
858155324Simp		return;
859213496Scognet
860155324Simp	if (status & ETH_ISR_RCOM) {
861238895Simp		bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
862155324Simp		    BUS_DMASYNC_POSTREAD);
863213496Scognet
864238895Simp		rxdhead = &sc->rx_descs[sc->rxhead];
865238895Simp		while (rxdhead->addr & ETH_CPU_OWNER) {
866213496Scognet			if (!sc->is_emacb) {
867213496Scognet				/*
868213496Scognet				 * Simulate SAM9 FIRST/LAST bits for RM9200.
869213496Scognet				 * RM9200 EMAC has only on Rx buffer per packet.
870213496Scognet				 * But sometime we are handed a zero lenght packet.
871213496Scognet				 */
872213496Scognet				if ((rxdhead->status & ETH_LEN_MASK) == 0)
873213496Scognet					rxdhead->status = 0; /* Mark error */
874213496Scognet				else
875213496Scognet					rxdhead->status |= ETH_BUF_FIRST | ETH_BUF_LAST;
876213496Scognet			}
877213496Scognet
878213496Scognet			if ((rxdhead->status & ETH_BUF_FIRST) == 0) {
879213496Scognet				/* Something went wrong during RX so
880213496Scognet				   release back to EMAC all buffers of invalid packets.
881213496Scognet				*/
882213496Scognet				rxdhead->status = 0;
883213496Scognet				rxdhead->addr &= ~ETH_CPU_OWNER;
884213496Scognet				sc->rxhead = NEXT_RX_IDX(sc, sc->rxhead);
885213496Scognet				rxdhead = &sc->rx_descs[sc->rxhead];
886156831Simp				continue;
887155324Simp			}
888163937Simp
889213496Scognet			/* Find end of packet or start of next */
890213496Scognet			idx = sc->rxhead;
891213496Scognet			if ((sc->rx_descs[idx].status & ETH_BUF_LAST) == 0) {
892213496Scognet				idx = NEXT_RX_IDX(sc, idx);
893213496Scognet
894213496Scognet				while ((sc->rx_descs[idx].addr & ETH_CPU_OWNER) &&
895213496Scognet					((sc->rx_descs[idx].status &
896213496Scognet					    (ETH_BUF_FIRST|ETH_BUF_LAST))== 0))
897213496Scognet					idx = NEXT_RX_IDX(sc, idx);
898213496Scognet			}
899213496Scognet
900213496Scognet			/* Packet NOT yet completely in memory; we are done */
901213496Scognet			if ((sc->rx_descs[idx].addr & ETH_CPU_OWNER) == 0 ||
902213496Scognet			    ((sc->rx_descs[idx].status & (ETH_BUF_FIRST|ETH_BUF_LAST))== 0))
903213496Scognet					break;
904213496Scognet
905213496Scognet			/* Packets with no end descriptor are invalid. */
906213496Scognet			if ((sc->rx_descs[idx].status & ETH_BUF_LAST) == 0) {
907213496Scognet					rxdhead->status &= ~ETH_BUF_FIRST;
908213496Scognet					continue;
909213496Scognet			}
910213496Scognet
911213496Scognet			/* FCS is not coppied into mbuf. */
912213496Scognet			remain = (sc->rx_descs[idx].status & ETH_LEN_MASK) - 4;
913213496Scognet
914248189Sglebius			/* Get an appropriately sized mbuf. */
915248207Sglebius			mb = m_get2(remain + ETHER_ALIGN, M_NOWAIT, MT_DATA,
916248207Sglebius			    M_PKTHDR);
917213496Scognet			if (mb == NULL) {
918213496Scognet				sc->ifp->if_iqdrops++;
919213496Scognet				rxdhead->status = 0;
920213496Scognet				continue;
921213496Scognet			}
922213496Scognet			mb->m_data += ETHER_ALIGN;
923213496Scognet			mb->m_pkthdr.rcvif = ifp;
924213496Scognet
925213496Scognet			WR4(sc, ETH_RSR, RD4(sc, ETH_RSR));	/* Reset status */
926213496Scognet
927213496Scognet			/* Now we process the buffers that make up the packet */
928213496Scognet			do {
929213496Scognet
930213496Scognet				/* Last buffer may just be 1-4 bytes of FCS so remain
931213496Scognet				 * may be zero for last decriptor.  */
932213496Scognet				if (remain > 0) {
933213496Scognet						/* Make sure we get the current bytes */
934213496Scognet						bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead],
935213496Scognet						    BUS_DMASYNC_POSTREAD);
936213496Scognet
937213496Scognet						count = MIN(remain, sc->rx_buf_size);
938213496Scognet
939213496Scognet						/* XXX Performance robbing copy. Could
940213496Scognet						 * recieve directly to mbufs if not an
941238895Simp						 * RM9200. And even then we could likely
942238895Simp						 * copy just the protocol headers. XXX  */
943213496Scognet						m_append(mb, count, sc->rx_buf[sc->rxhead]);
944213496Scognet						remain -= count;
945213496Scognet				}
946213496Scognet
947213496Scognet				done = (rxdhead->status & ETH_BUF_LAST) != 0;
948213496Scognet
949213496Scognet				/* Return the descriptor to the EMAC */
950213496Scognet				rxdhead->status = 0;
951213496Scognet				rxdhead->addr &= ~ETH_CPU_OWNER;
952213496Scognet				bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
953213496Scognet				    BUS_DMASYNC_PREWRITE);
954213496Scognet
955213496Scognet				/* Move on to next descriptor with wrap */
956213496Scognet				sc->rxhead = NEXT_RX_IDX(sc, sc->rxhead);
957213496Scognet				rxdhead = &sc->rx_descs[sc->rxhead];
958213496Scognet
959213496Scognet			} while (!done);
960213496Scognet
961259381Sian			ifp->if_ipackets++;
962259381Sian			(*ifp->if_input)(ifp, mb);
963155324Simp		}
964155324Simp	}
965213496Scognet
966213496Scognet
967155324Simp	if (status & ETH_ISR_TCOM) {
968213496Scognet		bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map,
969213496Scognet		    BUS_DMASYNC_POSTREAD);
970213496Scognet
971156831Simp		ATE_LOCK(sc);
972163937Simp		/* XXX TSR register should be cleared */
973234281Smarius		if (!sc->is_emacb) {
974213496Scognet			/* Simulate Transmit descriptor table */
975213496Scognet
976213496Scognet			/* First packet done */
977213496Scognet			if (sc->txtail < sc->txhead)
978213496Scognet				sc->tx_descs[sc->txtail].status |= ETHB_TX_USED;
979213496Scognet
980213496Scognet			/* Second Packet done */
981213496Scognet			if (sc->txtail + 1 < sc->txhead &&
982213496Scognet			    RD4(sc, ETH_TSR) & ETH_TSR_IDLE)
983213496Scognet				sc->tx_descs[sc->txtail + 1].status |= ETHB_TX_USED;
984213496Scognet		}
985213496Scognet
986259381Sian		while ((sc->tx_descs[sc->txtail].status & ETHB_TX_USED) &&
987259381Sian		    sc->sent_mbuf[sc->txtail] != NULL) {
988213496Scognet			bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail],
989163937Simp			    BUS_DMASYNC_POSTWRITE);
990213496Scognet			bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]);
991213496Scognet			m_freem(sc->sent_mbuf[sc->txtail]);
992213496Scognet			sc->tx_descs[sc->txtail].addr = 0;
993213496Scognet			sc->sent_mbuf[sc->txtail] = NULL;
994163937Simp			ifp->if_opackets++;
995213496Scognet			sc->txtail = NEXT_TX_IDX(sc, sc->txtail);
996156831Simp		}
997213496Scognet
998213496Scognet		/* Flush descriptors to EMAC */
999213496Scognet		bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map, BUS_DMASYNC_PREWRITE);
1000213496Scognet
1001156831Simp		/*
1002156831Simp		 * We're no longer busy, so clear the busy flag and call the
1003156831Simp		 * start routine to xmit more packets.
1004156831Simp		 */
1005156831Simp		sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1006156831Simp		atestart_locked(sc->ifp);
1007156831Simp		ATE_UNLOCK(sc);
1008155324Simp	}
1009213496Scognet
1010155324Simp	if (status & ETH_ISR_RBNA) {
1011213496Scognet		/* Workaround RM9200 Errata #11 */
1012192028Sstas		if (bootverbose)
1013192028Sstas			device_printf(sc->dev, "RBNA workaround\n");
1014192027Sstas		reg = RD4(sc, ETH_CTL);
1015192027Sstas		WR4(sc, ETH_CTL, reg & ~ETH_CTL_RE);
1016192027Sstas		BARRIER(sc, ETH_CTL, 4, BUS_SPACE_BARRIER_WRITE);
1017192027Sstas		WR4(sc, ETH_CTL, reg | ETH_CTL_RE);
1018155324Simp	}
1019238895Simp
1020238895Simp	/* XXX need to work around SAM9260 errata 43.2.4.1:
1021238895Simp	 * disable the mac, reset tx buffer, enable mac on TUND */
1022155324Simp}
1023155324Simp
1024155324Simp/*
1025192063Sstas * Reset and initialize the chip.
1026155324Simp */
1027155324Simpstatic void
1028155324Simpateinit_locked(void *xsc)
1029155324Simp{
1030155324Simp	struct ate_softc *sc = xsc;
1031155324Simp	struct ifnet *ifp = sc->ifp;
1032213496Scognet	struct mii_data *mii;
1033192064Sstas	uint8_t eaddr[ETHER_ADDR_LEN];
1034192027Sstas	uint32_t reg;
1035155324Simp
1036155324Simp	ATE_ASSERT_LOCKED(sc);
1037155324Simp
1038155324Simp	/*
1039155324Simp	 * XXX TODO(3)
1040155324Simp	 * we need to turn on the EMAC clock in the pmc.  With the
1041155324Simp	 * default boot loader, this is already turned on.  However, we
1042155324Simp	 * need to think about how best to turn it on/off as the interface
1043155324Simp	 * is brought up/down, as well as dealing with the mii bus...
1044155324Simp	 *
1045213496Scognet	 * We also need to multiplex the pins correctly (in board_xxx.c).
1046155324Simp	 */
1047155324Simp
1048155324Simp	/*
1049155324Simp	 * There are two different ways that the mii bus is connected
1050213496Scognet	 * to this chip mii or rmii.
1051155324Simp	 */
1052213496Scognet	if (!sc->is_emacb) {
1053213496Scognet		/* RM9200 */
1054213496Scognet		reg = RD4(sc, ETH_CFG);
1055213496Scognet		if (sc->use_rmii)
1056213496Scognet			reg |= ETH_CFG_RMII;
1057213496Scognet		else
1058213496Scognet			reg &= ~ETH_CFG_RMII;
1059213496Scognet		WR4(sc, ETH_CFG, reg);
1060213496Scognet	} else  {
1061213496Scognet		/* SAM9 */
1062213496Scognet		reg = ETHB_UIO_CLKE;
1063234281Smarius		reg |= (sc->use_rmii) ? ETHB_UIO_RMII : 0;
1064213496Scognet		WR4(sc, ETHB_UIO, reg);
1065213496Scognet	}
1066159708Simp
1067191960Sstas	ate_rxfilter(sc);
1068191960Sstas
1069191960Sstas	/*
1070192064Sstas	 * Set the chip MAC address.
1071192064Sstas	 */
1072192064Sstas	bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN);
1073192064Sstas	ate_set_mac(sc, eaddr);
1074192064Sstas
1075213496Scognet	/* Make sure we know state of TX queue */
1076213496Scognet	sc->txhead = sc->txtail = 0;
1077213496Scognet	if (sc->is_emacb) {
1078213496Scognet		/* Write the descriptor queue address. */
1079213496Scognet		WR4(sc, ETHB_TBQP, sc->tx_desc_phys);
1080213496Scognet	}
1081213496Scognet
1082192064Sstas	/*
1083191960Sstas	 * Turn on MACs and interrupt processing.
1084191960Sstas	 */
1085155324Simp	WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE);
1086156831Simp	WR4(sc, ETH_IER, ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA);
1087155324Simp
1088192063Sstas	/* Enable big packets. */
1089165779Sticso	WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
1090165779Sticso
1091155324Simp	/*
1092155324Simp	 * Set 'running' flag, and clear output active flag
1093192063Sstas	 * and attempt to start the output.
1094155324Simp	 */
1095155324Simp	ifp->if_drv_flags |= IFF_DRV_RUNNING;
1096155324Simp	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1097163937Simp
1098163937Simp	mii = device_get_softc(sc->miibus);
1099163937Simp	mii_pollstat(mii);
1100163937Simp	ate_stat_update(sc, mii->mii_media_active);
1101155324Simp	atestart_locked(ifp);
1102155324Simp
1103155324Simp	callout_reset(&sc->tick_ch, hz, ate_tick, sc);
1104155324Simp}
1105155324Simp
1106155324Simp/*
1107192063Sstas * Dequeue packets and transmit.
1108155324Simp */
1109155324Simpstatic void
1110155324Simpatestart_locked(struct ifnet *ifp)
1111155324Simp{
1112155324Simp	struct ate_softc *sc = ifp->if_softc;
1113155324Simp	struct mbuf *m, *mdefrag;
1114155324Simp	bus_dma_segment_t segs[1];
1115163937Simp	int nseg, e;
1116155324Simp
1117155324Simp	ATE_ASSERT_LOCKED(sc);
1118155324Simp	if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
1119155324Simp		return;
1120155324Simp
1121213496Scognet	while (sc->tx_descs[sc->txhead].status & ETHB_TX_USED) {
1122156831Simp		/*
1123192063Sstas		 * Check to see if there's room to put another packet into the
1124213496Scognet		 * xmit queue. The old EMAC version has a ping-pong buffer for
1125213496Scognet		 * xmit packets.  We use OACTIVE to indicate "we can stuff more
1126213496Scognet		 * into our buffers (clear) or not (set)."
1127156831Simp		 */
1128259381Sian		/* RM9200 has only two hardware entries */
1129259381Sian		if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) {
1130259381Sian			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1131259381Sian			return;
1132156831Simp		}
1133213496Scognet
1134156831Simp		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1135213496Scognet		if (m == 0)
1136213496Scognet			break;
1137213496Scognet
1138213496Scognet		e = bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txhead], m,
1139163937Simp		    segs, &nseg, 0);
1140163937Simp		if (e == EFBIG) {
1141243882Sglebius			mdefrag = m_defrag(m, M_NOWAIT);
1142163937Simp			if (mdefrag == NULL) {
1143163937Simp				IFQ_DRV_PREPEND(&ifp->if_snd, m);
1144163937Simp				return;
1145163937Simp			}
1146163937Simp			m = mdefrag;
1147163937Simp			e = bus_dmamap_load_mbuf_sg(sc->mtag,
1148213496Scognet			    sc->tx_map[sc->txhead], m, segs, &nseg, 0);
1149156831Simp		}
1150163937Simp		if (e != 0) {
1151156831Simp			m_freem(m);
1152156831Simp			continue;
1153156831Simp		}
1154259381Sian
1155259381Sian		/*
1156259381Sian		 * There's a small race between the loop in ate_intr finishing
1157259381Sian		 * and the check above to see if the packet was finished, as well
1158259381Sian		 * as when atestart gets called via other paths. Lose the race
1159259381Sian		 * gracefully and free the mbuf...
1160259381Sian		 */
1161259381Sian		if (sc->sent_mbuf[sc->txhead] != NULL) {
1162259381Sian			bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail],
1163259381Sian			    BUS_DMASYNC_POSTWRITE);
1164259381Sian			bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]);
1165259381Sian			m_free(sc->sent_mbuf[sc->txhead]);
1166259381Sian			ifp->if_opackets++;
1167259381Sian		}
1168259381Sian
1169213496Scognet		sc->sent_mbuf[sc->txhead] = m;
1170213496Scognet
1171213496Scognet		bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txhead],
1172156831Simp		    BUS_DMASYNC_PREWRITE);
1173155324Simp
1174213496Scognet		/* Tell the hardware to xmit the packet. */
1175213496Scognet		if (!sc->is_emacb) {
1176213496Scognet			WR4(sc, ETH_TAR, segs[0].ds_addr);
1177213496Scognet			BARRIER(sc, ETH_TAR, 4, BUS_SPACE_BARRIER_WRITE);
1178213496Scognet			WR4(sc, ETH_TCR, segs[0].ds_len);
1179213496Scognet		} else {
1180213496Scognet			bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map,
1181213496Scognet			    BUS_DMASYNC_POSTWRITE);
1182213496Scognet			sc->tx_descs[sc->txhead].addr = segs[0].ds_addr;
1183213496Scognet			sc->tx_descs[sc->txhead].status = segs[0].ds_len |
1184213496Scognet			    (sc->tx_descs[sc->txhead].status & ETHB_TX_WRAP) |
1185213496Scognet			    ETHB_TX_BUF_LAST;
1186213496Scognet			bus_dmamap_sync(sc->tx_desc_tag, sc->tx_desc_map,
1187213496Scognet			    BUS_DMASYNC_PREWRITE);
1188213496Scognet			WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETHB_CTL_TGO);
1189213496Scognet		}
1190213496Scognet		sc->txhead = NEXT_TX_IDX(sc, sc->txhead);
1191234281Smarius
1192213496Scognet		/* Tap off here if there is a bpf listener. */
1193156831Simp		BPF_MTAP(ifp, m);
1194213496Scognet	}
1195155324Simp
1196213496Scognet	if ((sc->tx_descs[sc->txhead].status & ETHB_TX_USED) == 0)
1197213496Scognet	    ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1198155324Simp}
1199155324Simp
1200155324Simpstatic void
1201155324Simpateinit(void *xsc)
1202155324Simp{
1203155324Simp	struct ate_softc *sc = xsc;
1204192063Sstas
1205155324Simp	ATE_LOCK(sc);
1206155324Simp	ateinit_locked(sc);
1207155324Simp	ATE_UNLOCK(sc);
1208155324Simp}
1209155324Simp
1210155324Simpstatic void
1211155324Simpatestart(struct ifnet *ifp)
1212155324Simp{
1213155324Simp	struct ate_softc *sc = ifp->if_softc;
1214192063Sstas
1215155324Simp	ATE_LOCK(sc);
1216155324Simp	atestart_locked(ifp);
1217155324Simp	ATE_UNLOCK(sc);
1218155324Simp}
1219155324Simp
1220155324Simp/*
1221192063Sstas * Turn off interrupts, and stop the NIC.  Can be called with sc->ifp NULL,
1222155324Simp * so be careful.
1223155324Simp */
1224155324Simpstatic void
1225155324Simpatestop(struct ate_softc *sc)
1226155324Simp{
1227192018Sstas	struct ifnet *ifp;
1228192018Sstas	int i;
1229155324Simp
1230192018Sstas	ATE_ASSERT_LOCKED(sc);
1231192018Sstas	ifp = sc->ifp;
1232155324Simp	if (ifp) {
1233213496Scognet		//ifp->if_timer = 0;
1234155324Simp		ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1235155324Simp	}
1236155324Simp
1237155324Simp	callout_stop(&sc->tick_ch);
1238155324Simp
1239155324Simp	/*
1240155324Simp	 * Enable some parts of the MAC that are needed always (like the
1241155324Simp	 * MII bus.  This turns off the RE and TE bits, which will remain
1242155405Scognet	 * off until ateinit() is called to turn them on.  With RE and TE
1243155324Simp	 * turned off, there's no DMA to worry about after this write.
1244155324Simp	 */
1245155324Simp	WR4(sc, ETH_CTL, ETH_CTL_MPE);
1246155324Simp
1247155324Simp	/*
1248155324Simp	 * Turn off all the configured options and revert to defaults.
1249155324Simp	 */
1250155324Simp
1251213496Scognet	/* Make sure thate the MDIO clk is less than
1252213496Scognet	 * 2.5 Mhz. Can no longer default to /32 since
1253213496Scognet	 * SAM9 family may have MCK > 80 Mhz */
1254213496Scognet	if (at91_master_clock <= 2000000)
1255213496Scognet		WR4(sc, ETH_CFG, ETH_CFG_CLK_8);
1256213496Scognet	else if (at91_master_clock <= 4000000)
1257213496Scognet		WR4(sc, ETH_CFG, ETH_CFG_CLK_16);
1258213496Scognet	else if (at91_master_clock <= 800000)
1259213496Scognet		WR4(sc, ETH_CFG, ETH_CFG_CLK_32);
1260213496Scognet	else
1261213496Scognet		WR4(sc, ETH_CFG, ETH_CFG_CLK_64);
1262213496Scognet
1263155324Simp	/*
1264155324Simp	 * Turn off all the interrupts, and ack any pending ones by reading
1265155324Simp	 * the ISR.
1266155324Simp	 */
1267155324Simp	WR4(sc, ETH_IDR, 0xffffffff);
1268155324Simp	RD4(sc, ETH_ISR);
1269155324Simp
1270155324Simp	/*
1271155324Simp	 * Clear out the Transmit and Receiver Status registers of any
1272155324Simp	 * errors they may be reporting
1273155324Simp	 */
1274155324Simp	WR4(sc, ETH_TSR, 0xffffffff);
1275155324Simp	WR4(sc, ETH_RSR, 0xffffffff);
1276155324Simp
1277213496Scognet	/* Release TX resources. */
1278192018Sstas	for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
1279192018Sstas		if (sc->sent_mbuf[i] != NULL) {
1280192018Sstas			bus_dmamap_sync(sc->mtag, sc->tx_map[i],
1281192018Sstas			    BUS_DMASYNC_POSTWRITE);
1282192018Sstas			bus_dmamap_unload(sc->mtag, sc->tx_map[i]);
1283192018Sstas			m_freem(sc->sent_mbuf[i]);
1284192018Sstas			sc->sent_mbuf[i] = NULL;
1285192018Sstas		}
1286192018Sstas	}
1287155324Simp
1288213496Scognet	/* Turn off transeiver input clock */
1289213496Scognet	if (sc->is_emacb)
1290238895Simp		WR4(sc, ETHB_UIO, RD4(sc, ETHB_UIO) & ~ETHB_UIO_CLKE);
1291213496Scognet
1292155324Simp	/*
1293155324Simp	 * XXX we should power down the EMAC if it isn't in use, after
1294155324Simp	 * putting it into loopback mode.  This saves about 400uA according
1295155324Simp	 * to the datasheet.
1296155324Simp	 */
1297155324Simp}
1298155324Simp
1299191959Sstasstatic void
1300191959Sstasate_rxfilter(struct ate_softc *sc)
1301191959Sstas{
1302191959Sstas	struct ifnet *ifp;
1303191959Sstas	uint32_t reg;
1304191960Sstas	int enabled;
1305191959Sstas
1306191959Sstas	KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
1307191959Sstas	ATE_ASSERT_LOCKED(sc);
1308191959Sstas	ifp = sc->ifp;
1309191959Sstas
1310213496Scognet	/* Wipe out old filter settings. */
1311191959Sstas	reg = RD4(sc, ETH_CFG);
1312191959Sstas	reg &= ~(ETH_CFG_CAF | ETH_CFG_MTI | ETH_CFG_UNI);
1313191959Sstas	reg |= ETH_CFG_NBC;
1314191960Sstas	sc->flags &= ~ATE_FLAG_MULTICAST;
1315191959Sstas
1316213496Scognet	/* Set new parameters. */
1317191959Sstas	if ((ifp->if_flags & IFF_BROADCAST) != 0)
1318191959Sstas		reg &= ~ETH_CFG_NBC;
1319191960Sstas	if ((ifp->if_flags & IFF_PROMISC) != 0) {
1320191959Sstas		reg |= ETH_CFG_CAF;
1321191960Sstas	} else {
1322191960Sstas		enabled = ate_setmcast(sc);
1323191960Sstas		if (enabled != 0) {
1324191960Sstas			reg |= ETH_CFG_MTI;
1325191960Sstas			sc->flags |= ATE_FLAG_MULTICAST;
1326191960Sstas		}
1327191960Sstas	}
1328191959Sstas	WR4(sc, ETH_CFG, reg);
1329191959Sstas}
1330191959Sstas
1331155324Simpstatic int
1332155324Simpateioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1333155324Simp{
1334155324Simp	struct ate_softc *sc = ifp->if_softc;
1335213496Scognet	struct mii_data *mii;
1336234281Smarius	struct ifreq *ifr = (struct ifreq *)data;
1337191959Sstas	int drv_flags, flags;
1338191960Sstas	int mask, error, enabled;
1339155324Simp
1340191960Sstas	error = 0;
1341191959Sstas	flags = ifp->if_flags;
1342191959Sstas	drv_flags = ifp->if_drv_flags;
1343155324Simp	switch (cmd) {
1344155324Simp	case SIOCSIFFLAGS:
1345155324Simp		ATE_LOCK(sc);
1346191959Sstas		if ((flags & IFF_UP) != 0) {
1347191959Sstas			if ((drv_flags & IFF_DRV_RUNNING) != 0) {
1348191959Sstas				if (((flags ^ sc->if_flags)
1349191959Sstas				    & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
1350191959Sstas					ate_rxfilter(sc);
1351191959Sstas			} else {
1352213496Scognet				if ((sc->flags & ATE_FLAG_DETACHING) == 0)
1353213496Scognet					ateinit_locked(sc);
1354191959Sstas			}
1355191959Sstas		} else if ((drv_flags & IFF_DRV_RUNNING) != 0) {
1356213496Scognet			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1357155324Simp			atestop(sc);
1358155324Simp		}
1359191959Sstas		sc->if_flags = flags;
1360155324Simp		ATE_UNLOCK(sc);
1361155324Simp		break;
1362155324Simp
1363155324Simp	case SIOCADDMULTI:
1364155324Simp	case SIOCDELMULTI:
1365191960Sstas		if ((drv_flags & IFF_DRV_RUNNING) != 0) {
1366191960Sstas			ATE_LOCK(sc);
1367191960Sstas			enabled = ate_setmcast(sc);
1368191960Sstas			if (enabled != (sc->flags & ATE_FLAG_MULTICAST))
1369191960Sstas				ate_rxfilter(sc);
1370191960Sstas			ATE_UNLOCK(sc);
1371191960Sstas		}
1372155324Simp		break;
1373155324Simp
1374213496Scognet	case SIOCSIFMEDIA:
1375213496Scognet	case SIOCGIFMEDIA:
1376213496Scognet		mii = device_get_softc(sc->miibus);
1377213496Scognet		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1378213496Scognet		break;
1379165779Sticso	case SIOCSIFCAP:
1380165779Sticso		mask = ifp->if_capenable ^ ifr->ifr_reqcap;
1381165779Sticso		if (mask & IFCAP_VLAN_MTU) {
1382165779Sticso			ATE_LOCK(sc);
1383165779Sticso			if (ifr->ifr_reqcap & IFCAP_VLAN_MTU) {
1384165779Sticso				WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
1385165779Sticso				ifp->if_capenable |= IFCAP_VLAN_MTU;
1386165779Sticso			} else {
1387165779Sticso				WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_BIG);
1388165779Sticso				ifp->if_capenable &= ~IFCAP_VLAN_MTU;
1389165779Sticso			}
1390165779Sticso			ATE_UNLOCK(sc);
1391165779Sticso		}
1392155324Simp	default:
1393155324Simp		error = ether_ioctl(ifp, cmd, data);
1394155324Simp		break;
1395155324Simp	}
1396155324Simp	return (error);
1397155324Simp}
1398155324Simp
1399155324Simpstatic void
1400155324Simpate_child_detached(device_t dev, device_t child)
1401155324Simp{
1402155324Simp	struct ate_softc *sc;
1403155324Simp
1404155324Simp	sc = device_get_softc(dev);
1405155324Simp	if (child == sc->miibus)
1406155324Simp		sc->miibus = NULL;
1407155324Simp}
1408155324Simp
1409155324Simp/*
1410155324Simp * MII bus support routines.
1411155324Simp */
1412155324Simpstatic int
1413155324Simpate_miibus_readreg(device_t dev, int phy, int reg)
1414155324Simp{
1415155324Simp	struct ate_softc *sc;
1416155324Simp	int val;
1417155324Simp
1418155324Simp	/*
1419155324Simp	 * XXX if we implement agressive power savings, then we need
1420155324Simp	 * XXX to make sure that the clock to the emac is on here
1421155324Simp	 */
1422155324Simp
1423155324Simp	sc = device_get_softc(dev);
1424155324Simp	DELAY(1);	/* Hangs w/o this delay really 30.5us atm */
1425155324Simp	WR4(sc, ETH_MAN, ETH_MAN_REG_RD(phy, reg));
1426155324Simp	while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0)
1427155324Simp		continue;
1428155324Simp	val = RD4(sc, ETH_MAN) & ETH_MAN_VALUE_MASK;
1429155324Simp
1430155324Simp	return (val);
1431155324Simp}
1432155324Simp
1433194015Savgstatic int
1434155324Simpate_miibus_writereg(device_t dev, int phy, int reg, int data)
1435155324Simp{
1436155324Simp	struct ate_softc *sc;
1437234281Smarius
1438155324Simp	/*
1439155324Simp	 * XXX if we implement agressive power savings, then we need
1440155324Simp	 * XXX to make sure that the clock to the emac is on here
1441155324Simp	 */
1442155324Simp
1443155324Simp	sc = device_get_softc(dev);
1444155324Simp	WR4(sc, ETH_MAN, ETH_MAN_REG_WR(phy, reg, data));
1445155324Simp	while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0)
1446155324Simp		continue;
1447194015Savg	return (0);
1448155324Simp}
1449155324Simp
1450155324Simpstatic device_method_t ate_methods[] = {
1451155324Simp	/* Device interface */
1452155324Simp	DEVMETHOD(device_probe,		ate_probe),
1453155324Simp	DEVMETHOD(device_attach,	ate_attach),
1454155324Simp	DEVMETHOD(device_detach,	ate_detach),
1455155324Simp
1456155324Simp	/* Bus interface */
1457155324Simp	DEVMETHOD(bus_child_detached,	ate_child_detached),
1458155324Simp
1459155324Simp	/* MII interface */
1460155324Simp	DEVMETHOD(miibus_readreg,	ate_miibus_readreg),
1461155324Simp	DEVMETHOD(miibus_writereg,	ate_miibus_writereg),
1462155324Simp
1463234281Smarius	DEVMETHOD_END
1464155324Simp};
1465155324Simp
1466155324Simpstatic driver_t ate_driver = {
1467155324Simp	"ate",
1468155324Simp	ate_methods,
1469155324Simp	sizeof(struct ate_softc),
1470155324Simp};
1471155324Simp
1472266196Sian#ifdef FDT
1473266196SianDRIVER_MODULE(ate, simplebus, ate_driver, ate_devclass, NULL, NULL);
1474266196Sian#else
1475234281SmariusDRIVER_MODULE(ate, atmelarm, ate_driver, ate_devclass, NULL, NULL);
1476266196Sian#endif
1477234281SmariusDRIVER_MODULE(miibus, ate, miibus_driver, miibus_devclass, NULL, NULL);
1478155324SimpMODULE_DEPEND(ate, miibus, 1, 1, 1);
1479155324SimpMODULE_DEPEND(ate, ether, 1, 1, 1);
1480