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

Annotation of sys/dev/pci/if_txp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_txp.c,v 1.84 2007/04/11 14:41:15 claudio Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2001
        !             5:  *     Jason L. Wright <jason@thought.net>, Theo de Raadt, and
        !             6:  *     Aaron Campbell <aaron@monkey.org>.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following 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 AUTHORS ``AS IS'' AND ANY EXPRESS OR
        !            18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            19:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR THE VOICES IN THEIR HEADS
        !            21:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            22:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            23:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            24:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            25:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            26:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            27:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * Driver for 3c990 (Typhoon) Ethernet ASIC
        !            32:  */
        !            33:
        !            34: #include "bpfilter.h"
        !            35: #include "vlan.h"
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/sockio.h>
        !            40: #include <sys/mbuf.h>
        !            41: #include <sys/malloc.h>
        !            42: #include <sys/kernel.h>
        !            43: #include <sys/socket.h>
        !            44: #include <sys/device.h>
        !            45: #include <sys/timeout.h>
        !            46:
        !            47: #include <net/if.h>
        !            48: #include <net/if_dl.h>
        !            49: #include <net/if_types.h>
        !            50:
        !            51: #ifdef INET
        !            52: #include <netinet/in.h>
        !            53: #include <netinet/in_systm.h>
        !            54: #include <netinet/in_var.h>
        !            55: #include <netinet/ip.h>
        !            56: #include <netinet/if_ether.h>
        !            57: #endif
        !            58:
        !            59: #include <net/if_media.h>
        !            60:
        !            61: #if NBPFILTER > 0
        !            62: #include <net/bpf.h>
        !            63: #endif
        !            64:
        !            65: #if NVLAN > 0
        !            66: #include <net/if_types.h>
        !            67: #include <net/if_vlan_var.h>
        !            68: #endif
        !            69:
        !            70: #include <machine/bus.h>
        !            71:
        !            72: #include <dev/mii/mii.h>
        !            73: #include <dev/mii/miivar.h>
        !            74: #include <dev/pci/pcireg.h>
        !            75: #include <dev/pci/pcivar.h>
        !            76: #include <dev/pci/pcidevs.h>
        !            77:
        !            78: #include <dev/pci/if_txpreg.h>
        !            79:
        !            80: /*
        !            81:  * These currently break the 3c990 firmware, hopefully will be resolved
        !            82:  * at some point.
        !            83:  */
        !            84: #undef TRY_TX_UDP_CSUM
        !            85: #undef TRY_TX_TCP_CSUM
        !            86:
        !            87: int txp_probe(struct device *, void *, void *);
        !            88: void txp_attach(struct device *, struct device *, void *);
        !            89: void txp_attachhook(void *vsc);
        !            90: int txp_intr(void *);
        !            91: void txp_tick(void *);
        !            92: void txp_shutdown(void *);
        !            93: int txp_ioctl(struct ifnet *, u_long, caddr_t);
        !            94: void txp_start(struct ifnet *);
        !            95: void txp_stop(struct txp_softc *);
        !            96: void txp_init(struct txp_softc *);
        !            97: void txp_watchdog(struct ifnet *);
        !            98:
        !            99: int txp_chip_init(struct txp_softc *);
        !           100: int txp_reset_adapter(struct txp_softc *);
        !           101: int txp_download_fw(struct txp_softc *);
        !           102: int txp_download_fw_wait(struct txp_softc *);
        !           103: int txp_download_fw_section(struct txp_softc *,
        !           104:     struct txp_fw_section_header *, int, u_char *, size_t);
        !           105: int txp_alloc_rings(struct txp_softc *);
        !           106: void txp_dma_free(struct txp_softc *, struct txp_dma_alloc *);
        !           107: int txp_dma_malloc(struct txp_softc *, bus_size_t, struct txp_dma_alloc *, int);
        !           108: void txp_set_filter(struct txp_softc *);
        !           109:
        !           110: int txp_cmd_desc_numfree(struct txp_softc *);
        !           111: int txp_command(struct txp_softc *, u_int16_t, u_int16_t, u_int32_t,
        !           112:     u_int32_t, u_int16_t *, u_int32_t *, u_int32_t *, int);
        !           113: int txp_command2(struct txp_softc *, u_int16_t, u_int16_t,
        !           114:     u_int32_t, u_int32_t, struct txp_ext_desc *, u_int8_t,
        !           115:     struct txp_rsp_desc **, int);
        !           116: int txp_response(struct txp_softc *, u_int32_t, u_int16_t, u_int16_t,
        !           117:     struct txp_rsp_desc **);
        !           118: void txp_rsp_fixup(struct txp_softc *, struct txp_rsp_desc *,
        !           119:     struct txp_rsp_desc *);
        !           120: void txp_capabilities(struct txp_softc *);
        !           121:
        !           122: void txp_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !           123: int txp_ifmedia_upd(struct ifnet *);
        !           124: void txp_show_descriptor(void *);
        !           125: void txp_tx_reclaim(struct txp_softc *, struct txp_tx_ring *,
        !           126:     struct txp_dma_alloc *);
        !           127: void txp_rxbuf_reclaim(struct txp_softc *);
        !           128: void txp_rx_reclaim(struct txp_softc *, struct txp_rx_ring *,
        !           129:     struct txp_dma_alloc *);
        !           130:
        !           131: struct cfattach txp_ca = {
        !           132:        sizeof(struct txp_softc), txp_probe, txp_attach,
        !           133: };
        !           134:
        !           135: struct cfdriver txp_cd = {
        !           136:        0, "txp", DV_IFNET
        !           137: };
        !           138:
        !           139: const struct pci_matchid txp_devices[] = {
        !           140:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990 },
        !           141:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990TX },
        !           142:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990TX95 },
        !           143:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990TX97 },
        !           144:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990SVR95 },
        !           145:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990SVR97 },
        !           146:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C990BTXM },
        !           147:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C990BSVR },
        !           148:        { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CR990FX },
        !           149: };
        !           150:
        !           151: int
        !           152: txp_probe(parent, match, aux)
        !           153:        struct device *parent;
        !           154:        void *match, *aux;
        !           155: {
        !           156:        return (pci_matchbyid((struct pci_attach_args *)aux, txp_devices,
        !           157:            sizeof(txp_devices)/sizeof(txp_devices[0])));
        !           158: }
        !           159:
        !           160: void
        !           161: txp_attachhook(void *vsc)
        !           162: {
        !           163:        struct txp_softc *sc = vsc;
        !           164:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           165:        u_int16_t p1;
        !           166:        u_int32_t p2;
        !           167:        int s;
        !           168:
        !           169:        s = splnet();
        !           170:        printf("%s: ", sc->sc_dev.dv_xname);
        !           171:
        !           172:        if (txp_chip_init(sc)) {
        !           173:                printf("failed chip init\n");
        !           174:                splx(s);
        !           175:                return;
        !           176:        }
        !           177:
        !           178:        if (txp_download_fw(sc)) {
        !           179:                splx(s);
        !           180:                return;
        !           181:        }
        !           182:
        !           183:        if (txp_alloc_rings(sc)) {
        !           184:                splx(s);
        !           185:                return;
        !           186:        }
        !           187:
        !           188:        if (txp_command(sc, TXP_CMD_MAX_PKT_SIZE_WRITE, TXP_MAX_PKTLEN, 0, 0,
        !           189:            NULL, NULL, NULL, 1)) {
        !           190:                splx(s);
        !           191:                return;
        !           192:        }
        !           193:
        !           194:        if (txp_command(sc, TXP_CMD_STATION_ADDRESS_READ, 0, 0, 0,
        !           195:            &p1, &p2, NULL, 1)) {
        !           196:                splx(s);
        !           197:                return;
        !           198:        }
        !           199:
        !           200:        txp_set_filter(sc);
        !           201:
        !           202:        p1 = htole16(p1);
        !           203:        sc->sc_arpcom.ac_enaddr[0] = ((u_int8_t *)&p1)[1];
        !           204:        sc->sc_arpcom.ac_enaddr[1] = ((u_int8_t *)&p1)[0];
        !           205:        p2 = htole32(p2);
        !           206:        sc->sc_arpcom.ac_enaddr[2] = ((u_int8_t *)&p2)[3];
        !           207:        sc->sc_arpcom.ac_enaddr[3] = ((u_int8_t *)&p2)[2];
        !           208:        sc->sc_arpcom.ac_enaddr[4] = ((u_int8_t *)&p2)[1];
        !           209:        sc->sc_arpcom.ac_enaddr[5] = ((u_int8_t *)&p2)[0];
        !           210:
        !           211:        printf("address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           212:        sc->sc_cold = 0;
        !           213:
        !           214:        ifmedia_init(&sc->sc_ifmedia, 0, txp_ifmedia_upd, txp_ifmedia_sts);
        !           215:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
        !           216:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
        !           217:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
        !           218:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
        !           219:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL);
        !           220:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
        !           221:        ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
        !           222:
        !           223:        sc->sc_xcvr = TXP_XCVR_AUTO;
        !           224:        txp_command(sc, TXP_CMD_XCVR_SELECT, TXP_XCVR_AUTO, 0, 0,
        !           225:            NULL, NULL, NULL, 0);
        !           226:        ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO);
        !           227:
        !           228:        ifp->if_softc = sc;
        !           229:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           230:        ifp->if_ioctl = txp_ioctl;
        !           231:        ifp->if_start = txp_start;
        !           232:        ifp->if_watchdog = txp_watchdog;
        !           233:        ifp->if_baudrate = 10000000;
        !           234:        IFQ_SET_MAXLEN(&ifp->if_snd, TX_ENTRIES);
        !           235:        IFQ_SET_READY(&ifp->if_snd);
        !           236:        ifp->if_capabilities = 0;
        !           237:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           238:
        !           239:        txp_capabilities(sc);
        !           240:
        !           241:        timeout_set(&sc->sc_tick, txp_tick, sc);
        !           242:
        !           243:        /*
        !           244:         * Attach us everywhere
        !           245:         */
        !           246:        if_attach(ifp);
        !           247:        ether_ifattach(ifp);
        !           248:
        !           249:        shutdownhook_establish(txp_shutdown, sc);
        !           250:        splx(s);
        !           251: }
        !           252:
        !           253: void
        !           254: txp_attach(parent, self, aux)
        !           255:        struct device *parent, *self;
        !           256:        void *aux;
        !           257: {
        !           258:        struct txp_softc *sc = (struct txp_softc *)self;
        !           259:        struct pci_attach_args *pa = aux;
        !           260:        pci_chipset_tag_t pc = pa->pa_pc;
        !           261:        pci_intr_handle_t ih;
        !           262:        const char *intrstr = NULL;
        !           263:        bus_size_t iosize;
        !           264:
        !           265:        sc->sc_cold = 1;
        !           266:
        !           267:        if (pci_mapreg_map(pa, TXP_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
        !           268:            &sc->sc_bt, &sc->sc_bh, NULL, &iosize, 0)) {
        !           269:                printf(": can't map mem space %d\n", 0);
        !           270:                return;
        !           271:        }
        !           272:
        !           273:        sc->sc_dmat = pa->pa_dmat;
        !           274:
        !           275:        /*
        !           276:         * Allocate our interrupt.
        !           277:         */
        !           278:        if (pci_intr_map(pa, &ih)) {
        !           279:                printf(": couldn't map interrupt\n");
        !           280:                return;
        !           281:        }
        !           282:
        !           283:        intrstr = pci_intr_string(pc, ih);
        !           284:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, txp_intr, sc,
        !           285:            self->dv_xname);
        !           286:        if (sc->sc_ih == NULL) {
        !           287:                printf(": couldn't establish interrupt");
        !           288:                if (intrstr != NULL)
        !           289:                        printf(" at %s", intrstr);
        !           290:                printf("\n");
        !           291:                return;
        !           292:        }
        !           293:        printf(": %s\n", intrstr);
        !           294:
        !           295:        if (rootvp == NULL)
        !           296:                mountroothook_establish(txp_attachhook, sc);
        !           297:        else
        !           298:                txp_attachhook(sc);
        !           299:
        !           300: }
        !           301:
        !           302: int
        !           303: txp_chip_init(sc)
        !           304:        struct txp_softc *sc;
        !           305: {
        !           306:        /* disable interrupts */
        !           307:        WRITE_REG(sc, TXP_IER, 0);
        !           308:        WRITE_REG(sc, TXP_IMR,
        !           309:            TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
        !           310:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !           311:            TXP_INT_LATCH);
        !           312:
        !           313:        /* ack all interrupts */
        !           314:        WRITE_REG(sc, TXP_ISR, TXP_INT_RESERVED | TXP_INT_LATCH |
        !           315:            TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
        !           316:            TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
        !           317:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !           318:            TXP_INT_A2H_3 | TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0);
        !           319:
        !           320:        if (txp_reset_adapter(sc))
        !           321:                return (-1);
        !           322:
        !           323:        /* disable interrupts */
        !           324:        WRITE_REG(sc, TXP_IER, 0);
        !           325:        WRITE_REG(sc, TXP_IMR,
        !           326:            TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
        !           327:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !           328:            TXP_INT_LATCH);
        !           329:
        !           330:        /* ack all interrupts */
        !           331:        WRITE_REG(sc, TXP_ISR, TXP_INT_RESERVED | TXP_INT_LATCH |
        !           332:            TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
        !           333:            TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
        !           334:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !           335:            TXP_INT_A2H_3 | TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0);
        !           336:
        !           337:        return (0);
        !           338: }
        !           339:
        !           340: int
        !           341: txp_reset_adapter(sc)
        !           342:        struct txp_softc *sc;
        !           343: {
        !           344:        u_int32_t r;
        !           345:        int i;
        !           346:
        !           347:        WRITE_REG(sc, TXP_SRR, TXP_SRR_ALL);
        !           348:        DELAY(1000);
        !           349:        WRITE_REG(sc, TXP_SRR, 0);
        !           350:
        !           351:        /* Should wait max 6 seconds */
        !           352:        for (i = 0; i < 6000; i++) {
        !           353:                r = READ_REG(sc, TXP_A2H_0);
        !           354:                if (r == STAT_WAITING_FOR_HOST_REQUEST)
        !           355:                        break;
        !           356:                DELAY(1000);
        !           357:        }
        !           358:
        !           359:        if (r != STAT_WAITING_FOR_HOST_REQUEST) {
        !           360:                printf("%s: reset hung\n", TXP_DEVNAME(sc));
        !           361:                return (-1);
        !           362:        }
        !           363:
        !           364:        return (0);
        !           365: }
        !           366:
        !           367: int
        !           368: txp_download_fw(sc)
        !           369:        struct txp_softc *sc;
        !           370: {
        !           371:        struct txp_fw_file_header *fileheader;
        !           372:        struct txp_fw_section_header *secthead;
        !           373:        u_int32_t r, i, ier, imr;
        !           374:        size_t buflen;
        !           375:        int sect, err;
        !           376:        u_char *buf;
        !           377:
        !           378:        ier = READ_REG(sc, TXP_IER);
        !           379:        WRITE_REG(sc, TXP_IER, ier | TXP_INT_A2H_0);
        !           380:
        !           381:        imr = READ_REG(sc, TXP_IMR);
        !           382:        WRITE_REG(sc, TXP_IMR, imr | TXP_INT_A2H_0);
        !           383:
        !           384:        for (i = 0; i < 10000; i++) {
        !           385:                r = READ_REG(sc, TXP_A2H_0);
        !           386:                if (r == STAT_WAITING_FOR_HOST_REQUEST)
        !           387:                        break;
        !           388:                DELAY(50);
        !           389:        }
        !           390:        if (r != STAT_WAITING_FOR_HOST_REQUEST) {
        !           391:                printf("not waiting for host request\n");
        !           392:                return (-1);
        !           393:        }
        !           394:
        !           395:        /* Ack the status */
        !           396:        WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0);
        !           397:
        !           398:        err = loadfirmware("3c990", &buf, &buflen);
        !           399:        if (err) {
        !           400:                printf("failed loadfirmware of file 3c990: errno %d\n",
        !           401:                    err);
        !           402:                return (err);
        !           403:        }
        !           404:
        !           405:        fileheader = (struct txp_fw_file_header *)buf;
        !           406:        if (bcmp("TYPHOON", fileheader->magicid, sizeof(fileheader->magicid))) {
        !           407:                printf("firmware invalid magic\n");
        !           408:                goto fail;
        !           409:        }
        !           410:
        !           411:        /* Tell boot firmware to get ready for image */
        !           412:        WRITE_REG(sc, TXP_H2A_1, letoh32(fileheader->addr));
        !           413:        WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_RUNTIME_IMAGE);
        !           414:
        !           415:        if (txp_download_fw_wait(sc)) {
        !           416:                printf("fw wait failed, initial\n");
        !           417:                goto fail;
        !           418:        }
        !           419:
        !           420:        secthead = (struct txp_fw_section_header *)(buf +
        !           421:            sizeof(struct txp_fw_file_header));
        !           422:
        !           423:        for (sect = 0; sect < letoh32(fileheader->nsections); sect++) {
        !           424:                if (txp_download_fw_section(sc, secthead, sect, buf, buflen))
        !           425:                        goto fail;
        !           426:                secthead = (struct txp_fw_section_header *)
        !           427:                    (((u_int8_t *)secthead) + letoh32(secthead->nbytes) +
        !           428:                        sizeof(*secthead));
        !           429:        }
        !           430:
        !           431:        WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_DOWNLOAD_COMPLETE);
        !           432:
        !           433:        for (i = 0; i < 10000; i++) {
        !           434:                r = READ_REG(sc, TXP_A2H_0);
        !           435:                if (r == STAT_WAITING_FOR_BOOT)
        !           436:                        break;
        !           437:                DELAY(50);
        !           438:        }
        !           439:        if (r != STAT_WAITING_FOR_BOOT) {
        !           440:                printf("not waiting for boot\n");
        !           441:                goto fail;
        !           442:        }
        !           443:
        !           444:        WRITE_REG(sc, TXP_IER, ier);
        !           445:        WRITE_REG(sc, TXP_IMR, imr);
        !           446:
        !           447:        free(buf, M_DEVBUF);
        !           448:        printf("loaded firmware, ");
        !           449:        return (0);
        !           450: fail:
        !           451:        free(buf, M_DEVBUF);
        !           452:        return (-1);
        !           453: }
        !           454:
        !           455: int
        !           456: txp_download_fw_wait(sc)
        !           457:        struct txp_softc *sc;
        !           458: {
        !           459:        u_int32_t i, r;
        !           460:
        !           461:        for (i = 0; i < 10000; i++) {
        !           462:                r = READ_REG(sc, TXP_ISR);
        !           463:                if (r & TXP_INT_A2H_0)
        !           464:                        break;
        !           465:                DELAY(50);
        !           466:        }
        !           467:
        !           468:        if (!(r & TXP_INT_A2H_0)) {
        !           469:                printf("fw wait failed comm0\n");
        !           470:                return (-1);
        !           471:        }
        !           472:
        !           473:        WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0);
        !           474:
        !           475:        r = READ_REG(sc, TXP_A2H_0);
        !           476:        if (r != STAT_WAITING_FOR_SEGMENT) {
        !           477:                printf("fw not waiting for segment\n");
        !           478:                return (-1);
        !           479:        }
        !           480:        return (0);
        !           481: }
        !           482:
        !           483: int
        !           484: txp_download_fw_section(sc, sect, sectnum, buf, buflen)
        !           485:        struct txp_softc *sc;
        !           486:        struct txp_fw_section_header *sect;
        !           487:        int sectnum;
        !           488:        u_char *buf;
        !           489:        size_t buflen;
        !           490: {
        !           491:        struct txp_dma_alloc dma;
        !           492:        int rseg, err = 0;
        !           493:        struct mbuf m;
        !           494:        u_int16_t csum;
        !           495:
        !           496:        /* Skip zero length sections */
        !           497:        if (sect->nbytes == 0)
        !           498:                return (0);
        !           499:
        !           500:        /* Make sure we aren't past the end of the image */
        !           501:        rseg = ((u_int8_t *)sect) - ((u_int8_t *)buf);
        !           502:        if (rseg >= buflen) {
        !           503:                printf("fw invalid section address, section %d\n", sectnum);
        !           504:                return (-1);
        !           505:        }
        !           506:
        !           507:        /* Make sure this section doesn't go past the end */
        !           508:        rseg += letoh32(sect->nbytes);
        !           509:        if (rseg >= buflen) {
        !           510:                printf("fw truncated section %d\n", sectnum);
        !           511:                return (-1);
        !           512:        }
        !           513:
        !           514:        /* map a buffer, copy segment to it, get physaddr */
        !           515:        if (txp_dma_malloc(sc, letoh32(sect->nbytes), &dma, 0)) {
        !           516:                printf("fw dma malloc failed, section %d\n", sectnum);
        !           517:                return (-1);
        !           518:        }
        !           519:
        !           520:        bcopy(((u_int8_t *)sect) + sizeof(*sect), dma.dma_vaddr,
        !           521:            letoh32(sect->nbytes));
        !           522:
        !           523:        /*
        !           524:         * dummy up mbuf and verify section checksum
        !           525:         */
        !           526:        m.m_type = MT_DATA;
        !           527:        m.m_next = m.m_nextpkt = NULL;
        !           528:        m.m_len = letoh32(sect->nbytes);
        !           529:        m.m_data = dma.dma_vaddr;
        !           530:        m.m_flags = 0;
        !           531:        csum = in_cksum(&m, letoh32(sect->nbytes));
        !           532:        if (csum != sect->cksum) {
        !           533:                printf("fw section %d, bad cksum (expected 0x%x got 0x%x)\n",
        !           534:                    sectnum, sect->cksum, csum);
        !           535:                err = -1;
        !           536:                goto bail;
        !           537:        }
        !           538:
        !           539:        bus_dmamap_sync(sc->sc_dmat, dma.dma_map, 0,
        !           540:            dma.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
        !           541:
        !           542:        WRITE_REG(sc, TXP_H2A_1, letoh32(sect->nbytes));
        !           543:        WRITE_REG(sc, TXP_H2A_2, letoh16(sect->cksum));
        !           544:        WRITE_REG(sc, TXP_H2A_3, letoh32(sect->addr));
        !           545:        WRITE_REG(sc, TXP_H2A_4, dma.dma_paddr >> 32);
        !           546:        WRITE_REG(sc, TXP_H2A_5, dma.dma_paddr & 0xffffffff);
        !           547:        WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_SEGMENT_AVAILABLE);
        !           548:
        !           549:        if (txp_download_fw_wait(sc)) {
        !           550:                printf("%s: fw wait failed, section %d\n",
        !           551:                    sc->sc_dev.dv_xname, sectnum);
        !           552:                err = -1;
        !           553:        }
        !           554:
        !           555:        bus_dmamap_sync(sc->sc_dmat, dma.dma_map, 0,
        !           556:            dma.dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           557:
        !           558: bail:
        !           559:        txp_dma_free(sc, &dma);
        !           560:
        !           561:        return (err);
        !           562: }
        !           563:
        !           564: int
        !           565: txp_intr(vsc)
        !           566:        void *vsc;
        !           567: {
        !           568:        struct txp_softc *sc = vsc;
        !           569:        struct txp_hostvar *hv = sc->sc_hostvar;
        !           570:        u_int32_t isr;
        !           571:        int claimed = 0;
        !           572:
        !           573:        /* mask all interrupts */
        !           574:        WRITE_REG(sc, TXP_IMR, TXP_INT_RESERVED | TXP_INT_SELF |
        !           575:            TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
        !           576:            TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 |
        !           577:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !           578:            TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |  TXP_INT_LATCH);
        !           579:
        !           580:        bus_dmamap_sync(sc->sc_dmat, sc->sc_host_dma.dma_map, 0,
        !           581:            sizeof(struct txp_hostvar), BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
        !           582:
        !           583:        isr = READ_REG(sc, TXP_ISR);
        !           584:        while (isr) {
        !           585:                claimed = 1;
        !           586:                WRITE_REG(sc, TXP_ISR, isr);
        !           587:
        !           588:                if ((*sc->sc_rxhir.r_roff) != (*sc->sc_rxhir.r_woff))
        !           589:                        txp_rx_reclaim(sc, &sc->sc_rxhir, &sc->sc_rxhiring_dma);
        !           590:                if ((*sc->sc_rxlor.r_roff) != (*sc->sc_rxlor.r_woff))
        !           591:                        txp_rx_reclaim(sc, &sc->sc_rxlor, &sc->sc_rxloring_dma);
        !           592:
        !           593:                if (hv->hv_rx_buf_write_idx == hv->hv_rx_buf_read_idx)
        !           594:                        txp_rxbuf_reclaim(sc);
        !           595:
        !           596:                if (sc->sc_txhir.r_cnt && (sc->sc_txhir.r_cons !=
        !           597:                    TXP_OFFSET2IDX(letoh32(*(sc->sc_txhir.r_off)))))
        !           598:                        txp_tx_reclaim(sc, &sc->sc_txhir, &sc->sc_txhiring_dma);
        !           599:
        !           600:                if (sc->sc_txlor.r_cnt && (sc->sc_txlor.r_cons !=
        !           601:                    TXP_OFFSET2IDX(letoh32(*(sc->sc_txlor.r_off)))))
        !           602:                        txp_tx_reclaim(sc, &sc->sc_txlor, &sc->sc_txloring_dma);
        !           603:
        !           604:                isr = READ_REG(sc, TXP_ISR);
        !           605:        }
        !           606:
        !           607:        bus_dmamap_sync(sc->sc_dmat, sc->sc_host_dma.dma_map, 0,
        !           608:            sizeof(struct txp_hostvar), BUS_DMASYNC_POSTWRITE|BUS_DMASYNC_POSTREAD);
        !           609:
        !           610:        /* unmask all interrupts */
        !           611:        WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3);
        !           612:
        !           613:        txp_start(&sc->sc_arpcom.ac_if);
        !           614:
        !           615:        return (claimed);
        !           616: }
        !           617:
        !           618: void
        !           619: txp_rx_reclaim(sc, r, dma)
        !           620:        struct txp_softc *sc;
        !           621:        struct txp_rx_ring *r;
        !           622:        struct txp_dma_alloc *dma;
        !           623: {
        !           624:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           625:        struct txp_rx_desc *rxd;
        !           626:        struct mbuf *m;
        !           627:        struct txp_swdesc *sd;
        !           628:        u_int32_t roff, woff;
        !           629:        int sumflags = 0, idx;
        !           630:
        !           631:        roff = letoh32(*r->r_roff);
        !           632:        woff = letoh32(*r->r_woff);
        !           633:        idx = roff / sizeof(struct txp_rx_desc);
        !           634:        rxd = r->r_desc + idx;
        !           635:
        !           636:        while (roff != woff) {
        !           637:
        !           638:                bus_dmamap_sync(sc->sc_dmat, dma->dma_map,
        !           639:                    idx * sizeof(struct txp_rx_desc), sizeof(struct txp_rx_desc),
        !           640:                    BUS_DMASYNC_POSTREAD);
        !           641:
        !           642:                if (rxd->rx_flags & RX_FLAGS_ERROR) {
        !           643:                        printf("%s: error 0x%x\n", sc->sc_dev.dv_xname,
        !           644:                            letoh32(rxd->rx_stat));
        !           645:                        ifp->if_ierrors++;
        !           646:                        goto next;
        !           647:                }
        !           648:
        !           649:                /* retrieve stashed pointer */
        !           650:                bcopy((u_long *)&rxd->rx_vaddrlo, &sd, sizeof(sd));
        !           651:
        !           652:                bus_dmamap_sync(sc->sc_dmat, sd->sd_map, 0,
        !           653:                    sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !           654:                bus_dmamap_unload(sc->sc_dmat, sd->sd_map);
        !           655:                bus_dmamap_destroy(sc->sc_dmat, sd->sd_map);
        !           656:                m = sd->sd_mbuf;
        !           657:                free(sd, M_DEVBUF);
        !           658:                m->m_pkthdr.len = m->m_len = letoh16(rxd->rx_len);
        !           659:
        !           660: #if NVLAN > 0
        !           661:                /*
        !           662:                 * XXX Another firmware bug: the vlan encapsulation
        !           663:                 * is always removed, even when we tell the card not
        !           664:                 * to do that.  Restore the vlan encapsulation below.
        !           665:                 */
        !           666:                if (rxd->rx_stat & htole32(RX_STAT_VLAN)) {
        !           667:                        struct ether_vlan_header vh;
        !           668:
        !           669:                        if (m->m_pkthdr.len < ETHER_HDR_LEN) {
        !           670:                                m_freem(m);
        !           671:                                goto next;
        !           672:                        }
        !           673:                        m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&vh);
        !           674:                        vh.evl_proto = vh.evl_encap_proto;
        !           675:                        vh.evl_tag = rxd->rx_vlan >> 16;
        !           676:                        vh.evl_encap_proto = htons(ETHERTYPE_VLAN);
        !           677:                        m_adj(m, ETHER_HDR_LEN);
        !           678:                        M_PREPEND(m, sizeof(vh), M_DONTWAIT);
        !           679:                        if (m == NULL)
        !           680:                                goto next;
        !           681:                        m_copyback(m, 0, sizeof(vh), &vh);
        !           682:                }
        !           683: #endif
        !           684:
        !           685: #ifdef __STRICT_ALIGNMENT
        !           686:                {
        !           687:                        /*
        !           688:                         * XXX Nice chip, except it won't accept "off by 2"
        !           689:                         * buffers, so we're force to copy.  Supposedly
        !           690:                         * this will be fixed in a newer firmware rev
        !           691:                         * and this will be temporary.
        !           692:                         */
        !           693:                        struct mbuf *mnew;
        !           694:
        !           695:                        MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !           696:                        if (mnew == NULL) {
        !           697:                                m_freem(m);
        !           698:                                goto next;
        !           699:                        }
        !           700:                        if (m->m_len > (MHLEN - 2)) {
        !           701:                                MCLGET(mnew, M_DONTWAIT);
        !           702:                                if (!(mnew->m_flags & M_EXT)) {
        !           703:                                        m_freem(mnew);
        !           704:                                        m_freem(m);
        !           705:                                        goto next;
        !           706:                                }
        !           707:                        }
        !           708:                        mnew->m_pkthdr.rcvif = ifp;
        !           709:                        mnew->m_pkthdr.len = mnew->m_len = m->m_len;
        !           710:                        mnew->m_data += 2;
        !           711:                        bcopy(m->m_data, mnew->m_data, m->m_len);
        !           712:                        m_freem(m);
        !           713:                        m = mnew;
        !           714:                }
        !           715: #endif
        !           716:
        !           717: #if NBPFILTER > 0
        !           718:                /*
        !           719:                 * Handle BPF listeners. Let the BPF user see the packet.
        !           720:                 */
        !           721:                if (ifp->if_bpf)
        !           722:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           723: #endif
        !           724:
        !           725:                if (rxd->rx_stat & htole32(RX_STAT_IPCKSUMBAD))
        !           726:                        sumflags |= M_IPV4_CSUM_IN_BAD;
        !           727:                else if (rxd->rx_stat & htole32(RX_STAT_IPCKSUMGOOD))
        !           728:                        sumflags |= M_IPV4_CSUM_IN_OK;
        !           729:
        !           730:                if (rxd->rx_stat & htole32(RX_STAT_TCPCKSUMBAD))
        !           731:                        sumflags |= M_TCP_CSUM_IN_BAD;
        !           732:                else if (rxd->rx_stat & htole32(RX_STAT_TCPCKSUMGOOD))
        !           733:                        sumflags |= M_TCP_CSUM_IN_OK;
        !           734:
        !           735:                if (rxd->rx_stat & htole32(RX_STAT_UDPCKSUMBAD))
        !           736:                        sumflags |= M_UDP_CSUM_IN_BAD;
        !           737:                else if (rxd->rx_stat & htole32(RX_STAT_UDPCKSUMGOOD))
        !           738:                        sumflags |= M_UDP_CSUM_IN_OK;
        !           739:
        !           740:                m->m_pkthdr.csum_flags = sumflags;
        !           741:
        !           742:                ether_input_mbuf(ifp, m);
        !           743:
        !           744: next:
        !           745:                bus_dmamap_sync(sc->sc_dmat, dma->dma_map,
        !           746:                    idx * sizeof(struct txp_rx_desc), sizeof(struct txp_rx_desc),
        !           747:                    BUS_DMASYNC_PREREAD);
        !           748:
        !           749:                roff += sizeof(struct txp_rx_desc);
        !           750:                if (roff == (RX_ENTRIES * sizeof(struct txp_rx_desc))) {
        !           751:                        idx = 0;
        !           752:                        roff = 0;
        !           753:                        rxd = r->r_desc;
        !           754:                } else {
        !           755:                        idx++;
        !           756:                        rxd++;
        !           757:                }
        !           758:                woff = letoh32(*r->r_woff);
        !           759:        }
        !           760:
        !           761:        *r->r_roff = htole32(woff);
        !           762: }
        !           763:
        !           764: void
        !           765: txp_rxbuf_reclaim(sc)
        !           766:        struct txp_softc *sc;
        !           767: {
        !           768:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           769:        struct txp_hostvar *hv = sc->sc_hostvar;
        !           770:        struct txp_rxbuf_desc *rbd;
        !           771:        struct txp_swdesc *sd;
        !           772:        u_int32_t i, end;
        !           773:
        !           774:        end = TXP_OFFSET2IDX(letoh32(hv->hv_rx_buf_read_idx));
        !           775:        i = TXP_OFFSET2IDX(letoh32(hv->hv_rx_buf_write_idx));
        !           776:
        !           777:        if (++i == RXBUF_ENTRIES)
        !           778:                i = 0;
        !           779:
        !           780:        rbd = sc->sc_rxbufs + i;
        !           781:
        !           782:        while (i != end) {
        !           783:                sd = (struct txp_swdesc *)malloc(sizeof(struct txp_swdesc),
        !           784:                    M_DEVBUF, M_NOWAIT);
        !           785:                if (sd == NULL)
        !           786:                        break;
        !           787:
        !           788:                MGETHDR(sd->sd_mbuf, M_DONTWAIT, MT_DATA);
        !           789:                if (sd->sd_mbuf == NULL)
        !           790:                        goto err_sd;
        !           791:
        !           792:                MCLGET(sd->sd_mbuf, M_DONTWAIT);
        !           793:                if ((sd->sd_mbuf->m_flags & M_EXT) == 0)
        !           794:                        goto err_mbuf;
        !           795:                /* reserve some space for a possible VLAN header */
        !           796:                sd->sd_mbuf->m_data += 8;
        !           797:                sd->sd_mbuf->m_pkthdr.len = sd->sd_mbuf->m_len = MCLBYTES - 8;
        !           798:                sd->sd_mbuf->m_pkthdr.rcvif = ifp;
        !           799:                if (bus_dmamap_create(sc->sc_dmat, TXP_MAX_PKTLEN, 1,
        !           800:                    TXP_MAX_PKTLEN, 0, BUS_DMA_NOWAIT, &sd->sd_map))
        !           801:                        goto err_mbuf;
        !           802:                if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, sd->sd_mbuf,
        !           803:                    BUS_DMA_NOWAIT)) {
        !           804:                        bus_dmamap_destroy(sc->sc_dmat, sd->sd_map);
        !           805:                        goto err_mbuf;
        !           806:                }
        !           807:
        !           808:                bus_dmamap_sync(sc->sc_dmat, sc->sc_rxbufring_dma.dma_map,
        !           809:                    i * sizeof(struct txp_rxbuf_desc),
        !           810:                    sizeof(struct txp_rxbuf_desc), BUS_DMASYNC_POSTWRITE);
        !           811:
        !           812:                /* stash away pointer */
        !           813:                bcopy(&sd, (u_long *)&rbd->rb_vaddrlo, sizeof(sd));
        !           814:
        !           815:                rbd->rb_paddrlo = ((u_int64_t)sd->sd_map->dm_segs[0].ds_addr)
        !           816:                    & 0xffffffff;
        !           817:                rbd->rb_paddrhi = ((u_int64_t)sd->sd_map->dm_segs[0].ds_addr)
        !           818:                    >> 32;
        !           819:
        !           820:                bus_dmamap_sync(sc->sc_dmat, sd->sd_map, 0,
        !           821:                    sd->sd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
        !           822:
        !           823:                bus_dmamap_sync(sc->sc_dmat, sc->sc_rxbufring_dma.dma_map,
        !           824:                    i * sizeof(struct txp_rxbuf_desc),
        !           825:                    sizeof(struct txp_rxbuf_desc), BUS_DMASYNC_PREWRITE);
        !           826:
        !           827:                hv->hv_rx_buf_write_idx = htole32(TXP_IDX2OFFSET(i));
        !           828:
        !           829:                if (++i == RXBUF_ENTRIES) {
        !           830:                        i = 0;
        !           831:                        rbd = sc->sc_rxbufs;
        !           832:                } else
        !           833:                        rbd++;
        !           834:        }
        !           835:        return;
        !           836:
        !           837: err_mbuf:
        !           838:        m_freem(sd->sd_mbuf);
        !           839: err_sd:
        !           840:        free(sd, M_DEVBUF);
        !           841: }
        !           842:
        !           843: /*
        !           844:  * Reclaim mbufs and entries from a transmit ring.
        !           845:  */
        !           846: void
        !           847: txp_tx_reclaim(sc, r, dma)
        !           848:        struct txp_softc *sc;
        !           849:        struct txp_tx_ring *r;
        !           850:        struct txp_dma_alloc *dma;
        !           851: {
        !           852:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           853:        u_int32_t idx = TXP_OFFSET2IDX(letoh32(*(r->r_off)));
        !           854:        u_int32_t cons = r->r_cons, cnt = r->r_cnt;
        !           855:        struct txp_tx_desc *txd = r->r_desc + cons;
        !           856:        struct txp_swdesc *sd = sc->sc_txd + cons;
        !           857:        struct mbuf *m;
        !           858:
        !           859:        while (cons != idx) {
        !           860:                if (cnt == 0)
        !           861:                        break;
        !           862:
        !           863:                bus_dmamap_sync(sc->sc_dmat, dma->dma_map,
        !           864:                    cons * sizeof(struct txp_tx_desc),
        !           865:                    sizeof(struct txp_tx_desc),
        !           866:                    BUS_DMASYNC_POSTWRITE);
        !           867:
        !           868:                if ((txd->tx_flags & TX_FLAGS_TYPE_M) ==
        !           869:                    TX_FLAGS_TYPE_DATA) {
        !           870:                        bus_dmamap_sync(sc->sc_dmat, sd->sd_map, 0,
        !           871:                            sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           872:                        bus_dmamap_unload(sc->sc_dmat, sd->sd_map);
        !           873:                        m = sd->sd_mbuf;
        !           874:                        if (m != NULL) {
        !           875:                                m_freem(m);
        !           876:                                txd->tx_addrlo = 0;
        !           877:                                txd->tx_addrhi = 0;
        !           878:                                ifp->if_opackets++;
        !           879:                        }
        !           880:                }
        !           881:                ifp->if_flags &= ~IFF_OACTIVE;
        !           882:
        !           883:                if (++cons == TX_ENTRIES) {
        !           884:                        txd = r->r_desc;
        !           885:                        cons = 0;
        !           886:                        sd = sc->sc_txd;
        !           887:                } else {
        !           888:                        txd++;
        !           889:                        sd++;
        !           890:                }
        !           891:
        !           892:                cnt--;
        !           893:        }
        !           894:
        !           895:        r->r_cons = cons;
        !           896:        r->r_cnt = cnt;
        !           897:        if (cnt == 0)
        !           898:                ifp->if_timer = 0;
        !           899: }
        !           900:
        !           901: void
        !           902: txp_shutdown(vsc)
        !           903:        void *vsc;
        !           904: {
        !           905:        struct txp_softc *sc = (struct txp_softc *)vsc;
        !           906:
        !           907:        /* mask all interrupts */
        !           908:        WRITE_REG(sc, TXP_IMR,
        !           909:            TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
        !           910:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !           911:            TXP_INT_LATCH);
        !           912:
        !           913:        txp_command(sc, TXP_CMD_TX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 0);
        !           914:        txp_command(sc, TXP_CMD_RX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 0);
        !           915:        txp_command(sc, TXP_CMD_HALT, 0, 0, 0, NULL, NULL, NULL, 0);
        !           916: }
        !           917:
        !           918: int
        !           919: txp_alloc_rings(sc)
        !           920:        struct txp_softc *sc;
        !           921: {
        !           922:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           923:        struct txp_boot_record *boot;
        !           924:        struct txp_swdesc *sd;
        !           925:        u_int32_t r;
        !           926:        int i, j;
        !           927:
        !           928:        /* boot record */
        !           929:        if (txp_dma_malloc(sc, sizeof(struct txp_boot_record), &sc->sc_boot_dma,
        !           930:            BUS_DMA_COHERENT)) {
        !           931:                printf("can't allocate boot record\n");
        !           932:                return (-1);
        !           933:        }
        !           934:        boot = (struct txp_boot_record *)sc->sc_boot_dma.dma_vaddr;
        !           935:        bzero(boot, sizeof(*boot));
        !           936:        sc->sc_boot = boot;
        !           937:
        !           938:        /* host variables */
        !           939:        if (txp_dma_malloc(sc, sizeof(struct txp_hostvar), &sc->sc_host_dma,
        !           940:            BUS_DMA_COHERENT)) {
        !           941:                printf("can't allocate host ring\n");
        !           942:                goto bail_boot;
        !           943:        }
        !           944:        bzero(sc->sc_host_dma.dma_vaddr, sizeof(struct txp_hostvar));
        !           945:        boot->br_hostvar_lo = htole32(sc->sc_host_dma.dma_paddr & 0xffffffff);
        !           946:        boot->br_hostvar_hi = htole32(sc->sc_host_dma.dma_paddr >> 32);
        !           947:        sc->sc_hostvar = (struct txp_hostvar *)sc->sc_host_dma.dma_vaddr;
        !           948:
        !           949:        /* high priority tx ring */
        !           950:        if (txp_dma_malloc(sc, sizeof(struct txp_tx_desc) * TX_ENTRIES,
        !           951:            &sc->sc_txhiring_dma, BUS_DMA_COHERENT)) {
        !           952:                printf("can't allocate high tx ring\n");
        !           953:                goto bail_host;
        !           954:        }
        !           955:        bzero(sc->sc_txhiring_dma.dma_vaddr, sizeof(struct txp_tx_desc) * TX_ENTRIES);
        !           956:        boot->br_txhipri_lo = htole32(sc->sc_txhiring_dma.dma_paddr & 0xffffffff);
        !           957:        boot->br_txhipri_hi = htole32(sc->sc_txhiring_dma.dma_paddr >> 32);
        !           958:        boot->br_txhipri_siz = htole32(TX_ENTRIES * sizeof(struct txp_tx_desc));
        !           959:        sc->sc_txhir.r_reg = TXP_H2A_1;
        !           960:        sc->sc_txhir.r_desc = (struct txp_tx_desc *)sc->sc_txhiring_dma.dma_vaddr;
        !           961:        sc->sc_txhir.r_cons = sc->sc_txhir.r_prod = sc->sc_txhir.r_cnt = 0;
        !           962:        sc->sc_txhir.r_off = &sc->sc_hostvar->hv_tx_hi_desc_read_idx;
        !           963:        for (i = 0; i < TX_ENTRIES; i++) {
        !           964:                if (bus_dmamap_create(sc->sc_dmat, TXP_MAX_PKTLEN,
        !           965:                    TX_ENTRIES - 4, TXP_MAX_SEGLEN, 0,
        !           966:                    BUS_DMA_NOWAIT, &sc->sc_txd[i].sd_map) != 0) {
        !           967:                        for (j = 0; j < i; j++) {
        !           968:                                bus_dmamap_destroy(sc->sc_dmat,
        !           969:                                    sc->sc_txd[j].sd_map);
        !           970:                                sc->sc_txd[j].sd_map = NULL;
        !           971:                        }
        !           972:                        goto bail_txhiring;
        !           973:                }
        !           974:        }
        !           975:
        !           976:        /* low priority tx ring */
        !           977:        if (txp_dma_malloc(sc, sizeof(struct txp_tx_desc) * TX_ENTRIES,
        !           978:            &sc->sc_txloring_dma, BUS_DMA_COHERENT)) {
        !           979:                printf("can't allocate low tx ring\n");
        !           980:                goto bail_txhiring;
        !           981:        }
        !           982:        bzero(sc->sc_txloring_dma.dma_vaddr, sizeof(struct txp_tx_desc) * TX_ENTRIES);
        !           983:        boot->br_txlopri_lo = htole32(sc->sc_txloring_dma.dma_paddr & 0xffffffff);
        !           984:        boot->br_txlopri_hi = htole32(sc->sc_txloring_dma.dma_paddr >> 32);
        !           985:        boot->br_txlopri_siz = htole32(TX_ENTRIES * sizeof(struct txp_tx_desc));
        !           986:        sc->sc_txlor.r_reg = TXP_H2A_3;
        !           987:        sc->sc_txlor.r_desc = (struct txp_tx_desc *)sc->sc_txloring_dma.dma_vaddr;
        !           988:        sc->sc_txlor.r_cons = sc->sc_txlor.r_prod = sc->sc_txlor.r_cnt = 0;
        !           989:        sc->sc_txlor.r_off = &sc->sc_hostvar->hv_tx_lo_desc_read_idx;
        !           990:
        !           991:        /* high priority rx ring */
        !           992:        if (txp_dma_malloc(sc, sizeof(struct txp_rx_desc) * RX_ENTRIES,
        !           993:            &sc->sc_rxhiring_dma, BUS_DMA_COHERENT)) {
        !           994:                printf("can't allocate high rx ring\n");
        !           995:                goto bail_txloring;
        !           996:        }
        !           997:        bzero(sc->sc_rxhiring_dma.dma_vaddr, sizeof(struct txp_rx_desc) * RX_ENTRIES);
        !           998:        boot->br_rxhipri_lo = htole32(sc->sc_rxhiring_dma.dma_paddr & 0xffffffff);
        !           999:        boot->br_rxhipri_hi = htole32(sc->sc_rxhiring_dma.dma_paddr >> 32);
        !          1000:        boot->br_rxhipri_siz = htole32(RX_ENTRIES * sizeof(struct txp_rx_desc));
        !          1001:        sc->sc_rxhir.r_desc =
        !          1002:            (struct txp_rx_desc *)sc->sc_rxhiring_dma.dma_vaddr;
        !          1003:        sc->sc_rxhir.r_roff = &sc->sc_hostvar->hv_rx_hi_read_idx;
        !          1004:        sc->sc_rxhir.r_woff = &sc->sc_hostvar->hv_rx_hi_write_idx;
        !          1005:        bus_dmamap_sync(sc->sc_dmat, sc->sc_rxhiring_dma.dma_map,
        !          1006:            0, sc->sc_rxhiring_dma.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
        !          1007:
        !          1008:        /* low priority ring */
        !          1009:        if (txp_dma_malloc(sc, sizeof(struct txp_rx_desc) * RX_ENTRIES,
        !          1010:            &sc->sc_rxloring_dma, BUS_DMA_COHERENT)) {
        !          1011:                printf("can't allocate low rx ring\n");
        !          1012:                goto bail_rxhiring;
        !          1013:        }
        !          1014:        bzero(sc->sc_rxloring_dma.dma_vaddr, sizeof(struct txp_rx_desc) * RX_ENTRIES);
        !          1015:        boot->br_rxlopri_lo = htole32(sc->sc_rxloring_dma.dma_paddr & 0xffffffff);
        !          1016:        boot->br_rxlopri_hi = htole32(sc->sc_rxloring_dma.dma_paddr >> 32);
        !          1017:        boot->br_rxlopri_siz = htole32(RX_ENTRIES * sizeof(struct txp_rx_desc));
        !          1018:        sc->sc_rxlor.r_desc =
        !          1019:            (struct txp_rx_desc *)sc->sc_rxloring_dma.dma_vaddr;
        !          1020:        sc->sc_rxlor.r_roff = &sc->sc_hostvar->hv_rx_lo_read_idx;
        !          1021:        sc->sc_rxlor.r_woff = &sc->sc_hostvar->hv_rx_lo_write_idx;
        !          1022:        bus_dmamap_sync(sc->sc_dmat, sc->sc_rxloring_dma.dma_map,
        !          1023:            0, sc->sc_rxloring_dma.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
        !          1024:
        !          1025:        /* command ring */
        !          1026:        if (txp_dma_malloc(sc, sizeof(struct txp_cmd_desc) * CMD_ENTRIES,
        !          1027:            &sc->sc_cmdring_dma, BUS_DMA_COHERENT)) {
        !          1028:                printf("can't allocate command ring\n");
        !          1029:                goto bail_rxloring;
        !          1030:        }
        !          1031:        bzero(sc->sc_cmdring_dma.dma_vaddr, sizeof(struct txp_cmd_desc) * CMD_ENTRIES);
        !          1032:        boot->br_cmd_lo = htole32(sc->sc_cmdring_dma.dma_paddr & 0xffffffff);
        !          1033:        boot->br_cmd_hi = htole32(sc->sc_cmdring_dma.dma_paddr >> 32);
        !          1034:        boot->br_cmd_siz = htole32(CMD_ENTRIES * sizeof(struct txp_cmd_desc));
        !          1035:        sc->sc_cmdring.base = (struct txp_cmd_desc *)sc->sc_cmdring_dma.dma_vaddr;
        !          1036:        sc->sc_cmdring.size = CMD_ENTRIES * sizeof(struct txp_cmd_desc);
        !          1037:        sc->sc_cmdring.lastwrite = 0;
        !          1038:
        !          1039:        /* response ring */
        !          1040:        if (txp_dma_malloc(sc, sizeof(struct txp_rsp_desc) * RSP_ENTRIES,
        !          1041:            &sc->sc_rspring_dma, BUS_DMA_COHERENT)) {
        !          1042:                printf("can't allocate response ring\n");
        !          1043:                goto bail_cmdring;
        !          1044:        }
        !          1045:        bzero(sc->sc_rspring_dma.dma_vaddr, sizeof(struct txp_rsp_desc) * RSP_ENTRIES);
        !          1046:        boot->br_resp_lo = htole32(sc->sc_rspring_dma.dma_paddr & 0xffffffff);
        !          1047:        boot->br_resp_hi = htole32(sc->sc_rspring_dma.dma_paddr >> 32);
        !          1048:        boot->br_resp_siz = htole32(CMD_ENTRIES * sizeof(struct txp_rsp_desc));
        !          1049:        sc->sc_rspring.base = (struct txp_rsp_desc *)sc->sc_rspring_dma.dma_vaddr;
        !          1050:        sc->sc_rspring.size = RSP_ENTRIES * sizeof(struct txp_rsp_desc);
        !          1051:        sc->sc_rspring.lastwrite = 0;
        !          1052:
        !          1053:        /* receive buffer ring */
        !          1054:        if (txp_dma_malloc(sc, sizeof(struct txp_rxbuf_desc) * RXBUF_ENTRIES,
        !          1055:            &sc->sc_rxbufring_dma, BUS_DMA_COHERENT)) {
        !          1056:                printf("can't allocate rx buffer ring\n");
        !          1057:                goto bail_rspring;
        !          1058:        }
        !          1059:        bzero(sc->sc_rxbufring_dma.dma_vaddr, sizeof(struct txp_rxbuf_desc) * RXBUF_ENTRIES);
        !          1060:        boot->br_rxbuf_lo = htole32(sc->sc_rxbufring_dma.dma_paddr & 0xffffffff);
        !          1061:        boot->br_rxbuf_hi = htole32(sc->sc_rxbufring_dma.dma_paddr >> 32);
        !          1062:        boot->br_rxbuf_siz = htole32(RXBUF_ENTRIES * sizeof(struct txp_rxbuf_desc));
        !          1063:        sc->sc_rxbufs = (struct txp_rxbuf_desc *)sc->sc_rxbufring_dma.dma_vaddr;
        !          1064:        for (i = 0; i < RXBUF_ENTRIES; i++) {
        !          1065:                sd = (struct txp_swdesc *)malloc(sizeof(struct txp_swdesc),
        !          1066:                    M_DEVBUF, M_NOWAIT);
        !          1067:
        !          1068:                /* stash away pointer */
        !          1069:                bcopy(&sd, (u_long *)&sc->sc_rxbufs[i].rb_vaddrlo, sizeof(sd));
        !          1070:
        !          1071:                if (sd == NULL)
        !          1072:                        break;
        !          1073:
        !          1074:                MGETHDR(sd->sd_mbuf, M_DONTWAIT, MT_DATA);
        !          1075:                if (sd->sd_mbuf == NULL) {
        !          1076:                        goto bail_rxbufring;
        !          1077:                }
        !          1078:
        !          1079:                MCLGET(sd->sd_mbuf, M_DONTWAIT);
        !          1080:                if ((sd->sd_mbuf->m_flags & M_EXT) == 0) {
        !          1081:                        goto bail_rxbufring;
        !          1082:                }
        !          1083:                /* reserve some space for a possible VLAN header */
        !          1084:                sd->sd_mbuf->m_data += 8;
        !          1085:                sd->sd_mbuf->m_pkthdr.len = sd->sd_mbuf->m_len = MCLBYTES - 8;
        !          1086:                sd->sd_mbuf->m_pkthdr.rcvif = ifp;
        !          1087:                if (bus_dmamap_create(sc->sc_dmat, TXP_MAX_PKTLEN, 1,
        !          1088:                    TXP_MAX_PKTLEN, 0, BUS_DMA_NOWAIT, &sd->sd_map)) {
        !          1089:                        goto bail_rxbufring;
        !          1090:                }
        !          1091:                if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, sd->sd_mbuf,
        !          1092:                    BUS_DMA_NOWAIT)) {
        !          1093:                        bus_dmamap_destroy(sc->sc_dmat, sd->sd_map);
        !          1094:                        goto bail_rxbufring;
        !          1095:                }
        !          1096:                bus_dmamap_sync(sc->sc_dmat, sd->sd_map, 0,
        !          1097:                    sd->sd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
        !          1098:
        !          1099:                sc->sc_rxbufs[i].rb_paddrlo =
        !          1100:                    ((u_int64_t)sd->sd_map->dm_segs[0].ds_addr) & 0xffffffff;
        !          1101:                sc->sc_rxbufs[i].rb_paddrhi =
        !          1102:                    ((u_int64_t)sd->sd_map->dm_segs[0].ds_addr) >> 32;
        !          1103:        }
        !          1104:        bus_dmamap_sync(sc->sc_dmat, sc->sc_rxbufring_dma.dma_map,
        !          1105:            0, sc->sc_rxbufring_dma.dma_map->dm_mapsize,
        !          1106:            BUS_DMASYNC_PREWRITE);
        !          1107:        sc->sc_hostvar->hv_rx_buf_write_idx = htole32((RXBUF_ENTRIES - 1) *
        !          1108:            sizeof(struct txp_rxbuf_desc));
        !          1109:
        !          1110:        /* zero dma */
        !          1111:        if (txp_dma_malloc(sc, sizeof(u_int32_t), &sc->sc_zero_dma,
        !          1112:            BUS_DMA_COHERENT)) {
        !          1113:                printf("can't allocate response ring\n");
        !          1114:                goto bail_rxbufring;
        !          1115:        }
        !          1116:        bzero(sc->sc_zero_dma.dma_vaddr, sizeof(u_int32_t));
        !          1117:        boot->br_zero_lo = htole32(sc->sc_zero_dma.dma_paddr & 0xffffffff);
        !          1118:        boot->br_zero_hi = htole32(sc->sc_zero_dma.dma_paddr >> 32);
        !          1119:
        !          1120:        /* See if it's waiting for boot, and try to boot it */
        !          1121:        for (i = 0; i < 10000; i++) {
        !          1122:                r = READ_REG(sc, TXP_A2H_0);
        !          1123:                if (r == STAT_WAITING_FOR_BOOT)
        !          1124:                        break;
        !          1125:                DELAY(50);
        !          1126:        }
        !          1127:        if (r != STAT_WAITING_FOR_BOOT) {
        !          1128:                printf("not waiting for boot\n");
        !          1129:                goto bail;
        !          1130:        }
        !          1131:        WRITE_REG(sc, TXP_H2A_2, sc->sc_boot_dma.dma_paddr >> 32);
        !          1132:        WRITE_REG(sc, TXP_H2A_1, sc->sc_boot_dma.dma_paddr & 0xffffffff);
        !          1133:        WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_REGISTER_BOOT_RECORD);
        !          1134:
        !          1135:        /* See if it booted */
        !          1136:        for (i = 0; i < 10000; i++) {
        !          1137:                r = READ_REG(sc, TXP_A2H_0);
        !          1138:                if (r == STAT_RUNNING)
        !          1139:                        break;
        !          1140:                DELAY(50);
        !          1141:        }
        !          1142:        if (r != STAT_RUNNING) {
        !          1143:                printf("fw not running\n");
        !          1144:                goto bail;
        !          1145:        }
        !          1146:
        !          1147:        /* Clear TX and CMD ring write registers */
        !          1148:        WRITE_REG(sc, TXP_H2A_1, TXP_BOOTCMD_NULL);
        !          1149:        WRITE_REG(sc, TXP_H2A_2, TXP_BOOTCMD_NULL);
        !          1150:        WRITE_REG(sc, TXP_H2A_3, TXP_BOOTCMD_NULL);
        !          1151:        WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_NULL);
        !          1152:
        !          1153:        return (0);
        !          1154:
        !          1155: bail:
        !          1156:        txp_dma_free(sc, &sc->sc_zero_dma);
        !          1157: bail_rxbufring:
        !          1158:        for (i = 0; i < RXBUF_ENTRIES; i++) {
        !          1159:                bcopy((u_long *)&sc->sc_rxbufs[i].rb_vaddrlo, &sd, sizeof(sd));
        !          1160:                if (sd)
        !          1161:                        free(sd, M_DEVBUF);
        !          1162:        }
        !          1163:        txp_dma_free(sc, &sc->sc_rxbufring_dma);
        !          1164: bail_rspring:
        !          1165:        txp_dma_free(sc, &sc->sc_rspring_dma);
        !          1166: bail_cmdring:
        !          1167:        txp_dma_free(sc, &sc->sc_cmdring_dma);
        !          1168: bail_rxloring:
        !          1169:        txp_dma_free(sc, &sc->sc_rxloring_dma);
        !          1170: bail_rxhiring:
        !          1171:        txp_dma_free(sc, &sc->sc_rxhiring_dma);
        !          1172: bail_txloring:
        !          1173:        txp_dma_free(sc, &sc->sc_txloring_dma);
        !          1174: bail_txhiring:
        !          1175:        txp_dma_free(sc, &sc->sc_txhiring_dma);
        !          1176: bail_host:
        !          1177:        txp_dma_free(sc, &sc->sc_host_dma);
        !          1178: bail_boot:
        !          1179:        txp_dma_free(sc, &sc->sc_boot_dma);
        !          1180:        return (-1);
        !          1181: }
        !          1182:
        !          1183: int
        !          1184: txp_dma_malloc(sc, size, dma, mapflags)
        !          1185:        struct txp_softc *sc;
        !          1186:        bus_size_t size;
        !          1187:        struct txp_dma_alloc *dma;
        !          1188:        int mapflags;
        !          1189: {
        !          1190:        int r;
        !          1191:
        !          1192:        if ((r = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
        !          1193:            &dma->dma_seg, 1, &dma->dma_nseg, 0)) != 0)
        !          1194:                goto fail_0;
        !          1195:
        !          1196:        if ((r = bus_dmamem_map(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg,
        !          1197:            size, &dma->dma_vaddr, mapflags | BUS_DMA_NOWAIT)) != 0)
        !          1198:                goto fail_1;
        !          1199:
        !          1200:        if ((r = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
        !          1201:            BUS_DMA_NOWAIT, &dma->dma_map)) != 0)
        !          1202:                goto fail_2;
        !          1203:
        !          1204:        if ((r = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_vaddr,
        !          1205:            size, NULL, BUS_DMA_NOWAIT)) != 0)
        !          1206:                goto fail_3;
        !          1207:
        !          1208:        dma->dma_paddr = dma->dma_map->dm_segs[0].ds_addr;
        !          1209:        return (0);
        !          1210:
        !          1211: fail_3:
        !          1212:        bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
        !          1213: fail_2:
        !          1214:        bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, size);
        !          1215: fail_1:
        !          1216:        bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg);
        !          1217: fail_0:
        !          1218:        return (r);
        !          1219: }
        !          1220:
        !          1221: void
        !          1222: txp_dma_free(sc, dma)
        !          1223:        struct txp_softc *sc;
        !          1224:        struct txp_dma_alloc *dma;
        !          1225: {
        !          1226:        bus_dmamap_unload(sc->sc_dmat, dma->dma_map);
        !          1227:        bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, dma->dma_map->dm_mapsize);
        !          1228:        bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg);
        !          1229:        bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
        !          1230: }
        !          1231:
        !          1232: int
        !          1233: txp_ioctl(ifp, command, data)
        !          1234:        struct ifnet *ifp;
        !          1235:        u_long command;
        !          1236:        caddr_t data;
        !          1237: {
        !          1238:        struct txp_softc *sc = ifp->if_softc;
        !          1239:        struct ifreq *ifr = (struct ifreq *)data;
        !          1240:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          1241:        int s, error = 0;
        !          1242:
        !          1243:        s = splnet();
        !          1244:
        !          1245:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
        !          1246:                splx(s);
        !          1247:                return error;
        !          1248:        }
        !          1249:
        !          1250:        switch(command) {
        !          1251:        case SIOCSIFADDR:
        !          1252:                ifp->if_flags |= IFF_UP;
        !          1253:                switch (ifa->ifa_addr->sa_family) {
        !          1254: #ifdef INET
        !          1255:                case AF_INET:
        !          1256:                        txp_init(sc);
        !          1257:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !          1258:                        break;
        !          1259: #endif /* INET */
        !          1260:                default:
        !          1261:                        txp_init(sc);
        !          1262:                        break;
        !          1263:                }
        !          1264:                break;
        !          1265:        case SIOCSIFFLAGS:
        !          1266:                if (ifp->if_flags & IFF_UP) {
        !          1267:                        txp_init(sc);
        !          1268:                } else {
        !          1269:                        if (ifp->if_flags & IFF_RUNNING)
        !          1270:                                txp_stop(sc);
        !          1271:                }
        !          1272:                break;
        !          1273:        case SIOCADDMULTI:
        !          1274:        case SIOCDELMULTI:
        !          1275:                error = (command == SIOCADDMULTI) ?
        !          1276:                    ether_addmulti(ifr, &sc->sc_arpcom) :
        !          1277:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !          1278:
        !          1279:                if (error == ENETRESET) {
        !          1280:                        /*
        !          1281:                         * Multicast list has changed; set the hardware
        !          1282:                         * filter accordingly.
        !          1283:                         */
        !          1284:                        if (ifp->if_flags & IFF_RUNNING)
        !          1285:                                txp_set_filter(sc);
        !          1286:                        error = 0;
        !          1287:                }
        !          1288:                break;
        !          1289:        case SIOCGIFMEDIA:
        !          1290:        case SIOCSIFMEDIA:
        !          1291:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, command);
        !          1292:                break;
        !          1293:        default:
        !          1294:                error = ENOTTY;
        !          1295:                break;
        !          1296:        }
        !          1297:
        !          1298:        splx(s);
        !          1299:
        !          1300:        return(error);
        !          1301: }
        !          1302:
        !          1303: void
        !          1304: txp_init(sc)
        !          1305:        struct txp_softc *sc;
        !          1306: {
        !          1307:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1308:        int s;
        !          1309:
        !          1310:        txp_stop(sc);
        !          1311:
        !          1312:        s = splnet();
        !          1313:
        !          1314:        txp_set_filter(sc);
        !          1315:
        !          1316:        txp_command(sc, TXP_CMD_TX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1);
        !          1317:        txp_command(sc, TXP_CMD_RX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1);
        !          1318:
        !          1319:        WRITE_REG(sc, TXP_IER, TXP_INT_RESERVED | TXP_INT_SELF |
        !          1320:            TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
        !          1321:            TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 |
        !          1322:            TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
        !          1323:            TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |  TXP_INT_LATCH);
        !          1324:        WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3);
        !          1325:
        !          1326:        ifp->if_flags |= IFF_RUNNING;
        !          1327:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1328:        ifp->if_timer = 0;
        !          1329:
        !          1330:        if (!timeout_pending(&sc->sc_tick))
        !          1331:                timeout_add(&sc->sc_tick, hz);
        !          1332:
        !          1333:        splx(s);
        !          1334: }
        !          1335:
        !          1336: void
        !          1337: txp_tick(vsc)
        !          1338:        void *vsc;
        !          1339: {
        !          1340:        struct txp_softc *sc = vsc;
        !          1341:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1342:        struct txp_rsp_desc *rsp = NULL;
        !          1343:        struct txp_ext_desc *ext;
        !          1344:        int s;
        !          1345:
        !          1346:        s = splnet();
        !          1347:        txp_rxbuf_reclaim(sc);
        !          1348:
        !          1349:        if (txp_command2(sc, TXP_CMD_READ_STATISTICS, 0, 0, 0, NULL, 0,
        !          1350:            &rsp, 1))
        !          1351:                goto out;
        !          1352:        if (rsp->rsp_numdesc != 6)
        !          1353:                goto out;
        !          1354:        if (txp_command(sc, TXP_CMD_CLEAR_STATISTICS, 0, 0, 0,
        !          1355:            NULL, NULL, NULL, 1))
        !          1356:                goto out;
        !          1357:        ext = (struct txp_ext_desc *)(rsp + 1);
        !          1358:
        !          1359:        ifp->if_ierrors += ext[3].ext_2 + ext[3].ext_3 + ext[3].ext_4 +
        !          1360:            ext[4].ext_1 + ext[4].ext_4;
        !          1361:        ifp->if_oerrors += ext[0].ext_1 + ext[1].ext_1 + ext[1].ext_4 +
        !          1362:            ext[2].ext_1;
        !          1363:        ifp->if_collisions += ext[0].ext_2 + ext[0].ext_3 + ext[1].ext_2 +
        !          1364:            ext[1].ext_3;
        !          1365:        ifp->if_opackets += rsp->rsp_par2;
        !          1366:        ifp->if_ipackets += ext[2].ext_3;
        !          1367:
        !          1368: out:
        !          1369:        if (rsp != NULL)
        !          1370:                free(rsp, M_DEVBUF);
        !          1371:
        !          1372:        splx(s);
        !          1373:        timeout_add(&sc->sc_tick, hz);
        !          1374: }
        !          1375:
        !          1376: void
        !          1377: txp_start(ifp)
        !          1378:        struct ifnet *ifp;
        !          1379: {
        !          1380:        struct txp_softc *sc = ifp->if_softc;
        !          1381:        struct txp_tx_ring *r = &sc->sc_txhir;
        !          1382:        struct txp_tx_desc *txd;
        !          1383:        int txdidx;
        !          1384:        struct txp_frag_desc *fxd;
        !          1385:        struct mbuf *m, *mnew;
        !          1386:        struct txp_swdesc *sd;
        !          1387:        u_int32_t firstprod, firstcnt, prod, cnt, i;
        !          1388: #if NVLAN > 0
        !          1389:        struct ifvlan           *ifv;
        !          1390: #endif
        !          1391:
        !          1392:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !          1393:                return;
        !          1394:
        !          1395:        prod = r->r_prod;
        !          1396:        cnt = r->r_cnt;
        !          1397:
        !          1398:        while (1) {
        !          1399:                IFQ_POLL(&ifp->if_snd, m);
        !          1400:                if (m == NULL)
        !          1401:                        break;
        !          1402:                mnew = NULL;
        !          1403:
        !          1404:                firstprod = prod;
        !          1405:                firstcnt = cnt;
        !          1406:
        !          1407:                sd = sc->sc_txd + prod;
        !          1408:                sd->sd_mbuf = m;
        !          1409:
        !          1410:                if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, m,
        !          1411:                    BUS_DMA_NOWAIT)) {
        !          1412:                        MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !          1413:                        if (mnew == NULL)
        !          1414:                                goto oactive1;
        !          1415:                        if (m->m_pkthdr.len > MHLEN) {
        !          1416:                                MCLGET(mnew, M_DONTWAIT);
        !          1417:                                if ((mnew->m_flags & M_EXT) == 0) {
        !          1418:                                        m_freem(mnew);
        !          1419:                                        goto oactive1;
        !          1420:                                }
        !          1421:                        }
        !          1422:                        m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, caddr_t));
        !          1423:                        mnew->m_pkthdr.len = mnew->m_len = m->m_pkthdr.len;
        !          1424:                        IFQ_DEQUEUE(&ifp->if_snd, m);
        !          1425:                        m_freem(m);
        !          1426:                        m = mnew;
        !          1427:                        if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, m,
        !          1428:                            BUS_DMA_NOWAIT))
        !          1429:                                goto oactive1;
        !          1430:                }
        !          1431:
        !          1432:                if ((TX_ENTRIES - cnt) < 4)
        !          1433:                        goto oactive;
        !          1434:
        !          1435:                txd = r->r_desc + prod;
        !          1436:                txdidx = prod;
        !          1437:                txd->tx_flags = TX_FLAGS_TYPE_DATA;
        !          1438:                txd->tx_numdesc = 0;
        !          1439:                txd->tx_addrlo = 0;
        !          1440:                txd->tx_addrhi = 0;
        !          1441:                txd->tx_totlen = m->m_pkthdr.len;
        !          1442:                txd->tx_pflags = 0;
        !          1443:                txd->tx_numdesc = sd->sd_map->dm_nsegs;
        !          1444:
        !          1445:                if (++prod == TX_ENTRIES)
        !          1446:                        prod = 0;
        !          1447:
        !          1448:                if (++cnt >= (TX_ENTRIES - 4))
        !          1449:                        goto oactive;
        !          1450:
        !          1451: #if NVLAN > 0
        !          1452:                if ((m->m_flags & (M_PROTO1|M_PKTHDR)) == (M_PROTO1|M_PKTHDR) &&
        !          1453:                    m->m_pkthdr.rcvif != NULL) {
        !          1454:                        ifv = m->m_pkthdr.rcvif->if_softc;
        !          1455:                        txd->tx_pflags = TX_PFLAGS_VLAN |
        !          1456:                            (htons(ifv->ifv_tag) << TX_PFLAGS_VLANTAG_S);
        !          1457:                }
        !          1458: #endif
        !          1459:
        !          1460:                if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
        !          1461:                        txd->tx_pflags |= TX_PFLAGS_IPCKSUM;
        !          1462: #ifdef TRY_TX_TCP_CSUM
        !          1463:                if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
        !          1464:                        txd->tx_pflags |= TX_PFLAGS_TCPCKSUM;
        !          1465: #endif
        !          1466: #ifdef TRY_TX_UDP_CSUM
        !          1467:                if (m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
        !          1468:                        txd->tx_pflags |= TX_PFLAGS_UDPCKSUM;
        !          1469: #endif
        !          1470:
        !          1471:                bus_dmamap_sync(sc->sc_dmat, sd->sd_map, 0,
        !          1472:                    sd->sd_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
        !          1473:
        !          1474:                fxd = (struct txp_frag_desc *)(r->r_desc + prod);
        !          1475:                for (i = 0; i < sd->sd_map->dm_nsegs; i++) {
        !          1476:                        if (++cnt >= (TX_ENTRIES - 4)) {
        !          1477:                                bus_dmamap_sync(sc->sc_dmat, sd->sd_map,
        !          1478:                                    0, sd->sd_map->dm_mapsize,
        !          1479:                                    BUS_DMASYNC_POSTWRITE);
        !          1480:                                goto oactive;
        !          1481:                        }
        !          1482:
        !          1483:                        fxd->frag_flags = FRAG_FLAGS_TYPE_FRAG |
        !          1484:                            FRAG_FLAGS_VALID;
        !          1485:                        fxd->frag_rsvd1 = 0;
        !          1486:                        fxd->frag_len = sd->sd_map->dm_segs[i].ds_len;
        !          1487:                        fxd->frag_addrlo =
        !          1488:                            ((u_int64_t)sd->sd_map->dm_segs[i].ds_addr) &
        !          1489:                            0xffffffff;
        !          1490:                        fxd->frag_addrhi =
        !          1491:                            ((u_int64_t)sd->sd_map->dm_segs[i].ds_addr) >>
        !          1492:                            32;
        !          1493:                        fxd->frag_rsvd2 = 0;
        !          1494:
        !          1495:                        bus_dmamap_sync(sc->sc_dmat,
        !          1496:                            sc->sc_txhiring_dma.dma_map,
        !          1497:                            prod * sizeof(struct txp_frag_desc),
        !          1498:                            sizeof(struct txp_frag_desc), BUS_DMASYNC_PREWRITE);
        !          1499:
        !          1500:                        if (++prod == TX_ENTRIES) {
        !          1501:                                fxd = (struct txp_frag_desc *)r->r_desc;
        !          1502:                                prod = 0;
        !          1503:                        } else
        !          1504:                                fxd++;
        !          1505:
        !          1506:                }
        !          1507:
        !          1508:                /*
        !          1509:                 * if mnew isn't NULL, we already dequeued and copied
        !          1510:                 * the packet.
        !          1511:                 */
        !          1512:                if (mnew == NULL)
        !          1513:                        IFQ_DEQUEUE(&ifp->if_snd, m);
        !          1514:
        !          1515:                ifp->if_timer = 5;
        !          1516:
        !          1517: #if NBPFILTER > 0
        !          1518:                if (ifp->if_bpf)
        !          1519:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
        !          1520: #endif
        !          1521:
        !          1522:                txd->tx_flags |= TX_FLAGS_VALID;
        !          1523:                bus_dmamap_sync(sc->sc_dmat, sc->sc_txhiring_dma.dma_map,
        !          1524:                    txdidx * sizeof(struct txp_tx_desc),
        !          1525:                    sizeof(struct txp_tx_desc), BUS_DMASYNC_PREWRITE);
        !          1526:
        !          1527: #if 0
        !          1528:                {
        !          1529:                        struct mbuf *mx;
        !          1530:                        int i;
        !          1531:
        !          1532:                        printf("txd: flags 0x%x ndesc %d totlen %d pflags 0x%x\n",
        !          1533:                            txd->tx_flags, txd->tx_numdesc, txd->tx_totlen,
        !          1534:                            txd->tx_pflags);
        !          1535:                        for (mx = m; mx != NULL; mx = mx->m_next) {
        !          1536:                                for (i = 0; i < mx->m_len; i++) {
        !          1537:                                        printf(":%02x",
        !          1538:                                            (u_int8_t)m->m_data[i]);
        !          1539:                                }
        !          1540:                        }
        !          1541:                        printf("\n");
        !          1542:                }
        !          1543: #endif
        !          1544:
        !          1545:                WRITE_REG(sc, r->r_reg, TXP_IDX2OFFSET(prod));
        !          1546:        }
        !          1547:
        !          1548:        r->r_prod = prod;
        !          1549:        r->r_cnt = cnt;
        !          1550:        return;
        !          1551:
        !          1552: oactive:
        !          1553:        bus_dmamap_unload(sc->sc_dmat, sd->sd_map);
        !          1554: oactive1:
        !          1555:        ifp->if_flags |= IFF_OACTIVE;
        !          1556:        r->r_prod = firstprod;
        !          1557:        r->r_cnt = firstcnt;
        !          1558: }
        !          1559:
        !          1560: /*
        !          1561:  * Handle simple commands sent to the typhoon
        !          1562:  */
        !          1563: int
        !          1564: txp_command(sc, id, in1, in2, in3, out1, out2, out3, wait)
        !          1565:        struct txp_softc *sc;
        !          1566:        u_int16_t id, in1, *out1;
        !          1567:        u_int32_t in2, in3, *out2, *out3;
        !          1568:        int wait;
        !          1569: {
        !          1570:        struct txp_rsp_desc *rsp = NULL;
        !          1571:
        !          1572:        if (txp_command2(sc, id, in1, in2, in3, NULL, 0, &rsp, wait))
        !          1573:                return (-1);
        !          1574:
        !          1575:        if (!wait)
        !          1576:                return (0);
        !          1577:
        !          1578:        if (out1 != NULL)
        !          1579:                *out1 = letoh16(rsp->rsp_par1);
        !          1580:        if (out2 != NULL)
        !          1581:                *out2 = letoh32(rsp->rsp_par2);
        !          1582:        if (out3 != NULL)
        !          1583:                *out3 = letoh32(rsp->rsp_par3);
        !          1584:        free(rsp, M_DEVBUF);
        !          1585:        return (0);
        !          1586: }
        !          1587:
        !          1588: int
        !          1589: txp_command2(sc, id, in1, in2, in3, in_extp, in_extn, rspp, wait)
        !          1590:        struct txp_softc *sc;
        !          1591:        u_int16_t id, in1;
        !          1592:        u_int32_t in2, in3;
        !          1593:        struct txp_ext_desc *in_extp;
        !          1594:        u_int8_t in_extn;
        !          1595:        struct txp_rsp_desc **rspp;
        !          1596:        int wait;
        !          1597: {
        !          1598:        struct txp_hostvar *hv = sc->sc_hostvar;
        !          1599:        struct txp_cmd_desc *cmd;
        !          1600:        struct txp_ext_desc *ext;
        !          1601:        u_int32_t idx, i;
        !          1602:        u_int16_t seq;
        !          1603:
        !          1604:        if (txp_cmd_desc_numfree(sc) < (in_extn + 1)) {
        !          1605:                printf("%s: no free cmd descriptors\n", TXP_DEVNAME(sc));
        !          1606:                return (-1);
        !          1607:        }
        !          1608:
        !          1609:        idx = sc->sc_cmdring.lastwrite;
        !          1610:        cmd = (struct txp_cmd_desc *)(((u_int8_t *)sc->sc_cmdring.base) + idx);
        !          1611:        bzero(cmd, sizeof(*cmd));
        !          1612:
        !          1613:        cmd->cmd_numdesc = in_extn;
        !          1614:        seq = sc->sc_seq++;
        !          1615:        cmd->cmd_seq = htole16(seq);
        !          1616:        cmd->cmd_id = htole16(id);
        !          1617:        cmd->cmd_par1 = htole16(in1);
        !          1618:        cmd->cmd_par2 = htole32(in2);
        !          1619:        cmd->cmd_par3 = htole32(in3);
        !          1620:        cmd->cmd_flags = CMD_FLAGS_TYPE_CMD |
        !          1621:            (wait ? CMD_FLAGS_RESP : 0) | CMD_FLAGS_VALID;
        !          1622:
        !          1623:        idx += sizeof(struct txp_cmd_desc);
        !          1624:        if (idx == sc->sc_cmdring.size)
        !          1625:                idx = 0;
        !          1626:
        !          1627:        for (i = 0; i < in_extn; i++) {
        !          1628:                ext = (struct txp_ext_desc *)(((u_int8_t *)sc->sc_cmdring.base) + idx);
        !          1629:                bcopy(in_extp, ext, sizeof(struct txp_ext_desc));
        !          1630:                in_extp++;
        !          1631:                idx += sizeof(struct txp_cmd_desc);
        !          1632:                if (idx == sc->sc_cmdring.size)
        !          1633:                        idx = 0;
        !          1634:        }
        !          1635:
        !          1636:        sc->sc_cmdring.lastwrite = idx;
        !          1637:
        !          1638:        WRITE_REG(sc, TXP_H2A_2, sc->sc_cmdring.lastwrite);
        !          1639:        bus_dmamap_sync(sc->sc_dmat, sc->sc_host_dma.dma_map, 0,
        !          1640:            sizeof(struct txp_hostvar), BUS_DMASYNC_PREREAD);
        !          1641:
        !          1642:        if (!wait)
        !          1643:                return (0);
        !          1644:
        !          1645:        for (i = 0; i < 10000; i++) {
        !          1646:                bus_dmamap_sync(sc->sc_dmat, sc->sc_host_dma.dma_map, 0,
        !          1647:                    sizeof(struct txp_hostvar), BUS_DMASYNC_POSTREAD);
        !          1648:                idx = letoh32(hv->hv_resp_read_idx);
        !          1649:                if (idx != letoh32(hv->hv_resp_write_idx)) {
        !          1650:                        *rspp = NULL;
        !          1651:                        if (txp_response(sc, idx, id, seq, rspp))
        !          1652:                                return (-1);
        !          1653:                        if (*rspp != NULL)
        !          1654:                                break;
        !          1655:                }
        !          1656:                bus_dmamap_sync(sc->sc_dmat, sc->sc_host_dma.dma_map, 0,
        !          1657:                    sizeof(struct txp_hostvar), BUS_DMASYNC_PREREAD);
        !          1658:                DELAY(50);
        !          1659:        }
        !          1660:        if (i == 1000 || (*rspp) == NULL) {
        !          1661:                printf("%s: 0x%x command failed\n", TXP_DEVNAME(sc), id);
        !          1662:                return (-1);
        !          1663:        }
        !          1664:
        !          1665:        return (0);
        !          1666: }
        !          1667:
        !          1668: int
        !          1669: txp_response(sc, ridx, id, seq, rspp)
        !          1670:        struct txp_softc *sc;
        !          1671:        u_int32_t ridx;
        !          1672:        u_int16_t id;
        !          1673:        u_int16_t seq;
        !          1674:        struct txp_rsp_desc **rspp;
        !          1675: {
        !          1676:        struct txp_hostvar *hv = sc->sc_hostvar;
        !          1677:        struct txp_rsp_desc *rsp;
        !          1678:
        !          1679:        while (ridx != letoh32(hv->hv_resp_write_idx)) {
        !          1680:                rsp = (struct txp_rsp_desc *)(((u_int8_t *)sc->sc_rspring.base) + ridx);
        !          1681:
        !          1682:                if (id == letoh16(rsp->rsp_id) && letoh16(rsp->rsp_seq) == seq) {
        !          1683:                        *rspp = (struct txp_rsp_desc *)malloc(
        !          1684:                            sizeof(struct txp_rsp_desc) * (rsp->rsp_numdesc + 1),
        !          1685:                            M_DEVBUF, M_NOWAIT);
        !          1686:                        if ((*rspp) == NULL)
        !          1687:                                return (-1);
        !          1688:                        txp_rsp_fixup(sc, rsp, *rspp);
        !          1689:                        return (0);
        !          1690:                }
        !          1691:
        !          1692:                if (rsp->rsp_flags & RSP_FLAGS_ERROR) {
        !          1693:                        printf("%s: response error: id 0x%x\n",
        !          1694:                            TXP_DEVNAME(sc), letoh16(rsp->rsp_id));
        !          1695:                        txp_rsp_fixup(sc, rsp, NULL);
        !          1696:                        ridx = letoh32(hv->hv_resp_read_idx);
        !          1697:                        continue;
        !          1698:                }
        !          1699:
        !          1700:                switch (letoh16(rsp->rsp_id)) {
        !          1701:                case TXP_CMD_CYCLE_STATISTICS:
        !          1702:                case TXP_CMD_MEDIA_STATUS_READ:
        !          1703:                        break;
        !          1704:                case TXP_CMD_HELLO_RESPONSE:
        !          1705:                        printf("%s: hello\n", TXP_DEVNAME(sc));
        !          1706:                        break;
        !          1707:                default:
        !          1708:                        printf("%s: unknown id(0x%x)\n", TXP_DEVNAME(sc),
        !          1709:                            letoh16(rsp->rsp_id));
        !          1710:                }
        !          1711:
        !          1712:                txp_rsp_fixup(sc, rsp, NULL);
        !          1713:                ridx = letoh32(hv->hv_resp_read_idx);
        !          1714:                hv->hv_resp_read_idx = letoh32(ridx);
        !          1715:        }
        !          1716:
        !          1717:        return (0);
        !          1718: }
        !          1719:
        !          1720: void
        !          1721: txp_rsp_fixup(sc, rsp, dst)
        !          1722:        struct txp_softc *sc;
        !          1723:        struct txp_rsp_desc *rsp, *dst;
        !          1724: {
        !          1725:        struct txp_rsp_desc *src = rsp;
        !          1726:        struct txp_hostvar *hv = sc->sc_hostvar;
        !          1727:        u_int32_t i, ridx;
        !          1728:
        !          1729:        ridx = letoh32(hv->hv_resp_read_idx);
        !          1730:
        !          1731:        for (i = 0; i < rsp->rsp_numdesc + 1; i++) {
        !          1732:                if (dst != NULL)
        !          1733:                        bcopy(src, dst++, sizeof(struct txp_rsp_desc));
        !          1734:                ridx += sizeof(struct txp_rsp_desc);
        !          1735:                if (ridx == sc->sc_rspring.size) {
        !          1736:                        src = sc->sc_rspring.base;
        !          1737:                        ridx = 0;
        !          1738:                } else
        !          1739:                        src++;
        !          1740:                sc->sc_rspring.lastwrite = ridx;
        !          1741:                hv->hv_resp_read_idx = htole32(ridx);
        !          1742:        }
        !          1743:
        !          1744:        hv->hv_resp_read_idx = htole32(ridx);
        !          1745: }
        !          1746:
        !          1747: int
        !          1748: txp_cmd_desc_numfree(sc)
        !          1749:        struct txp_softc *sc;
        !          1750: {
        !          1751:        struct txp_hostvar *hv = sc->sc_hostvar;
        !          1752:        struct txp_boot_record *br = sc->sc_boot;
        !          1753:        u_int32_t widx, ridx, nfree;
        !          1754:
        !          1755:        widx = sc->sc_cmdring.lastwrite;
        !          1756:        ridx = letoh32(hv->hv_cmd_read_idx);
        !          1757:
        !          1758:        if (widx == ridx) {
        !          1759:                /* Ring is completely free */
        !          1760:                nfree = letoh32(br->br_cmd_siz) - sizeof(struct txp_cmd_desc);
        !          1761:        } else {
        !          1762:                if (widx > ridx)
        !          1763:                        nfree = letoh32(br->br_cmd_siz) -
        !          1764:                            (widx - ridx + sizeof(struct txp_cmd_desc));
        !          1765:                else
        !          1766:                        nfree = ridx - widx - sizeof(struct txp_cmd_desc);
        !          1767:        }
        !          1768:
        !          1769:        return (nfree / sizeof(struct txp_cmd_desc));
        !          1770: }
        !          1771:
        !          1772: void
        !          1773: txp_stop(sc)
        !          1774:        struct txp_softc *sc;
        !          1775: {
        !          1776:        txp_command(sc, TXP_CMD_TX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 1);
        !          1777:        txp_command(sc, TXP_CMD_RX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 1);
        !          1778:
        !          1779:        if (timeout_pending(&sc->sc_tick))
        !          1780:                timeout_del(&sc->sc_tick);
        !          1781: }
        !          1782:
        !          1783: void
        !          1784: txp_watchdog(ifp)
        !          1785:        struct ifnet *ifp;
        !          1786: {
        !          1787: }
        !          1788:
        !          1789: int
        !          1790: txp_ifmedia_upd(ifp)
        !          1791:        struct ifnet *ifp;
        !          1792: {
        !          1793:        struct txp_softc *sc = ifp->if_softc;
        !          1794:        struct ifmedia *ifm = &sc->sc_ifmedia;
        !          1795:        u_int16_t new_xcvr;
        !          1796:
        !          1797:        if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
        !          1798:                return (EINVAL);
        !          1799:
        !          1800:        if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) {
        !          1801:                if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
        !          1802:                        new_xcvr = TXP_XCVR_10_FDX;
        !          1803:                else
        !          1804:                        new_xcvr = TXP_XCVR_10_HDX;
        !          1805:        } else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
        !          1806:                if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
        !          1807:                        new_xcvr = TXP_XCVR_100_FDX;
        !          1808:                else
        !          1809:                        new_xcvr = TXP_XCVR_100_HDX;
        !          1810:        } else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
        !          1811:                new_xcvr = TXP_XCVR_AUTO;
        !          1812:        } else
        !          1813:                return (EINVAL);
        !          1814:
        !          1815:        /* nothing to do */
        !          1816:        if (sc->sc_xcvr == new_xcvr)
        !          1817:                return (0);
        !          1818:
        !          1819:        txp_command(sc, TXP_CMD_XCVR_SELECT, new_xcvr, 0, 0,
        !          1820:            NULL, NULL, NULL, 0);
        !          1821:        sc->sc_xcvr = new_xcvr;
        !          1822:
        !          1823:        return (0);
        !          1824: }
        !          1825:
        !          1826: void
        !          1827: txp_ifmedia_sts(ifp, ifmr)
        !          1828:        struct ifnet *ifp;
        !          1829:        struct ifmediareq *ifmr;
        !          1830: {
        !          1831:        struct txp_softc *sc = ifp->if_softc;
        !          1832:        struct ifmedia *ifm = &sc->sc_ifmedia;
        !          1833:        u_int16_t bmsr, bmcr, anlpar;
        !          1834:
        !          1835:        ifmr->ifm_status = IFM_AVALID;
        !          1836:        ifmr->ifm_active = IFM_ETHER;
        !          1837:
        !          1838:        if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMSR, 0,
        !          1839:            &bmsr, NULL, NULL, 1))
        !          1840:                goto bail;
        !          1841:        if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMSR, 0,
        !          1842:            &bmsr, NULL, NULL, 1))
        !          1843:                goto bail;
        !          1844:
        !          1845:        if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMCR, 0,
        !          1846:            &bmcr, NULL, NULL, 1))
        !          1847:                goto bail;
        !          1848:
        !          1849:        if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_ANLPAR, 0,
        !          1850:            &anlpar, NULL, NULL, 1))
        !          1851:                goto bail;
        !          1852:
        !          1853:        if (bmsr & BMSR_LINK)
        !          1854:                ifmr->ifm_status |= IFM_ACTIVE;
        !          1855:
        !          1856:        if (bmcr & BMCR_ISO) {
        !          1857:                ifmr->ifm_active |= IFM_NONE;
        !          1858:                ifmr->ifm_status = 0;
        !          1859:                return;
        !          1860:        }
        !          1861:
        !          1862:        if (bmcr & BMCR_LOOP)
        !          1863:                ifmr->ifm_active |= IFM_LOOP;
        !          1864:
        !          1865:        if (bmcr & BMCR_AUTOEN) {
        !          1866:                if ((bmsr & BMSR_ACOMP) == 0) {
        !          1867:                        ifmr->ifm_active |= IFM_NONE;
        !          1868:                        return;
        !          1869:                }
        !          1870:
        !          1871:                if (anlpar & ANLPAR_T4)
        !          1872:                        ifmr->ifm_active |= IFM_100_T4;
        !          1873:                else if (anlpar & ANLPAR_TX_FD)
        !          1874:                        ifmr->ifm_active |= IFM_100_TX|IFM_FDX;
        !          1875:                else if (anlpar & ANLPAR_TX)
        !          1876:                        ifmr->ifm_active |= IFM_100_TX;
        !          1877:                else if (anlpar & ANLPAR_10_FD)
        !          1878:                        ifmr->ifm_active |= IFM_10_T|IFM_FDX;
        !          1879:                else if (anlpar & ANLPAR_10)
        !          1880:                        ifmr->ifm_active |= IFM_10_T;
        !          1881:                else
        !          1882:                        ifmr->ifm_active |= IFM_NONE;
        !          1883:        } else
        !          1884:                ifmr->ifm_active = ifm->ifm_cur->ifm_media;
        !          1885:        return;
        !          1886:
        !          1887: bail:
        !          1888:        ifmr->ifm_active |= IFM_NONE;
        !          1889:        ifmr->ifm_status &= ~IFM_AVALID;
        !          1890: }
        !          1891:
        !          1892: void
        !          1893: txp_show_descriptor(d)
        !          1894:        void *d;
        !          1895: {
        !          1896:        struct txp_cmd_desc *cmd = d;
        !          1897:        struct txp_rsp_desc *rsp = d;
        !          1898:        struct txp_tx_desc *txd = d;
        !          1899:        struct txp_frag_desc *frgd = d;
        !          1900:
        !          1901:        switch (cmd->cmd_flags & CMD_FLAGS_TYPE_M) {
        !          1902:        case CMD_FLAGS_TYPE_CMD:
        !          1903:                /* command descriptor */
        !          1904:                printf("[cmd flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n",
        !          1905:                    cmd->cmd_flags, cmd->cmd_numdesc, letoh16(cmd->cmd_id),
        !          1906:                    letoh16(cmd->cmd_seq), letoh16(cmd->cmd_par1),
        !          1907:                    letoh32(cmd->cmd_par2), letoh32(cmd->cmd_par3));
        !          1908:                break;
        !          1909:        case CMD_FLAGS_TYPE_RESP:
        !          1910:                /* response descriptor */
        !          1911:                printf("[rsp flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n",
        !          1912:                    rsp->rsp_flags, rsp->rsp_numdesc, letoh16(rsp->rsp_id),
        !          1913:                    letoh16(rsp->rsp_seq), letoh16(rsp->rsp_par1),
        !          1914:                    letoh32(rsp->rsp_par2), letoh32(rsp->rsp_par3));
        !          1915:                break;
        !          1916:        case CMD_FLAGS_TYPE_DATA:
        !          1917:                /* data header (assuming tx for now) */
        !          1918:                printf("[data flags 0x%x num %d totlen %d addr 0x%x/0x%x pflags 0x%x]",
        !          1919:                    txd->tx_flags, txd->tx_numdesc, txd->tx_totlen,
        !          1920:                    txd->tx_addrlo, txd->tx_addrhi, txd->tx_pflags);
        !          1921:                break;
        !          1922:        case CMD_FLAGS_TYPE_FRAG:
        !          1923:                /* fragment descriptor */
        !          1924:                printf("[frag flags 0x%x rsvd1 0x%x len %d addr 0x%x/0x%x rsvd2 0x%x]",
        !          1925:                    frgd->frag_flags, frgd->frag_rsvd1, frgd->frag_len,
        !          1926:                    frgd->frag_addrlo, frgd->frag_addrhi, frgd->frag_rsvd2);
        !          1927:                break;
        !          1928:        default:
        !          1929:                printf("[unknown(%x) flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n",
        !          1930:                    cmd->cmd_flags & CMD_FLAGS_TYPE_M,
        !          1931:                    cmd->cmd_flags, cmd->cmd_numdesc, letoh16(cmd->cmd_id),
        !          1932:                    letoh16(cmd->cmd_seq), letoh16(cmd->cmd_par1),
        !          1933:                    letoh32(cmd->cmd_par2), letoh32(cmd->cmd_par3));
        !          1934:                break;
        !          1935:        }
        !          1936: }
        !          1937:
        !          1938: void
        !          1939: txp_set_filter(sc)
        !          1940:        struct txp_softc *sc;
        !          1941: {
        !          1942:        struct arpcom *ac = &sc->sc_arpcom;
        !          1943:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1944:        u_int32_t hashbit, hash[2];
        !          1945:        u_int16_t filter;
        !          1946:        int mcnt = 0;
        !          1947:        struct ether_multi *enm;
        !          1948:        struct ether_multistep step;
        !          1949:
        !          1950:        if (ifp->if_flags & IFF_PROMISC) {
        !          1951:                filter = TXP_RXFILT_PROMISC;
        !          1952:                goto setit;
        !          1953:        }
        !          1954:
        !          1955: again:
        !          1956:        filter = TXP_RXFILT_DIRECT;
        !          1957:
        !          1958:        if (ifp->if_flags & IFF_BROADCAST)
        !          1959:                filter |= TXP_RXFILT_BROADCAST;
        !          1960:
        !          1961:        if (ifp->if_flags & IFF_ALLMULTI)
        !          1962:                filter |= TXP_RXFILT_ALLMULTI;
        !          1963:        else {
        !          1964:                hash[0] = hash[1] = 0;
        !          1965:
        !          1966:                ETHER_FIRST_MULTI(step, ac, enm);
        !          1967:                while (enm != NULL) {
        !          1968:                        if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !          1969:                                /*
        !          1970:                                 * We must listen to a range of multicast
        !          1971:                                 * addresses.  For now, just accept all
        !          1972:                                 * multicasts, rather than trying to set only
        !          1973:                                 * those filter bits needed to match the range.
        !          1974:                                 * (At this time, the only use of address
        !          1975:                                 * ranges is for IP multicast routing, for
        !          1976:                                 * which the range is big enough to require
        !          1977:                                 * all bits set.)
        !          1978:                                 */
        !          1979:                                ifp->if_flags |= IFF_ALLMULTI;
        !          1980:                                goto again;
        !          1981:                        }
        !          1982:
        !          1983:                        mcnt++;
        !          1984:                        hashbit = (u_int16_t)(ether_crc32_be(enm->enm_addrlo,
        !          1985:                            ETHER_ADDR_LEN) & (64 - 1));
        !          1986:                        hash[hashbit / 32] |= (1 << hashbit % 32);
        !          1987:                        ETHER_NEXT_MULTI(step, enm);
        !          1988:                }
        !          1989:
        !          1990:                if (mcnt > 0) {
        !          1991:                        filter |= TXP_RXFILT_HASHMULTI;
        !          1992:                        txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE,
        !          1993:                            2, hash[0], hash[1], NULL, NULL, NULL, 0);
        !          1994:                }
        !          1995:        }
        !          1996:
        !          1997: setit:
        !          1998:        txp_command(sc, TXP_CMD_RX_FILTER_WRITE, filter, 0, 0,
        !          1999:            NULL, NULL, NULL, 1);
        !          2000: }
        !          2001:
        !          2002: void
        !          2003: txp_capabilities(sc)
        !          2004:        struct txp_softc *sc;
        !          2005: {
        !          2006:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          2007:        struct txp_rsp_desc *rsp = NULL;
        !          2008:        struct txp_ext_desc *ext;
        !          2009:
        !          2010:        if (txp_command2(sc, TXP_CMD_OFFLOAD_READ, 0, 0, 0, NULL, 0, &rsp, 1))
        !          2011:                goto out;
        !          2012:
        !          2013:        if (rsp->rsp_numdesc != 1)
        !          2014:                goto out;
        !          2015:        ext = (struct txp_ext_desc *)(rsp + 1);
        !          2016:
        !          2017:        sc->sc_tx_capability = ext->ext_1 & OFFLOAD_MASK;
        !          2018:        sc->sc_rx_capability = ext->ext_2 & OFFLOAD_MASK;
        !          2019:
        !          2020:        ifp->if_capabilities |= IFCAP_VLAN_MTU;
        !          2021:
        !          2022: #if NVLAN > 0
        !          2023:        if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_VLAN) {
        !          2024:                sc->sc_tx_capability |= OFFLOAD_VLAN;
        !          2025:                ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
        !          2026:        }
        !          2027: #endif
        !          2028:
        !          2029: #if 0
        !          2030:        /* not ready yet */
        !          2031:        if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_IPSEC) {
        !          2032:                sc->sc_tx_capability |= OFFLOAD_IPSEC;
        !          2033:                sc->sc_rx_capability |= OFFLOAD_IPSEC;
        !          2034:                ifp->if_capabilities |= IFCAP_IPSEC;
        !          2035:        }
        !          2036: #endif
        !          2037:
        !          2038:        if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_IPCKSUM) {
        !          2039:                sc->sc_tx_capability |= OFFLOAD_IPCKSUM;
        !          2040:                sc->sc_rx_capability |= OFFLOAD_IPCKSUM;
        !          2041:                ifp->if_capabilities |= IFCAP_CSUM_IPv4;
        !          2042:        }
        !          2043:
        !          2044:        if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_TCPCKSUM) {
        !          2045:                sc->sc_rx_capability |= OFFLOAD_TCPCKSUM;
        !          2046: #ifdef TRY_TX_TCP_CSUM
        !          2047:                sc->sc_tx_capability |= OFFLOAD_TCPCKSUM;
        !          2048:                ifp->if_capabilities |= IFCAP_CSUM_TCPv4;
        !          2049: #endif
        !          2050:        }
        !          2051:
        !          2052:        if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_UDPCKSUM) {
        !          2053:                sc->sc_rx_capability |= OFFLOAD_UDPCKSUM;
        !          2054: #ifdef TRY_TX_UDP_CSUM
        !          2055:                sc->sc_tx_capability |= OFFLOAD_UDPCKSUM;
        !          2056:                ifp->if_capabilities |= IFCAP_CSUM_UDPv4;
        !          2057: #endif
        !          2058:        }
        !          2059:
        !          2060:        if (txp_command(sc, TXP_CMD_OFFLOAD_WRITE, 0,
        !          2061:            sc->sc_tx_capability, sc->sc_rx_capability, NULL, NULL, NULL, 1))
        !          2062:                goto out;
        !          2063:
        !          2064: out:
        !          2065:        if (rsp != NULL)
        !          2066:                free(rsp, M_DEVBUF);
        !          2067: }

CVSweb