xref: /openbsd-src/sys/dev/fdt/if_dwxe.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: if_dwxe.c,v 1.15 2019/10/07 00:40:04 jmatthew 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_IS_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 	dwxe_fill_rx_ring(sc);
970 
971 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring), 0,
972 	    DWXE_DMA_LEN(sc->sc_rxring),
973 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
974 
975 	if_input(ifp, &ml);
976 }
977 
978 void
979 dwxe_up(struct dwxe_softc *sc)
980 {
981 	struct ifnet *ifp = &sc->sc_ac.ac_if;
982 	struct dwxe_buf *txb, *rxb;
983 	int i;
984 
985 	/* Allocate Tx descriptor ring. */
986 	sc->sc_txring = dwxe_dmamem_alloc(sc,
987 	    DWXE_NTXDESC * sizeof(struct dwxe_desc), 8);
988 	sc->sc_txdesc = DWXE_DMA_KVA(sc->sc_txring);
989 
990 	sc->sc_txbuf = malloc(sizeof(struct dwxe_buf) * DWXE_NTXDESC,
991 	    M_DEVBUF, M_WAITOK);
992 	for (i = 0; i < DWXE_NTXDESC; i++) {
993 		txb = &sc->sc_txbuf[i];
994 		bus_dmamap_create(sc->sc_dmat, MCLBYTES, DWXE_NTXSEGS,
995 		    MCLBYTES, 0, BUS_DMA_WAITOK, &txb->tb_map);
996 		txb->tb_m = NULL;
997 
998 		sc->sc_txdesc[i].sd_next =
999 		    DWXE_DMA_DVA(sc->sc_txring) +
1000 		    ((i+1) % DWXE_NTXDESC) * sizeof(struct dwxe_desc);
1001 	}
1002 
1003 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring),
1004 	    0, DWXE_DMA_LEN(sc->sc_txring), BUS_DMASYNC_PREWRITE);
1005 
1006 	sc->sc_tx_prod = sc->sc_tx_cons = 0;
1007 	sc->sc_tx_cnt = 0;
1008 
1009 	dwxe_write(sc, DWXE_TX_DESC_LIST, DWXE_DMA_DVA(sc->sc_txring));
1010 
1011 	/* Allocate  descriptor ring. */
1012 	sc->sc_rxring = dwxe_dmamem_alloc(sc,
1013 	    DWXE_NRXDESC * sizeof(struct dwxe_desc), 8);
1014 	sc->sc_rxdesc = DWXE_DMA_KVA(sc->sc_rxring);
1015 
1016 	sc->sc_rxbuf = malloc(sizeof(struct dwxe_buf) * DWXE_NRXDESC,
1017 	    M_DEVBUF, M_WAITOK);
1018 
1019 	for (i = 0; i < DWXE_NRXDESC; i++) {
1020 		rxb = &sc->sc_rxbuf[i];
1021 		bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1022 		    MCLBYTES, 0, BUS_DMA_WAITOK, &rxb->tb_map);
1023 		rxb->tb_m = NULL;
1024 
1025 		sc->sc_rxdesc[i].sd_next =
1026 		    DWXE_DMA_DVA(sc->sc_rxring) +
1027 		    ((i+1) % DWXE_NRXDESC) * sizeof(struct dwxe_desc);
1028 	}
1029 
1030 	if_rxr_init(&sc->sc_rx_ring, 2, DWXE_NRXDESC);
1031 
1032 	sc->sc_rx_prod = sc->sc_rx_cons = 0;
1033 	dwxe_fill_rx_ring(sc);
1034 
1035 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_rxring),
1036 	    0, DWXE_DMA_LEN(sc->sc_rxring),
1037 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1038 
1039 	dwxe_write(sc, DWXE_RX_DESC_LIST, DWXE_DMA_DVA(sc->sc_rxring));
1040 
1041 	dwxe_lladdr_write(sc);
1042 
1043 	//dwxe_write(sc, DWXE_BASIC_CTL1, DWXE_BASIC_CTL1_SOFT_RST);
1044 
1045 	/* Configure media. */
1046 	if (LIST_FIRST(&sc->sc_mii.mii_phys))
1047 		mii_mediachg(&sc->sc_mii);
1048 
1049 	/* Program promiscuous mode and multicast filters. */
1050 	dwxe_iff(sc);
1051 
1052 	ifp->if_flags |= IFF_RUNNING;
1053 	ifq_clr_oactive(&ifp->if_snd);
1054 
1055 	dwxe_write(sc, DWXE_INT_EN, DWXE_INT_EN_RX_INT |
1056 	    DWXE_INT_EN_TX_INT | DWXE_INT_EN_TX_BUF_UA_INT);
1057 
1058 	dwxe_write(sc, DWXE_TX_CTL1, dwxe_read(sc, DWXE_TX_CTL1) |
1059 	    DWXE_TX_CTL1_TX_MD | DWXE_TX_CTL1_TX_NEXT_FRM |
1060 	    DWXE_TX_CTL1_TX_DMA_EN);
1061 	dwxe_write(sc, DWXE_RX_CTL1, dwxe_read(sc, DWXE_RX_CTL1) |
1062 	    DWXE_RX_CTL1_RX_MD | DWXE_RX_CTL1_RX_DMA_EN);
1063 
1064 	dwxe_write(sc, DWXE_TX_CTL0, dwxe_read(sc, DWXE_TX_CTL0) |
1065 	    DWXE_TX_CTL0_TX_TRANSMITTER_EN);
1066 	dwxe_write(sc, DWXE_RX_CTL0, dwxe_read(sc, DWXE_RX_CTL0) |
1067 	    DWXE_RX_CTL0_RX_RECEIVER_EN | DWXE_RX_CTL0_RX_DO_CRC);
1068 
1069 	timeout_add_sec(&sc->sc_tick, 1);
1070 }
1071 
1072 void
1073 dwxe_down(struct dwxe_softc *sc)
1074 {
1075 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1076 	struct dwxe_buf *txb, *rxb;
1077 	uint32_t dmactrl;
1078 	int i;
1079 
1080 	timeout_del(&sc->sc_rxto);
1081 	timeout_del(&sc->sc_tick);
1082 
1083 	ifp->if_flags &= ~IFF_RUNNING;
1084 	ifq_clr_oactive(&ifp->if_snd);
1085 	ifp->if_timer = 0;
1086 
1087 	dwxe_stop_dma(sc);
1088 
1089 	dwxe_write(sc, DWXE_TX_CTL0, dwxe_read(sc,
1090 	    DWXE_TX_CTL0) & ~DWXE_TX_CTL0_TX_TRANSMITTER_EN);
1091 
1092 	dwxe_write(sc, DWXE_RX_CTL0, dwxe_read(sc,
1093 	    DWXE_RX_CTL0) & ~DWXE_RX_CTL0_RX_RECEIVER_EN);
1094 
1095 	dmactrl = dwxe_read(sc, DWXE_TX_CTL1);
1096 	dmactrl &= ~DWXE_TX_CTL1_TX_DMA_EN;
1097 	dwxe_write(sc, DWXE_TX_CTL1, dmactrl);
1098 
1099 	dmactrl = dwxe_read(sc, DWXE_RX_CTL1);
1100 	dmactrl &= ~DWXE_RX_CTL1_RX_DMA_EN;
1101 	dwxe_write(sc, DWXE_RX_CTL1, dmactrl);
1102 
1103 	dwxe_write(sc, DWXE_INT_EN, 0);
1104 
1105 	for (i = 0; i < DWXE_NTXDESC; i++) {
1106 		txb = &sc->sc_txbuf[i];
1107 		if (txb->tb_m) {
1108 			bus_dmamap_sync(sc->sc_dmat, txb->tb_map, 0,
1109 			    txb->tb_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1110 			bus_dmamap_unload(sc->sc_dmat, txb->tb_map);
1111 			m_freem(txb->tb_m);
1112 		}
1113 		bus_dmamap_destroy(sc->sc_dmat, txb->tb_map);
1114 	}
1115 
1116 	dwxe_dmamem_free(sc, sc->sc_txring);
1117 	free(sc->sc_txbuf, M_DEVBUF, 0);
1118 
1119 	for (i = 0; i < DWXE_NRXDESC; i++) {
1120 		rxb = &sc->sc_rxbuf[i];
1121 		if (rxb->tb_m) {
1122 			bus_dmamap_sync(sc->sc_dmat, rxb->tb_map, 0,
1123 			    rxb->tb_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1124 			bus_dmamap_unload(sc->sc_dmat, rxb->tb_map);
1125 			m_freem(rxb->tb_m);
1126 		}
1127 		bus_dmamap_destroy(sc->sc_dmat, rxb->tb_map);
1128 	}
1129 
1130 	dwxe_dmamem_free(sc, sc->sc_rxring);
1131 	free(sc->sc_rxbuf, M_DEVBUF, 0);
1132 }
1133 
1134 /* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */
1135 static uint32_t
1136 bitrev32(uint32_t x)
1137 {
1138 	x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
1139 	x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
1140 	x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
1141 	x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
1142 
1143 	return (x >> 16) | (x << 16);
1144 }
1145 
1146 void
1147 dwxe_iff(struct dwxe_softc *sc)
1148 {
1149 	struct arpcom *ac = &sc->sc_ac;
1150 	struct ifnet *ifp = &sc->sc_ac.ac_if;
1151 	struct ether_multi *enm;
1152 	struct ether_multistep step;
1153 	uint32_t crc, hash[2], hashbit, hashreg;
1154 	uint32_t reg;
1155 
1156 	reg = 0;
1157 
1158 	ifp->if_flags &= ~IFF_ALLMULTI;
1159 	bzero(hash, sizeof(hash));
1160 	if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
1161 		ifp->if_flags |= IFF_ALLMULTI;
1162 		reg |= DWXE_RX_FRM_FLT_RX_ALL_MULTICAST;
1163 		if (ifp->if_flags & IFF_PROMISC)
1164 			reg |= DWXE_RX_FRM_FLT_DIS_ADDR_FILTER;
1165 	} else {
1166 		reg |= DWXE_RX_FRM_FLT_HASH_MULTICAST;
1167 		ETHER_FIRST_MULTI(step, ac, enm);
1168 		while (enm != NULL) {
1169 			crc = ether_crc32_le(enm->enm_addrlo,
1170 			    ETHER_ADDR_LEN) & 0x7f;
1171 
1172 			crc = bitrev32(~crc) >> 26;
1173 			hashreg = (crc >> 5);
1174 			hashbit = (crc & 0x1f);
1175 			hash[hashreg] |= (1 << hashbit);
1176 
1177 			ETHER_NEXT_MULTI(step, enm);
1178 		}
1179 	}
1180 
1181 	dwxe_lladdr_write(sc);
1182 
1183 	dwxe_write(sc, DWXE_RX_HASH0, hash[1]);
1184 	dwxe_write(sc, DWXE_RX_HASH1, hash[0]);
1185 
1186 	dwxe_write(sc, DWXE_RX_FRM_FLT, reg);
1187 }
1188 
1189 int
1190 dwxe_encap(struct dwxe_softc *sc, struct mbuf *m, int *idx)
1191 {
1192 	struct dwxe_desc *txd, *txd_start;
1193 	bus_dmamap_t map;
1194 	int cur, frag, i;
1195 
1196 	cur = frag = *idx;
1197 	map = sc->sc_txbuf[cur].tb_map;
1198 
1199 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT)) {
1200 		if (m_defrag(m, M_DONTWAIT))
1201 			return (EFBIG);
1202 		if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT))
1203 			return (EFBIG);
1204 	}
1205 
1206 	if (map->dm_nsegs > (DWXE_NTXDESC - sc->sc_tx_cnt - 2)) {
1207 		bus_dmamap_unload(sc->sc_dmat, map);
1208 		return (ENOBUFS);
1209 	}
1210 
1211 	/* Sync the DMA map. */
1212 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
1213 	    BUS_DMASYNC_PREWRITE);
1214 
1215 	txd = txd_start = &sc->sc_txdesc[frag];
1216 	for (i = 0; i < map->dm_nsegs; i++) {
1217 		txd->sd_addr = map->dm_segs[i].ds_addr;
1218 		txd->sd_len = map->dm_segs[i].ds_len;
1219 		if (i == 0)
1220 			txd->sd_len |= DWXE_TX_FIR_DESC;
1221 		if (i == (map->dm_nsegs - 1))
1222 			txd->sd_len |= DWXE_TX_LAST_DESC | DWXE_TX_INT_CTL;
1223 		if (i != 0)
1224 			txd->sd_status = DWXE_TX_DESC_CTL;
1225 
1226 		bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring),
1227 		    frag * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
1228 
1229 		cur = frag;
1230 		if (frag == (DWXE_NTXDESC - 1)) {
1231 			txd = &sc->sc_txdesc[0];
1232 			frag = 0;
1233 		} else {
1234 			txd++;
1235 			frag++;
1236 		}
1237 		KASSERT(frag != sc->sc_tx_cons);
1238 	}
1239 
1240 	txd_start->sd_status = DWXE_TX_DESC_CTL;
1241 	bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring),
1242 	    *idx * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
1243 
1244 	dwxe_write(sc, DWXE_TX_CTL1, dwxe_read(sc,
1245 	     DWXE_TX_CTL1) | DWXE_TX_CTL1_TX_DMA_START);
1246 
1247 	KASSERT(sc->sc_txbuf[cur].tb_m == NULL);
1248 	sc->sc_txbuf[*idx].tb_map = sc->sc_txbuf[cur].tb_map;
1249 	sc->sc_txbuf[cur].tb_map = map;
1250 	sc->sc_txbuf[cur].tb_m = m;
1251 
1252 	sc->sc_tx_cnt += map->dm_nsegs;
1253 	*idx = frag;
1254 
1255 	return (0);
1256 }
1257 
1258 void
1259 dwxe_reset(struct dwxe_softc *sc)
1260 {
1261 	int n;
1262 
1263 	dwxe_stop_dma(sc);
1264 
1265 	dwxe_write(sc, DWXE_BASIC_CTL1, DWXE_BASIC_CTL1_SOFT_RST);
1266 
1267 	for (n = 0; n < 1000; n++) {
1268 		if ((dwxe_read(sc, DWXE_BASIC_CTL1) &
1269 		    DWXE_BASIC_CTL1_SOFT_RST) == 0)
1270 			return;
1271 		delay(10);
1272 	}
1273 
1274 	printf("%s: reset timeout\n", sc->sc_dev.dv_xname);
1275 }
1276 
1277 void
1278 dwxe_stop_dma(struct dwxe_softc *sc)
1279 {
1280 	uint32_t dmactrl;
1281 
1282 	/* Stop DMA. */
1283 	dmactrl = dwxe_read(sc, DWXE_TX_CTL1);
1284 	dmactrl &= ~DWXE_TX_CTL1_TX_DMA_EN;
1285 	dmactrl |= DWXE_TX_CTL1_TX_FIFO_FLUSH;
1286 	dwxe_write(sc, DWXE_TX_CTL1, dmactrl);
1287 }
1288 
1289 struct dwxe_dmamem *
1290 dwxe_dmamem_alloc(struct dwxe_softc *sc, bus_size_t size, bus_size_t align)
1291 {
1292 	struct dwxe_dmamem *tdm;
1293 	int nsegs;
1294 
1295 	tdm = malloc(sizeof(*tdm), M_DEVBUF, M_WAITOK | M_ZERO);
1296 	tdm->tdm_size = size;
1297 
1298 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1299 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tdm->tdm_map) != 0)
1300 		goto tdmfree;
1301 
1302 	if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &tdm->tdm_seg, 1,
1303 	    &nsegs, BUS_DMA_WAITOK) != 0)
1304 		goto destroy;
1305 
1306 	if (bus_dmamem_map(sc->sc_dmat, &tdm->tdm_seg, nsegs, size,
1307 	    &tdm->tdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
1308 		goto free;
1309 
1310 	if (bus_dmamap_load(sc->sc_dmat, tdm->tdm_map, tdm->tdm_kva, size,
1311 	    NULL, BUS_DMA_WAITOK) != 0)
1312 		goto unmap;
1313 
1314 	bzero(tdm->tdm_kva, size);
1315 
1316 	return (tdm);
1317 
1318 unmap:
1319 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, size);
1320 free:
1321 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
1322 destroy:
1323 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
1324 tdmfree:
1325 	free(tdm, M_DEVBUF, 0);
1326 
1327 	return (NULL);
1328 }
1329 
1330 void
1331 dwxe_dmamem_free(struct dwxe_softc *sc, struct dwxe_dmamem *tdm)
1332 {
1333 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, tdm->tdm_size);
1334 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
1335 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
1336 	free(tdm, M_DEVBUF, 0);
1337 }
1338 
1339 struct mbuf *
1340 dwxe_alloc_mbuf(struct dwxe_softc *sc, bus_dmamap_t map)
1341 {
1342 	struct mbuf *m = NULL;
1343 
1344 	m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
1345 	if (!m)
1346 		return (NULL);
1347 	m->m_len = m->m_pkthdr.len = MCLBYTES;
1348 	m_adj(m, ETHER_ALIGN);
1349 
1350 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) {
1351 		printf("%s: could not load mbuf DMA map", DEVNAME(sc));
1352 		m_freem(m);
1353 		return (NULL);
1354 	}
1355 
1356 	bus_dmamap_sync(sc->sc_dmat, map, 0,
1357 	    m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1358 
1359 	return (m);
1360 }
1361 
1362 void
1363 dwxe_fill_rx_ring(struct dwxe_softc *sc)
1364 {
1365 	struct dwxe_desc *rxd;
1366 	struct dwxe_buf *rxb;
1367 	u_int slots;
1368 
1369 	for (slots = if_rxr_get(&sc->sc_rx_ring, DWXE_NRXDESC);
1370 	    slots > 0; slots--) {
1371 		rxb = &sc->sc_rxbuf[sc->sc_rx_prod];
1372 		rxb->tb_m = dwxe_alloc_mbuf(sc, rxb->tb_map);
1373 		if (rxb->tb_m == NULL)
1374 			break;
1375 
1376 		rxd = &sc->sc_rxdesc[sc->sc_rx_prod];
1377 		rxd->sd_len = rxb->tb_map->dm_segs[0].ds_len - 1;
1378 		rxd->sd_addr = rxb->tb_map->dm_segs[0].ds_addr;
1379 		rxd->sd_status = DWXE_RX_DESC_CTL;
1380 
1381 		if (sc->sc_rx_prod == (DWXE_NRXDESC - 1))
1382 			sc->sc_rx_prod = 0;
1383 		else
1384 			sc->sc_rx_prod++;
1385 	}
1386 	if_rxr_put(&sc->sc_rx_ring, slots);
1387 
1388 	if (if_rxr_inuse(&sc->sc_rx_ring) == 0)
1389 		timeout_add(&sc->sc_rxto, 1);
1390 }
1391