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