[BACK]Return to mtd8xx.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/mtd8xx.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mtd8xx.c,v 1.12 2006/03/25 22:41:43 djm 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
                     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_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    164:        ifp->if_ioctl = mtd_ioctl;
                    165:        ifp->if_start = mtd_start;
                    166:        ifp->if_watchdog = mtd_watchdog;
                    167:        ifp->if_baudrate = 10000000;
                    168:        IFQ_SET_READY(&ifp->if_snd);
                    169:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    170:
                    171:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    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
                    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
                    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
                    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
                    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
                    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
                    311: mtd_miibus_statchg(struct device *self)
                    312: {
                    313:        /* NOTHING */
                    314: }
                    315:
                    316:
                    317: void
                    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: allmulti:
                    327:        rxfilt = CSR_READ_4(MTD_TCRRCR) & ~RCR_AM;
                    328:        if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
                    329:                rxfilt |= RCR_AM;
                    330:                CSR_WRITE_4(MTD_TCRRCR, rxfilt);
                    331:                CSR_WRITE_4(MTD_MAR0, 0xffffffff);
                    332:                CSR_WRITE_4(MTD_MAR4, 0xffffffff);
                    333:                return;
                    334:        }
                    335:
                    336:        /* First, zot all the existing hash bits. */
                    337:        CSR_WRITE_4(MTD_MAR0, 0);
                    338:        CSR_WRITE_4(MTD_MAR4, 0);
                    339:
                    340:        /* Now program new ones. */
                    341:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
                    342:        while (enm != NULL) {
                    343:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
                    344:                        ifp->if_flags |= IFF_ALLMULTI;
                    345:                        goto allmulti;
                    346:                }
                    347:                crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
                    348:                hash[crc >> 5] |= 1 << (crc & 0xf);
                    349:                ++mcnt;
                    350:                ETHER_NEXT_MULTI(step, enm);
                    351:        }
                    352:
                    353:        if (mcnt)
                    354:                rxfilt |= RCR_AM;
                    355:        CSR_WRITE_4(MTD_MAR0, hash[0]);
                    356:        CSR_WRITE_4(MTD_MAR4, hash[1]);
                    357:        CSR_WRITE_4(MTD_TCRRCR, rxfilt);
                    358: }
                    359:
                    360:
                    361: /*
                    362:  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
                    363:  * pointers to the fragment pointers.
                    364:  */
                    365: int
                    366: mtd_encap(struct mtd_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
                    367: {
                    368:        struct mtd_tx_desc *f = NULL;
                    369:        int frag, cur, cnt = 0, i, total_len = 0;
                    370:        bus_dmamap_t map;
                    371:
                    372:        /*
                    373:         * Start packing the mbufs in this chain into
                    374:         * the fragment pointers. Stop when we run out
                    375:         * of fragments or hit the end of the mbuf chain.
                    376:         */
                    377:        map = sc->sc_tx_sparemap;
                    378:
                    379:        if (bus_dmamap_load_mbuf(sc->sc_dmat, map,
                    380:            m_head, BUS_DMA_NOWAIT) != 0)
                    381:                return (1);
                    382:
                    383:        cur = frag = *txidx;
                    384:
                    385:        for (i = 0; i < map->dm_nsegs; i++) {
                    386:                if ((MTD_TX_LIST_CNT -
                    387:                    (sc->mtd_cdata.mtd_tx_cnt + cnt)) < 5) {
                    388:                        bus_dmamap_unload(sc->sc_dmat, map);
                    389:                        return (1);
                    390:                }
                    391:
                    392:                f = &sc->mtd_ldata->mtd_tx_list[frag];
                    393:                f->td_tcw = htole32(map->dm_segs[i].ds_len);
                    394:                total_len += map->dm_segs[i].ds_len;
                    395:                if (cnt == 0) {
                    396:                        f->td_tsw = 0;
                    397:                        f->td_tcw |= htole32(TCW_FD | TCW_CRC | TCW_PAD);
                    398:                } else
                    399:                        f->td_tsw = htole32(TSW_OWN);
                    400:                f->td_buf = htole32(map->dm_segs[i].ds_addr);
                    401:                cur = frag;
                    402:                frag = (frag + 1) % MTD_TX_LIST_CNT;
                    403:                cnt++;
                    404:        }
                    405:
                    406:        sc->mtd_cdata.mtd_tx_cnt += cnt;
                    407:        sc->mtd_cdata.mtd_tx_chain[cur].sd_mbuf = m_head;
                    408:        sc->sc_tx_sparemap = sc->mtd_cdata.mtd_tx_chain[cur].sd_map;
                    409:        sc->mtd_cdata.mtd_tx_chain[cur].sd_map = map;
                    410:        sc->mtd_ldata->mtd_tx_list[cur].td_tcw |= htole32(TCW_LD | TCW_IC);
                    411:        if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD891)
                    412:                sc->mtd_ldata->mtd_tx_list[cur].td_tcw |=
                    413:                    htole32(TCW_EIC | TCW_RTLC);
                    414:
                    415:        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
                    416:            BUS_DMASYNC_PREWRITE);
                    417:
                    418:        sc->mtd_ldata->mtd_tx_list[*txidx].td_tsw = htole32(TSW_OWN);
                    419:        sc->mtd_ldata->mtd_tx_list[*txidx].td_tcw |=
                    420:            htole32(total_len << TCW_PKTS_SHIFT);
                    421:
                    422:        bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
                    423:            offsetof(struct mtd_list_data, mtd_tx_list[0]),
                    424:            sizeof(struct mtd_tx_desc) * MTD_TX_LIST_CNT,
                    425:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    426:
                    427:        *txidx = frag;
                    428:
                    429:        return (0);
                    430: }
                    431:
                    432:
                    433: /*
                    434:  * Initialize the transmit descriptors.
                    435:  */
                    436: static void
                    437: mtd_list_tx_init(struct mtd_softc *sc)
                    438: {
                    439:        struct mtd_chain_data *cd;
                    440:        struct mtd_list_data *ld;
                    441:        int i;
                    442:
                    443:        cd = &sc->mtd_cdata;
                    444:        ld = sc->mtd_ldata;
                    445:        for (i = 0; i < MTD_TX_LIST_CNT; i++) {
                    446:                cd->mtd_tx_chain[i].sd_mbuf = NULL;
                    447:                ld->mtd_tx_list[i].td_tsw = 0;
                    448:                ld->mtd_tx_list[i].td_tcw = 0;
                    449:                ld->mtd_tx_list[i].td_buf = 0;
                    450:                ld->mtd_tx_list[i].td_next = htole32(
                    451:                    sc->sc_listmap->dm_segs[0].ds_addr +
                    452:                    offsetof(struct mtd_list_data,
                    453:                    mtd_tx_list[(i + 1) % MTD_TX_LIST_CNT]));
                    454:        }
                    455:
                    456:        cd->mtd_tx_prod = cd->mtd_tx_cons = cd->mtd_tx_cnt = 0;
                    457: }
                    458:
                    459:
                    460: /*
                    461:  * Initialize the RX descriptors and allocate mbufs for them. Note that
                    462:  * we arrange the descriptors in a closed ring, so that the last descriptor
                    463:  * points back to the first.
                    464:  */
                    465: static int
                    466: mtd_list_rx_init(struct mtd_softc *sc)
                    467: {
                    468:        struct mtd_list_data *ld;
                    469:        int i;
                    470:
                    471:        ld = sc->mtd_ldata;
                    472:
                    473:        for (i = 0; i < MTD_RX_LIST_CNT; i++) {
                    474:                if (mtd_newbuf(sc, i, NULL))
                    475:                        return (1);
                    476:                ld->mtd_rx_list[i].rd_next = htole32(
                    477:                    sc->sc_listmap->dm_segs[0].ds_addr +
                    478:                    offsetof(struct mtd_list_data,
                    479:                    mtd_rx_list[(i + 1) % MTD_RX_LIST_CNT])
                    480:                );
                    481:        }
                    482:
                    483:        sc->mtd_cdata.mtd_rx_prod = 0;
                    484:
                    485:        return (0);
                    486: }
                    487:
                    488:
                    489: /*
                    490:  * Initialize an RX descriptor and attach an MBUF cluster.
                    491:  */
                    492: static int
                    493: mtd_newbuf(struct mtd_softc *sc, int i, struct mbuf *m)
                    494: {
                    495:        struct mbuf *m_new = NULL;
                    496:        struct mtd_rx_desc *c;
                    497:        bus_dmamap_t map;
                    498:
                    499:        c = &sc->mtd_ldata->mtd_rx_list[i];
                    500:
                    501:        if (m == NULL) {
                    502:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
                    503:                if (m_new == NULL)
                    504:                        return (1);
                    505:
                    506:                MCLGET(m_new, M_DONTWAIT);
                    507:                if (!(m_new->m_flags & M_EXT)) {
                    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:                        m_freem(m_new);
                    516:                        return (1);
                    517:                }
                    518:                map = sc->mtd_cdata.mtd_rx_chain[i].sd_map;
                    519:                sc->mtd_cdata.mtd_rx_chain[i].sd_map = sc->sc_rx_sparemap;
                    520:                sc->sc_rx_sparemap = map;
                    521:        } else {
                    522:                m_new = m;
                    523:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
                    524:                m_new->m_data = m_new->m_ext.ext_buf;
                    525:        }
                    526:
                    527:        m_adj(m_new, sizeof(u_int64_t));
                    528:
                    529:        bus_dmamap_sync(sc->sc_dmat, sc->mtd_cdata.mtd_rx_chain[i].sd_map, 0,
                    530:            sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_mapsize,
                    531:            BUS_DMASYNC_PREREAD);
                    532:
                    533:        sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = m_new;
                    534:        c->rd_buf = htole32(
                    535:            sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_segs[0].ds_addr +
                    536:            sizeof(u_int64_t));
                    537:        c->rd_rcw = htole32(ETHER_MAX_DIX_LEN);
                    538:        c->rd_rsr = htole32(RSR_OWN);
                    539:
                    540:        bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
                    541:            offsetof(struct mtd_list_data, mtd_rx_list[i]),
                    542:            sizeof(struct mtd_rx_desc),
                    543:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    544:
                    545:        return (0);
                    546: }
                    547:
                    548:
                    549: static void
                    550: mtd_reset(struct mtd_softc *sc)
                    551: {
                    552:        int i;
                    553:
                    554:        /* Set software reset bit */
                    555:        CSR_WRITE_4(MTD_BCR, BCR_SWR);
                    556:
                    557:        /*
                    558:         * Wait until software reset completed.
                    559:         */
                    560:        for (i = 0; i < MTD_TIMEOUT; ++i) {
                    561:                DELAY(10);
                    562:                if (!(CSR_READ_4(MTD_BCR) & BCR_SWR)) {
                    563:                        /*
                    564:                         * Wait a little while for the chip to get
                    565:                         * its brains in order.
                    566:                         */
                    567:                        DELAY(1000);
                    568:                        return;
                    569:                }
                    570:        }
                    571:
                    572:        /* Reset timed out. */
                    573:        printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
                    574: }
                    575:
                    576:
                    577: static int
                    578: mtd_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
                    579: {
                    580:        struct mtd_softc *sc = ifp->if_softc;
                    581:        struct ifreq *ifr = (struct ifreq *)data;
                    582:        struct ifaddr *ifa = (struct ifaddr *)data;
                    583:        int s, error;
                    584:
                    585:        s = splnet();
                    586:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
                    587:                splx(s);
                    588:                return (error);
                    589:        }
                    590:
                    591:        switch (command) {
                    592:        case SIOCSIFADDR:
                    593:                ifp->if_flags |= IFF_UP;
                    594:                mtd_init(ifp);
                    595:                switch (ifa->ifa_addr->sa_family) {
                    596: #ifdef INET
                    597:                case AF_INET:
                    598:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    599:                        break;
                    600: #endif /* INET */
                    601:                }
                    602:                break;
                    603:        case SIOCSIFMTU:
                    604:                if (ifr->ifr_mtu >= ETHERMIN && ifr->ifr_mtu <= ETHERMTU)
                    605:                        ifp->if_mtu = ifr->ifr_mtu;
                    606:                else
                    607:                        error = EINVAL;
                    608:                break;
                    609:
                    610:        case SIOCSIFFLAGS:
                    611:                if (ifp->if_flags & IFF_UP)
                    612:                        mtd_init(ifp);
                    613:                else {
                    614:                        if (ifp->if_flags & IFF_RUNNING)
                    615:                                mtd_stop(ifp);
                    616:                }
                    617:                error = 0;
                    618:                break;
                    619:        case SIOCADDMULTI:
                    620:        case SIOCDELMULTI:
                    621:                error = (command == SIOCADDMULTI) ?
                    622:                    ether_addmulti(ifr, &sc->sc_arpcom) :
                    623:                    ether_delmulti(ifr, &sc->sc_arpcom);
                    624:
                    625:                if (error == ENETRESET) {
                    626:                        /*
                    627:                         * Multicast list has changed; set the hardware
                    628:                         * filter accordingly.
                    629:                         */
                    630:                        if (ifp->if_flags & IFF_RUNNING)
                    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
                    650: mtd_init(struct ifnet *ifp)
                    651: {
                    652:        struct mtd_softc *sc = ifp->if_softc;
                    653:        int s;
                    654:
                    655:        s = splnet();
                    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
                    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, BPF_DIRECTION_OUT);
                    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
                    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
                    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
                    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
                    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 *) - ETHER_ALIGN, total_len + ETHER_ALIGN,
                    954:                    0, ifp, 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, ETHER_ALIGN);
                    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, BPF_DIRECTION_IN);
                    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
                    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
                   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: };

CVSweb