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

Annotation of sys/dev/pci/if_vic.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_vic.c,v 1.49 2007/06/15 02:29:50 dlg Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org>
                      5:  * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
                     20: /*
                     21:  * Driver for the VMware Virtual NIC ("vmxnet")
                     22:  */
                     23:
                     24: #include "bpfilter.h"
                     25:
                     26: #include <sys/param.h>
                     27: #include <sys/systm.h>
                     28: #include <sys/sockio.h>
                     29: #include <sys/mbuf.h>
                     30: #include <sys/kernel.h>
                     31: #include <sys/socket.h>
                     32: #include <sys/malloc.h>
                     33: #include <sys/timeout.h>
                     34: #include <sys/device.h>
                     35:
                     36: #include <machine/bus.h>
                     37: #include <machine/intr.h>
                     38:
                     39: #include <net/if.h>
                     40: #include <net/if_dl.h>
                     41: #include <net/if_media.h>
                     42: #include <net/if_types.h>
                     43:
                     44: #if NBPFILTER > 0
                     45: #include <net/bpf.h>
                     46: #endif
                     47:
                     48: #ifdef INET
                     49: #include <netinet/in.h>
                     50: #include <netinet/if_ether.h>
                     51: #endif
                     52:
                     53: #include <dev/pci/pcireg.h>
                     54: #include <dev/pci/pcivar.h>
                     55: #include <dev/pci/pcidevs.h>
                     56:
                     57: #define VIC_PCI_BAR            PCI_MAPREG_START /* Base Address Register */
                     58:
                     59: #define VIC_MAGIC              0xbabe864f
                     60:
                     61: /* Register address offsets */
                     62: #define VIC_DATA_ADDR          0x0000          /* Shared data address */
                     63: #define VIC_DATA_LENGTH                0x0004          /* Shared data length */
                     64: #define VIC_Tx_ADDR            0x0008          /* Tx pointer address */
                     65:
                     66: /* Command register */
                     67: #define VIC_CMD                        0x000c          /* Command register */
                     68: #define  VIC_CMD_INTR_ACK      0x0001  /* Acknowledge interrupt */
                     69: #define  VIC_CMD_MCASTFIL      0x0002  /* Multicast address filter */
                     70: #define   VIC_CMD_MCASTFIL_LENGTH      2
                     71: #define  VIC_CMD_IFF           0x0004  /* Interface flags */
                     72: #define   VIC_CMD_IFF_PROMISC  0x0001          /* Promiscous enabled */
                     73: #define   VIC_CMD_IFF_BROADCAST        0x0002          /* Broadcast enabled */
                     74: #define   VIC_CMD_IFF_MULTICAST        0x0004          /* Multicast enabled */
                     75: #define  VIC_CMD_INTR_DISABLE  0x0020  /* Enable interrupts */
                     76: #define  VIC_CMD_INTR_ENABLE   0x0040  /* Disable interrupts */
                     77: #define  VIC_CMD_Tx_DONE       0x0100  /* Tx done register */
                     78: #define  VIC_CMD_NUM_Rx_BUF    0x0200  /* Number of Rx buffers */
                     79: #define  VIC_CMD_NUM_Tx_BUF    0x0400  /* Number of Tx buffers */
                     80: #define  VIC_CMD_NUM_PINNED_BUF        0x0800  /* Number of pinned buffers */
                     81: #define  VIC_CMD_HWCAP         0x1000  /* Capability register */
                     82: #define   VIC_CMD_HWCAP_SG             (1<<0) /* Scatter-gather transmits */
                     83: #define   VIC_CMD_HWCAP_CSUM_IPv4      (1<<1) /* TCP/UDP cksum */
                     84: #define   VIC_CMD_HWCAP_CSUM_ALL       (1<<3) /* Hardware cksum */
                     85: #define   VIC_CMD_HWCAP_CSUM \
                     86:        (VIC_CMD_HWCAP_CSUM_IPv4 | VIC_CMD_HWCAP_CSUM_ALL)
                     87: #define   VIC_CMD_HWCAP_DMA_HIGH               (1<<4) /* High DMA mapping */
                     88: #define   VIC_CMD_HWCAP_TOE            (1<<5) /* TCP offload engine */
                     89: #define   VIC_CMD_HWCAP_TSO            (1<<6) /* TCP segmentation offload */
                     90: #define   VIC_CMD_HWCAP_TSO_SW         (1<<7) /* Software TCP segmentation */
                     91: #define   VIC_CMD_HWCAP_VPROM          (1<<8) /* Virtual PROM available */
                     92: #define   VIC_CMD_HWCAP_VLAN_Tx                (1<<9) /* Hardware VLAN MTU Rx */
                     93: #define   VIC_CMD_HWCAP_VLAN_Rx                (1<<10) /* Hardware VLAN MTU Tx */
                     94: #define   VIC_CMD_HWCAP_VLAN_SW                (1<<11) /* Software VLAN MTU */
                     95: #define   VIC_CMD_HWCAP_VLAN \
                     96:        (VIC_CMD_HWCAP_VLAN_Tx | VIC_CMD_HWCAP_VLAN_Rx | \
                     97:        VIC_CMD_HWCAP_VLAN_SW)
                     98: #define  VIC_CMD_HWCAP_BITS \
                     99:        "\20\01SG\02CSUM4\03CSUM\04HDMA\05TOE\06TSO" \
                    100:        "\07TSOSW\10VPROM\13VLANTx\14VLANRx\15VLANSW"
                    101: #define  VIC_CMD_FEATURE       0x2000  /* Additional feature register */
                    102: #define   VIC_CMD_FEATURE_0_Tx         (1<<0)
                    103: #define   VIC_CMD_FEATURE_TSO          (1<<1)
                    104:
                    105: #define VIC_LLADDR             0x0010          /* MAC address register */
                    106: #define VIC_VERSION_MINOR      0x0018          /* Minor version register */
                    107: #define VIC_VERSION_MAJOR      0x001c          /* Major version register */
                    108: #define VIC_VERSION_MAJOR_M    0xffff0000
                    109:
                    110: /* Status register */
                    111: #define VIC_STATUS             0x0020
                    112: #define  VIC_STATUS_CONNECTED          (1<<0)
                    113: #define  VIC_STATUS_ENABLED            (1<<1)
                    114:
                    115: #define VIC_TOE_ADDR           0x0024          /* TCP offload address */
                    116:
                    117: /* Virtual PROM address */
                    118: #define VIC_VPROM              0x0028
                    119: #define VIC_VPROM_LENGTH       6
                    120:
                    121: /* Shared DMA data structures */
                    122:
                    123: struct vic_sg {
                    124:        u_int32_t       sg_addr_low;
                    125:        u_int16_t       sg_addr_high;
                    126:        u_int16_t       sg_length;
                    127: } __packed;
                    128:
                    129: #define VIC_SG_MAX             6
                    130: #define VIC_SG_ADDR_MACH       0
                    131: #define VIC_SG_ADDR_PHYS       1
                    132: #define VIC_SG_ADDR_VIRT       3
                    133:
                    134: struct vic_sgarray {
                    135:        u_int16_t       sa_addr_type;
                    136:        u_int16_t       sa_length;
                    137:        struct vic_sg   sa_sg[VIC_SG_MAX];
                    138: } __packed;
                    139:
                    140: struct vic_rxdesc {
                    141:        u_int64_t       rx_physaddr;
                    142:        u_int32_t       rx_buflength;
                    143:        u_int32_t       rx_length;
                    144:        u_int16_t       rx_owner;
                    145:        u_int16_t       rx_flags;
                    146:        u_int32_t       rx_priv;
                    147: } __packed;
                    148:
                    149: #define VIC_RX_FLAGS_CSUMHW_OK 0x0001
                    150:
                    151: struct vic_txdesc {
                    152:        u_int16_t               tx_flags;
                    153:        u_int16_t               tx_owner;
                    154:        u_int32_t               tx_priv;
                    155:        u_int32_t               tx_tsomss;
                    156:        struct vic_sgarray      tx_sa;
                    157: } __packed;
                    158:
                    159: #define VIC_TX_FLAGS_KEEP      0x0001
                    160: #define VIC_TX_FLAGS_TXURN     0x0002
                    161: #define VIC_TX_FLAGS_CSUMHW    0x0004
                    162: #define VIC_TX_FLAGS_TSO       0x0008
                    163: #define VIC_TX_FLAGS_PINNED    0x0010
                    164: #define VIC_TX_FLAGS_QRETRY    0x1000
                    165:
                    166: struct vic_stats {
                    167:        u_int32_t               vs_tx_count;
                    168:        u_int32_t               vs_tx_packets;
                    169:        u_int32_t               vs_tx_0copy;
                    170:        u_int32_t               vs_tx_copy;
                    171:        u_int32_t               vs_tx_maxpending;
                    172:        u_int32_t               vs_tx_stopped;
                    173:        u_int32_t               vs_tx_overrun;
                    174:        u_int32_t               vs_intr;
                    175:        u_int32_t               vs_rx_packets;
                    176:        u_int32_t               vs_rx_underrun;
                    177: } __packed;
                    178:
                    179: struct vic_data {
                    180:        u_int32_t               vd_magic;
                    181:
                    182:        u_int32_t               vd_rx_length;
                    183:        u_int32_t               vd_rx_nextidx;
                    184:        u_int32_t               vd_rx_length2;
                    185:        u_int32_t               vd_rx_nextidx2;
                    186:
                    187:        u_int32_t               vd_irq;
                    188:        u_int32_t               vd_iff;
                    189:
                    190:        u_int32_t               vd_mcastfil[VIC_CMD_MCASTFIL_LENGTH];
                    191:
                    192:        u_int32_t               vd_reserved1[1];
                    193:
                    194:        u_int32_t               vd_tx_length;
                    195:        u_int32_t               vd_tx_curidx;
                    196:        u_int32_t               vd_tx_nextidx;
                    197:        u_int32_t               vd_tx_stopped;
                    198:        u_int32_t               vd_tx_triggerlvl;
                    199:        u_int32_t               vd_tx_queued;
                    200:        u_int32_t               vd_tx_minlength;
                    201:
                    202:        u_int32_t               vd_reserved2[6];
                    203:
                    204:        u_int32_t               vd_rx_saved_nextidx;
                    205:        u_int32_t               vd_rx_saved_nextidx2;
                    206:        u_int32_t               vd_tx_saved_nextidx;
                    207:
                    208:        u_int32_t               vd_length;
                    209:        u_int32_t               vd_rx_offset;
                    210:        u_int32_t               vd_rx_offset2;
                    211:        u_int32_t               vd_tx_offset;
                    212:        u_int32_t               vd_debug;
                    213:        u_int32_t               vd_tx_physaddr;
                    214:        u_int32_t               vd_tx_physaddr_length;
                    215:        u_int32_t               vd_tx_maxlength;
                    216:
                    217:        struct vic_stats        vd_stats;
                    218: } __packed;
                    219:
                    220: #define VIC_OWNER_DRIVER       0
                    221: #define VIC_OWNER_DRIVER_PEND  1
                    222: #define VIC_OWNER_NIC          2
                    223: #define VIC_OWNER_NIC_PEND     3
                    224:
                    225: #define VIC_JUMBO_FRAMELEN     9018
                    226: #define VIC_JUMBO_MTU          (VIC_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
                    227:
                    228: #define VIC_NBUF               100
                    229: #define VIC_NBUF_MAX           128
                    230: #define VIC_MAX_SCATTER                1       /* 8? */
                    231: #define VIC_QUEUE_SIZE         VIC_NBUF_MAX
                    232: #define VIC_QUEUE2_SIZE                1
                    233: #define VIC_INC(_x, _y)                (_x) = ((_x) + 1) % (_y)
                    234: #define VIC_TX_TIMEOUT         5
                    235:
                    236: #define VIC_MIN_FRAMELEN       (ETHER_MIN_LEN - ETHER_CRC_LEN)
                    237:
                    238: #define VIC_TXURN_WARN(_sc)    ((_sc)->sc_txpending >= ((_sc)->sc_ntxbuf - 5))
                    239: #define VIC_TXURN(_sc)         ((_sc)->sc_txpending >= (_sc)->sc_ntxbuf)
                    240:
                    241: struct vic_rxbuf {
                    242:        bus_dmamap_t            rxb_dmamap;
                    243:        struct mbuf             *rxb_m;
                    244: };
                    245:
                    246: struct vic_txbuf {
                    247:        bus_dmamap_t            txb_dmamap;
                    248:        struct mbuf             *txb_m;
                    249: };
                    250:
                    251: struct vic_softc {
                    252:        struct device           sc_dev;
                    253:
                    254:        pci_chipset_tag_t       sc_pc;
                    255:        pcitag_t                sc_tag;
                    256:
                    257:        bus_space_tag_t         sc_iot;
                    258:        bus_space_handle_t      sc_ioh;
                    259:        bus_size_t              sc_ios;
                    260:        bus_dma_tag_t           sc_dmat;
                    261:
                    262:        void                    *sc_ih;
                    263:
                    264:        struct timeout          sc_tick;
                    265:
                    266:        struct arpcom           sc_ac;
                    267:        struct ifmedia          sc_media;
                    268:
                    269:        u_int32_t               sc_nrxbuf;
                    270:        u_int32_t               sc_ntxbuf;
                    271:        u_int32_t               sc_cap;
                    272:        u_int32_t               sc_feature;
                    273:        u_int8_t                sc_lladdr[ETHER_ADDR_LEN];
                    274:
                    275:        bus_dmamap_t            sc_dma_map;
                    276:        bus_dma_segment_t       sc_dma_seg;
                    277:        size_t                  sc_dma_size;
                    278:        caddr_t                 sc_dma_kva;
                    279: #define VIC_DMA_DVA(_sc)       ((_sc)->sc_dma_map->dm_segs[0].ds_addr)
                    280: #define VIC_DMA_KVA(_sc)       ((void *)(_sc)->sc_dma_kva)
                    281:
                    282:        struct vic_data         *sc_data;
                    283:
                    284:        struct vic_rxbuf        *sc_rxbuf;
                    285:        struct vic_rxdesc       *sc_rxq;
                    286:        struct vic_rxdesc       *sc_rxq2;
                    287:
                    288:        struct vic_txbuf        *sc_txbuf;
                    289:        struct vic_txdesc       *sc_txq;
                    290:        volatile u_int          sc_txpending;
                    291: };
                    292:
                    293: struct cfdriver vic_cd = {
                    294:        0, "vic", DV_IFNET
                    295: };
                    296:
                    297: int            vic_match(struct device *, void *, void *);
                    298: void           vic_attach(struct device *, struct device *, void *);
                    299:
                    300: struct cfattach vic_ca = {
                    301:        sizeof(struct vic_softc), vic_match, vic_attach
                    302: };
                    303:
                    304: int            vic_intr(void *);
                    305: void           vic_shutdown(void *);
                    306:
                    307: int            vic_map_pci(struct vic_softc *, struct pci_attach_args *);
                    308: int            vic_query(struct vic_softc *);
                    309: int            vic_alloc_data(struct vic_softc *);
                    310: int            vic_init_data(struct vic_softc *sc);
                    311: int            vic_uninit_data(struct vic_softc *sc);
                    312:
                    313: u_int32_t      vic_read(struct vic_softc *, bus_size_t);
                    314: void           vic_write(struct vic_softc *, bus_size_t, u_int32_t);
                    315:
                    316: u_int32_t      vic_read_cmd(struct vic_softc *, u_int32_t);
                    317:
                    318: int            vic_alloc_dmamem(struct vic_softc *);
                    319: void           vic_free_dmamem(struct vic_softc *);
                    320:
                    321: void           vic_link_state(struct vic_softc *);
                    322: void           vic_rx_proc(struct vic_softc *);
                    323: void           vic_tx_proc(struct vic_softc *);
                    324: void           vic_iff(struct vic_softc *);
                    325: void           vic_getlladdr(struct vic_softc *);
                    326: void           vic_setlladdr(struct vic_softc *);
                    327: int            vic_media_change(struct ifnet *);
                    328: void           vic_media_status(struct ifnet *, struct ifmediareq *);
                    329: void           vic_start(struct ifnet *);
                    330: int            vic_load_txb(struct vic_softc *, struct vic_txbuf *,
                    331:                    struct mbuf *);
                    332: void           vic_watchdog(struct ifnet *);
                    333: int            vic_ioctl(struct ifnet *, u_long, caddr_t);
                    334: void           vic_init(struct ifnet *);
                    335: void           vic_stop(struct ifnet *);
                    336: void           vic_tick(void *);
                    337:
                    338: #define DEVNAME(_s)    ((_s)->sc_dev.dv_xname)
                    339:
                    340: struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t);
                    341:
                    342: const struct pci_matchid vic_devices[] = {
                    343:        { PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET }
                    344: };
                    345:
                    346: int
                    347: vic_match(struct device *parent, void *match, void *aux)
                    348: {
                    349:        return (pci_matchbyid((struct pci_attach_args *)aux,
                    350:            vic_devices, sizeof(vic_devices)/sizeof(vic_devices[0])));
                    351: }
                    352:
                    353: void
                    354: vic_attach(struct device *parent, struct device *self, void *aux)
                    355: {
                    356:        struct vic_softc                *sc = (struct vic_softc *)self;
                    357:        struct pci_attach_args          *pa = aux;
                    358:        struct ifnet                    *ifp;
                    359:
                    360:        if (vic_map_pci(sc, pa) != 0) {
                    361:                /* error printed by vic_map_pci */
                    362:                return;
                    363:        }
                    364:
                    365:        if (vic_query(sc) != 0) {
                    366:                /* error printed by vic_query */
                    367:                return;
                    368:        }
                    369:
                    370:        if (vic_alloc_data(sc) != 0) {
                    371:                /* error printed by vic_alloc */
                    372:                return;
                    373:        }
                    374:
                    375:        timeout_set(&sc->sc_tick, vic_tick, sc);
                    376:
                    377:        bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
                    378:
                    379:        ifp = &sc->sc_ac.ac_if;
                    380:        ifp->if_softc = sc;
                    381:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    382:        ifp->if_ioctl = vic_ioctl;
                    383:        ifp->if_start = vic_start;
                    384:        ifp->if_watchdog = vic_watchdog;
                    385:        ifp->if_hardmtu = VIC_JUMBO_MTU;
                    386:        strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
                    387:        IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_ntxbuf - 1);
                    388:        IFQ_SET_READY(&ifp->if_snd);
                    389:
                    390:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    391:
                    392: #if 0
                    393:        /* XXX interface capabilities */
                    394:        if (sc->sc_cap & VIC_CMD_HWCAP_VLAN)
                    395:                ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
                    396:        if (sc->sc_cap & VIC_CMD_HWCAP_CSUM)
                    397:                ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
                    398:                    IFCAP_CSUM_UDPv4;
                    399: #endif
                    400:
                    401:        ifmedia_init(&sc->sc_media, 0, vic_media_change, vic_media_status);
                    402:        ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
                    403:        ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
                    404:
                    405:        if_attach(ifp);
                    406:        ether_ifattach(ifp);
                    407:
                    408:        return;
                    409: }
                    410:
                    411: int
                    412: vic_map_pci(struct vic_softc *sc, struct pci_attach_args *pa)
                    413: {
                    414:        pcireg_t                        memtype;
                    415:        pci_intr_handle_t               ih;
                    416:        const char                      *intrstr;
                    417:
                    418:        sc->sc_pc = pa->pa_pc;
                    419:        sc->sc_tag = pa->pa_tag;
                    420:        sc->sc_dmat = pa->pa_dmat;
                    421:
                    422:        memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, VIC_PCI_BAR);
                    423:        if (pci_mapreg_map(pa, VIC_PCI_BAR, memtype, 0, &sc->sc_iot,
                    424:            &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
                    425:                printf(": unable to map system interface register\n");
                    426:                return (1);
                    427:        }
                    428:
                    429:        if (pci_intr_map(pa, &ih) != 0) {
                    430:                printf(": unable to map interrupt\n");
                    431:                goto unmap;
                    432:        }
                    433:
                    434:        intrstr = pci_intr_string(pa->pa_pc, ih);
                    435:        sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
                    436:            vic_intr, sc, DEVNAME(sc));
                    437:        if (sc->sc_ih == NULL) {
                    438:                printf(": unable to map interrupt%s%s\n",
                    439:                    intrstr == NULL ? "" : " at ",
                    440:                    intrstr == NULL ? "" : intrstr);
                    441:                goto unmap;
                    442:        }
                    443:        printf(": %s\n", intrstr);
                    444:
                    445:        return (0);
                    446:
                    447: unmap:
                    448:        bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
                    449:        sc->sc_ios = 0;
                    450:        return (1);
                    451: }
                    452:
                    453: int
                    454: vic_query(struct vic_softc *sc)
                    455: {
                    456:        u_int32_t                       major, minor;
                    457:
                    458:        major = vic_read(sc, VIC_VERSION_MAJOR);
                    459:        minor = vic_read(sc, VIC_VERSION_MINOR);
                    460:
                    461:        /* Check for a supported version */
                    462:        if ((major & VIC_VERSION_MAJOR_M) !=
                    463:            (VIC_MAGIC & VIC_VERSION_MAJOR_M)) {
                    464:                printf("%s: magic mismatch\n", DEVNAME(sc));
                    465:                return (1);
                    466:        }
                    467:
                    468:        if (VIC_MAGIC > major || VIC_MAGIC < minor) {
                    469:                printf("%s: unsupported version (%X)\n", DEVNAME(sc),
                    470:                    major & ~VIC_VERSION_MAJOR_M);
                    471:                return (1);
                    472:        }
                    473:
                    474:        sc->sc_nrxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Rx_BUF);
                    475:        sc->sc_ntxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Tx_BUF);
                    476:        sc->sc_feature = vic_read_cmd(sc, VIC_CMD_FEATURE);
                    477:        sc->sc_cap = vic_read_cmd(sc, VIC_CMD_HWCAP);
                    478:
                    479:        vic_getlladdr(sc);
                    480:
                    481:        printf("%s: VMXnet %04X, address %s\n", DEVNAME(sc),
                    482:            major & ~VIC_VERSION_MAJOR_M, ether_sprintf(sc->sc_lladdr));
                    483:
                    484: #ifdef VIC_DEBUG
                    485:        printf("%s: feature 0x%8x, cap 0x%8x, rx/txbuf %d/%d\n", DEVNAME(sc),
                    486:            sc->sc_feature, sc->sc_cap, sc->sc_nrxbuf, sc->sc_ntxbuf);
                    487: #endif
                    488:
                    489:        if (sc->sc_nrxbuf > VIC_NBUF_MAX || sc->sc_nrxbuf == 0)
                    490:                sc->sc_nrxbuf = VIC_NBUF;
                    491:        if (sc->sc_ntxbuf > VIC_NBUF_MAX || sc->sc_ntxbuf == 0)
                    492:                sc->sc_ntxbuf = VIC_NBUF;
                    493:
                    494:        return (0);
                    495: }
                    496:
                    497: int
                    498: vic_alloc_data(struct vic_softc *sc)
                    499: {
                    500:        u_int8_t                        *kva;
                    501:        u_int                           offset;
                    502:        struct vic_rxdesc               *rxd;
                    503:        int                             i;
                    504:
                    505:        sc->sc_rxbuf = malloc(sizeof(struct vic_rxbuf) * sc->sc_nrxbuf,
                    506:            M_NOWAIT, M_DEVBUF);
                    507:        if (sc->sc_rxbuf == NULL) {
                    508:                printf("%s: unable to allocate rxbuf\n", DEVNAME(sc));
                    509:                goto err;
                    510:        }
                    511:
                    512:        sc->sc_txbuf = malloc(sizeof(struct vic_txbuf) * sc->sc_ntxbuf,
                    513:            M_NOWAIT, M_DEVBUF);
                    514:        if (sc->sc_txbuf == NULL) {
                    515:                printf("%s: unable to allocate txbuf\n", DEVNAME(sc));
                    516:                goto freerx;
                    517:        }
                    518:
                    519:        sc->sc_dma_size = sizeof(struct vic_data) +
                    520:            (sc->sc_nrxbuf + VIC_QUEUE2_SIZE) * sizeof(struct vic_rxdesc) +
                    521:            sc->sc_ntxbuf * sizeof(struct vic_txdesc);
                    522:
                    523:        if (vic_alloc_dmamem(sc) != 0) {
                    524:                printf("%s: unable to allocate dma region\n", DEVNAME(sc));
                    525:                goto freetx;
                    526:        }
                    527:        kva = VIC_DMA_KVA(sc);
                    528:
                    529:        /* set up basic vic data */
                    530:        sc->sc_data = VIC_DMA_KVA(sc);
                    531:
                    532:        sc->sc_data->vd_magic = VIC_MAGIC;
                    533:        sc->sc_data->vd_length = sc->sc_dma_size;
                    534:
                    535:        offset = sizeof(struct vic_data);
                    536:
                    537:        /* set up the rx ring */
                    538:        sc->sc_rxq = (struct vic_rxdesc *)&kva[offset];
                    539:
                    540:        sc->sc_data->vd_rx_offset = offset;
                    541:        sc->sc_data->vd_rx_length = sc->sc_nrxbuf;
                    542:
                    543:        offset += sizeof(struct vic_rxdesc) * sc->sc_nrxbuf;
                    544:
                    545:        /* set up the dummy rx ring 2 with an unusable entry */
                    546:        sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset];
                    547:
                    548:        sc->sc_data->vd_rx_offset2 = offset;
                    549:        sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE;
                    550:
                    551:        for (i = 0; i < VIC_QUEUE2_SIZE; i++) {
                    552:                rxd = &sc->sc_rxq2[i];
                    553:
                    554:                rxd->rx_physaddr = 0;
                    555:                rxd->rx_buflength = 0;
                    556:                rxd->rx_length = 0;
                    557:                rxd->rx_owner = VIC_OWNER_DRIVER;
                    558:
                    559:                offset += sizeof(struct vic_rxdesc);
                    560:        }
                    561:
                    562:        /* set up the tx ring */
                    563:        sc->sc_txq = (struct vic_txdesc *)&kva[offset];
                    564:
                    565:        sc->sc_data->vd_tx_offset = offset;
                    566:        sc->sc_data->vd_tx_length = sc->sc_ntxbuf;
                    567:
                    568:        return (0);
                    569: freetx:
                    570:        free(sc->sc_txbuf, M_DEVBUF);
                    571: freerx:
                    572:        free(sc->sc_rxbuf, M_DEVBUF);
                    573: err:
                    574:        return (1);
                    575: }
                    576:
                    577: int
                    578: vic_init_data(struct vic_softc *sc)
                    579: {
                    580:        struct vic_rxbuf                *rxb;
                    581:        struct vic_rxdesc               *rxd;
                    582:        struct vic_txbuf                *txb;
                    583:
                    584:        int                             i;
                    585:
                    586:        for (i = 0; i < sc->sc_nrxbuf; i++) {
                    587:                rxb = &sc->sc_rxbuf[i];
                    588:                rxd = &sc->sc_rxq[i];
                    589:
                    590:                if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
                    591:                    MCLBYTES, 0, BUS_DMA_NOWAIT, &rxb->rxb_dmamap) != 0) {
                    592:                        printf("%s: unable to create dmamap for rxb %d\n",
                    593:                            DEVNAME(sc), i);
                    594:                        goto freerxbs;
                    595:                }
                    596:
                    597:                rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap);
                    598:                if (rxb->rxb_m == NULL) {
                    599:                        /* error already printed */
                    600:                        bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
                    601:                        goto freerxbs;
                    602:                }
                    603:
                    604:                bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
                    605:                    rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
                    606:
                    607:                rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr;
                    608:                rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len; /* XXX? */
                    609:                rxd->rx_length = 0;
                    610:                rxd->rx_owner = VIC_OWNER_NIC;
                    611:        }
                    612:
                    613:        for (i = 0; i < sc->sc_ntxbuf; i++) {
                    614:                txb = &sc->sc_txbuf[i];
                    615:                if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
                    616:                    (sc->sc_cap & VIC_CMD_HWCAP_SG) ? VIC_SG_MAX : 1,
                    617:                    MCLBYTES, 0, BUS_DMA_NOWAIT, &txb->txb_dmamap) != 0) {
                    618:                        printf("%s: unable to create dmamap for tx %d\n",
                    619:                            DEVNAME(sc), i);
                    620:                        goto freetxbs;
                    621:                }
                    622:                txb->txb_m = NULL;
                    623:        }
                    624:
                    625:        return (0);
                    626:
                    627: freetxbs:
                    628:        while (i--) {
                    629:                txb = &sc->sc_txbuf[i];
                    630:                bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
                    631:        }
                    632:
                    633:        i = sc->sc_nrxbuf;
                    634: freerxbs:
                    635:        while (i--) {
                    636:                rxb = &sc->sc_rxbuf[i];
                    637:                bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
                    638:                    rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
                    639:                bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
                    640:                bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
                    641:        }
                    642:
                    643:        return (1);
                    644: }
                    645:
                    646: int
                    647: vic_uninit_data(struct vic_softc *sc)
                    648: {
                    649:        struct vic_rxbuf                *rxb;
                    650:        struct vic_rxdesc               *rxd;
                    651:        struct vic_txbuf                *txb;
                    652:
                    653:        int                             i;
                    654:
                    655:        for (i = 0; i < sc->sc_nrxbuf; i++) {
                    656:                rxb = &sc->sc_rxbuf[i];
                    657:                rxd = &sc->sc_rxq[i];
                    658:
                    659:                bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
                    660:                    rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
                    661:                bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
                    662:                bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap);
                    663:
                    664:                m_freem(rxb->rxb_m);
                    665:                rxb->rxb_m = NULL;
                    666:        }
                    667:
                    668:        for (i = 0; i < sc->sc_ntxbuf; i++) {
                    669:                txb = &sc->sc_txbuf[i];
                    670:                bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap);
                    671:        }
                    672:
                    673:        return (0);
                    674: }
                    675:
                    676: void
                    677: vic_link_state(struct vic_softc *sc)
                    678: {
                    679:        struct ifnet *ifp = &sc->sc_ac.ac_if;
                    680:        u_int32_t status;
                    681:        int link_state = LINK_STATE_DOWN;
                    682:
                    683:        status = vic_read(sc, VIC_STATUS);
                    684:        if (status & VIC_STATUS_CONNECTED)
                    685:                link_state = LINK_STATE_FULL_DUPLEX;
                    686:        if (ifp->if_link_state != link_state) {
                    687:                ifp->if_link_state = link_state;
                    688:                if_link_state_change(ifp);
                    689:        }
                    690: }
                    691:
                    692: void
                    693: vic_shutdown(void *self)
                    694: {
                    695:        struct vic_softc *sc = (struct vic_softc *)self;
                    696:
                    697:        vic_stop(&sc->sc_ac.ac_if);
                    698: }
                    699:
                    700: int
                    701: vic_intr(void *arg)
                    702: {
                    703:        struct vic_softc *sc = (struct vic_softc *)arg;
                    704:
                    705:        vic_rx_proc(sc);
                    706:        vic_tx_proc(sc);
                    707:
                    708:        vic_write(sc, VIC_CMD, VIC_CMD_INTR_ACK);
                    709:
                    710:        return (1);
                    711: }
                    712:
                    713: void
                    714: vic_rx_proc(struct vic_softc *sc)
                    715: {
                    716:        struct ifnet                    *ifp = &sc->sc_ac.ac_if;
                    717:        struct vic_rxdesc               *rxd;
                    718:        struct vic_rxbuf                *rxb;
                    719:        struct mbuf                     *m;
                    720:        int                             len, idx;
                    721:
                    722:        if ((ifp->if_flags & IFF_RUNNING) == 0)
                    723:                return;
                    724:
                    725:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                    726:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                    727:
                    728:        for (;;) {
                    729:                idx = sc->sc_data->vd_rx_nextidx;
                    730:                if (idx >= sc->sc_data->vd_rx_length) {
                    731:                        ifp->if_ierrors++;
                    732:                        if (ifp->if_flags & IFF_DEBUG)
                    733:                                printf("%s: receive index error\n",
                    734:                                    sc->sc_dev.dv_xname);
                    735:                        break;
                    736:                }
                    737:
                    738:                rxd = &sc->sc_rxq[idx];
                    739:                if (rxd->rx_owner != VIC_OWNER_DRIVER)
                    740:                        break;
                    741:
                    742:                rxb = &sc->sc_rxbuf[idx];
                    743:
                    744:                len = rxd->rx_length;
                    745:                if (len < VIC_MIN_FRAMELEN) {
                    746:                        ifp->if_iqdrops++;
                    747:                        goto nextp;
                    748:                }
                    749:
                    750:                if (rxb->rxb_m == NULL) {
                    751:                        ifp->if_ierrors++;
                    752:                        printf("%s: rxb %d has no mbuf\n", DEVNAME(sc), idx);
                    753:                        break;
                    754:                }
                    755:
                    756:                bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
                    757:                    rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
                    758:                bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap);
                    759:
                    760:                m = rxb->rxb_m;
                    761:                rxb->rxb_m = NULL;
                    762:                m->m_pkthdr.rcvif = ifp;
                    763:                m->m_pkthdr.len = m->m_len = len;
                    764:
                    765:                /* Get new mbuf for the Rx queue */
                    766:                rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap);
                    767:                if (rxb->rxb_m == NULL) {
                    768:                        ifp->if_ierrors++;
                    769:                        printf("%s: mbuf alloc failed\n", DEVNAME(sc));
                    770:                        break;
                    771:                }
                    772:                bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0,
                    773:                    rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
                    774:
                    775:                rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr;
                    776:                rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len;
                    777:                rxd->rx_length = 0;
                    778:                rxd->rx_owner = VIC_OWNER_DRIVER;
                    779:
                    780:                ifp->if_ipackets++;
                    781:
                    782: #if NBPFILTER > 0
                    783:                if (ifp->if_bpf)
                    784:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    785: #endif
                    786:
                    787:                ether_input_mbuf(ifp, m);
                    788:
                    789: nextp:
                    790:                rxd->rx_owner = VIC_OWNER_NIC;
                    791:                VIC_INC(sc->sc_data->vd_rx_nextidx, sc->sc_data->vd_rx_length);
                    792:        }
                    793:
                    794:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                    795:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    796: }
                    797:
                    798: void
                    799: vic_tx_proc(struct vic_softc *sc)
                    800: {
                    801:        struct ifnet                    *ifp = &sc->sc_ac.ac_if;
                    802:        struct vic_txdesc               *txd;
                    803:        struct vic_txbuf                *txb;
                    804:        int                             idx;
                    805:
                    806:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                    807:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                    808:
                    809:        while (sc->sc_txpending > 0) {
                    810:                idx = sc->sc_data->vd_tx_curidx;
                    811:                if (idx >= sc->sc_data->vd_tx_length) {
                    812:                        ifp->if_oerrors++;
                    813:                        break;
                    814:                }
                    815:
                    816:                txd = &sc->sc_txq[idx];
                    817:                if (txd->tx_owner != VIC_OWNER_DRIVER)
                    818:                        break;
                    819:
                    820:                txb = &sc->sc_txbuf[idx];
                    821:                if (txb->txb_m == NULL) {
                    822:                        printf("%s: tx ring is corrupt\n", DEVNAME(sc));
                    823:                        ifp->if_oerrors++;
                    824:                        break;
                    825:                }
                    826:
                    827:                bus_dmamap_sync(sc->sc_dmat, txb->txb_dmamap, 0,
                    828:                    txb->txb_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                    829:                bus_dmamap_unload(sc->sc_dmat, txb->txb_dmamap);
                    830:
                    831:                m_freem(txb->txb_m);
                    832:                txb->txb_m = NULL;
                    833:                ifp->if_flags &= ~IFF_OACTIVE;
                    834:
                    835:                sc->sc_txpending--;
                    836:                sc->sc_data->vd_tx_stopped = 0;
                    837:
                    838:                VIC_INC(sc->sc_data->vd_tx_curidx, sc->sc_data->vd_tx_length);
                    839:        }
                    840:
                    841:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                    842:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    843:
                    844:        vic_start(ifp);
                    845: }
                    846:
                    847: void
                    848: vic_iff(struct vic_softc *sc)
                    849: {
                    850:        struct arpcom *ac = &sc->sc_ac;
                    851:        struct ifnet *ifp = &sc->sc_ac.ac_if;
                    852:        struct ether_multi *enm;
                    853:        struct ether_multistep step;
                    854:        u_int32_t crc;
                    855:        u_int16_t *mcastfil = (u_int16_t *)sc->sc_data->vd_mcastfil;
                    856:        u_int flags = 0;
                    857:
                    858:        bzero(&sc->sc_data->vd_mcastfil, sizeof(sc->sc_data->vd_mcastfil));
                    859:        ifp->if_flags &= ~IFF_ALLMULTI;
                    860:
                    861:        if ((ifp->if_flags & IFF_RUNNING) == 0)
                    862:                goto domulti;
                    863:        if (ifp->if_flags & IFF_PROMISC)
                    864:                goto allmulti;
                    865:
                    866:        ETHER_FIRST_MULTI(step, ac, enm);
                    867:        while (enm != NULL) {
                    868:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN))
                    869:                        goto allmulti;
                    870:
                    871:                crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
                    872:                crc >>= 26;
                    873:                mcastfil[crc >> 4] |= htole16(1 << (crc & 0xf));
                    874:
                    875:                ETHER_NEXT_MULTI(step, enm);
                    876:        }
                    877:
                    878:        goto domulti;
                    879:
                    880:  allmulti:
                    881:        ifp->if_flags |= IFF_ALLMULTI;
                    882:        memset(&sc->sc_data->vd_mcastfil, 0xff,
                    883:            sizeof(sc->sc_data->vd_mcastfil));
                    884:
                    885:  domulti:
                    886:        vic_write(sc, VIC_CMD, VIC_CMD_MCASTFIL);
                    887:
                    888:        if (ifp->if_flags & IFF_RUNNING) {
                    889:                flags = (ifp->if_flags & IFF_PROMISC) ?
                    890:                    VIC_CMD_IFF_PROMISC :
                    891:                    (VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST);
                    892:        }
                    893:        sc->sc_data->vd_iff = flags;
                    894:        vic_write(sc, VIC_CMD, VIC_CMD_IFF);
                    895: }
                    896:
                    897: void
                    898: vic_getlladdr(struct vic_softc *sc)
                    899: {
                    900:        u_int32_t reg;
                    901:
                    902:        /* Get MAC address */
                    903:        reg = (sc->sc_cap & VIC_CMD_HWCAP_VPROM) ? VIC_VPROM : VIC_LLADDR;
                    904:
                    905:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, reg, ETHER_ADDR_LEN,
                    906:            BUS_SPACE_BARRIER_READ);
                    907:        bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, reg, sc->sc_lladdr,
                    908:            ETHER_ADDR_LEN);
                    909:
                    910:        /* Update the MAC address register */
                    911:        if (reg == VIC_VPROM)
                    912:                vic_setlladdr(sc);
                    913: }
                    914:
                    915: void
                    916: vic_setlladdr(struct vic_softc *sc)
                    917: {
                    918:        bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, VIC_LLADDR,
                    919:            sc->sc_lladdr, ETHER_ADDR_LEN);
                    920:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, VIC_LLADDR, ETHER_ADDR_LEN,
                    921:            BUS_SPACE_BARRIER_WRITE);
                    922: }
                    923:
                    924: int
                    925: vic_media_change(struct ifnet *ifp)
                    926: {
                    927:        /* Ignore */
                    928:        return (0);
                    929: }
                    930:
                    931: void
                    932: vic_media_status(struct ifnet *ifp, struct ifmediareq *imr)
                    933: {
                    934:        struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
                    935:
                    936:        imr->ifm_active = IFM_ETHER | IFM_AUTO;
                    937:        imr->ifm_status = IFM_AVALID;
                    938:
                    939:        vic_link_state(sc);
                    940:
                    941:        if (LINK_STATE_IS_UP(ifp->if_link_state) &&
                    942:            ifp->if_flags & IFF_UP)
                    943:                imr->ifm_status |= IFM_ACTIVE;
                    944: }
                    945:
                    946: void
                    947: vic_start(struct ifnet *ifp)
                    948: {
                    949:        struct vic_softc                *sc;
                    950:        struct mbuf                     *m;
                    951:        struct vic_txbuf                *txb;
                    952:        struct vic_txdesc               *txd;
                    953:        struct vic_sg                   *sge;
                    954:        bus_dmamap_t                    dmap;
                    955:        int                             i, idx;
                    956:        int                             tx = 0;
                    957:
                    958:        if (!(ifp->if_flags & IFF_RUNNING))
                    959:                return;
                    960:
                    961:        if (ifp->if_flags & IFF_OACTIVE)
                    962:                return;
                    963:
                    964:        if (IFQ_IS_EMPTY(&ifp->if_snd))
                    965:                return;
                    966:
                    967:        sc = (struct vic_softc *)ifp->if_softc;
                    968:
                    969:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                    970:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                    971:
                    972:        for (;;) {
                    973:                if (VIC_TXURN(sc)) {
                    974:                        ifp->if_flags |= IFF_OACTIVE;
                    975:                        break;
                    976:                }
                    977:
                    978:                IFQ_POLL(&ifp->if_snd, m);
                    979:                if (m == NULL)
                    980:                        break;
                    981:
                    982:                idx = sc->sc_data->vd_tx_nextidx;
                    983:                if (idx >= sc->sc_data->vd_tx_length) {
                    984:                        printf("%s: tx idx is corrupt\n", DEVNAME(sc));
                    985:                        ifp->if_oerrors++;
                    986:                        break;
                    987:                }
                    988:
                    989:                txd = &sc->sc_txq[idx];
                    990:                txb = &sc->sc_txbuf[idx];
                    991:
                    992:                if (txb->txb_m != NULL) {
                    993:                        printf("%s: tx ring is corrupt\n", DEVNAME(sc));
                    994:                        sc->sc_data->vd_tx_stopped = 1;
                    995:                        ifp->if_oerrors++;
                    996:                        break;
                    997:                }
                    998:
                    999:                /*
                   1000:                 * we're committed to sending it now. if we cant map it into
                   1001:                 * dma memory then we drop it.
                   1002:                 */
                   1003:                IFQ_DEQUEUE(&ifp->if_snd, m);
                   1004:                if (vic_load_txb(sc, txb, m) != 0) {
                   1005:                        m_freem(m);
                   1006:                        ifp->if_oerrors++;
                   1007:                        /* continue? */
                   1008:                        break;
                   1009:                }
                   1010:
                   1011: #if NBPFILTER > 0
                   1012:                if (ifp->if_bpf)
                   1013:                        bpf_mtap(ifp->if_bpf, txb->txb_m, BPF_DIRECTION_OUT);
                   1014: #endif
                   1015:
                   1016:                dmap = txb->txb_dmamap;
                   1017:                txd->tx_flags = VIC_TX_FLAGS_KEEP;
                   1018:                txd->tx_owner = VIC_OWNER_NIC;
                   1019:                txd->tx_sa.sa_addr_type = VIC_SG_ADDR_PHYS;
                   1020:                txd->tx_sa.sa_length = dmap->dm_nsegs;
                   1021:                for (i = 0; i < dmap->dm_nsegs; i++) {
                   1022:                        sge = &txd->tx_sa.sa_sg[i];
                   1023:                        sge->sg_length = dmap->dm_segs[i].ds_len;
                   1024:                        sge->sg_addr_low = dmap->dm_segs[i].ds_addr;
                   1025:                }
                   1026:
                   1027:                if (VIC_TXURN_WARN(sc)) {
                   1028:                        txd->tx_flags |= VIC_TX_FLAGS_TXURN;
                   1029:                }
                   1030:
                   1031:                bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
                   1032:                    BUS_DMASYNC_PREWRITE);
                   1033:
                   1034:                ifp->if_opackets++;
                   1035:                sc->sc_txpending++;
                   1036:
                   1037:                VIC_INC(sc->sc_data->vd_tx_nextidx, sc->sc_data->vd_tx_length);
                   1038:
                   1039:                tx = 1;
                   1040:        }
                   1041:
                   1042:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                   1043:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1044:
                   1045:        if (tx)
                   1046:                vic_read(sc, VIC_Tx_ADDR);
                   1047: }
                   1048:
                   1049: int
                   1050: vic_load_txb(struct vic_softc *sc, struct vic_txbuf *txb, struct mbuf *m)
                   1051: {
                   1052:        bus_dmamap_t                    dmap = txb->txb_dmamap;
                   1053:        struct mbuf                     *m0 = NULL;
                   1054:        int                             error;
                   1055:
                   1056:        error = bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m, BUS_DMA_NOWAIT);
                   1057:        switch (error) {
                   1058:        case 0:
                   1059:                txb->txb_m = m;
                   1060:                break;
                   1061:
                   1062:        case EFBIG: /* mbuf chain is too fragmented */
                   1063:                MGETHDR(m0, M_DONTWAIT, MT_DATA);
                   1064:                if (m0 == NULL)
                   1065:                        return (ENOBUFS);
                   1066:                if (m->m_pkthdr.len > MHLEN) {
                   1067:                        MCLGET(m0, M_DONTWAIT);
                   1068:                        if (!(m0->m_flags & M_EXT)) {
                   1069:                                m_freem(m0);
                   1070:                                return (ENOBUFS);
                   1071:                        }
                   1072:                }
                   1073:                m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
                   1074:                m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
                   1075:                error = bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m0,
                   1076:                    BUS_DMA_NOWAIT);
                   1077:                if (error != 0) {
                   1078:                        m_freem(m0);
                   1079:                        printf("%s: tx dmamap load error %d\n", DEVNAME(sc),
                   1080:                            error);
                   1081:                        return (ENOBUFS);
                   1082:                }
                   1083:                m_freem(m);
                   1084:                txb->txb_m = m0;
                   1085:                break;
                   1086:
                   1087:        default:
                   1088:                printf("%s: tx dmamap load error %d\n", DEVNAME(sc), error);
                   1089:                return (ENOBUFS);
                   1090:        }
                   1091:
                   1092:        return (0);
                   1093: }
                   1094:
                   1095: void
                   1096: vic_watchdog(struct ifnet *ifp)
                   1097: {
                   1098: #if 0
                   1099:        struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
                   1100:
                   1101:        if (sc->sc_txpending && sc->sc_txtimeout > 0) {
                   1102:                if (--sc->sc_txtimeout == 0) {
                   1103:                        printf("%s: device timeout\n", sc->sc_dev.dv_xname);
                   1104:                        ifp->if_flags &= ~IFF_RUNNING;
                   1105:                        vic_init(ifp);
                   1106:                        ifp->if_oerrors++;
                   1107:                        return;
                   1108:                }
                   1109:        }
                   1110:
                   1111:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
                   1112:                vic_start(ifp);
                   1113: #endif
                   1114: }
                   1115:
                   1116: int
                   1117: vic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                   1118: {
                   1119:        struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
                   1120:        struct ifreq *ifr = (struct ifreq *)data;
                   1121:        struct ifaddr *ifa;
                   1122:        int s, error = 0;
                   1123:
                   1124:        s = splnet();
                   1125:
                   1126:        if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
                   1127:                splx(s);
                   1128:                return (error);
                   1129:        }
                   1130:
                   1131:        switch (cmd) {
                   1132:        case SIOCSIFADDR:
                   1133:                ifa = (struct ifaddr *)data;
                   1134:                ifp->if_flags |= IFF_UP;
                   1135: #ifdef INET
                   1136:                if (ifa->ifa_addr->sa_family == AF_INET)
                   1137:                        arp_ifinit(&sc->sc_ac, ifa);
                   1138: #endif
                   1139:                /* FALLTHROUGH */
                   1140:        case SIOCSIFFLAGS:
                   1141:                if (ifp->if_flags & IFF_UP) {
                   1142:                        if (ifp->if_flags & IFF_RUNNING)
                   1143:                                vic_iff(sc);
                   1144:                        else
                   1145:                                vic_init(ifp);
                   1146:                } else {
                   1147:                        if (ifp->if_flags & IFF_RUNNING)
                   1148:                                vic_stop(ifp);
                   1149:                }
                   1150:                break;
                   1151:
                   1152:        case SIOCSIFMTU:
                   1153:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
                   1154:                        error = EINVAL;
                   1155:                else if (ifp->if_mtu != ifr->ifr_mtu)
                   1156:                        ifp->if_mtu = ifr->ifr_mtu;
                   1157:                break;
                   1158:
                   1159:        case SIOCADDMULTI:
                   1160:        case SIOCDELMULTI:
                   1161:                ifr = (struct ifreq *)data;
                   1162:                error = (cmd == SIOCADDMULTI) ?
                   1163:                    ether_addmulti(ifr, &sc->sc_ac) :
                   1164:                    ether_delmulti(ifr, &sc->sc_ac);
                   1165:
                   1166:                if (error == ENETRESET) {
                   1167:                        if (ifp->if_flags & IFF_RUNNING)
                   1168:                                vic_iff(sc);
                   1169:                        error = 0;
                   1170:                }
                   1171:                break;
                   1172:
                   1173:        case SIOCGIFMEDIA:
                   1174:        case SIOCSIFMEDIA:
                   1175:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                   1176:                break;
                   1177:
                   1178:        default:
                   1179:                error = ENOTTY;
                   1180:                break;
                   1181:        }
                   1182:
                   1183:        if (error == ENETRESET) {
                   1184:                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
                   1185:                    (IFF_UP | IFF_RUNNING))
                   1186:                        vic_iff(ifp->if_softc);
                   1187:                error = 0;
                   1188:        }
                   1189:
                   1190:        splx(s);
                   1191:
                   1192:        return (error);
                   1193: }
                   1194:
                   1195: void
                   1196: vic_init(struct ifnet *ifp)
                   1197: {
                   1198:        struct vic_softc        *sc = (struct vic_softc *)ifp->if_softc;
                   1199:        int                     s;
                   1200:
                   1201:        if (vic_init_data(sc) != 0)
                   1202:                return;
                   1203:
                   1204:        sc->sc_data->vd_tx_curidx = 0;
                   1205:        sc->sc_data->vd_tx_nextidx = 0;
                   1206:        sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0;
                   1207:
                   1208:        sc->sc_data->vd_rx_nextidx = 0;
                   1209:        sc->sc_data->vd_rx_nextidx2 = 0;
                   1210:
                   1211:        sc->sc_data->vd_rx_saved_nextidx = 0;
                   1212:        sc->sc_data->vd_rx_saved_nextidx2 = 0;
                   1213:        sc->sc_data->vd_tx_saved_nextidx = 0;
                   1214:
                   1215:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                   1216:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                   1217:
                   1218:        s = splnet();
                   1219:
                   1220:        vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc));
                   1221:        vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size);
                   1222:
                   1223:        ifp->if_flags |= IFF_RUNNING;
                   1224:        ifp->if_flags &= ~IFF_OACTIVE;
                   1225:
                   1226:        vic_iff(sc);
                   1227:        vic_write(sc, VIC_CMD, VIC_CMD_INTR_ENABLE);
                   1228:
                   1229:        splx(s);
                   1230:
                   1231:        timeout_add(&sc->sc_tick, hz);
                   1232: }
                   1233:
                   1234: void
                   1235: vic_stop(struct ifnet *ifp)
                   1236: {
                   1237:        struct vic_softc *sc = (struct vic_softc *)ifp->if_softc;
                   1238:        int s;
                   1239:
                   1240:        s = splnet();
                   1241:
                   1242:        timeout_del(&sc->sc_tick);
                   1243:
                   1244:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                   1245:
                   1246:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size,
                   1247:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                   1248:
                   1249:        /* XXX wait for tx to complete */
                   1250:        while (sc->sc_txpending > 0) {
                   1251:                splx(s);
                   1252:                delay(1000);
                   1253:                s = splnet();
                   1254:        }
                   1255:
                   1256:        sc->sc_data->vd_tx_stopped = 1;
                   1257:
                   1258:        vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE);
                   1259:
                   1260:        vic_iff(sc);
                   1261:        vic_write(sc, VIC_DATA_ADDR, 0);
                   1262:
                   1263:        vic_uninit_data(sc);
                   1264:
                   1265:        splx(s);
                   1266: }
                   1267:
                   1268: struct mbuf *
                   1269: vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map)
                   1270: {
                   1271:        struct mbuf *m = NULL;
                   1272:
                   1273:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1274:        if (m == NULL)
                   1275:                return (NULL);
                   1276:
                   1277:        MCLGET(m, M_DONTWAIT);
                   1278:        if ((m->m_flags & M_EXT) == 0) {
                   1279:                m_freem(m);
                   1280:                return (NULL);
                   1281:        }
                   1282:        m->m_len = m->m_pkthdr.len = MCLBYTES;
                   1283:
                   1284:        if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) {
                   1285:                printf("%s: could not load mbuf DMA map", DEVNAME(sc));
                   1286:                m_freem(m);
                   1287:                return (NULL);
                   1288:        }
                   1289:
                   1290:        return (m);
                   1291: }
                   1292:
                   1293: void
                   1294: vic_tick(void *arg)
                   1295: {
                   1296:        struct vic_softc                *sc = (struct vic_softc *)arg;
                   1297:
                   1298:        vic_link_state(sc);
                   1299:
                   1300:        timeout_add(&sc->sc_tick, hz);
                   1301: }
                   1302:
                   1303: u_int32_t
                   1304: vic_read(struct vic_softc *sc, bus_size_t r)
                   1305: {
                   1306:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                   1307:            BUS_SPACE_BARRIER_READ);
                   1308:        return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
                   1309: }
                   1310:
                   1311: void
                   1312: vic_write(struct vic_softc *sc, bus_size_t r, u_int32_t v)
                   1313: {
                   1314:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
                   1315:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                   1316:            BUS_SPACE_BARRIER_WRITE);
                   1317: }
                   1318:
                   1319: u_int32_t
                   1320: vic_read_cmd(struct vic_softc *sc, u_int32_t cmd)
                   1321: {
                   1322:        vic_write(sc, VIC_CMD, cmd);
                   1323:        return (vic_read(sc, VIC_CMD));
                   1324: }
                   1325:
                   1326: int
                   1327: vic_alloc_dmamem(struct vic_softc *sc)
                   1328: {
                   1329:        int nsegs;
                   1330:
                   1331:        if (bus_dmamap_create(sc->sc_dmat, sc->sc_dma_size, 1,
                   1332:            sc->sc_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
                   1333:            &sc->sc_dma_map) != 0)
                   1334:                goto err;
                   1335:
                   1336:        if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_dma_size, 16, 0,
                   1337:            &sc->sc_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT) != 0)
                   1338:                goto destroy;
                   1339:
                   1340:        if (bus_dmamem_map(sc->sc_dmat, &sc->sc_dma_seg, nsegs,
                   1341:            sc->sc_dma_size, &sc->sc_dma_kva, BUS_DMA_NOWAIT) != 0)
                   1342:                goto free;
                   1343:
                   1344:        if (bus_dmamap_load(sc->sc_dmat, sc->sc_dma_map, sc->sc_dma_kva,
                   1345:            sc->sc_dma_size, NULL, BUS_DMA_NOWAIT) != 0)
                   1346:                goto unmap;
                   1347:
                   1348:        bzero(sc->sc_dma_kva, sc->sc_dma_size);
                   1349:
                   1350:        return (0);
                   1351:
                   1352: unmap:
                   1353:        bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size);
                   1354: free:
                   1355:        bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1);
                   1356: destroy:
                   1357:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map);
                   1358: err:
                   1359:        return (1);
                   1360: }
                   1361:
                   1362: void
                   1363: vic_free_dmamem(struct vic_softc *sc)
                   1364: {
                   1365:        bus_dmamap_unload(sc->sc_dmat, sc->sc_dma_map);
                   1366:        bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size);
                   1367:        bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1);
                   1368:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map);
                   1369: }

CVSweb