xref: /openbsd-src/sys/dev/fdt/if_dwxe.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: if_dwxe.c,v 1.17 2020/07/10 13:26:36 patrick Exp $	*/
2 /*
3  * Copyright (c) 2008 Mark Kettenis
4  * Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for the ethernet controller on the Allwinner H3/A64 SoCs.
21  */
22 
23 #include "bpfilter.h"
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/device.h>
28 #include <sys/kernel.h>
29 #include <sys/malloc.h>
30 #include <sys/mbuf.h>
31 #include <sys/queue.h>
32 #include <sys/socket.h>
33 #include <sys/sockio.h>
34 #include <sys/timeout.h>
35 
36 #include <machine/bus.h>
37 #include <machine/fdt.h>
38 
39 #include <net/if.h>
40 #include <net/if_media.h>
41 
42 #include <dev/ofw/openfirm.h>
43 #include <dev/ofw/ofw_clock.h>
44 #include <dev/ofw/ofw_misc.h>
45 #include <dev/ofw/ofw_pinctrl.h>
46 #include <dev/ofw/ofw_regulator.h>
47 #include <dev/ofw/fdt.h>
48 
49 #include <dev/mii/mii.h>
50 #include <dev/mii/miivar.h>
51 
52 #if NBPFILTER > 0
53 #include <net/bpf.h>
54 #endif
55 
56 #include <netinet/in.h>
57 #include <netinet/if_ether.h>
58 
59 /*
60  * DWXE registers.
61  */
62 
63 #define DWXE_BASIC_CTL0		0x00
64 #define  DWXE_BASIC_CTL0_DUPLEX		(1 << 0)
65 #define  DWXE_BASIC_CTL0_LOOPBACK		(1 << 1)
66 #define  DWXE_BASIC_CTL0_SPEED_1000		(0 << 2)
67 #define  DWXE_BASIC_CTL0_SPEED_10		(2 << 2)
68 #define  DWXE_BASIC_CTL0_SPEED_100		(3 << 2)
69 #define  DWXE_BASIC_CTL0_SPEED_MASK		(3 << 2)
70 #define DWXE_BASIC_CTL1		0x04
71 #define  DWXE_BASIC_CTL1_SOFT_RST		(1 << 0)
72 #define  DWXE_BASIC_CTL1_RX_TX_PRI		(1 << 1)
73 #define  DWXE_BASIC_CTL1_BURST_LEN_MASK	(0x3f << 24)
74 #define  DWXE_BASIC_CTL1_BURST_LEN(x)		((x) << 24)
75 #define DWXE_INT_STA			0x08
76 #define  DWXE_INT_STA_TX_INT			(1 << 0)
77 #define  DWXE_INT_STA_TX_DMA_STOP_INT		(1 << 1)
78 #define  DWXE_INT_STA_TX_BUF_UA_INT		(1 << 2)
79 #define  DWXE_INT_STA_TX_TIMEOUT_INT		(1 << 3)
80 #define  DWXE_INT_STA_TX_UNDERFLOW_INT	(1 << 4)
81 #define  DWXE_INT_STA_TX_EARLY_INT		(1 << 5)
82 #define  DWXE_INT_STA_RX_INT			(1 << 8)
83 #define  DWXE_INT_STA_RX_BUF_UA_INT		(1 << 9)
84 #define  DWXE_INT_STA_RX_DMA_STOP_INT		(1 << 10)
85 #define  DWXE_INT_STA_RX_TIMEOUT_INT		(1 << 11)
86 #define  DWXE_INT_STA_RX_OVERFLOW_INT		(1 << 12)
87 #define  DWXE_INT_STA_RX_EARLY_INT		(1 << 13)
88 #define  DWXE_INT_STA_RGMII_STA_INT		(1 << 16)
89 #define DWXE_INT_EN			0x0C
90 #define  DWXE_INT_EN_TX_INT			(1 << 0)
91 #define  DWXE_INT_EN_TX_DMA_STOP_INT		(1 << 1)
92 #define  DWXE_INT_EN_TX_BUF_UA_INT		(1 << 2)
93 #define  DWXE_INT_EN_TX_TIMEOUT_INT		(1 << 3)
94 #define  DWXE_INT_EN_TX_UNDERFLOW_INT		(1 << 4)
95 #define  DWXE_INT_EN_TX_EARLY_INT		(1 << 5)
96 #define  DWXE_INT_EN_RX_INT			(1 << 8)
97 #define  DWXE_INT_EN_RX_BUF_UA_INT		(1 << 9)
98 #define  DWXE_INT_EN_RX_DMA_STOP_INT		(1 << 10)
99 #define  DWXE_INT_EN_RX_TIMEOUT_INT		(1 << 11)
100 #define  DWXE_INT_EN_RX_OVERFLOW_INT		(1 << 12)
101 #define  DWXE_INT_EN_RX_EARLY_INT		(1 << 13)
102 #define  DWXE_INT_EN_RGMII_EN_INT		(1 << 16)
103 #define DWXE_TX_CTL0			0x10
104 #define  DWXE_TX_CTL0_TX_TRANSMITTER_EN	(1U << 31)
105 #define DWXE_TX_CTL1			0x14
106 #define  DWXE_TX_CTL1_TX_FIFO_FLUSH		(1 << 0)
107 #define  DWXE_TX_CTL1_TX_MD			(1 << 1)
108 #define  DWXE_TX_CTL1_TX_NEXT_FRM		(1 << 2)
109 #define  DWXE_TX_CTL1_TX_TH_MASK		(0x3 << 8)
110 #define  DWXE_TX_CTL1_TX_TH_64		0
111 #define  DWXE_TX_CTL1_TX_TH_128		(0x1 << 8)
112 #define  DWXE_TX_CTL1_TX_TH_192		(0x2 << 8)
113 #define  DWXE_TX_CTL1_TX_TH_256		(0x3 << 8)
114 #define  DWXE_TX_CTL1_TX_DMA_EN		(1 << 30)
115 #define  DWXE_TX_CTL1_TX_DMA_START		(1U << 31)
116 #define DWXE_TX_FLOW_CTL		0x1C
117 #define  DWXE_TX_FLOW_CTL_EN			(1 << 0)
118 #define DWXE_TX_DESC_LIST		0x20
119 #define DWXE_RX_CTL0			0x24
120 #define  DWXE_RX_CTL0_RX_FLOW_CTL_EN		(1 << 16)
121 #define  DWXE_RX_CTL0_RX_DO_CRC		(1 << 27)
122 #define  DWXE_RX_CTL0_RX_RECEIVER_EN		(1U << 31)
123 #define DWXE_RX_CTL1			0x28
124 #define  DWXE_RX_CTL1_RX_MD			(1 << 1)
125 #define  DWXE_RX_CTL1_RX_TH_MASK		(0x3 << 4)
126 #define  DWXE_RX_CTL1_RX_TH_32		(0x0 << 4)
127 #define  DWXE_RX_CTL1_RX_TH_64		(0x1 << 4)
128 #define  DWXE_RX_CTL1_RX_TH_96		(0x2 << 4)
129 #define  DWXE_RX_CTL1_RX_TH_128		(0x3 << 4)
130 #define  DWXE_RX_CTL1_RX_DMA_EN		(1 << 30)
131 #define  DWXE_RX_CTL1_RX_DMA_START		(1U << 31)
132 #define DWXE_RX_DESC_LIST		0x34
133 #define DWXE_RX_FRM_FLT		0x38
134 #define DWXE_RX_FRM_FLT_RX_ALL		(1 << 0)
135 #define DWXE_RX_FRM_FLT_HASH_UNICAST		(1 << 8)
136 #define DWXE_RX_FRM_FLT_HASH_MULTICAST	(1 << 9)
137 #define DWXE_RX_FRM_FLT_CTL			(1 << 13)
138 #define DWXE_RX_FRM_FLT_RX_ALL_MULTICAST	(1 << 16)
139 #define DWXE_RX_FRM_FLT_DIS_BROADCAST		(1 << 17)
140 #define DWXE_RX_FRM_FLT_DIS_ADDR_FILTER	(1U << 31)
141 #define DWXE_RX_HASH0			0x40
142 #define DWXE_RX_HASH1			0x44
143 #define DWXE_MDIO_CMD			0x48
144 #define  DWXE_MDIO_CMD_MII_BUSY		(1 << 0)
145 #define  DWXE_MDIO_CMD_MII_WRITE		(1 << 1)
146 #define  DWXE_MDIO_CMD_PHY_REG_SHIFT		4
147 #define  DWXE_MDIO_CMD_PHY_ADDR_SHIFT		12
148 #define  DWXE_MDIO_CMD_MDC_DIV_RATIO_M_SHIFT	20
149 #define  DWXE_MDIO_CMD_MDC_DIV_RATIO_M_MASK	0x7
150 #define  DWXE_MDIO_CMD_MDC_DIV_RATIO_M_16	0
151 #define  DWXE_MDIO_CMD_MDC_DIV_RATIO_M_32	1
152 #define  DWXE_MDIO_CMD_MDC_DIV_RATIO_M_64	2
153 #define  DWXE_MDIO_CMD_MDC_DIV_RATIO_M_128	3
154 #define DWXE_MDIO_DATA		0x4C
155 #define DWXE_MACADDR_HI		0x50
156 #define DWXE_MACADDR_LO		0x54
157 #define DWXE_TX_DMA_STA		0xB0
158 #define DWXE_TX_CUR_DESC		0xB4
159 #define DWXE_TX_CUR_BUF		0xB8
160 #define DWXE_RX_DMA_STA		0xC0
161 #define DWXE_RX_CUR_DESC		0xC4
162 #define DWXE_RX_CUR_BUF		0xC8
163 
164 /*
165  * DWXE descriptors.
166  */
167 
168 struct dwxe_desc {
169 	uint32_t sd_status;
170 	uint32_t sd_len;
171 	uint32_t sd_addr;
172 	uint32_t sd_next;
173 };
174 
175 /* Tx status bits. */
176 #define DWXE_TX_DEFER			(1 << 0)
177 #define DWXE_TX_UNDERFLOW_ERR		(1 << 1)
178 #define DWXE_TX_DEFER_ERR		(1 << 2)
179 #define DWXE_TX_COL_CNT_MASK		(0xf << 3)
180 #define DWXE_TX_COL_CNT_SHIFT		3
181 #define DWXE_TX_COL_ERR_1		(1 << 8)
182 #define DWXE_TX_COL_ERR_0		(1 << 9)
183 #define DWXE_TX_CRS_ERR		(1 << 10)
184 #define DWXE_TX_PAYLOAD_ERR		(1 << 12)
185 #define DWXE_TX_LENGTH_ERR		(1 << 14)
186 #define DWXE_TX_HEADER_ERR		(1 << 16)
187 #define DWXE_TX_DESC_CTL		(1 << 31)
188 
189 /* Rx status bits */
190 #define DWXE_RX_PAYLOAD_ERR		(1 << 0)
191 #define DWXE_RX_CRC_ERR		(1 << 1)
192 #define DWXE_RX_PHY_ERR		(1 << 3)
193 #define DWXE_RX_LENGTH_ERR		(1 << 4)
194 #define DWXE_RX_FRM_TYPE		(1 << 5)
195 #define DWXE_RX_COL_ERR		(1 << 6)
196 #define DWXE_RX_HEADER_ERR		(1 << 7)
197 #define DWXE_RX_LAST_DESC		(1 << 8)
198 #define DWXE_RX_FIR_DESC		(1 << 9)
199 #define DWXE_RX_OVERFLOW_ERR		(1 << 11)
200 #define DWXE_RX_SAF_FAIL		(1 << 13)
201 #define DWXE_RX_NO_ENOUGH_BUF_ERR	(1 << 14)
202 #define DWXE_RX_FRM_LEN_MASK		0x3fff
203 #define DWXE_RX_FRM_LEN_SHIFT		16
204 #define DWXE_RX_DAF_FAIL		(1 << 30)
205 #define DWXE_RX_DESC_CTL		(1 << 31)
206 
207 /* Tx size bits */
208 #define DWXE_TX_BUF_SIZE		(0xfff << 0)
209 #define DWXE_TX_CRC_CTL		(1 << 26)
210 #define DWXE_TX_CHECKSUM_CTL_MASK	(0x3 << 27)
211 #define DWXE_TX_CHECKSUM_CTL_IP	(1 << 27)
212 #define DWXE_TX_CHECKSUM_CTL_NO_PSE	(2 << 27)
213 #define DWXE_TX_CHECKSUM_CTL_FULL	(3 << 27)
214 #define DWXE_TX_FIR_DESC		(1 << 29)
215 #define DWXE_TX_LAST_DESC		(1 << 30)
216 #define DWXE_TX_INT_CTL		(1 << 31)
217 
218 /* Rx size bits */
219 #define DWXE_RX_BUF_SIZE		(0xfff << 0)
220 #define DWXE_RX_INT_CTL		(1 << 31)
221 
222 /* EMAC syscon bits */
223 #define SYSCON_EMAC			0x30
224 #define SYSCON_ETCS_MASK		(0x3 << 0)
225 #define SYSCON_ETCS_MII			(0 << 0)
226 #define SYSCON_ETCS_EXT_GMII		(1 << 0)
227 #define SYSCON_ETCS_INT_GMII		(2 << 0)
228 #define SYSCON_EPIT			(1 << 2) /* 1: RGMII, 0: MII */
229 #define SYSCON_ERXDC_MASK		(0xf << 5)
230 #define SYSCON_ERXDC_SHIFT		5
231 #define SYSCON_ETXDC_MASK		(0x7 << 10)
232 #define SYSCON_ETXDC_SHIFT		10
233 #define SYSCON_RMII_EN			(1 << 13) /* 1: enable RMII (overrides EPIT) */
234 #define SYSCON_H3_EPHY_SELECT		(1 << 15) /* 1: internal PHY, 0: external PHY */
235 #define SYSCON_H3_EPHY_SHUTDOWN		(1 << 16) /* 1: shutdown, 0: power up */
236 #define SYSCON_H3_EPHY_LED_POL		(1 << 17) /* 1: active low, 0: active high */
237 #define SYSCON_H3_EPHY_CLK_SEL		(1 << 18) /* 1: 24MHz, 0: 25MHz */
238 #define SYSCON_H3_EPHY_ADDR_MASK	(0x1f << 20)
239 #define SYSCON_H3_EPHY_ADDR_SHIFT	20
240 
241 /* GMAC syscon bits (Allwinner R40) */
242 #define SYSCON_GMAC			0x00
243 #define SYSCON_GTCS_MASK		SYSCON_ETCS_MASK
244 #define SYSCON_GTCS_MII			SYSCON_ETCS_MII
245 #define SYSCON_GTCS_EXT_GMII		SYSCON_ETCS_EXT_GMII
246 #define SYSCON_GTCS_INT_GMII		SYSCON_ETCS_INT_GMII
247 #define SYSCON_GPIT			SYSCON_EPIT
248 #define SYSCON_GRXDC_MASK		(0x7 << 5)
249 #define SYSCON_GRXDC_SHIFT		5
250 
251 struct dwxe_buf {
252 	bus_dmamap_t	tb_map;
253 	struct mbuf	*tb_m;
254 };
255 
256 #define DWXE_NTXDESC	256
257 #define DWXE_NTXSEGS	16
258 
259 #define DWXE_NRXDESC	256
260 
261 struct dwxe_dmamem {
262 	bus_dmamap_t		tdm_map;
263 	bus_dma_segment_t	tdm_seg;
264 	size_t			tdm_size;
265 	caddr_t			tdm_kva;
266 };
267 #define DWXE_DMA_MAP(_tdm)	((_tdm)->tdm_map)
268 #define DWXE_DMA_LEN(_tdm)	((_tdm)->tdm_size)
269 #define DWXE_DMA_DVA(_tdm)	((_tdm)->tdm_map->dm_segs[0].ds_addr)
270 #define DWXE_DMA_KVA(_tdm)	((void *)(_tdm)->tdm_kva)
271 
272 struct dwxe_softc {
273 	struct device		sc_dev;
274 	int			sc_node;
275 	bus_space_tag_t		sc_iot;
276 	bus_space_handle_t	sc_ioh;
277 	bus_dma_tag_t		sc_dmat;
278 
279 	struct arpcom		sc_ac;
280 #define sc_lladdr	sc_ac.ac_enaddr
281 	struct mii_data		sc_mii;
282 #define sc_media	sc_mii.mii_media
283 	int			sc_link;
284 	int			sc_phyloc;
285 
286 	struct dwxe_dmamem	*sc_txring;
287 	struct dwxe_buf		*sc_txbuf;
288 	struct dwxe_desc	*sc_txdesc;
289 	int			sc_tx_prod;
290 	int			sc_tx_cnt;
291 	int			sc_tx_cons;
292 
293 	struct dwxe_dmamem	*sc_rxring;
294 	struct dwxe_buf		*sc_rxbuf;
295 	struct dwxe_desc	*sc_rxdesc;
296 	int			sc_rx_prod;
297 	struct if_rxring	sc_rx_ring;
298 	int			sc_rx_cons;
299 
300 	struct timeout		sc_tick;
301 	struct timeout		sc_rxto;
302 
303 	uint32_t		sc_clk;
304 };
305 
306 #define DEVNAME(_s)	((_s)->sc_dev.dv_xname)
307 
308 int	dwxe_match(struct device *, void *, void *);
309 void	dwxe_attach(struct device *, struct device *, void *);
310 void	dwxe_phy_setup_emac(struct dwxe_softc *);
311 void	dwxe_phy_setup_gmac(struct dwxe_softc *);
312 
313 struct cfattach dwxe_ca = {
314 	sizeof(struct dwxe_softc), dwxe_match, dwxe_attach
315 };
316 
317 struct cfdriver dwxe_cd = {
318 	NULL, "dwxe", DV_IFNET
319 };
320 
321 uint32_t dwxe_read(struct dwxe_softc *, bus_addr_t);
322 void	dwxe_write(struct dwxe_softc *, bus_addr_t, uint32_t);
323 
324 int	dwxe_ioctl(struct ifnet *, u_long, caddr_t);
325 void	dwxe_start(struct ifnet *);
326 void	dwxe_watchdog(struct ifnet *);
327 
328 int	dwxe_media_change(struct ifnet *);
329 void	dwxe_media_status(struct ifnet *, struct ifmediareq *);
330 
331 int	dwxe_mii_readreg(struct device *, int, int);
332 void	dwxe_mii_writereg(struct device *, int, int, int);
333 void	dwxe_mii_statchg(struct device *);
334 
335 void	dwxe_lladdr_read(struct dwxe_softc *, uint8_t *);
336 void	dwxe_lladdr_write(struct dwxe_softc *);
337 
338 void	dwxe_tick(void *);
339 void	dwxe_rxtick(void *);
340 
341 int	dwxe_intr(void *);
342 void	dwxe_tx_proc(struct dwxe_softc *);
343 void	dwxe_rx_proc(struct dwxe_softc *);
344 
345 void	dwxe_up(struct dwxe_softc *);
346 void	dwxe_down(struct dwxe_softc *);
347 void	dwxe_iff(struct dwxe_softc *);
348 int	dwxe_encap(struct dwxe_softc *, struct mbuf *, int *);
349 
350 void	dwxe_reset(struct dwxe_softc *);
351 void	dwxe_stop_dma(struct dwxe_softc *);
352 
353 struct dwxe_dmamem *
354 	dwxe_dmamem_alloc(struct dwxe_softc *, bus_size_t, bus_size_t);
355 void	dwxe_dmamem_free(struct dwxe_softc *, struct dwxe_dmamem *);
356 struct mbuf *dwxe_alloc_mbuf(struct dwxe_softc *, bus_dmamap_t);
357 void	dwxe_fill_rx_ring(struct dwxe_softc *);
358 
359 int
360 dwxe_match(struct device *parent, void *cfdata, void *aux)
361 {
362 	struct fdt_attach_args *faa = aux;
363 
364 	return OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-emac") ||
365 	    OF_is_compatible(faa->fa_node, "allwinner,sun8i-r40-gmac") ||
366 	    OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-emac");
367 }
368 
369 void
370 dwxe_attach(struct device *parent, struct device *self, void *aux)
371 {
372 	struct dwxe_softc *sc = (void *)self;
373 	struct fdt_attach_args *faa = aux;
374 	struct ifnet *ifp;
375 	uint32_t phy, phy_supply;
376 	int node;
377 
378 	sc->sc_node = faa->fa_node;
379 	sc->sc_iot = faa->fa_iot;
380 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
381 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
382 		printf("%s: cannot map registers\n", self->dv_xname);
383 		return;
384 	}
385 	sc->sc_dmat = faa->fa_dmat;
386 
387 	/* Lookup PHY. */
388 	phy = OF_getpropint(faa->fa_node, "phy-handle", 0);
389 	node = OF_getnodebyphandle(phy);
390 	if (node)
391 		sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY);
392 	else
393 		sc->sc_phyloc = MII_PHY_ANY;
394 
395 	pinctrl_byname(faa->fa_node, "default");
396 
397 	/* Enable clock. */
398 	clock_enable(faa->fa_node, "stmmaceth");
399 	reset_deassert(faa->fa_node, "stmmaceth");
400 	delay(5000);
401 
402 	/* Power up PHY. */
403 	phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0);
404 	if (phy_supply)
405 		regulator_enable(phy_supply);
406 
407 	sc->sc_clk = clock_get_frequency(faa->fa_node, "stmmaceth");
408 	if (sc->sc_clk > 160000000)
409 		sc->sc_clk = DWXE_MDIO_CMD_MDC_DIV_RATIO_M_128;
410 	else if (sc->sc_clk > 80000000)
411 		sc->sc_clk = DWXE_MDIO_CMD_MDC_DIV_RATIO_M_64;
412 	else if (sc->sc_clk > 40000000)
413 		sc->sc_clk = DWXE_MDIO_CMD_MDC_DIV_RATIO_M_32;
414 	else
415 		sc->sc_clk = DWXE_MDIO_CMD_MDC_DIV_RATIO_M_16;
416 
417 	if (OF_getprop(faa->fa_node, "local-mac-address",
418 	    &sc->sc_lladdr, ETHER_ADDR_LEN) != ETHER_ADDR_LEN)
419 		dwxe_lladdr_read(sc, sc->sc_lladdr);
420 	printf(": address %s\n", ether_sprintf(sc->sc_lladdr));
421 
422 	/* Do hardware specific initializations. */
423 	if (OF_is_compatible(faa->fa_node, "allwinner,sun8i-r40-gmac"))
424 		dwxe_phy_setup_gmac(sc);
425 	else
426 		dwxe_phy_setup_emac(sc);
427 
428 	timeout_set(&sc->sc_tick, dwxe_tick, sc);
429 	timeout_set(&sc->sc_rxto, dwxe_rxtick, sc);
430 
431 	ifp = &sc->sc_ac.ac_if;
432 	ifp->if_softc = sc;
433 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
434 	ifp->if_ioctl = dwxe_ioctl;
435 	ifp->if_start = dwxe_start;
436 	ifp->if_watchdog = dwxe_watchdog;
437 	ifq_set_maxlen(&ifp->if_snd, DWXE_NTXDESC - 1);
438 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
439 
440 	ifp->if_capabilities = IFCAP_VLAN_MTU;
441 
442 	sc->sc_mii.mii_ifp = ifp;
443 	sc->sc_mii.mii_readreg = dwxe_mii_readreg;
444 	sc->sc_mii.mii_writereg = dwxe_mii_writereg;
445 	sc->sc_mii.mii_statchg = dwxe_mii_statchg;
446 
447 	ifmedia_init(&sc->sc_media, 0, dwxe_media_change, dwxe_media_status);
448 
449 	dwxe_reset(sc);
450 
451 	mii_attach(self, &sc->sc_mii, 0xffffffff, sc->sc_phyloc,
452 	    MII_OFFSET_ANY, MIIF_NOISOLATE);
453 	if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
454 		printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);
455 		ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
456 		ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
457 	} else
458 		ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
459 
460 	if_attach(ifp);
461 	ether_ifattach(ifp);
462 
463 	fdt_intr_establish(faa->fa_node, IPL_NET, dwxe_intr, sc,
464 	    sc->sc_dev.dv_xname);
465 }
466 
467 void
468 dwxe_phy_setup_emac(struct dwxe_softc *sc)
469 {
470 	struct regmap *rm;
471 	uint32_t syscon;
472 	uint32_t tx_delay, rx_delay;
473 	char *phy_mode;
474 	int len;
475 
476 	rm = regmap_byphandle(OF_getpropint(sc->sc_node, "syscon", 0));
477 	if (rm == NULL)
478 		return;
479 
480 	syscon = regmap_read_4(rm, SYSCON_EMAC);
481 	syscon &= ~(SYSCON_ETCS_MASK|SYSCON_EPIT|SYSCON_RMII_EN);
482 	syscon &= ~(SYSCON_ETXDC_MASK | SYSCON_ERXDC_MASK);
483 	syscon &= ~SYSCON_H3_EPHY_SELECT;
484 
485 	if ((len = OF_getproplen(sc->sc_node, "phy-mode")) <= 0)
486 		return;
487 	phy_mode = malloc(len, M_TEMP, M_WAITOK);
488 	OF_getprop(sc->sc_node, "phy-mode", phy_mode, len);
489 	if (!strncmp(phy_mode, "rgmii", strlen("rgmii")))
490 		syscon |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
491 	else if (!strncmp(phy_mode, "rmii", strlen("rmii")))
492 		syscon |= SYSCON_EPIT | SYSCON_ETCS_EXT_GMII;
493 	else if (!strncmp(phy_mode, "mii", strlen("mii")) &&
494 	    OF_is_compatible(sc->sc_node, "allwinner,sun8i-h3-emac")) {
495 		syscon &= ~SYSCON_H3_EPHY_SHUTDOWN;
496 		syscon |= SYSCON_H3_EPHY_SELECT | SYSCON_H3_EPHY_CLK_SEL;
497 		if (OF_getproplen(sc->sc_node, "allwinner,leds-active-low") == 0)
498 			syscon |= SYSCON_H3_EPHY_LED_POL;
499 		else
500 			syscon &= ~SYSCON_H3_EPHY_LED_POL;
501 		syscon &= ~SYSCON_H3_EPHY_ADDR_MASK;
502 		syscon |= (sc->sc_phyloc << SYSCON_H3_EPHY_ADDR_SHIFT);
503 	}
504 	free(phy_mode, M_TEMP, len);
505 
506 	tx_delay = OF_getpropint(sc->sc_node, "allwinner,tx-delay-ps", 0);
507 	rx_delay = OF_getpropint(sc->sc_node, "allwinner,rx-delay-ps", 0);
508 	syscon |= ((tx_delay / 100) << SYSCON_ETXDC_SHIFT) & SYSCON_ETXDC_MASK;
509 	syscon |= ((rx_delay / 100) << SYSCON_ERXDC_SHIFT) & SYSCON_ERXDC_MASK;
510 
511 	regmap_write_4(rm, SYSCON_EMAC, syscon);
512 	dwxe_reset(sc);
513 }
514 
515 void
516 dwxe_phy_setup_gmac(struct dwxe_softc *sc)
517 {
518 	struct regmap *rm;
519 	uint32_t syscon;
520 	uint32_t rx_delay;
521 	char *phy_mode;
522 	int len;
523 
524 	rm = regmap_byphandle(OF_getpropint(sc->sc_node, "syscon", 0));
525 	if (rm == NULL)
526 		return;
527 
528 	syscon = regmap_read_4(rm, SYSCON_GMAC);
529 	syscon &= ~(SYSCON_GTCS_MASK|SYSCON_GPIT|SYSCON_ERXDC_MASK);
530 
531 	if ((len = OF_getproplen(sc->sc_node, "phy-mode")) <= 0)
532 		return;
533 	phy_mode = malloc(len, M_TEMP, M_WAITOK);
534 	OF_getprop(sc->sc_node, "phy-mode", phy_mode, len);
535 	if (!strncmp(phy_mode, "rgmii", strlen("rgmii")))
536 		syscon |= SYSCON_GPIT | SYSCON_GTCS_INT_GMII;
537 	else if (!strncmp(phy_mode, "rmii", strlen("rmii")))
538 		syscon |= SYSCON_GPIT | SYSCON_GTCS_EXT_GMII;
539 	free(phy_mode, M_TEMP, len);
540 
541 	rx_delay = OF_getpropint(sc->sc_node, "allwinner,rx-delay-ps", 0);
542 	syscon |= ((rx_delay / 100) << SYSCON_ERXDC_SHIFT) & SYSCON_ERXDC_MASK;
543 
544 	regmap_write_4(rm, SYSCON_GMAC, syscon);
545 	dwxe_reset(sc);
546 }
547 
548 uint32_t
549 dwxe_read(struct dwxe_softc *sc, bus_addr_t addr)
550 {
551 	return bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr);
552 }
553 
554 void
555 dwxe_write(struct dwxe_softc *sc, bus_addr_t addr, uint32_t data)
556 {
557 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, data);
558 }
559 
560 void
561 dwxe_lladdr_read(struct dwxe_softc *sc, uint8_t *lladdr)
562 {
563 	uint32_t machi, maclo;
564 
565 	machi = dwxe_read(sc, DWXE_MACADDR_HI);
566 	maclo = dwxe_read(sc, DWXE_MACADDR_LO);
567 
568 	lladdr[0] = (maclo >> 0) & 0xff;
569 	lladdr[1] = (maclo >> 8) & 0xff;
570 	lladdr[2] = (maclo >> 16) & 0xff;
571 	lladdr[3] = (maclo >> 24) & 0xff;
572 	lladdr[4] = (machi >> 0) & 0xff;
573 	lladdr[5] = (machi >> 8) & 0xff;
574 }
575 
576 void
577 dwxe_lladdr_write(struct dwxe_softc *sc)
578 {
579 	dwxe_write(sc, DWXE_MACADDR_HI,
580 	    sc->sc_lladdr[5] << 8 | sc->sc_lladdr[4] << 0);
581 	dwxe_write(sc, DWXE_MACADDR_LO,
582 	    sc->sc_lladdr[3] << 24 | sc->sc_lladdr[2] << 16 |
583 	    sc->sc_lladdr[1] << 8 | sc->sc_lladdr[0] << 0);
584 }
585 
586 void
587 dwxe_start(struct ifnet *ifp)
588 {
589 	struct dwxe_softc *sc = ifp->if_softc;
590 	struct mbuf *m;
591 	int error, idx;
592 
593 	if (!(ifp->if_flags & IFF_RUNNING))
594 		return;
595 	if (ifq_is_oactive(&ifp->if_snd))
596 		return;
597 	if (ifq_empty(&ifp->if_snd))
598 		return;
599 	if (!sc->sc_link)
600 		return;
601 
602 	idx = sc->sc_tx_prod;
603 	while ((sc->sc_txdesc[idx].sd_status & DWXE_TX_DESC_CTL) == 0) {
604 		m = ifq_deq_begin(&ifp->if_snd);
605 		if (m == NULL)
606 			break;
607 
608 		error = dwxe_encap(sc, m, &idx);
609 		if (error == ENOBUFS) {
610 			ifq_deq_rollback(&ifp->if_snd, m);
611 			ifq_set_oactive(&ifp->if_snd);
612 			break;
613 		}
614 		if (error == EFBIG) {
615 			ifq_deq_commit(&ifp->if_snd, m);
616 			m_freem(m); /* give up: drop it */
617 			ifp->if_oerrors++;
618 			continue;
619 		}
620 
621 		/* Now we are committed to transmit the packet. */
622 		ifq_deq_commit(&ifp->if_snd, m);
623 
624 #if NBPFILTER > 0
625 		if (ifp->if_bpf)
626 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
627 #endif
628 	}
629 
630 	if (sc->sc_tx_prod != idx) {
631 		sc->sc_tx_prod = idx;
632 
633 		/* Set a timeout in case the chip goes out to lunch. */
634 		ifp->if_timer = 5;
635 	}
636 }
637 
638 int
639 dwxe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
640 {
641 	struct dwxe_softc *sc = ifp->if_softc;
642 	struct ifreq *ifr = (struct ifreq *)addr;
643 	int error = 0, s;
644 
645 	s = splnet();
646 
647 	switch (cmd) {
648 	case SIOCSIFADDR:
649 		ifp->if_flags |= IFF_UP;
650 		/* FALLTHROUGH */
651 	case SIOCSIFFLAGS:
652 		if (ifp->if_flags & IFF_UP) {
653 			if (ifp->if_flags & IFF_RUNNING)
654 				error = ENETRESET;
655 			else
656 				dwxe_up(sc);
657 		} else {
658 			if (ifp->if_flags & IFF_RUNNING)
659 				dwxe_down(sc);
660 		}
661 		break;
662 
663 	case SIOCGIFMEDIA:
664 	case SIOCSIFMEDIA:
665 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
666 		break;
667 
668 	case SIOCGIFRXR:
669 		error = if_rxr_ioctl((struct if_rxrinfo *)ifr->ifr_data,
670 		    NULL, MCLBYTES, &sc->sc_rx_ring);
671 		break;
672 
673 	default:
674 		error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr);
675 		break;
676 	}
677 
678 	if (error == ENETRESET) {
679 		if (ifp->if_flags & IFF_RUNNING)
680 			dwxe_iff(sc);
681 		error = 0;
682 	}
683 
684 	splx(s);
685 	return (error);
686 }
687 
688 void
689 dwxe_watchdog(struct ifnet *ifp)
690 {
691 	printf("%s\n", __func__);
692 }
693 
694 int
695 dwxe_media_change(struct ifnet *ifp)
696 {
697 	struct dwxe_softc *sc = ifp->if_softc;
698 
699 	if (LIST_FIRST(&sc->sc_mii.mii_phys))
700 		mii_mediachg(&sc->sc_mii);
701 
702 	return (0);
703 }
704 
705 void
706 dwxe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
707 {
708 	struct dwxe_softc *sc = ifp->if_softc;
709 
710 	if (LIST_FIRST(&sc->sc_mii.mii_phys)) {
711 		mii_pollstat(&sc->sc_mii);
712 		ifmr->ifm_active = sc->sc_mii.mii_media_active;
713 		ifmr->ifm_status = sc->sc_mii.mii_media_status;
714 	}
715 }
716 
717 int
718 dwxe_mii_readreg(struct device *self, int phy, int reg)
719 {
720 	struct dwxe_softc *sc = (void *)self;
721 	int n;
722 
723 	dwxe_write(sc, DWXE_MDIO_CMD,
724 	    sc->sc_clk << DWXE_MDIO_CMD_MDC_DIV_RATIO_M_SHIFT |
725 	    phy << DWXE_MDIO_CMD_PHY_ADDR_SHIFT |
726 	    reg << DWXE_MDIO_CMD_PHY_REG_SHIFT |
727 	    DWXE_MDIO_CMD_MII_BUSY);
728 	for (n = 0; n < 1000; n++) {
729 		if ((dwxe_read(sc, DWXE_MDIO_CMD) &
730 		    DWXE_MDIO_CMD_MII_BUSY) == 0)
731 			return dwxe_read(sc, DWXE_MDIO_DATA);
732 		delay(10);
733 	}
734 
735 	printf("%s: mii_read timeout\n", sc->sc_dev.dv_xname);
736 	return (0);
737 }
738 
739 void
740 dwxe_mii_writereg(struct device *self, int phy, int reg, int val)
741 {
742 	struct dwxe_softc *sc = (void *)self;
743 	int n;
744 
745 	dwxe_write(sc, DWXE_MDIO_DATA, val);
746 	dwxe_write(sc, DWXE_MDIO_CMD,
747 	    sc->sc_clk << DWXE_MDIO_CMD_MDC_DIV_RATIO_M_SHIFT |
748 	    phy << DWXE_MDIO_CMD_PHY_ADDR_SHIFT |
749 	    reg << DWXE_MDIO_CMD_PHY_REG_SHIFT |
750 	    DWXE_MDIO_CMD_MII_WRITE |
751 	    DWXE_MDIO_CMD_MII_BUSY);
752 	for (n = 0; n < 1000; n++) {
753 		if ((dwxe_read(sc, DWXE_MDIO_CMD) &
754 		    DWXE_MDIO_CMD_MII_BUSY) == 0)
755 			return;
756 		delay(10);
757 	}
758 
759 	printf("%s: mii_write timeout\n", sc->sc_dev.dv_xname);
760 }
761 
762 void
763 dwxe_mii_statchg(struct device *self)
764 {
765 	struct dwxe_softc *sc = (void *)self;
766 	uint32_t basicctrl;
767 
768 	basicctrl = dwxe_read(sc, DWXE_BASIC_CTL0);
769 	basicctrl &= ~DWXE_BASIC_CTL0_SPEED_MASK;
770 
771 	switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
772 	case IFM_1000_SX:
773 	case IFM_1000_LX:
774 	case IFM_1000_CX:
775 	case IFM_1000_T:
776 		basicctrl |= DWXE_BASIC_CTL0_SPEED_1000;
777 		sc->sc_link = 1;
778 		break;
779 	case IFM_100_TX:
780 		basicctrl |= DWXE_BASIC_CTL0_SPEED_100;
781 		sc->sc_link = 1;
782 		break;
783 	case IFM_10_T:
784 		basicctrl |= DWXE_BASIC_CTL0_SPEED_10;
785 		sc->sc_link = 1;
786 		break;
787 	default:
788 		sc->sc_link = 0;
789 		return;
790 	}
791 
792 	if (sc->sc_link == 0)
793 		return;
794 
795 	basicctrl &= ~DWXE_BASIC_CTL0_DUPLEX;
796 	if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
797 		basicctrl |= DWXE_BASIC_CTL0_DUPLEX;
798 
799 	/* XXX: RX/TX flow control? */
800 
801 	dwxe_write(sc, DWXE_BASIC_CTL0, basicctrl);
802 }
803 
804 void
805 dwxe_tick(void *arg)
806 {
807 	struct dwxe_softc *sc = arg;
808 	int s;
809 
810 	s = splnet();
811 	mii_tick(&sc->sc_mii);
812 	splx(s);
813 
814 	timeout_add_sec(&sc->sc_tick, 1);
815 }
816 
817 void
818 dwxe_rxtick(void *arg)
819 {
820 	struct dwxe_softc *sc = arg;
821 	uint32_t ctl;
822 	int s;
823 
824 	s = splnet();
825 
826 	ctl = dwxe_read(sc, DWXE_RX_CTL1);
827 	dwxe_write(sc, DWXE_RX_CTL1, ctl & ~DWXE_RX_CTL1_RX_DMA_EN);
828 
829 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring),
830 	    0, DWXE_DMA_LEN(sc->sc_rxring),
831 	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
832 
833 	dwxe_write(sc, DWXE_RX_DESC_LIST, 0);
834 
835 	sc->sc_rx_prod = sc->sc_rx_cons = 0;
836 	dwxe_fill_rx_ring(sc);
837 
838 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring),
839 	    0, DWXE_DMA_LEN(sc->sc_rxring),
840 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
841 
842 	dwxe_write(sc, DWXE_RX_DESC_LIST, DWXE_DMA_DVA(sc->sc_rxring));
843 	dwxe_write(sc, DWXE_RX_CTL1, ctl);
844 
845 	splx(s);
846 }
847 
848 int
849 dwxe_intr(void *arg)
850 {
851 	struct dwxe_softc *sc = arg;
852 	uint32_t reg;
853 
854 	reg = dwxe_read(sc, DWXE_INT_STA);
855 	dwxe_write(sc, DWXE_INT_STA, reg);
856 
857 	if (reg & DWXE_INT_STA_RX_INT)
858 		dwxe_rx_proc(sc);
859 
860 	if (reg & DWXE_INT_STA_TX_INT ||
861 	    reg & DWXE_INT_STA_TX_BUF_UA_INT)
862 		dwxe_tx_proc(sc);
863 
864 	return (1);
865 }
866 
867 void
868 dwxe_tx_proc(struct dwxe_softc *sc)
869 {
870 	struct ifnet *ifp = &sc->sc_ac.ac_if;
871 	struct dwxe_desc *txd;
872 	struct dwxe_buf *txb;
873 	int idx, txfree;
874 
875 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring), 0,
876 	    DWXE_DMA_LEN(sc->sc_txring),
877 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
878 
879 	txfree = 0;
880 	while (sc->sc_tx_cnt > 0) {
881 		idx = sc->sc_tx_cons;
882 		KASSERT(idx < DWXE_NTXDESC);
883 
884 		txd = &sc->sc_txdesc[idx];
885 		if (txd->sd_status & DWXE_TX_DESC_CTL)
886 			break;
887 
888 		txb = &sc->sc_txbuf[idx];
889 		if (txb->tb_m) {
890 			bus_dmamap_sync(sc->sc_dmat, txb->tb_map, 0,
891 			    txb->tb_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
892 			bus_dmamap_unload(sc->sc_dmat, txb->tb_map);
893 
894 			m_freem(txb->tb_m);
895 			txb->tb_m = NULL;
896 		}
897 
898 		txfree++;
899 		sc->sc_tx_cnt--;
900 
901 		if (sc->sc_tx_cons == (DWXE_NTXDESC - 1))
902 			sc->sc_tx_cons = 0;
903 		else
904 			sc->sc_tx_cons++;
905 
906 		txd->sd_status = 0;
907 	}
908 
909 	if (sc->sc_tx_cnt == 0)
910 		ifp->if_timer = 0;
911 
912 	if (txfree) {
913 		if (ifq_is_oactive(&ifp->if_snd))
914 			ifq_restart(&ifp->if_snd);
915 	}
916 }
917 
918 void
919 dwxe_rx_proc(struct dwxe_softc *sc)
920 {
921 	struct ifnet *ifp = &sc->sc_ac.ac_if;
922 	struct dwxe_desc *rxd;
923 	struct dwxe_buf *rxb;
924 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
925 	struct mbuf *m;
926 	int idx, len;
927 
928 	if ((ifp->if_flags & IFF_RUNNING) == 0)
929 		return;
930 
931 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring), 0,
932 	    DWXE_DMA_LEN(sc->sc_rxring),
933 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
934 
935 	while (if_rxr_inuse(&sc->sc_rx_ring) > 0) {
936 		idx = sc->sc_rx_cons;
937 		KASSERT(idx < DWXE_NRXDESC);
938 
939 		rxd = &sc->sc_rxdesc[idx];
940 		if (rxd->sd_status & DWXE_RX_DESC_CTL)
941 			break;
942 
943 		len = (rxd->sd_status >> DWXE_RX_FRM_LEN_SHIFT)
944 		    & DWXE_RX_FRM_LEN_MASK;
945 		rxb = &sc->sc_rxbuf[idx];
946 		KASSERT(rxb->tb_m);
947 
948 		bus_dmamap_sync(sc->sc_dmat, rxb->tb_map, 0,
949 		    len, BUS_DMASYNC_POSTREAD);
950 		bus_dmamap_unload(sc->sc_dmat, rxb->tb_map);
951 
952 		/* Strip off CRC. */
953 		len -= ETHER_CRC_LEN;
954 		KASSERT(len > 0);
955 
956 		m = rxb->tb_m;
957 		rxb->tb_m = NULL;
958 		m->m_pkthdr.len = m->m_len = len;
959 
960 		ml_enqueue(&ml, m);
961 
962 		if_rxr_put(&sc->sc_rx_ring, 1);
963 		if (sc->sc_rx_cons == (DWXE_NRXDESC - 1))
964 			sc->sc_rx_cons = 0;
965 		else
966 			sc->sc_rx_cons++;
967 	}
968 
969 	if (ifiq_input(&ifp->if_rcv, &ml))
970 		if_rxr_livelocked(&sc->sc_rx_ring);
971 
972 	dwxe_fill_rx_ring(sc);
973 
974 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring), 0,
975 	    DWXE_DMA_LEN(sc->sc_rxring),
976 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
977 }
978 
979 void
980 dwxe_up(struct dwxe_softc *sc)
981 {
982 	struct ifnet *ifp = &sc->sc_ac.ac_if;
983 	struct dwxe_buf *txb, *rxb;
984 	int i;
985 
986 	/* Allocate Tx descriptor ring. */
987 	sc->sc_txring = dwxe_dmamem_alloc(sc,
988 	    DWXE_NTXDESC * sizeof(struct dwxe_desc), 8);
989 	sc->sc_txdesc = DWXE_DMA_KVA(sc->sc_txring);
990 
991 	sc->sc_txbuf = malloc(sizeof(struct dwxe_buf) * DWXE_NTXDESC,
992 	    M_DEVBUF, M_WAITOK);
993 	for (i = 0; i < DWXE_NTXDESC; i++) {
994 		txb = &sc->sc_txbuf[i];
995 		bus_dmamap_create(sc->sc_dmat, MCLBYTES, DWXE_NTXSEGS,
996 		    MCLBYTES, 0, BUS_DMA_WAITOK, &txb->tb_map);
997 		txb->tb_m = NULL;
998 
999 		sc->sc_txdesc[i].sd_next =
1000 		    DWXE_DMA_DVA(sc->sc_txring) +
1001 		    ((i+1) % DWXE_NTXDESC) * sizeof(struct dwxe_desc);
1002 	}
1003 
1004 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring),
1005 	    0, DWXE_DMA_LEN(sc->sc_txring), BUS_DMASYNC_PREWRITE);
1006 
1007 	sc->sc_tx_prod = sc->sc_tx_cons = 0;
1008 	sc->sc_tx_cnt = 0;
1009 
1010 	dwxe_write(sc, DWXE_TX_DESC_LIST, DWXE_DMA_DVA(sc->sc_txring));
1011 
1012 	/* Allocate  descriptor ring. */
1013 	sc->sc_rxring = dwxe_dmamem_alloc(sc,
1014 	    DWXE_NRXDESC * sizeof(struct dwxe_desc), 8);
1015 	sc->sc_rxdesc = DWXE_DMA_KVA(sc->sc_rxring);
1016 
1017 	sc->sc_rxbuf = malloc(sizeof(struct dwxe_buf) * DWXE_NRXDESC,
1018 	    M_DEVBUF, M_WAITOK);
1019 
1020 	for (i = 0; i < DWXE_NRXDESC; i++) {
1021 		rxb = &sc->sc_rxbuf[i];
1022 		bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1023 		    MCLBYTES, 0, BUS_DMA_WAITOK, &rxb->tb_map);
1024 		rxb->tb_m = NULL;
1025 
1026 		sc->sc_rxdesc[i].sd_next =
1027 		    DWXE_DMA_DVA(sc->sc_rxring) +
1028 		    ((i+1) % DWXE_NRXDESC) * sizeof(struct dwxe_desc);
1029 	}
1030 
1031 	if_rxr_init(&sc->sc_rx_ring, 2, DWXE_NRXDESC);
1032 
1033 	sc->sc_rx_prod = sc->sc_rx_cons = 0;
1034 	dwxe_fill_rx_ring(sc);
1035 
1036 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring),
1037 	    0, DWXE_DMA_LEN(sc->sc_rxring),
1038 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1039 
1040 	dwxe_write(sc, DWXE_RX_DESC_LIST, DWXE_DMA_DVA(sc->sc_rxring));
1041 
1042 	dwxe_lladdr_write(sc);
1043 
1044 	//dwxe_write(sc, DWXE_BASIC_CTL1, DWXE_BASIC_CTL1_SOFT_RST);
1045 
1046 	/* Configure media. */
1047 	if (LIST_FIRST(&sc->sc_mii.mii_phys))
1048 		mii_mediachg(&sc->sc_mii);
1049 
1050 	/* Program promiscuous mode and multicast filters. */
1051 	dwxe_iff(sc);
1052 
1053 	ifp->if_flags |= IFF_RUNNING;
1054 	ifq_clr_oactive(&ifp->if_snd);
1055 
1056 	dwxe_write(sc, DWXE_INT_EN, DWXE_INT_EN_RX_INT |
1057 	    DWXE_INT_EN_TX_INT | DWXE_INT_EN_TX_BUF_UA_INT);
1058 
1059 	dwxe_write(sc, DWXE_TX_CTL1, dwxe_read(sc, DWXE_TX_CTL1) |
1060 	    DWXE_TX_CTL1_TX_MD | DWXE_TX_CTL1_TX_NEXT_FRM |
1061 	    DWXE_TX_CTL1_TX_DMA_EN);
1062 	dwxe_write(sc, DWXE_RX_CTL1, dwxe_read(sc, DWXE_RX_CTL1) |
1063 	    DWXE_RX_CTL1_RX_MD | DWXE_RX_CTL1_RX_DMA_EN);
1064 
1065 	dwxe_write(sc, DWXE_TX_CTL0, dwxe_read(sc, DWXE_TX_CTL0) |
1066 	    DWXE_TX_CTL0_TX_TRANSMITTER_EN);
1067 	dwxe_write(sc, DWXE_RX_CTL0, dwxe_read(sc, DWXE_RX_CTL0) |
1068 	    DWXE_RX_CTL0_RX_RECEIVER_EN | DWXE_RX_CTL0_RX_DO_CRC);
1069 
1070 	timeout_add_sec(&sc->sc_tick, 1);
1071 }
1072 
1073 void
1074 dwxe_down(struct dwxe_softc *sc)
1075 {
1076 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1077 	struct dwxe_buf *txb, *rxb;
1078 	uint32_t dmactrl;
1079 	int i;
1080 
1081 	timeout_del(&sc->sc_rxto);
1082 	timeout_del(&sc->sc_tick);
1083 
1084 	ifp->if_flags &= ~IFF_RUNNING;
1085 	ifq_clr_oactive(&ifp->if_snd);
1086 	ifp->if_timer = 0;
1087 
1088 	dwxe_stop_dma(sc);
1089 
1090 	dwxe_write(sc, DWXE_TX_CTL0, dwxe_read(sc,
1091 	    DWXE_TX_CTL0) & ~DWXE_TX_CTL0_TX_TRANSMITTER_EN);
1092 
1093 	dwxe_write(sc, DWXE_RX_CTL0, dwxe_read(sc,
1094 	    DWXE_RX_CTL0) & ~DWXE_RX_CTL0_RX_RECEIVER_EN);
1095 
1096 	dmactrl = dwxe_read(sc, DWXE_TX_CTL1);
1097 	dmactrl &= ~DWXE_TX_CTL1_TX_DMA_EN;
1098 	dwxe_write(sc, DWXE_TX_CTL1, dmactrl);
1099 
1100 	dmactrl = dwxe_read(sc, DWXE_RX_CTL1);
1101 	dmactrl &= ~DWXE_RX_CTL1_RX_DMA_EN;
1102 	dwxe_write(sc, DWXE_RX_CTL1, dmactrl);
1103 
1104 	dwxe_write(sc, DWXE_INT_EN, 0);
1105 
1106 	for (i = 0; i < DWXE_NTXDESC; i++) {
1107 		txb = &sc->sc_txbuf[i];
1108 		if (txb->tb_m) {
1109 			bus_dmamap_sync(sc->sc_dmat, txb->tb_map, 0,
1110 			    txb->tb_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1111 			bus_dmamap_unload(sc->sc_dmat, txb->tb_map);
1112 			m_freem(txb->tb_m);
1113 		}
1114 		bus_dmamap_destroy(sc->sc_dmat, txb->tb_map);
1115 	}
1116 
1117 	dwxe_dmamem_free(sc, sc->sc_txring);
1118 	free(sc->sc_txbuf, M_DEVBUF, 0);
1119 
1120 	for (i = 0; i < DWXE_NRXDESC; i++) {
1121 		rxb = &sc->sc_rxbuf[i];
1122 		if (rxb->tb_m) {
1123 			bus_dmamap_sync(sc->sc_dmat, rxb->tb_map, 0,
1124 			    rxb->tb_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1125 			bus_dmamap_unload(sc->sc_dmat, rxb->tb_map);
1126 			m_freem(rxb->tb_m);
1127 		}
1128 		bus_dmamap_destroy(sc->sc_dmat, rxb->tb_map);
1129 	}
1130 
1131 	dwxe_dmamem_free(sc, sc->sc_rxring);
1132 	free(sc->sc_rxbuf, M_DEVBUF, 0);
1133 }
1134 
1135 /* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */
1136 static uint32_t
1137 bitrev32(uint32_t x)
1138 {
1139 	x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
1140 	x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
1141 	x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
1142 	x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
1143 
1144 	return (x >> 16) | (x << 16);
1145 }
1146 
1147 void
1148 dwxe_iff(struct dwxe_softc *sc)
1149 {
1150 	struct arpcom *ac = &sc->sc_ac;
1151 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1152 	struct ether_multi *enm;
1153 	struct ether_multistep step;
1154 	uint32_t crc, hash[2], hashbit, hashreg;
1155 	uint32_t reg;
1156 
1157 	reg = 0;
1158 
1159 	ifp->if_flags &= ~IFF_ALLMULTI;
1160 	bzero(hash, sizeof(hash));
1161 	if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
1162 		ifp->if_flags |= IFF_ALLMULTI;
1163 		reg |= DWXE_RX_FRM_FLT_RX_ALL_MULTICAST;
1164 		if (ifp->if_flags & IFF_PROMISC)
1165 			reg |= DWXE_RX_FRM_FLT_DIS_ADDR_FILTER;
1166 	} else {
1167 		reg |= DWXE_RX_FRM_FLT_HASH_MULTICAST;
1168 		ETHER_FIRST_MULTI(step, ac, enm);
1169 		while (enm != NULL) {
1170 			crc = ether_crc32_le(enm->enm_addrlo,
1171 			    ETHER_ADDR_LEN) & 0x7f;
1172 
1173 			crc = bitrev32(~crc) >> 26;
1174 			hashreg = (crc >> 5);
1175 			hashbit = (crc & 0x1f);
1176 			hash[hashreg] |= (1 << hashbit);
1177 
1178 			ETHER_NEXT_MULTI(step, enm);
1179 		}
1180 	}
1181 
1182 	dwxe_lladdr_write(sc);
1183 
1184 	dwxe_write(sc, DWXE_RX_HASH0, hash[1]);
1185 	dwxe_write(sc, DWXE_RX_HASH1, hash[0]);
1186 
1187 	dwxe_write(sc, DWXE_RX_FRM_FLT, reg);
1188 }
1189 
1190 int
1191 dwxe_encap(struct dwxe_softc *sc, struct mbuf *m, int *idx)
1192 {
1193 	struct dwxe_desc *txd, *txd_start;
1194 	bus_dmamap_t map;
1195 	int cur, frag, i;
1196 
1197 	cur = frag = *idx;
1198 	map = sc->sc_txbuf[cur].tb_map;
1199 
1200 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT)) {
1201 		if (m_defrag(m, M_DONTWAIT))
1202 			return (EFBIG);
1203 		if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT))
1204 			return (EFBIG);
1205 	}
1206 
1207 	if (map->dm_nsegs > (DWXE_NTXDESC - sc->sc_tx_cnt - 2)) {
1208 		bus_dmamap_unload(sc->sc_dmat, map);
1209 		return (ENOBUFS);
1210 	}
1211 
1212 	/* Sync the DMA map. */
1213 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
1214 	    BUS_DMASYNC_PREWRITE);
1215 
1216 	txd = txd_start = &sc->sc_txdesc[frag];
1217 	for (i = 0; i < map->dm_nsegs; i++) {
1218 		txd->sd_addr = map->dm_segs[i].ds_addr;
1219 		txd->sd_len = map->dm_segs[i].ds_len;
1220 		if (i == 0)
1221 			txd->sd_len |= DWXE_TX_FIR_DESC;
1222 		if (i == (map->dm_nsegs - 1))
1223 			txd->sd_len |= DWXE_TX_LAST_DESC | DWXE_TX_INT_CTL;
1224 		if (i != 0)
1225 			txd->sd_status = DWXE_TX_DESC_CTL;
1226 
1227 		bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring),
1228 		    frag * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
1229 
1230 		cur = frag;
1231 		if (frag == (DWXE_NTXDESC - 1)) {
1232 			txd = &sc->sc_txdesc[0];
1233 			frag = 0;
1234 		} else {
1235 			txd++;
1236 			frag++;
1237 		}
1238 		KASSERT(frag != sc->sc_tx_cons);
1239 	}
1240 
1241 	txd_start->sd_status = DWXE_TX_DESC_CTL;
1242 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring),
1243 	    *idx * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
1244 
1245 	dwxe_write(sc, DWXE_TX_CTL1, dwxe_read(sc,
1246 	     DWXE_TX_CTL1) | DWXE_TX_CTL1_TX_DMA_START);
1247 
1248 	KASSERT(sc->sc_txbuf[cur].tb_m == NULL);
1249 	sc->sc_txbuf[*idx].tb_map = sc->sc_txbuf[cur].tb_map;
1250 	sc->sc_txbuf[cur].tb_map = map;
1251 	sc->sc_txbuf[cur].tb_m = m;
1252 
1253 	sc->sc_tx_cnt += map->dm_nsegs;
1254 	*idx = frag;
1255 
1256 	return (0);
1257 }
1258 
1259 void
1260 dwxe_reset(struct dwxe_softc *sc)
1261 {
1262 	int n;
1263 
1264 	dwxe_stop_dma(sc);
1265 
1266 	dwxe_write(sc, DWXE_BASIC_CTL1, DWXE_BASIC_CTL1_SOFT_RST);
1267 
1268 	for (n = 0; n < 1000; n++) {
1269 		if ((dwxe_read(sc, DWXE_BASIC_CTL1) &
1270 		    DWXE_BASIC_CTL1_SOFT_RST) == 0)
1271 			return;
1272 		delay(10);
1273 	}
1274 
1275 	printf("%s: reset timeout\n", sc->sc_dev.dv_xname);
1276 }
1277 
1278 void
1279 dwxe_stop_dma(struct dwxe_softc *sc)
1280 {
1281 	uint32_t dmactrl;
1282 
1283 	/* Stop DMA. */
1284 	dmactrl = dwxe_read(sc, DWXE_TX_CTL1);
1285 	dmactrl &= ~DWXE_TX_CTL1_TX_DMA_EN;
1286 	dmactrl |= DWXE_TX_CTL1_TX_FIFO_FLUSH;
1287 	dwxe_write(sc, DWXE_TX_CTL1, dmactrl);
1288 }
1289 
1290 struct dwxe_dmamem *
1291 dwxe_dmamem_alloc(struct dwxe_softc *sc, bus_size_t size, bus_size_t align)
1292 {
1293 	struct dwxe_dmamem *tdm;
1294 	int nsegs;
1295 
1296 	tdm = malloc(sizeof(*tdm), M_DEVBUF, M_WAITOK | M_ZERO);
1297 	tdm->tdm_size = size;
1298 
1299 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1300 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tdm->tdm_map) != 0)
1301 		goto tdmfree;
1302 
1303 	if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &tdm->tdm_seg, 1,
1304 	    &nsegs, BUS_DMA_WAITOK) != 0)
1305 		goto destroy;
1306 
1307 	if (bus_dmamem_map(sc->sc_dmat, &tdm->tdm_seg, nsegs, size,
1308 	    &tdm->tdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
1309 		goto free;
1310 
1311 	if (bus_dmamap_load(sc->sc_dmat, tdm->tdm_map, tdm->tdm_kva, size,
1312 	    NULL, BUS_DMA_WAITOK) != 0)
1313 		goto unmap;
1314 
1315 	bzero(tdm->tdm_kva, size);
1316 
1317 	return (tdm);
1318 
1319 unmap:
1320 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, size);
1321 free:
1322 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
1323 destroy:
1324 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
1325 tdmfree:
1326 	free(tdm, M_DEVBUF, 0);
1327 
1328 	return (NULL);
1329 }
1330 
1331 void
1332 dwxe_dmamem_free(struct dwxe_softc *sc, struct dwxe_dmamem *tdm)
1333 {
1334 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, tdm->tdm_size);
1335 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
1336 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
1337 	free(tdm, M_DEVBUF, 0);
1338 }
1339 
1340 struct mbuf *
1341 dwxe_alloc_mbuf(struct dwxe_softc *sc, bus_dmamap_t map)
1342 {
1343 	struct mbuf *m = NULL;
1344 
1345 	m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
1346 	if (!m)
1347 		return (NULL);
1348 	m->m_len = m->m_pkthdr.len = MCLBYTES;
1349 	m_adj(m, ETHER_ALIGN);
1350 
1351 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) {
1352 		printf("%s: could not load mbuf DMA map", DEVNAME(sc));
1353 		m_freem(m);
1354 		return (NULL);
1355 	}
1356 
1357 	bus_dmamap_sync(sc->sc_dmat, map, 0,
1358 	    m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1359 
1360 	return (m);
1361 }
1362 
1363 void
1364 dwxe_fill_rx_ring(struct dwxe_softc *sc)
1365 {
1366 	struct dwxe_desc *rxd;
1367 	struct dwxe_buf *rxb;
1368 	u_int slots;
1369 
1370 	for (slots = if_rxr_get(&sc->sc_rx_ring, DWXE_NRXDESC);
1371 	    slots > 0; slots--) {
1372 		rxb = &sc->sc_rxbuf[sc->sc_rx_prod];
1373 		rxb->tb_m = dwxe_alloc_mbuf(sc, rxb->tb_map);
1374 		if (rxb->tb_m == NULL)
1375 			break;
1376 
1377 		rxd = &sc->sc_rxdesc[sc->sc_rx_prod];
1378 		rxd->sd_len = rxb->tb_map->dm_segs[0].ds_len - 1;
1379 		rxd->sd_addr = rxb->tb_map->dm_segs[0].ds_addr;
1380 		rxd->sd_status = DWXE_RX_DESC_CTL;
1381 
1382 		if (sc->sc_rx_prod == (DWXE_NRXDESC - 1))
1383 			sc->sc_rx_prod = 0;
1384 		else
1385 			sc->sc_rx_prod++;
1386 	}
1387 	if_rxr_put(&sc->sc_rx_ring, slots);
1388 
1389 	if (if_rxr_inuse(&sc->sc_rx_ring) == 0)
1390 		timeout_add(&sc->sc_rxto, 1);
1391 }
1392