if_ate.c revision 192027
1155324Simp/*-
2155324Simp * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
3155324Simp *
4155324Simp * Redistribution and use in source and binary forms, with or without
5155324Simp * modification, are permitted provided that the following conditions
6155324Simp * are met:
7155324Simp * 1. Redistributions of source code must retain the above copyright
8155324Simp *    notice, this list of conditions and the following disclaimer.
9155324Simp * 2. Redistributions in binary form must reproduce the above copyright
10155324Simp *    notice, this list of conditions and the following disclaimer in the
11155324Simp *    documentation and/or other materials provided with the distribution.
12155324Simp *
13185267Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14185267Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15185267Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16185267Simp * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17185267Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18185267Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19185267Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20185267Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21185267Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22185267Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23185267Simp * SUCH DAMAGE.
24155324Simp */
25155324Simp
26192018Sstas/* TODO
27155324Simp *
28192018Sstas * 1) Turn on the clock in pmc?  Turn off?
29192018Sstas * 2) GPIO initializtion in board setup code.
30155324Simp */
31155324Simp
32155324Simp#include <sys/cdefs.h>
33155324Simp__FBSDID("$FreeBSD: head/sys/arm/at91/if_ate.c 192027 2009-05-12 21:14:36Z stas $");
34155324Simp
35155324Simp#include <sys/param.h>
36155324Simp#include <sys/systm.h>
37155324Simp#include <sys/bus.h>
38155324Simp#include <sys/kernel.h>
39155324Simp#include <sys/mbuf.h>
40155324Simp#include <sys/malloc.h>
41155324Simp#include <sys/module.h>
42155324Simp#include <sys/rman.h>
43155324Simp#include <sys/socket.h>
44155324Simp#include <sys/sockio.h>
45163522Simp#include <sys/sysctl.h>
46155324Simp#include <machine/bus.h>
47155324Simp
48155324Simp#include <net/ethernet.h>
49155324Simp#include <net/if.h>
50155324Simp#include <net/if_arp.h>
51155324Simp#include <net/if_dl.h>
52155324Simp#include <net/if_media.h>
53155324Simp#include <net/if_mib.h>
54155324Simp#include <net/if_types.h>
55155324Simp
56155324Simp#ifdef INET
57155324Simp#include <netinet/in.h>
58155324Simp#include <netinet/in_systm.h>
59155324Simp#include <netinet/in_var.h>
60155324Simp#include <netinet/ip.h>
61155324Simp#endif
62155324Simp
63155324Simp#include <net/bpf.h>
64155324Simp#include <net/bpfdesc.h>
65155324Simp
66155324Simp#include <dev/mii/mii.h>
67155324Simp#include <dev/mii/miivar.h>
68155324Simp#include <arm/at91/if_atereg.h>
69155324Simp
70155324Simp#include "miibus_if.h"
71155324Simp
72165778Sticso#define ATE_MAX_TX_BUFFERS 2		/* We have ping-pong tx buffers */
73156831Simp#define ATE_MAX_RX_BUFFERS 64
74155324Simp
75191959Sstas/*
76191959Sstas * Driver-specific flags.
77191959Sstas */
78191959Sstas#define	ATE_FLAG_DETACHING	0x01
79191960Sstas#define	ATE_FLAG_MULTICAST	0x02
80191959Sstas
81155324Simpstruct ate_softc
82155324Simp{
83155324Simp	struct ifnet *ifp;		/* ifnet pointer */
84155324Simp	struct mtx sc_mtx;		/* basically a perimeter lock */
85155324Simp	device_t dev;			/* Myself */
86155324Simp	device_t miibus;		/* My child miibus */
87155324Simp	void *intrhand;			/* Interrupt handle */
88155324Simp	struct resource *irq_res;	/* IRQ resource */
89155324Simp	struct resource	*mem_res;	/* Memory resource */
90155324Simp	struct callout tick_ch;		/* Tick callout */
91155324Simp	bus_dma_tag_t mtag;		/* bus dma tag for mbufs */
92155324Simp	bus_dmamap_t tx_map[ATE_MAX_TX_BUFFERS];
93157562Simp	struct mbuf *sent_mbuf[ATE_MAX_TX_BUFFERS]; /* Sent mbufs */
94155324Simp	bus_dma_tag_t rxtag;
95155324Simp	bus_dmamap_t rx_map[ATE_MAX_RX_BUFFERS];
96157562Simp	void *rx_buf[ATE_MAX_RX_BUFFERS]; /* RX buffer space */
97157562Simp	int rx_buf_ptr;
98155324Simp	bus_dma_tag_t rx_desc_tag;
99155324Simp	bus_dmamap_t rx_desc_map;
100155324Simp	int txcur;			/* current tx map pointer */
101155324Simp	bus_addr_t rx_desc_phys;
102155324Simp	eth_rx_desc_t *rx_descs;
103159708Simp	int use_rmii;
104155324Simp	struct	ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */
105191959Sstas	int	flags;
106191959Sstas	int	if_flags;
107155324Simp};
108155324Simp
109155324Simpstatic inline uint32_t
110155324SimpRD4(struct ate_softc *sc, bus_size_t off)
111155324Simp{
112155324Simp	return bus_read_4(sc->mem_res, off);
113155324Simp}
114155324Simp
115155324Simpstatic inline void
116155324SimpWR4(struct ate_softc *sc, bus_size_t off, uint32_t val)
117155324Simp{
118155324Simp	bus_write_4(sc->mem_res, off, val);
119155324Simp}
120155324Simp
121192027Sstasstatic inline void
122192027SstasBARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags)
123192027Sstas{
124192027Sstas
125192027Sstas	bus_barrier(sc->mem_res, off, len, flags);
126192027Sstas}
127192027Sstas
128155324Simp#define ATE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
129155324Simp#define	ATE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
130155324Simp#define ATE_LOCK_INIT(_sc) \
131155324Simp	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
132155324Simp	    MTX_NETWORK_LOCK, MTX_DEF)
133155324Simp#define ATE_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
134155324Simp#define ATE_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED);
135155324Simp#define ATE_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
136155324Simp
137155324Simpstatic devclass_t ate_devclass;
138155324Simp
139155324Simp/* ifnet entry points */
140155324Simp
141155324Simpstatic void ateinit_locked(void *);
142155324Simpstatic void atestart_locked(struct ifnet *);
143155324Simp
144155324Simpstatic void ateinit(void *);
145155324Simpstatic void atestart(struct ifnet *);
146155324Simpstatic void atestop(struct ate_softc *);
147155324Simpstatic int ateioctl(struct ifnet * ifp, u_long, caddr_t);
148155324Simp
149155324Simp/* bus entry points */
150155324Simp
151155324Simpstatic int ate_probe(device_t dev);
152155324Simpstatic int ate_attach(device_t dev);
153155324Simpstatic int ate_detach(device_t dev);
154155324Simpstatic void ate_intr(void *);
155155324Simp
156155324Simp/* helper routines */
157155324Simpstatic int ate_activate(device_t dev);
158192018Sstasstatic void ate_deactivate(struct ate_softc *sc);
159155324Simpstatic int ate_ifmedia_upd(struct ifnet *ifp);
160155324Simpstatic void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
161166573Simpstatic int ate_get_mac(struct ate_softc *sc, u_char *eaddr);
162155445Scognetstatic void ate_set_mac(struct ate_softc *sc, u_char *eaddr);
163191959Sstasstatic void	ate_rxfilter(struct ate_softc *sc);
164155324Simp
165155324Simp/*
166155324Simp * The AT91 family of products has the ethernet called EMAC.  However,
167155324Simp * it isn't self identifying.  It is anticipated that the parent bus
168155324Simp * code will take care to only add ate devices where they really are.  As
169155324Simp * such, we do nothing here to identify the device and just set its name.
170155324Simp */
171155324Simpstatic int
172155324Simpate_probe(device_t dev)
173155324Simp{
174155324Simp	device_set_desc(dev, "EMAC");
175155324Simp	return (0);
176155324Simp}
177155324Simp
178155324Simpstatic int
179155324Simpate_attach(device_t dev)
180155324Simp{
181155324Simp	struct ate_softc *sc = device_get_softc(dev);
182155324Simp	struct ifnet *ifp = NULL;
183163522Simp	struct sysctl_ctx_list *sctx;
184163522Simp	struct sysctl_oid *soid;
185182477Sstas	u_char eaddr[ETHER_ADDR_LEN];
186182477Sstas	uint32_t rnd;
187192018Sstas	int rid, err;
188155324Simp
189155324Simp	sc->dev = dev;
190192018Sstas	ATE_LOCK_INIT(sc);
191192018Sstas
192192018Sstas	/*
193192018Sstas	 * Allocate resources.
194192018Sstas	 */
195192018Sstas	rid = 0;
196192018Sstas	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
197192018Sstas	    RF_ACTIVE);
198192018Sstas	if (sc->mem_res == NULL) {
199192018Sstas		device_printf(dev, "could not allocate memory resources.\n");
200192018Sstas		err = ENOMEM;
201192018Sstas		goto out;
202192018Sstas	}
203192018Sstas	rid = 0;
204192018Sstas	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
205192018Sstas	    RF_ACTIVE);
206192018Sstas	if (sc->irq_res == NULL) {
207192018Sstas		device_printf(dev, "could not allocate interrupt resources.\n");
208192018Sstas		err = ENOMEM;
209192018Sstas		goto out;
210192018Sstas	}
211192018Sstas
212155324Simp	err = ate_activate(dev);
213155324Simp	if (err)
214155324Simp		goto out;
215155324Simp
216159708Simp	sc->use_rmii = (RD4(sc, ETH_CFG) & ETH_CFG_RMII) == ETH_CFG_RMII;
217159708Simp
218182476Sstas	/* Sysctls */
219163522Simp	sctx = device_get_sysctl_ctx(dev);
220163522Simp	soid = device_get_sysctl_tree(dev);
221163522Simp	SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "rmii",
222163522Simp	    CTLFLAG_RD, &sc->use_rmii, 0, "rmii in use");
223163522Simp
224155324Simp	/* calling atestop before ifp is set is OK */
225192018Sstas	ATE_LOCK(sc);
226155324Simp	atestop(sc);
227192018Sstas	ATE_UNLOCK(sc);
228155324Simp	callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
229155324Simp
230166573Simp	if ((err = ate_get_mac(sc, eaddr)) != 0) {
231182477Sstas		/*
232182524Sstas		 * No MAC address configured. Generate the random one.
233182477Sstas		 */
234182477Sstas		if  (bootverbose)
235182477Sstas			device_printf(dev,
236182524Sstas			    "Generating random ethernet address.\n");
237182477Sstas		rnd = arc4random();
238182477Sstas
239182477Sstas		/*
240182555Simp		 * Set OUI to convenient locally assigned address.  'b'
241182555Simp		 * is 0x62, which has the locally assigned bit set, and
242182555Simp		 * the broadcast/multicast bit clear.
243182477Sstas		 */
244182555Simp		eaddr[0] = 'b';
245182555Simp		eaddr[1] = 's';
246182555Simp		eaddr[2] = 'd';
247182477Sstas		eaddr[3] = (rnd >> 16) & 0xff;
248182477Sstas		eaddr[4] = (rnd >> 8) & 0xff;
249182477Sstas		eaddr[5] = rnd & 0xff;
250166573Simp	}
251155445Scognet	ate_set_mac(sc, eaddr);
252155324Simp
253155405Scognet	sc->ifp = ifp = if_alloc(IFT_ETHER);
254155324Simp	if (mii_phy_probe(dev, &sc->miibus, ate_ifmedia_upd, ate_ifmedia_sts)) {
255155324Simp		device_printf(dev, "Cannot find my PHY.\n");
256155324Simp		err = ENXIO;
257155324Simp		goto out;
258155324Simp	}
259155324Simp
260155324Simp	ifp->if_softc = sc;
261155324Simp	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
262155324Simp	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
263165779Sticso	ifp->if_capabilities |= IFCAP_VLAN_MTU;
264165779Sticso	ifp->if_capenable |= IFCAP_VLAN_MTU; /* the hw bits already set */
265155324Simp	ifp->if_start = atestart;
266155324Simp	ifp->if_ioctl = ateioctl;
267155324Simp	ifp->if_init = ateinit;
268155324Simp	ifp->if_baudrate = 10000000;
269155324Simp	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
270166625Smlaier	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
271155324Simp	IFQ_SET_READY(&ifp->if_snd);
272155324Simp	ifp->if_timer = 0;
273155324Simp	ifp->if_linkmib = &sc->mibdata;
274155324Simp	ifp->if_linkmiblen = sizeof(sc->mibdata);
275155324Simp	sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS;
276191959Sstas	sc->if_flags = ifp->if_flags;
277155324Simp
278155324Simp	ether_ifattach(ifp, eaddr);
279155324Simp
280155324Simp	/*
281192018Sstas	 * Activate the interrupt.
282155324Simp	 */
283155324Simp	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
284166901Spiso	    NULL, ate_intr, sc, &sc->intrhand);
285155324Simp	if (err) {
286192018Sstas		device_printf(dev, "could not establish interrupt handler.\n");
287155324Simp		ether_ifdetach(ifp);
288192018Sstas		goto out;
289155324Simp	}
290192018Sstas
291192018Sstasout:
292155324Simp	if (err)
293192018Sstas		ate_detach(dev);
294155324Simp	return (err);
295155324Simp}
296155324Simp
297155324Simpstatic int
298155324Simpate_detach(device_t dev)
299155324Simp{
300192018Sstas	struct ate_softc *sc;
301192018Sstas	struct ifnet *ifp;
302192018Sstas
303192018Sstas	sc = device_get_softc(dev);
304192018Sstas	KASSERT(sc != NULL, ("[ate: %d]: sc is NULL", __LINE__));
305192018Sstas	ifp = sc->ifp;
306192018Sstas	if (device_is_attached(dev)) {
307192018Sstas		ATE_LOCK(sc);
308192018Sstas			sc->flags |= ATE_FLAG_DETACHING;
309192018Sstas			atestop(sc);
310192018Sstas		ATE_UNLOCK(sc);
311192018Sstas		callout_drain(&sc->tick_ch);
312192018Sstas		ether_ifdetach(ifp);
313192018Sstas	}
314192018Sstas	if (sc->miibus != NULL) {
315192018Sstas		device_delete_child(dev, sc->miibus);
316192018Sstas		sc->miibus = NULL;
317192018Sstas	}
318192018Sstas	bus_generic_detach(sc->dev);
319192018Sstas	ate_deactivate(sc);
320192018Sstas	if (sc->intrhand != NULL) {
321192018Sstas		bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
322192018Sstas		sc->intrhand = NULL;
323192018Sstas	}
324192018Sstas	if (ifp != NULL) {
325192018Sstas		if_free(ifp);
326192018Sstas		sc->ifp = NULL;
327192018Sstas	}
328192018Sstas	if (sc->mem_res != NULL) {
329192018Sstas		bus_release_resource(dev, SYS_RES_IOPORT,
330192018Sstas		    rman_get_rid(sc->mem_res), sc->mem_res);
331192018Sstas		sc->mem_res = NULL;
332192018Sstas	}
333192018Sstas	if (sc->irq_res != NULL) {
334192018Sstas		bus_release_resource(dev, SYS_RES_IRQ,
335192018Sstas		    rman_get_rid(sc->irq_res), sc->irq_res);
336192018Sstas		sc->irq_res = NULL;
337192018Sstas	}
338192018Sstas	ATE_LOCK_DESTROY(sc);
339192018Sstas	return (0);
340155324Simp}
341155324Simp
342155324Simpstatic void
343155324Simpate_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
344155324Simp{
345155324Simp	struct ate_softc *sc;
346155324Simp
347155324Simp	if (error != 0)
348155324Simp		return;
349155324Simp	sc = (struct ate_softc *)arg;
350155324Simp	sc->rx_desc_phys = segs[0].ds_addr;
351155324Simp}
352155324Simp
353157562Simpstatic void
354157562Simpate_load_rx_buf(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
355157562Simp{
356157562Simp	struct ate_softc *sc;
357157562Simp	int i;
358157562Simp
359157562Simp	if (error != 0)
360157562Simp		return;
361157562Simp	sc = (struct ate_softc *)arg;
362157562Simp	i = sc->rx_buf_ptr;
363157562Simp
364157562Simp	/*
365157562Simp	 * For the last buffer, set the wrap bit so the controller
366157562Simp	 * restarts from the first descriptor.
367157562Simp	 */
368163937Simp	bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
369157562Simp	if (i == ATE_MAX_RX_BUFFERS - 1)
370157562Simp		sc->rx_descs[i].addr = segs[0].ds_addr | ETH_WRAP_BIT;
371157562Simp	else
372157562Simp		sc->rx_descs[i].addr = segs[0].ds_addr;
373163937Simp	bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_POSTWRITE);
374157562Simp	sc->rx_descs[i].status = 0;
375157562Simp	/* Flush the memory in the mbuf */
376157562Simp	bus_dmamap_sync(sc->rxtag, sc->rx_map[i], BUS_DMASYNC_PREREAD);
377157562Simp}
378157562Simp
379155324Simp/*
380155324Simp * Compute the multicast filter for this device using the standard
381155324Simp * algorithm.  I wonder why this isn't in ether somewhere as a lot
382155324Simp * of different MAC chips use this method (or the reverse the bits)
383155324Simp * method.
384155324Simp */
385191960Sstasstatic int
386155324Simpate_setmcast(struct ate_softc *sc)
387155324Simp{
388155324Simp	uint32_t index;
389155324Simp	uint32_t mcaf[2];
390155324Simp	u_char *af = (u_char *) mcaf;
391155324Simp	struct ifmultiaddr *ifma;
392191960Sstas	struct ifnet *ifp;
393155324Simp
394191960Sstas	ifp = sc->ifp;
395191960Sstas
396191960Sstas	if ((ifp->if_flags & IFF_PROMISC) != 0)
397191960Sstas		return (0);
398191960Sstas	if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
399191960Sstas		WR4(sc, ETH_HSL, 0xffffffff);
400191960Sstas		WR4(sc, ETH_HSH, 0xffffffff);
401191960Sstas		return (1);
402191960Sstas	}
403191960Sstas
404191960Sstas	/*
405191960Sstas	 * Compute the multicast hash.
406191960Sstas	 */
407155324Simp	mcaf[0] = 0;
408155324Simp	mcaf[1] = 0;
409191960Sstas	IF_ADDR_LOCK(ifp);
410191960Sstas	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
411155324Simp		if (ifma->ifma_addr->sa_family != AF_LINK)
412155324Simp			continue;
413155324Simp		index = ether_crc32_be(LLADDR((struct sockaddr_dl *)
414155324Simp		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
415155324Simp		af[index >> 3] |= 1 << (index & 7);
416155324Simp	}
417191960Sstas	IF_ADDR_UNLOCK(ifp);
418155324Simp
419155324Simp	/*
420155324Simp	 * Write the hash to the hash register.  This card can also
421155324Simp	 * accept unicast packets as well as multicast packets using this
422155324Simp	 * register for easier bridging operations, but we don't take
423155324Simp	 * advantage of that.  Locks here are to avoid LOR with the
424155324Simp	 * IF_ADDR_LOCK, but might not be strictly necessary.
425155324Simp	 */
426155324Simp	WR4(sc, ETH_HSL, mcaf[0]);
427155324Simp	WR4(sc, ETH_HSH, mcaf[1]);
428191960Sstas	return (mcaf[0] || mcaf[1]);
429155324Simp}
430155324Simp
431155324Simpstatic int
432155324Simpate_activate(device_t dev)
433155324Simp{
434155324Simp	struct ate_softc *sc;
435192018Sstas	int err, i;
436155324Simp
437155324Simp	sc = device_get_softc(dev);
438155324Simp	/*
439155324Simp	 * Allocate DMA tags and maps
440155324Simp	 */
441183670Simp	err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
442183670Simp	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
443183670Simp	    1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->mtag);
444155324Simp	if (err != 0)
445155324Simp		goto errout;
446155324Simp	for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
447155324Simp		err = bus_dmamap_create(sc->mtag, 0, &sc->tx_map[i]);
448155324Simp		if (err != 0)
449155324Simp			goto errout;
450155324Simp	}
451155324Simp	 /*
452155324Simp	  * Allocate our Rx buffers.  This chip has a rx structure that's filled
453155324Simp	  * in
454155324Simp	  */
455155324Simp
456155324Simp	/*
457155324Simp	 * Allocate DMA tags and maps for RX.
458155324Simp	 */
459183670Simp	err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
460183670Simp	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
461183670Simp	    1, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx, &sc->rxtag);
462155324Simp	if (err != 0)
463155324Simp		goto errout;
464155324Simp
465155324Simp	/* Dma TAG and MAP for the rx descriptors. */
466183670Simp	err = bus_dma_tag_create(bus_get_dma_tag(dev), sizeof(eth_rx_desc_t),
467183670Simp	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
468155324Simp	    ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), 1,
469155324Simp	    ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t), 0, busdma_lock_mutex,
470155324Simp	    &sc->sc_mtx, &sc->rx_desc_tag);
471155324Simp	if (err != 0)
472155324Simp		goto errout;
473156831Simp	if (bus_dmamem_alloc(sc->rx_desc_tag, (void **)&sc->rx_descs,
474156831Simp	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rx_desc_map) != 0)
475155324Simp		goto errout;
476157562Simp	if (bus_dmamap_load(sc->rx_desc_tag, sc->rx_desc_map,
477155324Simp	    sc->rx_descs, ATE_MAX_RX_BUFFERS * sizeof(eth_rx_desc_t),
478155324Simp	    ate_getaddr, sc, 0) != 0)
479155324Simp		goto errout;
480155324Simp	for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
481157562Simp		sc->rx_buf_ptr = i;
482157562Simp		if (bus_dmamem_alloc(sc->rxtag, (void **)&sc->rx_buf[i],
483157562Simp		      BUS_DMA_NOWAIT, &sc->rx_map[i]) != 0)
484155324Simp			goto errout;
485157562Simp		if (bus_dmamap_load(sc->rxtag, sc->rx_map[i], sc->rx_buf[i],
486157562Simp		    MCLBYTES, ate_load_rx_buf, sc, 0) != 0)
487157562Simp			goto errout;
488155324Simp	}
489157562Simp	sc->rx_buf_ptr = 0;
490156831Simp	/* Flush the memory for the EMAC rx descriptor */
491155324Simp	bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map, BUS_DMASYNC_PREWRITE);
492155324Simp	/* Write the descriptor queue address. */
493155324Simp	WR4(sc, ETH_RBQP, sc->rx_desc_phys);
494155324Simp	return (0);
495192018Sstas
496155324Simperrout:
497155324Simp	return (ENOMEM);
498155324Simp}
499155324Simp
500155324Simpstatic void
501192018Sstasate_deactivate(struct ate_softc *sc)
502155324Simp{
503192018Sstas	int i;
504155324Simp
505192018Sstas	KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
506192018Sstas	if (sc->mtag != NULL) {
507192018Sstas		for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
508192018Sstas			if (sc->sent_mbuf[i] != NULL) {
509192018Sstas				bus_dmamap_sync(sc->mtag, sc->tx_map[i],
510192018Sstas				    BUS_DMASYNC_POSTWRITE);
511192018Sstas				bus_dmamap_unload(sc->mtag, sc->tx_map[i]);
512192018Sstas				m_freem(sc->sent_mbuf[i]);
513155324Simp			}
514192018Sstas			bus_dmamap_destroy(sc->mtag, sc->tx_map[i]);
515192018Sstas			sc->sent_mbuf[i] = NULL;
516192018Sstas			sc->tx_map[i] = NULL;
517155324Simp		}
518192018Sstas		bus_dma_tag_destroy(sc->mtag);
519192018Sstas	}
520192018Sstas	if (sc->rx_desc_tag != NULL) {
521192018Sstas		if (sc->rx_descs != NULL) {
522192018Sstas			if (sc->rx_desc_phys != 0) {
523192018Sstas				bus_dmamap_sync(sc->rx_desc_tag,
524192018Sstas				    sc->rx_desc_map, BUS_DMASYNC_POSTREAD);
525192018Sstas				bus_dmamap_unload(sc->rx_desc_tag,
526192018Sstas				    sc->rx_desc_map);
527192018Sstas				sc->rx_desc_phys = 0;
528155324Simp			}
529155324Simp		}
530155324Simp	}
531192018Sstas	if (sc->rxtag != NULL) {
532192018Sstas		for (i = 0; i < ATE_MAX_RX_BUFFERS; i++) {
533192018Sstas			if (sc->rx_buf[i] != NULL) {
534192018Sstas				if (sc->rx_descs[i].addr != 0) {
535192018Sstas					bus_dmamap_sync(sc->rxtag,
536192018Sstas					    sc->rx_map[i],
537192018Sstas					    BUS_DMASYNC_POSTREAD);
538192018Sstas					bus_dmamap_unload(sc->rxtag,
539192018Sstas					    sc->rx_map[i]);
540192018Sstas					sc->rx_descs[i].addr = 0;
541192018Sstas				}
542192018Sstas				bus_dmamem_free(sc->rxtag, sc->rx_buf[i],
543192018Sstas				    sc->rx_map[i]);
544192018Sstas				sc->rx_buf[i] = NULL;
545192018Sstas				sc->rx_map[i] = NULL;
546192018Sstas			}
547192018Sstas		}
548192018Sstas		bus_dma_tag_destroy(sc->rxtag);
549192018Sstas	}
550192018Sstas	if (sc->rx_desc_tag != NULL) {
551192018Sstas		if (sc->rx_descs != NULL)
552192018Sstas			bus_dmamem_free(sc->rx_desc_tag, sc->rx_descs,
553192018Sstas			    sc->rx_desc_map);
554192018Sstas		bus_dma_tag_destroy(sc->rx_desc_tag);
555192018Sstas		sc->rx_descs = NULL;
556192018Sstas		sc->rx_desc_tag = NULL;
557192018Sstas	}
558155324Simp}
559155324Simp
560155324Simp/*
561155324Simp * Change media according to request.
562155324Simp */
563155324Simpstatic int
564155324Simpate_ifmedia_upd(struct ifnet *ifp)
565155324Simp{
566155324Simp	struct ate_softc *sc = ifp->if_softc;
567155324Simp	struct mii_data *mii;
568155324Simp
569155324Simp	mii = device_get_softc(sc->miibus);
570155324Simp	ATE_LOCK(sc);
571155324Simp	mii_mediachg(mii);
572155324Simp	ATE_UNLOCK(sc);
573155324Simp	return (0);
574155324Simp}
575155324Simp
576155324Simp/*
577155324Simp * Notify the world which media we're using.
578155324Simp */
579155324Simpstatic void
580155324Simpate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
581155324Simp{
582155324Simp	struct ate_softc *sc = ifp->if_softc;
583155324Simp	struct mii_data *mii;
584155324Simp
585155324Simp	mii = device_get_softc(sc->miibus);
586155324Simp	ATE_LOCK(sc);
587155324Simp	mii_pollstat(mii);
588155324Simp	ifmr->ifm_active = mii->mii_media_active;
589155324Simp	ifmr->ifm_status = mii->mii_media_status;
590155324Simp	ATE_UNLOCK(sc);
591155324Simp}
592155324Simp
593155324Simpstatic void
594163937Simpate_stat_update(struct ate_softc *sc, int active)
595163937Simp{
596192027Sstas	uint32_t reg;
597192027Sstas
598163937Simp	/*
599163937Simp	 * The speed and full/half-duplex state needs to be reflected
600163937Simp	 * in the ETH_CFG register.
601163937Simp	 */
602192027Sstas	reg = RD4(sc, ETH_CFG);
603192027Sstas	reg &= ~(ETH_CFG_SPD | ETH_CFG_FD);
604192027Sstas	if (IFM_SUBTYPE(active) != IFM_10_T)
605192027Sstas		reg |= ETH_CFG_SPD;
606163937Simp	if (active & IFM_FDX)
607192027Sstas		reg |= ETH_CFG_FD;
608192027Sstas	WR4(sc, ETH_CFG, reg);
609163937Simp}
610163937Simp
611163937Simpstatic void
612155324Simpate_tick(void *xsc)
613155324Simp{
614155324Simp	struct ate_softc *sc = xsc;
615163937Simp	struct ifnet *ifp = sc->ifp;
616155324Simp	struct mii_data *mii;
617155324Simp	int active;
618163937Simp	uint32_t c;
619155324Simp
620155324Simp	/*
621155324Simp	 * The KB920x boot loader tests ETH_SR & ETH_SR_LINK and will ask
622155324Simp	 * the MII if there's a link if this bit is clear.  Not sure if we
623155324Simp	 * should do the same thing here or not.
624155324Simp	 */
625155324Simp	ATE_ASSERT_LOCKED(sc);
626155324Simp	if (sc->miibus != NULL) {
627155324Simp		mii = device_get_softc(sc->miibus);
628155324Simp		active = mii->mii_media_active;
629155324Simp		mii_tick(mii);
630155324Simp		if (mii->mii_media_status & IFM_ACTIVE &&
631163937Simp		     active != mii->mii_media_active)
632163937Simp			ate_stat_update(sc, mii->mii_media_active);
633155324Simp	}
634155324Simp
635155324Simp	/*
636155324Simp	 * Update the stats as best we can.  When we're done, clear
637155324Simp	 * the status counters and start over.  We're supposed to read these
638155324Simp	 * registers often enough that they won't overflow.  Hopefully
639155324Simp	 * once a second is often enough.  Some don't map well to
640155324Simp	 * the dot3Stats mib, so for those we just count them as general
641155324Simp	 * errors.  Stats for iframes, ibutes, oframes and obytes are
642155324Simp	 * collected elsewhere.  These registers zero on a read to prevent
643163937Simp	 * races.  For all the collision stats, also update the collision
644163937Simp	 * stats for the interface.
645155324Simp	 */
646155324Simp	sc->mibdata.dot3StatsAlignmentErrors += RD4(sc, ETH_ALE);
647155324Simp	sc->mibdata.dot3StatsFCSErrors += RD4(sc, ETH_SEQE);
648163937Simp	c = RD4(sc, ETH_SCOL);
649163937Simp	ifp->if_collisions += c;
650163937Simp	sc->mibdata.dot3StatsSingleCollisionFrames += c;
651163937Simp	c = RD4(sc, ETH_MCOL);
652163937Simp	sc->mibdata.dot3StatsMultipleCollisionFrames += c;
653163937Simp	ifp->if_collisions += c;
654155324Simp	sc->mibdata.dot3StatsSQETestErrors += RD4(sc, ETH_SQEE);
655155324Simp	sc->mibdata.dot3StatsDeferredTransmissions += RD4(sc, ETH_DTE);
656163937Simp	c = RD4(sc, ETH_LCOL);
657163937Simp	sc->mibdata.dot3StatsLateCollisions += c;
658163937Simp	ifp->if_collisions += c;
659163937Simp	c = RD4(sc, ETH_ECOL);
660163937Simp	sc->mibdata.dot3StatsExcessiveCollisions += c;
661163937Simp	ifp->if_collisions += c;
662155324Simp	sc->mibdata.dot3StatsCarrierSenseErrors += RD4(sc, ETH_CSE);
663155324Simp	sc->mibdata.dot3StatsFrameTooLongs += RD4(sc, ETH_ELR);
664155324Simp	sc->mibdata.dot3StatsInternalMacReceiveErrors += RD4(sc, ETH_DRFC);
665155324Simp	/*
666155324Simp	 * not sure where to lump these, so count them against the errors
667155324Simp	 * for the interface.
668155324Simp	 */
669163937Simp	sc->ifp->if_oerrors += RD4(sc, ETH_TUE);
670155324Simp	sc->ifp->if_ierrors += RD4(sc, ETH_CDE) + RD4(sc, ETH_RJB) +
671155324Simp	    RD4(sc, ETH_USF);
672155324Simp
673155324Simp	/*
674155324Simp	 * Schedule another timeout one second from now.
675155324Simp	 */
676155324Simp	callout_reset(&sc->tick_ch, hz, ate_tick, sc);
677155324Simp}
678155324Simp
679155324Simpstatic void
680155445Scognetate_set_mac(struct ate_softc *sc, u_char *eaddr)
681155445Scognet{
682155445Scognet	WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) |
683155445Scognet	    (eaddr[1] << 8) | eaddr[0]);
684155445Scognet	WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4]));
685155445Scognet}
686155445Scognet
687166573Simpstatic int
688155324Simpate_get_mac(struct ate_softc *sc, u_char *eaddr)
689155324Simp{
690182477Sstas	bus_size_t sa_low_reg[] = { ETH_SA1L, ETH_SA2L, ETH_SA3L, ETH_SA4L };
691182477Sstas	bus_size_t sa_high_reg[] = { ETH_SA1H, ETH_SA2H, ETH_SA3H, ETH_SA4H };
692166573Simp	uint32_t low, high;
693182477Sstas	int i;
694155324Simp
695166573Simp	/*
696166573Simp	 * The boot loader setup the MAC with an address, if one is set in
697182477Sstas	 * the loader. Grab one MAC address from the SA[1-4][HL] registers.
698166573Simp	 */
699182477Sstas	for (i = 0; i < 4; i++) {
700182477Sstas		low = RD4(sc, sa_low_reg[i]);
701182477Sstas		high = RD4(sc, sa_high_reg[i]);
702182477Sstas		if ((low | (high & 0xffff)) != 0) {
703182477Sstas			eaddr[0] = low & 0xff;
704182477Sstas			eaddr[1] = (low >> 8) & 0xff;
705182477Sstas			eaddr[2] = (low >> 16) & 0xff;
706182477Sstas			eaddr[3] = (low >> 24) & 0xff;
707182477Sstas			eaddr[4] = high & 0xff;
708182477Sstas			eaddr[5] = (high >> 8) & 0xff;
709182477Sstas			return (0);
710182477Sstas		}
711182477Sstas	}
712182477Sstas	return (ENXIO);
713155324Simp}
714155324Simp
715155324Simpstatic void
716155324Simpate_intr(void *xsc)
717155324Simp{
718155324Simp	struct ate_softc *sc = xsc;
719163937Simp	struct ifnet *ifp = sc->ifp;
720192027Sstas	struct mbuf *mb;
721192027Sstas	void *bp;
722192027Sstas	uint32_t status, reg, rx_stat;
723155324Simp	int i;
724156831Simp
725155324Simp	status = RD4(sc, ETH_ISR);
726155324Simp	if (status == 0)
727155324Simp		return;
728155324Simp	if (status & ETH_ISR_RCOM) {
729155324Simp		bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
730155324Simp		    BUS_DMASYNC_POSTREAD);
731157562Simp		while (sc->rx_descs[sc->rx_buf_ptr].addr & ETH_CPU_OWNER) {
732157562Simp			i = sc->rx_buf_ptr;
733157562Simp			sc->rx_buf_ptr = (i + 1) % ATE_MAX_RX_BUFFERS;
734157562Simp			bp = sc->rx_buf[i];
735156831Simp			rx_stat = sc->rx_descs[i].status;
736156831Simp			if ((rx_stat & ETH_LEN_MASK) == 0) {
737156831Simp				printf("ignoring bogus 0 len packet\n");
738163937Simp				bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
739163937Simp				    BUS_DMASYNC_PREWRITE);
740157562Simp				sc->rx_descs[i].addr &= ~ETH_CPU_OWNER;
741156831Simp				bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
742163937Simp				    BUS_DMASYNC_POSTWRITE);
743156831Simp				continue;
744155324Simp			}
745156831Simp			/* Flush memory for mbuf so we don't get stale bytes */
746156831Simp			bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
747156831Simp			    BUS_DMASYNC_POSTREAD);
748163937Simp			WR4(sc, ETH_RSR, RD4(sc, ETH_RSR));
749163937Simp
750156831Simp			/*
751156831Simp			 * The length returned by the device includes the
752156831Simp			 * ethernet CRC calculation for the packet, but
753156831Simp			 * ifnet drivers are supposed to discard it.
754156831Simp			 */
755157562Simp			mb = m_devget(sc->rx_buf[i],
756157562Simp			    (rx_stat & ETH_LEN_MASK) - ETHER_CRC_LEN,
757163937Simp			    ETHER_ALIGN, ifp, NULL);
758163937Simp			bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
759163937Simp			    BUS_DMASYNC_PREWRITE);
760157562Simp			sc->rx_descs[i].addr &= ~ETH_CPU_OWNER;
761157562Simp			bus_dmamap_sync(sc->rx_desc_tag, sc->rx_desc_map,
762163937Simp			    BUS_DMASYNC_POSTWRITE);
763156831Simp			bus_dmamap_sync(sc->rxtag, sc->rx_map[i],
764156831Simp			    BUS_DMASYNC_PREREAD);
765163937Simp			if (mb != NULL) {
766163937Simp				ifp->if_ipackets++;
767163937Simp				(*ifp->if_input)(ifp, mb);
768163937Simp			}
769163937Simp
770155324Simp		}
771155324Simp	}
772155324Simp	if (status & ETH_ISR_TCOM) {
773156831Simp		ATE_LOCK(sc);
774163937Simp		/* XXX TSR register should be cleared */
775156831Simp		if (sc->sent_mbuf[0]) {
776179693Swkoszek			bus_dmamap_sync(sc->mtag, sc->tx_map[0],
777163937Simp			    BUS_DMASYNC_POSTWRITE);
778192018Sstas			bus_dmamap_unload(sc->mtag, sc->tx_map[0]);
779155324Simp			m_freem(sc->sent_mbuf[0]);
780163937Simp			ifp->if_opackets++;
781156831Simp			sc->sent_mbuf[0] = NULL;
782156831Simp		}
783155324Simp		if (sc->sent_mbuf[1]) {
784155324Simp			if (RD4(sc, ETH_TSR) & ETH_TSR_IDLE) {
785179693Swkoszek				bus_dmamap_sync(sc->mtag, sc->tx_map[1],
786163937Simp				    BUS_DMASYNC_POSTWRITE);
787192018Sstas				bus_dmamap_unload(sc->mtag, sc->tx_map[1]);
788155324Simp				m_freem(sc->sent_mbuf[1]);
789163937Simp				ifp->if_opackets++;
790155324Simp				sc->txcur = 0;
791155324Simp				sc->sent_mbuf[0] = sc->sent_mbuf[1] = NULL;
792155324Simp			} else {
793155324Simp				sc->sent_mbuf[0] = sc->sent_mbuf[1];
794155324Simp				sc->sent_mbuf[1] = NULL;
795155324Simp				sc->txcur = 1;
796155324Simp			}
797155324Simp		} else {
798155324Simp			sc->sent_mbuf[0] = NULL;
799155324Simp			sc->txcur = 0;
800155324Simp		}
801156831Simp		/*
802156831Simp		 * We're no longer busy, so clear the busy flag and call the
803156831Simp		 * start routine to xmit more packets.
804156831Simp		 */
805156831Simp		sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
806156831Simp		atestart_locked(sc->ifp);
807156831Simp		ATE_UNLOCK(sc);
808155324Simp	}
809155324Simp	if (status & ETH_ISR_RBNA) {
810155324Simp		/* Workaround Errata #11 */
811192027Sstas		reg = RD4(sc, ETH_CTL);
812192027Sstas		WR4(sc, ETH_CTL, reg & ~ETH_CTL_RE);
813192027Sstas		BARRIER(sc, ETH_CTL, 4, BUS_SPACE_BARRIER_WRITE);
814192027Sstas		WR4(sc, ETH_CTL, reg | ETH_CTL_RE);
815155324Simp	}
816155324Simp}
817155324Simp
818155324Simp/*
819155324Simp * Reset and initialize the chip
820155324Simp */
821155324Simpstatic void
822155324Simpateinit_locked(void *xsc)
823155324Simp{
824155324Simp	struct ate_softc *sc = xsc;
825155324Simp	struct ifnet *ifp = sc->ifp;
826163937Simp 	struct mii_data *mii;
827192027Sstas	uint32_t reg;
828155324Simp
829155324Simp	ATE_ASSERT_LOCKED(sc);
830155324Simp
831155324Simp	/*
832155324Simp	 * XXX TODO(3)
833155324Simp	 * we need to turn on the EMAC clock in the pmc.  With the
834155324Simp	 * default boot loader, this is already turned on.  However, we
835155324Simp	 * need to think about how best to turn it on/off as the interface
836155324Simp	 * is brought up/down, as well as dealing with the mii bus...
837155324Simp	 *
838155324Simp	 * We also need to multiplex the pins correctly.
839155324Simp	 */
840155324Simp
841155324Simp	/*
842155324Simp	 * There are two different ways that the mii bus is connected
843155324Simp	 * to this chip.  Select the right one based on a compile-time
844155324Simp	 * option.
845155324Simp	 */
846192027Sstas	reg = RD4(sc, ETH_CFG);
847159708Simp	if (sc->use_rmii)
848192027Sstas		reg |= ETH_CFG_RMII;
849159708Simp	else
850192027Sstas		reg &= ~ETH_CFG_RMII;
851192027Sstas	WR4(sc, ETH_CFG, reg);
852159708Simp
853191960Sstas	ate_rxfilter(sc);
854191960Sstas
855191960Sstas	/*
856191960Sstas	 * Turn on MACs and interrupt processing.
857191960Sstas	 */
858155324Simp	WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE);
859156831Simp	WR4(sc, ETH_IER, ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA);
860155324Simp
861155324Simp	/*
862155324Simp	 * Boot loader fills in MAC address.  If that's not the case, then
863155324Simp	 * we should set SA1L and SA1H here to the appropriate value.  Note:
864155324Simp	 * the byte order is big endian, not little endian, so we have some
865155324Simp	 * swapping to do.  Again, if we need it (which I don't think we do).
866155324Simp	 */
867155324Simp
868165779Sticso	/* enable big packets */
869165779Sticso	WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
870165779Sticso
871155324Simp	/*
872155324Simp	 * Set 'running' flag, and clear output active flag
873155324Simp	 * and attempt to start the output
874155324Simp	 */
875155324Simp	ifp->if_drv_flags |= IFF_DRV_RUNNING;
876155324Simp	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
877163937Simp
878163937Simp	mii = device_get_softc(sc->miibus);
879163937Simp	mii_pollstat(mii);
880163937Simp	ate_stat_update(sc, mii->mii_media_active);
881155324Simp	atestart_locked(ifp);
882155324Simp
883155324Simp	callout_reset(&sc->tick_ch, hz, ate_tick, sc);
884155324Simp}
885155324Simp
886155324Simp/*
887155324Simp * dequeu packets and transmit
888155324Simp */
889155324Simpstatic void
890155324Simpatestart_locked(struct ifnet *ifp)
891155324Simp{
892155324Simp	struct ate_softc *sc = ifp->if_softc;
893155324Simp	struct mbuf *m, *mdefrag;
894155324Simp	bus_dma_segment_t segs[1];
895163937Simp	int nseg, e;
896155324Simp
897155324Simp	ATE_ASSERT_LOCKED(sc);
898155324Simp	if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
899155324Simp		return;
900155324Simp
901156831Simp	while (sc->txcur < ATE_MAX_TX_BUFFERS) {
902156831Simp		/*
903156831Simp		 * check to see if there's room to put another packet into the
904156831Simp		 * xmit queue.  The EMAC chip has a ping-pong buffer for xmit
905156831Simp		 * packets.  We use OACTIVE to indicate "we can stuff more into
906156831Simp		 * our buffers (clear) or not (set)."
907156831Simp		 */
908156831Simp		if (!(RD4(sc, ETH_TSR) & ETH_TSR_BNQ)) {
909156831Simp			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
910156831Simp			return;
911156831Simp		}
912156831Simp		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
913156831Simp		if (m == 0) {
914156831Simp			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
915156831Simp			return;
916156831Simp		}
917163937Simp		e = bus_dmamap_load_mbuf_sg(sc->mtag, sc->tx_map[sc->txcur], m,
918163937Simp		    segs, &nseg, 0);
919163937Simp		if (e == EFBIG) {
920163937Simp			mdefrag = m_defrag(m, M_DONTWAIT);
921163937Simp			if (mdefrag == NULL) {
922163937Simp				IFQ_DRV_PREPEND(&ifp->if_snd, m);
923163937Simp				return;
924163937Simp			}
925163937Simp			m = mdefrag;
926163937Simp			e = bus_dmamap_load_mbuf_sg(sc->mtag,
927163937Simp			    sc->tx_map[sc->txcur], m, segs, &nseg, 0);
928156831Simp		}
929163937Simp		if (e != 0) {
930156831Simp			m_freem(m);
931156831Simp			continue;
932156831Simp		}
933156831Simp		bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txcur],
934156831Simp		    BUS_DMASYNC_PREWRITE);
935155324Simp
936156831Simp		/*
937156831Simp		 * tell the hardware to xmit the packet.
938156831Simp		 */
939156831Simp		WR4(sc, ETH_TAR, segs[0].ds_addr);
940192027Sstas		BARRIER(sc, ETH_TAR, 8, BUS_SPACE_BARRIER_WRITE);
941156831Simp		WR4(sc, ETH_TCR, segs[0].ds_len);
942155324Simp
943156831Simp		/*
944156831Simp		 * Tap off here if there is a bpf listener.
945156831Simp		 */
946156831Simp		BPF_MTAP(ifp, m);
947155324Simp
948156831Simp		sc->sent_mbuf[sc->txcur] = m;
949156831Simp		sc->txcur++;
950156831Simp	}
951155324Simp}
952155324Simp
953155324Simpstatic void
954155324Simpateinit(void *xsc)
955155324Simp{
956155324Simp	struct ate_softc *sc = xsc;
957155324Simp	ATE_LOCK(sc);
958155324Simp	ateinit_locked(sc);
959155324Simp	ATE_UNLOCK(sc);
960155324Simp}
961155324Simp
962155324Simpstatic void
963155324Simpatestart(struct ifnet *ifp)
964155324Simp{
965155324Simp	struct ate_softc *sc = ifp->if_softc;
966155324Simp	ATE_LOCK(sc);
967155324Simp	atestart_locked(ifp);
968155324Simp	ATE_UNLOCK(sc);
969155324Simp}
970155324Simp
971155324Simp/*
972155324Simp * Turn off interrupts, and stop the nic.  Can be called with sc->ifp NULL
973155324Simp * so be careful.
974155324Simp */
975155324Simpstatic void
976155324Simpatestop(struct ate_softc *sc)
977155324Simp{
978192018Sstas	struct ifnet *ifp;
979192018Sstas	int i;
980155324Simp
981192018Sstas	ATE_ASSERT_LOCKED(sc);
982192018Sstas	ifp = sc->ifp;
983155324Simp	if (ifp) {
984155324Simp		ifp->if_timer = 0;
985155324Simp		ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
986155324Simp	}
987155324Simp
988155324Simp	callout_stop(&sc->tick_ch);
989155324Simp
990155324Simp	/*
991155324Simp	 * Enable some parts of the MAC that are needed always (like the
992155324Simp	 * MII bus.  This turns off the RE and TE bits, which will remain
993155405Scognet	 * off until ateinit() is called to turn them on.  With RE and TE
994155324Simp	 * turned off, there's no DMA to worry about after this write.
995155324Simp	 */
996155324Simp	WR4(sc, ETH_CTL, ETH_CTL_MPE);
997155324Simp
998155324Simp	/*
999155324Simp	 * Turn off all the configured options and revert to defaults.
1000155324Simp	 */
1001155324Simp	WR4(sc, ETH_CFG, ETH_CFG_CLK_32);
1002155324Simp
1003155324Simp	/*
1004155324Simp	 * Turn off all the interrupts, and ack any pending ones by reading
1005155324Simp	 * the ISR.
1006155324Simp	 */
1007155324Simp	WR4(sc, ETH_IDR, 0xffffffff);
1008155324Simp	RD4(sc, ETH_ISR);
1009155324Simp
1010155324Simp	/*
1011155324Simp	 * Clear out the Transmit and Receiver Status registers of any
1012155324Simp	 * errors they may be reporting
1013155324Simp	 */
1014155324Simp	WR4(sc, ETH_TSR, 0xffffffff);
1015155324Simp	WR4(sc, ETH_RSR, 0xffffffff);
1016155324Simp
1017155324Simp	/*
1018192018Sstas	 * Release TX resources.
1019155324Simp	 */
1020192018Sstas	for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) {
1021192018Sstas		if (sc->sent_mbuf[i] != NULL) {
1022192018Sstas			bus_dmamap_sync(sc->mtag, sc->tx_map[i],
1023192018Sstas			    BUS_DMASYNC_POSTWRITE);
1024192018Sstas			bus_dmamap_unload(sc->mtag, sc->tx_map[i]);
1025192018Sstas			m_freem(sc->sent_mbuf[i]);
1026192018Sstas			sc->sent_mbuf[i] = NULL;
1027192018Sstas		}
1028192018Sstas	}
1029155324Simp
1030155324Simp	/*
1031155324Simp	 * XXX we should power down the EMAC if it isn't in use, after
1032155324Simp	 * putting it into loopback mode.  This saves about 400uA according
1033155324Simp	 * to the datasheet.
1034155324Simp	 */
1035155324Simp}
1036155324Simp
1037191959Sstasstatic void
1038191959Sstasate_rxfilter(struct ate_softc *sc)
1039191959Sstas{
1040191959Sstas	struct ifnet *ifp;
1041191959Sstas	uint32_t reg;
1042191960Sstas	int enabled;
1043191959Sstas
1044191959Sstas	KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
1045191959Sstas	ATE_ASSERT_LOCKED(sc);
1046191959Sstas	ifp = sc->ifp;
1047191959Sstas
1048191959Sstas	/*
1049191959Sstas	 * Wipe out old filter settings.
1050191959Sstas	 */
1051191959Sstas	reg = RD4(sc, ETH_CFG);
1052191959Sstas	reg &= ~(ETH_CFG_CAF | ETH_CFG_MTI | ETH_CFG_UNI);
1053191959Sstas	reg |= ETH_CFG_NBC;
1054191960Sstas	sc->flags &= ~ATE_FLAG_MULTICAST;
1055191959Sstas
1056191959Sstas	/*
1057191959Sstas	 * Set new parameters.
1058191959Sstas	 */
1059191959Sstas	if ((ifp->if_flags & IFF_BROADCAST) != 0)
1060191959Sstas		reg &= ~ETH_CFG_NBC;
1061191960Sstas	if ((ifp->if_flags & IFF_PROMISC) != 0) {
1062191959Sstas		reg |= ETH_CFG_CAF;
1063191960Sstas	} else {
1064191960Sstas		enabled = ate_setmcast(sc);
1065191960Sstas		if (enabled != 0) {
1066191960Sstas			reg |= ETH_CFG_MTI;
1067191960Sstas			sc->flags |= ATE_FLAG_MULTICAST;
1068191960Sstas		}
1069191960Sstas	}
1070191959Sstas	WR4(sc, ETH_CFG, reg);
1071191959Sstas}
1072191959Sstas
1073155324Simpstatic int
1074155324Simpateioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1075155324Simp{
1076155324Simp	struct ate_softc *sc = ifp->if_softc;
1077157562Simp 	struct mii_data *mii;
1078157562Simp 	struct ifreq *ifr = (struct ifreq *)data;
1079191959Sstas	int drv_flags, flags;
1080191960Sstas	int mask, error, enabled;
1081155324Simp
1082191960Sstas	error = 0;
1083191959Sstas	flags = ifp->if_flags;
1084191959Sstas	drv_flags = ifp->if_drv_flags;
1085155324Simp	switch (cmd) {
1086155324Simp	case SIOCSIFFLAGS:
1087155324Simp		ATE_LOCK(sc);
1088191959Sstas		if ((flags & IFF_UP) != 0) {
1089191959Sstas			if ((drv_flags & IFF_DRV_RUNNING) != 0) {
1090191959Sstas				if (((flags ^ sc->if_flags)
1091191959Sstas				    & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
1092191959Sstas					ate_rxfilter(sc);
1093191959Sstas			} else {
1094191959Sstas				if ((sc->flags & ATE_FLAG_DETACHING) == 0)
1095191959Sstas					ateinit_locked(sc);
1096191959Sstas			}
1097191959Sstas		} else if ((drv_flags & IFF_DRV_RUNNING) != 0) {
1098155324Simp			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1099155324Simp			atestop(sc);
1100155324Simp		}
1101191959Sstas		sc->if_flags = flags;
1102155324Simp		ATE_UNLOCK(sc);
1103155324Simp		break;
1104155324Simp
1105155324Simp	case SIOCADDMULTI:
1106155324Simp	case SIOCDELMULTI:
1107191960Sstas		if ((drv_flags & IFF_DRV_RUNNING) != 0) {
1108191960Sstas			ATE_LOCK(sc);
1109191960Sstas			enabled = ate_setmcast(sc);
1110191960Sstas			if (enabled != (sc->flags & ATE_FLAG_MULTICAST))
1111191960Sstas				ate_rxfilter(sc);
1112191960Sstas			ATE_UNLOCK(sc);
1113191960Sstas		}
1114155324Simp		break;
1115155324Simp
1116157562Simp  	case SIOCSIFMEDIA:
1117157562Simp  	case SIOCGIFMEDIA:
1118157562Simp 		mii = device_get_softc(sc->miibus);
1119157562Simp 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1120157562Simp  		break;
1121165779Sticso	case SIOCSIFCAP:
1122165779Sticso		mask = ifp->if_capenable ^ ifr->ifr_reqcap;
1123165779Sticso		if (mask & IFCAP_VLAN_MTU) {
1124165779Sticso			ATE_LOCK(sc);
1125165779Sticso			if (ifr->ifr_reqcap & IFCAP_VLAN_MTU) {
1126165779Sticso				WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
1127165779Sticso				ifp->if_capenable |= IFCAP_VLAN_MTU;
1128165779Sticso			} else {
1129165779Sticso				WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_BIG);
1130165779Sticso				ifp->if_capenable &= ~IFCAP_VLAN_MTU;
1131165779Sticso			}
1132165779Sticso			ATE_UNLOCK(sc);
1133165779Sticso		}
1134155324Simp	default:
1135155324Simp		error = ether_ioctl(ifp, cmd, data);
1136155324Simp		break;
1137155324Simp	}
1138155324Simp	return (error);
1139155324Simp}
1140155324Simp
1141155324Simpstatic void
1142155324Simpate_child_detached(device_t dev, device_t child)
1143155324Simp{
1144155324Simp	struct ate_softc *sc;
1145155324Simp
1146155324Simp	sc = device_get_softc(dev);
1147155324Simp	if (child == sc->miibus)
1148155324Simp		sc->miibus = NULL;
1149155324Simp}
1150155324Simp
1151155324Simp/*
1152155324Simp * MII bus support routines.
1153155324Simp */
1154155324Simpstatic int
1155155324Simpate_miibus_readreg(device_t dev, int phy, int reg)
1156155324Simp{
1157155324Simp	struct ate_softc *sc;
1158155324Simp	int val;
1159155324Simp
1160155324Simp	/*
1161155324Simp	 * XXX if we implement agressive power savings, then we need
1162155324Simp	 * XXX to make sure that the clock to the emac is on here
1163155324Simp	 */
1164155324Simp
1165155324Simp	sc = device_get_softc(dev);
1166155324Simp	DELAY(1);	/* Hangs w/o this delay really 30.5us atm */
1167155324Simp	WR4(sc, ETH_MAN, ETH_MAN_REG_RD(phy, reg));
1168155324Simp	while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0)
1169155324Simp		continue;
1170155324Simp	val = RD4(sc, ETH_MAN) & ETH_MAN_VALUE_MASK;
1171155324Simp
1172155324Simp	return (val);
1173155324Simp}
1174155324Simp
1175155324Simpstatic void
1176155324Simpate_miibus_writereg(device_t dev, int phy, int reg, int data)
1177155324Simp{
1178155324Simp	struct ate_softc *sc;
1179155324Simp
1180155324Simp	/*
1181155324Simp	 * XXX if we implement agressive power savings, then we need
1182155324Simp	 * XXX to make sure that the clock to the emac is on here
1183155324Simp	 */
1184155324Simp
1185155324Simp	sc = device_get_softc(dev);
1186155324Simp	WR4(sc, ETH_MAN, ETH_MAN_REG_WR(phy, reg, data));
1187155324Simp	while ((RD4(sc, ETH_SR) & ETH_SR_IDLE) == 0)
1188155324Simp		continue;
1189155324Simp	return;
1190155324Simp}
1191155324Simp
1192155324Simpstatic device_method_t ate_methods[] = {
1193155324Simp	/* Device interface */
1194155324Simp	DEVMETHOD(device_probe,		ate_probe),
1195155324Simp	DEVMETHOD(device_attach,	ate_attach),
1196155324Simp	DEVMETHOD(device_detach,	ate_detach),
1197155324Simp
1198155324Simp	/* Bus interface */
1199155324Simp	DEVMETHOD(bus_child_detached,	ate_child_detached),
1200155324Simp
1201155324Simp	/* MII interface */
1202155324Simp	DEVMETHOD(miibus_readreg,	ate_miibus_readreg),
1203155324Simp	DEVMETHOD(miibus_writereg,	ate_miibus_writereg),
1204155324Simp
1205155324Simp	{ 0, 0 }
1206155324Simp};
1207155324Simp
1208155324Simpstatic driver_t ate_driver = {
1209155324Simp	"ate",
1210155324Simp	ate_methods,
1211155324Simp	sizeof(struct ate_softc),
1212155324Simp};
1213155324Simp
1214155324SimpDRIVER_MODULE(ate, atmelarm, ate_driver, ate_devclass, 0, 0);
1215155324SimpDRIVER_MODULE(miibus, ate, miibus_driver, miibus_devclass, 0, 0);
1216155324SimpMODULE_DEPEND(ate, miibus, 1, 1, 1);
1217155324SimpMODULE_DEPEND(ate, ether, 1, 1, 1);
1218