xref: /openbsd/sys/dev/ic/mtd8xx.c (revision 8529ddd3)
1 /*	$OpenBSD: mtd8xx.c,v 1.26 2015/04/13 08:45:48 mpi Exp $	*/
2 
3 /*
4  * Copyright (c) 2003 Oleg Safiullin <form@pdp11.org.ru>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include "bpfilter.h"
32 
33 #include <sys/param.h>
34 #include <sys/mbuf.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
39 
40 #include <net/if.h>
41 #include <net/if_media.h>
42 
43 #if NBPFILTER > 0
44 #include <net/bpf.h>
45 #endif
46 
47 #include <netinet/in.h>
48 #include <netinet/if_ether.h>
49 
50 #include <machine/bus.h>
51 
52 #include <dev/mii/mii.h>
53 #include <dev/mii/miivar.h>
54 
55 #include <dev/pci/pcidevs.h>
56 
57 #include <dev/ic/mtd8xxreg.h>
58 #include <dev/ic/mtd8xxvar.h>
59 
60 
61 static int mtd_ifmedia_upd(struct ifnet *);
62 static void mtd_ifmedia_sts(struct ifnet *, struct ifmediareq *);
63 
64 static u_int32_t mtd_mii_command(struct mtd_softc *, int, int, int);
65 static int mtd_miibus_readreg(struct device *, int, int);
66 static void mtd_miibus_writereg(struct device *, int, int, int);
67 static void mtd_miibus_statchg(struct device *);
68 static void mtd_setmulti(struct mtd_softc *);
69 
70 static int mtd_encap(struct mtd_softc *, struct mbuf *, u_int32_t *);
71 static int mtd_list_rx_init(struct mtd_softc *);
72 static void mtd_list_tx_init(struct mtd_softc *);
73 static int mtd_newbuf(struct mtd_softc *, int, struct mbuf *);
74 
75 static void mtd_reset(struct mtd_softc *sc);
76 static int mtd_ioctl(struct ifnet *, u_long, caddr_t);
77 static void mtd_init(struct ifnet *);
78 static void mtd_start(struct ifnet *);
79 static void mtd_stop(struct ifnet *);
80 static void mtd_watchdog(struct ifnet *);
81 
82 static void mtd_rxeof(struct mtd_softc *);
83 static int mtd_rx_resync(struct mtd_softc *);
84 static void mtd_txeof(struct mtd_softc *);
85 
86 
87 void
88 mtd_attach(struct mtd_softc *sc)
89 {
90 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
91 	u_int32_t enaddr[2];
92 	int i;
93 
94 	/* Reset the adapter. */
95 	mtd_reset(sc);
96 
97 	if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mtd_list_data),
98 	    PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,
99 	    BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) {
100 		printf(": can't alloc list mem\n");
101 		return;
102 	}
103 	if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,
104 	    sizeof(struct mtd_list_data), &sc->sc_listkva,
105 	    BUS_DMA_NOWAIT) != 0) {
106 		printf(": can't map list mem\n");
107 		return;
108 	}
109 	if (bus_dmamap_create(sc->sc_dmat, sizeof(struct mtd_list_data), 1,
110 	    sizeof(struct mtd_list_data), 0, BUS_DMA_NOWAIT,
111 	    &sc->sc_listmap) != 0) {
112 		printf(": can't alloc list map\n");
113 		return;
114 	}
115 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,
116 	    sizeof(struct mtd_list_data), NULL, BUS_DMA_NOWAIT) != 0) {
117 		printf(": can't load list map\n");
118 		return;
119 	}
120 	sc->mtd_ldata = (struct mtd_list_data *)sc->sc_listkva;
121 
122 	for (i = 0; i < MTD_RX_LIST_CNT; i++) {
123 		if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
124 		    0, BUS_DMA_NOWAIT,
125 		    &sc->mtd_cdata.mtd_rx_chain[i].sd_map) != 0) {
126 			printf(": can't create rx map\n");
127 			return;
128 		}
129 	}
130 	if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
131 	    BUS_DMA_NOWAIT, &sc->sc_rx_sparemap) != 0) {
132 		printf(": can't create rx spare map\n");
133 		return;
134 	}
135 
136 	for (i = 0; i < MTD_TX_LIST_CNT; i++) {
137 		if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
138 		    MTD_TX_LIST_CNT - 5, MCLBYTES, 0, BUS_DMA_NOWAIT,
139 		    &sc->mtd_cdata.mtd_tx_chain[i].sd_map) != 0) {
140 			printf(": can't create tx map\n");
141 			return;
142 		}
143 	}
144 	if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, MTD_TX_LIST_CNT - 5,
145 	    MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap) != 0) {
146 		printf(": can't create tx spare map\n");
147 		return;
148 	}
149 
150 
151 	/* Get station address. */
152 	enaddr[0] = letoh32(CSR_READ_4(MTD_PAR0));
153 	enaddr[1] = letoh32(CSR_READ_4(MTD_PAR4));
154 	bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
155 	printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
156 
157 	/* Initialize interface */
158 	ifp->if_softc = sc;
159 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
160 	ifp->if_ioctl = mtd_ioctl;
161 	ifp->if_start = mtd_start;
162 	ifp->if_watchdog = mtd_watchdog;
163 	IFQ_SET_READY(&ifp->if_snd);
164 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
165 
166 	ifp->if_capabilities = IFCAP_VLAN_MTU;
167 
168 	/*
169 	 * Initialize our media structures and probe the MII.
170 	 */
171 	sc->sc_mii.mii_ifp = ifp;
172 	sc->sc_mii.mii_readreg = mtd_miibus_readreg;
173 	sc->sc_mii.mii_writereg = mtd_miibus_writereg;
174 	sc->sc_mii.mii_statchg = mtd_miibus_statchg;
175 	ifmedia_init(&sc->sc_mii.mii_media, 0, mtd_ifmedia_upd,
176 	    mtd_ifmedia_sts);
177 	mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
178 	    MII_OFFSET_ANY, 0);
179 	if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
180 		ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE, 0,
181 		    NULL);
182 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE);
183 	} else
184 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
185 
186 	/*
187 	 * Attach us everywhere
188 	 */
189 	if_attach(ifp);
190 	ether_ifattach(ifp);
191 }
192 
193 
194 static int
195 mtd_ifmedia_upd(struct ifnet *ifp)
196 {
197 	struct mtd_softc *sc = ifp->if_softc;
198 
199 	return (mii_mediachg(&sc->sc_mii));
200 }
201 
202 
203 static void
204 mtd_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
205 {
206 	struct mtd_softc *sc = ifp->if_softc;
207 
208 	mii_pollstat(&sc->sc_mii);
209 	ifmr->ifm_active = sc->sc_mii.mii_media_active;
210 	ifmr->ifm_status = sc->sc_mii.mii_media_status;
211 }
212 
213 
214 static u_int32_t
215 mtd_mii_command(struct mtd_softc *sc, int opcode, int phy, int reg)
216 {
217 	u_int32_t miir, mask, data;
218 	int i;
219 
220 	miir = (CSR_READ_4(MTD_MIIMGT) & ~MIIMGT_MASK) | MIIMGT_WRITE |
221 	    MIIMGT_MDO;
222 
223 	for (i = 0; i < 32; i++) {
224 		miir &= ~MIIMGT_MDC;
225 		CSR_WRITE_4(MTD_MIIMGT, miir);
226 		miir |= MIIMGT_MDC;
227 		CSR_WRITE_4(MTD_MIIMGT, miir);
228 	}
229 
230 	data = opcode | (phy << 7) | (reg << 2);
231 
232 	for (mask = 0; mask; mask >>= 1) {
233 		miir &= ~(MIIMGT_MDC | MIIMGT_MDO);
234 		if (mask & data)
235 			miir |= MIIMGT_MDO;
236 		CSR_WRITE_4(MTD_MIIMGT, miir);
237 		miir |= MIIMGT_MDC;
238 		CSR_WRITE_4(MTD_MIIMGT, miir);
239 		DELAY(30);
240 
241 		if (mask == 0x4 && opcode == MII_OPCODE_RD)
242 			miir &= ~MIIMGT_WRITE;
243 	}
244 	return (miir);
245 }
246 
247 
248 
249 static int
250 mtd_miibus_readreg(struct device *self, int phy, int reg)
251 {
252 	struct mtd_softc *sc = (void *)self;
253 
254 	if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD803)
255 		return (phy ? 0 : (int)CSR_READ_2(MTD_PHYCSR + (reg << 1)));
256 	else {
257 		u_int32_t miir, mask, data;
258 
259 		miir = mtd_mii_command(sc, MII_OPCODE_RD, phy, reg);
260 		for (mask = 0x8000, data = 0; mask; mask >>= 1) {
261 			miir &= ~MIIMGT_MDC;
262 			CSR_WRITE_4(MTD_MIIMGT, miir);
263 			miir = CSR_READ_4(MTD_MIIMGT);
264 			if (miir & MIIMGT_MDI)
265 				data |= mask;
266 			miir |= MIIMGT_MDC;
267 			CSR_WRITE_4(MTD_MIIMGT, miir);
268 			DELAY(30);
269 		}
270 		miir &= ~MIIMGT_MDC;
271 		CSR_WRITE_4(MTD_MIIMGT, miir);
272 
273 		return ((int)data);
274 	}
275 }
276 
277 
278 static void
279 mtd_miibus_writereg(struct device *self, int phy, int reg, int val)
280 {
281 	struct mtd_softc *sc = (void *)self;
282 
283 	if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD803) {
284 		if (!phy)
285 			CSR_WRITE_2(MTD_PHYCSR + (reg << 1), val);
286 	} else {
287 		u_int32_t miir, mask;
288 
289 		miir = mtd_mii_command(sc, MII_OPCODE_WR, phy, reg);
290 		for (mask = 0x8000; mask; mask >>= 1) {
291 			miir &= ~(MIIMGT_MDC | MIIMGT_MDO);
292 			if (mask & (u_int32_t)val)
293 				miir |= MIIMGT_MDO;
294 			CSR_WRITE_4(MTD_MIIMGT, miir);
295 			miir |= MIIMGT_MDC;
296 			CSR_WRITE_4(MTD_MIIMGT, miir);
297 			DELAY(1);
298 		}
299 		miir &= ~MIIMGT_MDC;
300 		CSR_WRITE_4(MTD_MIIMGT, miir);
301 	}
302 }
303 
304 
305 static void
306 mtd_miibus_statchg(struct device *self)
307 {
308 	/* NOTHING */
309 }
310 
311 
312 void
313 mtd_setmulti(struct mtd_softc *sc)
314 {
315 	struct arpcom *ac = &sc->sc_arpcom;
316 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
317 	u_int32_t rxfilt, crc, hash[2] = { 0, 0 };
318 	struct ether_multistep step;
319 	struct ether_multi *enm;
320 	int mcnt = 0;
321 
322 	if (ac->ac_multirangecnt > 0)
323 		ifp->if_flags |= IFF_ALLMULTI;
324 
325 	rxfilt = CSR_READ_4(MTD_TCRRCR) & ~RCR_AM;
326 	if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
327 		rxfilt |= RCR_AM;
328 		CSR_WRITE_4(MTD_TCRRCR, rxfilt);
329 		CSR_WRITE_4(MTD_MAR0, 0xffffffff);
330 		CSR_WRITE_4(MTD_MAR4, 0xffffffff);
331 		return;
332 	}
333 
334 	/* First, zot all the existing hash bits. */
335 	CSR_WRITE_4(MTD_MAR0, 0);
336 	CSR_WRITE_4(MTD_MAR4, 0);
337 
338 	/* Now program new ones. */
339 	ETHER_FIRST_MULTI(step, ac, enm);
340 	while (enm != NULL) {
341 		crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
342 		hash[crc >> 5] |= 1 << (crc & 0xf);
343 		++mcnt;
344 		ETHER_NEXT_MULTI(step, enm);
345 	}
346 
347 	if (mcnt)
348 		rxfilt |= RCR_AM;
349 	CSR_WRITE_4(MTD_MAR0, hash[0]);
350 	CSR_WRITE_4(MTD_MAR4, hash[1]);
351 	CSR_WRITE_4(MTD_TCRRCR, rxfilt);
352 }
353 
354 
355 /*
356  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
357  * pointers to the fragment pointers.
358  */
359 int
360 mtd_encap(struct mtd_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
361 {
362 	struct mtd_tx_desc *f = NULL;
363 	int frag, cur, cnt = 0, i, total_len = 0;
364 	bus_dmamap_t map;
365 
366 	/*
367  	 * Start packing the mbufs in this chain into
368 	 * the fragment pointers. Stop when we run out
369  	 * of fragments or hit the end of the mbuf chain.
370 	 */
371 	map = sc->sc_tx_sparemap;
372 
373 	if (bus_dmamap_load_mbuf(sc->sc_dmat, map,
374 	    m_head, BUS_DMA_NOWAIT) != 0)
375 		return (1);
376 
377 	cur = frag = *txidx;
378 
379 	for (i = 0; i < map->dm_nsegs; i++) {
380 		if ((MTD_TX_LIST_CNT -
381 		    (sc->mtd_cdata.mtd_tx_cnt + cnt)) < 5) {
382 			bus_dmamap_unload(sc->sc_dmat, map);
383 			return (1);
384 		}
385 
386 		f = &sc->mtd_ldata->mtd_tx_list[frag];
387 		f->td_tcw = htole32(map->dm_segs[i].ds_len);
388 		total_len += map->dm_segs[i].ds_len;
389 		if (cnt == 0) {
390 			f->td_tsw = 0;
391 			f->td_tcw |= htole32(TCW_FD | TCW_CRC | TCW_PAD);
392 		} else
393 			f->td_tsw = htole32(TSW_OWN);
394 		f->td_buf = htole32(map->dm_segs[i].ds_addr);
395 		cur = frag;
396 		frag = (frag + 1) % MTD_TX_LIST_CNT;
397 		cnt++;
398 	}
399 
400 	sc->mtd_cdata.mtd_tx_cnt += cnt;
401 	sc->mtd_cdata.mtd_tx_chain[cur].sd_mbuf = m_head;
402 	sc->sc_tx_sparemap = sc->mtd_cdata.mtd_tx_chain[cur].sd_map;
403 	sc->mtd_cdata.mtd_tx_chain[cur].sd_map = map;
404 	sc->mtd_ldata->mtd_tx_list[cur].td_tcw |= htole32(TCW_LD | TCW_IC);
405 	if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD891)
406 		sc->mtd_ldata->mtd_tx_list[cur].td_tcw |=
407 		    htole32(TCW_EIC | TCW_RTLC);
408 
409 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
410 	    BUS_DMASYNC_PREWRITE);
411 
412 	sc->mtd_ldata->mtd_tx_list[*txidx].td_tsw = htole32(TSW_OWN);
413 	sc->mtd_ldata->mtd_tx_list[*txidx].td_tcw |=
414 	    htole32(total_len << TCW_PKTS_SHIFT);
415 
416 	bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
417 	    offsetof(struct mtd_list_data, mtd_tx_list[0]),
418 	    sizeof(struct mtd_tx_desc) * MTD_TX_LIST_CNT,
419 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
420 
421 	*txidx = frag;
422 
423 	return (0);
424 }
425 
426 
427 /*
428  * Initialize the transmit descriptors.
429  */
430 static void
431 mtd_list_tx_init(struct mtd_softc *sc)
432 {
433 	struct mtd_chain_data *cd;
434 	struct mtd_list_data *ld;
435 	int i;
436 
437 	cd = &sc->mtd_cdata;
438 	ld = sc->mtd_ldata;
439 	for (i = 0; i < MTD_TX_LIST_CNT; i++) {
440 		cd->mtd_tx_chain[i].sd_mbuf = NULL;
441 		ld->mtd_tx_list[i].td_tsw = 0;
442 		ld->mtd_tx_list[i].td_tcw = 0;
443 		ld->mtd_tx_list[i].td_buf = 0;
444 		ld->mtd_tx_list[i].td_next = htole32(
445 		    sc->sc_listmap->dm_segs[0].ds_addr +
446 		    offsetof(struct mtd_list_data,
447 		    mtd_tx_list[(i + 1) % MTD_TX_LIST_CNT]));
448 	}
449 
450 	cd->mtd_tx_prod = cd->mtd_tx_cons = cd->mtd_tx_cnt = 0;
451 }
452 
453 
454 /*
455  * Initialize the RX descriptors and allocate mbufs for them. Note that
456  * we arrange the descriptors in a closed ring, so that the last descriptor
457  * points back to the first.
458  */
459 static int
460 mtd_list_rx_init(struct mtd_softc *sc)
461 {
462 	struct mtd_list_data *ld;
463 	int i;
464 
465 	ld = sc->mtd_ldata;
466 
467 	for (i = 0; i < MTD_RX_LIST_CNT; i++) {
468 		if (mtd_newbuf(sc, i, NULL))
469 			return (1);
470 		ld->mtd_rx_list[i].rd_next = htole32(
471 		    sc->sc_listmap->dm_segs[0].ds_addr +
472 		    offsetof(struct mtd_list_data,
473 		    mtd_rx_list[(i + 1) % MTD_RX_LIST_CNT])
474 		);
475 	}
476 
477 	sc->mtd_cdata.mtd_rx_prod = 0;
478 
479 	return (0);
480 }
481 
482 
483 /*
484  * Initialize an RX descriptor and attach an MBUF cluster.
485  */
486 static int
487 mtd_newbuf(struct mtd_softc *sc, int i, struct mbuf *m)
488 {
489 	struct mbuf *m_new = NULL;
490 	struct mtd_rx_desc *c;
491 	bus_dmamap_t map;
492 
493 	c = &sc->mtd_ldata->mtd_rx_list[i];
494 
495 	if (m == NULL) {
496 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
497 		if (m_new == NULL)
498 			return (1);
499 
500 		MCLGET(m_new, M_DONTWAIT);
501 		if (!(m_new->m_flags & M_EXT)) {
502 			m_freem(m_new);
503 			return (1);
504 		}
505 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
506 		if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_sparemap,
507 		    mtod(m_new, caddr_t), MCLBYTES, NULL,
508 		    BUS_DMA_NOWAIT) != 0) {
509 			m_freem(m_new);
510 			return (1);
511 		}
512 		map = sc->mtd_cdata.mtd_rx_chain[i].sd_map;
513 		sc->mtd_cdata.mtd_rx_chain[i].sd_map = sc->sc_rx_sparemap;
514 		sc->sc_rx_sparemap = map;
515 	} else {
516 		m_new = m;
517 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
518 		m_new->m_data = m_new->m_ext.ext_buf;
519 	}
520 
521 	m_adj(m_new, sizeof(u_int64_t));
522 
523 	bus_dmamap_sync(sc->sc_dmat, sc->mtd_cdata.mtd_rx_chain[i].sd_map, 0,
524 	    sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_mapsize,
525 	    BUS_DMASYNC_PREREAD);
526 
527 	sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = m_new;
528 	c->rd_buf = htole32(
529 	    sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_segs[0].ds_addr +
530 	    sizeof(u_int64_t));
531 	c->rd_rcw = htole32(ETHER_MAX_DIX_LEN);
532 	c->rd_rsr = htole32(RSR_OWN);
533 
534 	bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
535 	    offsetof(struct mtd_list_data, mtd_rx_list[i]),
536 	    sizeof(struct mtd_rx_desc),
537 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
538 
539 	return (0);
540 }
541 
542 
543 static void
544 mtd_reset(struct mtd_softc *sc)
545 {
546 	int i;
547 
548 	/* Set software reset bit */
549 	CSR_WRITE_4(MTD_BCR, BCR_SWR);
550 
551 	/*
552 	 * Wait until software reset completed.
553 	 */
554 	for (i = 0; i < MTD_TIMEOUT; ++i) {
555 		DELAY(10);
556 		if (!(CSR_READ_4(MTD_BCR) & BCR_SWR)) {
557 			/*
558 			 * Wait a little while for the chip to get
559 			 * its brains in order.
560 			 */
561 			DELAY(1000);
562 			return;
563 		}
564 	}
565 
566 	/* Reset timed out. */
567 	printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
568 }
569 
570 
571 static int
572 mtd_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
573 {
574 	struct mtd_softc *sc = ifp->if_softc;
575 	struct ifaddr *ifa = (struct ifaddr *)data;
576 	struct ifreq *ifr = (struct ifreq *)data;
577 	int s, error = 0;
578 
579 	s = splnet();
580 
581 	switch (command) {
582 	case SIOCSIFADDR:
583 		ifp->if_flags |= IFF_UP;
584 		mtd_init(ifp);
585 		switch (ifa->ifa_addr->sa_family) {
586 		case AF_INET:
587 			arp_ifinit(&sc->sc_arpcom, ifa);
588 			break;
589 		}
590 		break;
591 
592 	case SIOCSIFFLAGS:
593 		if (ifp->if_flags & IFF_UP)
594 			mtd_init(ifp);
595 		else {
596 			if (ifp->if_flags & IFF_RUNNING)
597 				mtd_stop(ifp);
598 		}
599 		error = 0;
600 		break;
601 
602 	case SIOCGIFMEDIA:
603 	case SIOCSIFMEDIA:
604 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
605 		break;
606 	default:
607 		error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
608 	}
609 
610 	if (error == ENETRESET) {
611 		if (ifp->if_flags & IFF_RUNNING)
612 			mtd_setmulti(sc);
613 		error = 0;
614 	}
615 
616 	splx(s);
617 	return (error);
618 }
619 
620 
621 static void
622 mtd_init(struct ifnet *ifp)
623 {
624 	struct mtd_softc *sc = ifp->if_softc;
625 	int s;
626 
627 	s = splnet();
628 
629 	/*
630 	 * Cancel pending I/O and free all RX/TX buffers.
631 	 */
632 	mtd_stop(ifp);
633 
634 	/*
635 	 * Reset the chip to a known state.
636 	 */
637 	mtd_reset(sc);
638 
639 	/*
640 	 * Set cache alignment and burst length.
641 	 */
642 	CSR_WRITE_4(MTD_BCR, BCR_PBL8);
643 	CSR_WRITE_4(MTD_TCRRCR, TCR_TFTSF | RCR_RBLEN | RCR_RPBL512);
644 	if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD891) {
645 		CSR_SETBIT(MTD_BCR, BCR_PROG);
646 		CSR_SETBIT(MTD_TCRRCR, TCR_ENHANCED);
647 	}
648 
649 	if (ifp->if_flags & IFF_PROMISC)
650 		CSR_SETBIT(MTD_TCRRCR, RCR_PROM);
651 	else
652 		CSR_CLRBIT(MTD_TCRRCR, RCR_PROM);
653 
654 	if (ifp->if_flags & IFF_BROADCAST)
655 		CSR_SETBIT(MTD_TCRRCR, RCR_AB);
656 	else
657 		CSR_CLRBIT(MTD_TCRRCR, RCR_AB);
658 
659 	mtd_setmulti(sc);
660 
661 	if (mtd_list_rx_init(sc)) {
662 		printf("%s: can't allocate memeory for rx buffers\n",
663 		    sc->sc_dev.dv_xname);
664 		splx(s);
665 		return;
666 	}
667 	mtd_list_tx_init(sc);
668 
669 	CSR_WRITE_4(MTD_RXLBA, sc->sc_listmap->dm_segs[0].ds_addr +
670 	    offsetof(struct mtd_list_data, mtd_rx_list[0]));
671 	CSR_WRITE_4(MTD_TXLBA, sc->sc_listmap->dm_segs[0].ds_addr +
672 	    offsetof(struct mtd_list_data, mtd_tx_list[0]));
673 
674 	/*
675 	 * Enable interrupts.
676 	 */
677 	CSR_WRITE_4(MTD_IMR, IMR_INTRS);
678 	CSR_WRITE_4(MTD_ISR, 0xffffffff);
679 
680 	/* Enable receiver and transmitter */
681 	CSR_SETBIT(MTD_TCRRCR, TCR_TE | RCR_RE);
682 	CSR_WRITE_4(MTD_RXPDR, 0xffffffff);
683 
684 	ifp->if_flags |= IFF_RUNNING;
685 	ifp->if_flags &= ~IFF_OACTIVE;
686 	splx(s);
687 }
688 
689 
690 /*
691  * Main transmit routine. To avoid having to do mbuf copies, we put pointers
692  * to the mbuf data regions directly in the transmit lists. We also save a
693  * copy of the pointers since the transmit list fragment pointers are
694  * physical addresses.
695  */
696 static void
697 mtd_start(struct ifnet *ifp)
698 {
699 	struct mtd_softc *sc = ifp->if_softc;
700 	struct mbuf *m_head = NULL;
701 	int idx;
702 
703 	if (sc->mtd_cdata.mtd_tx_cnt) {
704 		ifp->if_flags |= IFF_OACTIVE;
705 		return;
706 	}
707 
708 	idx = sc->mtd_cdata.mtd_tx_prod;
709 	while (sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf == NULL) {
710 		IFQ_DEQUEUE(&ifp->if_snd, m_head);
711 		if (m_head == NULL)
712 			break;
713 
714 		if (mtd_encap(sc, m_head, &idx)) {
715 			ifp->if_flags |= IFF_OACTIVE;
716 			break;
717 		}
718 
719 		/*
720 		 * If there's a BPF listener, bounce a copy of this frame
721 		 * to him.
722 		 */
723 #if NBPFILTER > 0
724 		if (ifp->if_bpf != NULL)
725 			bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
726 #endif
727 	}
728 
729 	if (idx == sc->mtd_cdata.mtd_tx_prod)
730 		return;
731 
732 	/* Transmit */
733 	sc->mtd_cdata.mtd_tx_prod = idx;
734 	CSR_WRITE_4(MTD_TXPDR, 0xffffffff);
735 
736 	/*
737 	 * Set a timeout in case the chip goes out to lunch.
738 	 */
739 	ifp->if_timer = 5;
740 }
741 
742 
743 static void
744 mtd_stop(struct ifnet *ifp)
745 {
746 	struct mtd_softc *sc = ifp->if_softc;
747 	int i;
748 
749 	ifp->if_timer = 0;
750 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
751 
752 	CSR_CLRBIT(MTD_TCRRCR, (RCR_RE | TCR_TE));
753 	CSR_WRITE_4(MTD_IMR, 0);
754 	CSR_WRITE_4(MTD_TXLBA, 0);
755 	CSR_WRITE_4(MTD_RXLBA, 0);
756 
757 	/*
758 	 * Free data in the RX lists.
759 	 */
760 	for (i = 0; i < MTD_RX_LIST_CNT; i++) {
761 		if (sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_nsegs != 0) {
762 			bus_dmamap_t map = sc->mtd_cdata.mtd_rx_chain[i].sd_map;
763 
764 			bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
765 			    BUS_DMASYNC_POSTREAD);
766 			bus_dmamap_unload(sc->sc_dmat, map);
767 		}
768 		if (sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf != NULL) {
769 			m_freem(sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf);
770 			sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = NULL;
771 		}
772 	}
773 	bzero(&sc->mtd_ldata->mtd_rx_list, sizeof(sc->mtd_ldata->mtd_rx_list));
774 
775 	/*
776 	 * Free the TX list buffers.
777 	 */
778 	for (i = 0; i < MTD_TX_LIST_CNT; i++) {
779 		if (sc->mtd_cdata.mtd_tx_chain[i].sd_map->dm_nsegs != 0) {
780 			bus_dmamap_t map = sc->mtd_cdata.mtd_tx_chain[i].sd_map;
781 
782 			bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
783 			    BUS_DMASYNC_POSTWRITE);
784 			bus_dmamap_unload(sc->sc_dmat, map);
785 		}
786 		if (sc->mtd_cdata.mtd_tx_chain[i].sd_mbuf != NULL) {
787 			m_freem(sc->mtd_cdata.mtd_tx_chain[i].sd_mbuf);
788 			sc->mtd_cdata.mtd_tx_chain[i].sd_mbuf = NULL;
789 		}
790 	}
791 
792 	bzero(&sc->mtd_ldata->mtd_tx_list, sizeof(sc->mtd_ldata->mtd_tx_list));
793 
794 }
795 
796 
797 static void
798 mtd_watchdog(struct ifnet *ifp)
799 {
800 	struct mtd_softc *sc = ifp->if_softc;
801 
802 	ifp->if_oerrors++;
803 	printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
804 
805 	mtd_init(ifp);
806 
807 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
808 		mtd_start(ifp);
809 }
810 
811 
812 int
813 mtd_intr(void *xsc)
814 {
815 	struct mtd_softc *sc = xsc;
816 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
817 	u_int32_t status;
818 	int claimed = 0;
819 
820 	/* Suppress unwanted interrupts */
821 	if (!(ifp->if_flags & IFF_RUNNING)) {
822 		if (CSR_READ_4(MTD_ISR) & ISR_INTRS)
823 			mtd_stop(ifp);
824 		return (claimed);
825 	}
826 
827 	/* Disable interrupts. */
828 	CSR_WRITE_4(MTD_IMR, 0);
829 
830 	while((status = CSR_READ_4(MTD_ISR)) & ISR_INTRS) {
831 		claimed = 1;
832 
833 		CSR_WRITE_4(MTD_ISR, status);
834 
835 		/* RX interrupt. */
836 		if (status & ISR_RI) {
837 			int curpkts = ifp->if_ipackets;
838 
839 			mtd_rxeof(sc);
840 			if (curpkts == ifp->if_ipackets)
841 				while(mtd_rx_resync(sc))
842 					mtd_rxeof(sc);
843 		}
844 
845 		/* RX error interrupt. */
846 		if (status & (ISR_RXERI | ISR_RBU))
847 			ifp->if_ierrors++;
848 
849 		/* TX interrupt. */
850 		if (status & (ISR_TI | ISR_ETI | ISR_TBU))
851 			mtd_txeof(sc);
852 
853 		/* Fatal bus error interrupt. */
854 		if (status & ISR_FBE) {
855 			mtd_reset(sc);
856 			mtd_start(ifp);
857 		}
858 	}
859 
860 	/* Re-enable interrupts. */
861 	CSR_WRITE_4(MTD_IMR, IMR_INTRS);
862 
863 	if (!IFQ_IS_EMPTY(&ifp->if_snd))
864 		mtd_start(ifp);
865 
866 	return (claimed);
867 }
868 
869 
870 /*
871  * A frame has been uploaded: pass the resulting mbuf chain up to
872  * the higher level protocols.
873  */
874 static void
875 mtd_rxeof(struct mtd_softc *sc)
876 {
877 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
878 	struct mbuf *m;
879 	struct ifnet *ifp;
880 	struct mtd_rx_desc *cur_rx;
881 	int i, total_len = 0;
882 	u_int32_t rxstat;
883 
884 	ifp = &sc->sc_arpcom.ac_if;
885 	i = sc->mtd_cdata.mtd_rx_prod;
886 
887 	while(!(sc->mtd_ldata->mtd_rx_list[i].rd_rsr & htole32(RSR_OWN))) {
888 		struct mbuf *m0 = NULL;
889 
890 		bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
891 		    offsetof(struct mtd_list_data, mtd_rx_list[i]),
892 		    sizeof(struct mtd_rx_desc),
893 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
894 
895 		cur_rx = &sc->mtd_ldata->mtd_rx_list[i];
896 		rxstat = letoh32(cur_rx->rd_rsr);
897 		m = sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf;
898 		total_len = RSR_FLNG_GET(rxstat);
899 
900 		sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = NULL;
901 
902 		/*
903 		 * If an error occurs, update stats, clear the
904 		 * status word and leave the mbuf cluster in place:
905 		 * it should simply get re-used next time this descriptor
906 	 	 * comes up in the ring.
907 		 */
908 		if (rxstat & RSR_RXER) {
909 			ifp->if_ierrors++;
910 			mtd_newbuf(sc, i, m);
911 			if (rxstat & RSR_CRC) {
912 				i = (i + 1) % MTD_RX_LIST_CNT;
913 				continue;
914 			} else {
915 				mtd_init(ifp);
916 				break;
917 			}
918 		}
919 
920 		/* No errors; receive the packet. */
921 		total_len -= ETHER_CRC_LEN;
922 
923 		bus_dmamap_sync(sc->sc_dmat, sc->mtd_cdata.mtd_rx_chain[i].sd_map,
924 		    0, sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_mapsize,
925 		    BUS_DMASYNC_POSTREAD);
926 
927 		m0 = m_devget(mtod(m, char *), total_len,  ETHER_ALIGN);
928 		mtd_newbuf(sc, i, m);
929 		i = (i + 1) % MTD_RX_LIST_CNT;
930 		if (m0 == NULL) {
931 			ifp->if_ierrors++;
932 			continue;
933 		}
934 		m = m0;
935 
936 		ifp->if_ipackets++;
937 
938 		ml_enqueue(&ml, m);
939 	}
940 
941 	if_input(ifp, &ml);
942 
943 	sc->mtd_cdata.mtd_rx_prod = i;
944 }
945 
946 
947 /*
948  * This routine searches the RX ring for dirty descriptors in the
949  * event that the rxeof routine falls out of sync with the chip's
950  * current descriptor pointer. This may happen sometimes as a result
951  * of a "no RX buffer available" condition that happens when the chip
952  * consumes all of the RX buffers before the driver has a chance to
953  * process the RX ring. This routine may need to be called more than
954  * once to bring the driver back in sync with the chip, however we
955  * should still be getting RX DONE interrupts to drive the search
956  * for new packets in the RX ring, so we should catch up eventually.
957  */
958 static int
959 mtd_rx_resync(sc)
960 	struct mtd_softc *sc;
961 {
962 	int i, pos;
963 	struct mtd_rx_desc *cur_rx;
964 
965 	pos = sc->mtd_cdata.mtd_rx_prod;
966 
967 	for (i = 0; i < MTD_RX_LIST_CNT; i++) {
968 		bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
969 		    offsetof(struct mtd_list_data, mtd_rx_list[pos]),
970 		    sizeof(struct mtd_rx_desc),
971 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
972 
973 		cur_rx = &sc->mtd_ldata->mtd_rx_list[pos];
974 		if (!(cur_rx->rd_rsr & htole32(RSR_OWN)))
975 			break;
976 		pos = (pos + 1) % MTD_RX_LIST_CNT;
977 	}
978 
979 	/* If the ring really is empty, then just return. */
980 	if (i == MTD_RX_LIST_CNT)
981 		return (0);
982 
983 	/* We've fallen behind the chip: catch it. */
984 	sc->mtd_cdata.mtd_rx_prod = pos;
985 
986 	return (EAGAIN);
987 }
988 
989 
990 /*
991  * A frame was downloaded to the chip. It's safe for us to clean up
992  * the list buffers.
993  */
994 static void
995 mtd_txeof(struct mtd_softc *sc)
996 {
997 	struct mtd_tx_desc *cur_tx = NULL;
998 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
999 	int idx;
1000 
1001 	/* Clear the timeout timer. */
1002 	ifp->if_timer = 0;
1003 
1004 	/*
1005 	 * Go through our tx list and free mbufs for those
1006 	 * frames that have been transmitted.
1007 	 */
1008 	idx = sc->mtd_cdata.mtd_tx_cons;
1009 	while(idx != sc->mtd_cdata.mtd_tx_prod) {
1010 		u_int32_t txstat;
1011 
1012 		bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
1013 		    offsetof(struct mtd_list_data, mtd_tx_list[idx]),
1014 		    sizeof(struct mtd_tx_desc),
1015 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1016 
1017 		cur_tx = &sc->mtd_ldata->mtd_tx_list[idx];
1018 		txstat = letoh32(cur_tx->td_tsw);
1019 
1020 		if (txstat & TSW_OWN || txstat == TSW_UNSENT)
1021 			break;
1022 
1023 		if (!(cur_tx->td_tcw & htole32(TCW_LD))) {
1024 			sc->mtd_cdata.mtd_tx_cnt--;
1025 			idx = (idx + 1) % MTD_TX_LIST_CNT;
1026 			continue;
1027 		}
1028 
1029 		if (CSR_READ_4(MTD_TCRRCR) & TCR_ENHANCED)
1030 			ifp->if_collisions += TSR_NCR_GET(CSR_READ_4(MTD_TSR));
1031 		else {
1032 			if (txstat & TSW_TXERR) {
1033 				ifp->if_oerrors++;
1034 				if (txstat & TSW_EC)
1035 					ifp->if_collisions++;
1036 				if (txstat & TSW_LC)
1037 					ifp->if_collisions++;
1038 			}
1039 			ifp->if_collisions += TSW_NCR_GET(txstat);
1040 		}
1041 
1042 		ifp->if_opackets++;
1043 		if (sc->mtd_cdata.mtd_tx_chain[idx].sd_map->dm_nsegs != 0) {
1044 			bus_dmamap_t map =
1045 			    sc->mtd_cdata.mtd_tx_chain[idx].sd_map;
1046 			bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
1047 			    BUS_DMASYNC_POSTWRITE);
1048 			bus_dmamap_unload(sc->sc_dmat, map);
1049 		}
1050 		if (sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf != NULL) {
1051 			m_freem(sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf);
1052 			sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf = NULL;
1053 		}
1054 		sc->mtd_cdata.mtd_tx_cnt--;
1055 		idx = (idx + 1) % MTD_TX_LIST_CNT;
1056 	}
1057 
1058 	if (cur_tx != NULL) {
1059 		ifp->if_flags &= ~IFF_OACTIVE;
1060 		sc->mtd_cdata.mtd_tx_cons = idx;
1061 	} else
1062 		if (sc->mtd_ldata->mtd_tx_list[idx].td_tsw ==
1063 		    htole32(TSW_UNSENT)) {
1064 			sc->mtd_ldata->mtd_tx_list[idx].td_tsw =
1065 			    htole32(TSW_OWN);
1066 			ifp->if_timer = 5;
1067 			CSR_WRITE_4(MTD_TXPDR, 0xffffffff);
1068 		}
1069 }
1070 
1071 struct cfdriver mtd_cd = {
1072 	0, "mtd", DV_IFNET
1073 };
1074