[BACK]Return to if_sip.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/if_sip.c, Revision 1.115.4.1

1.115.4.1! ad          1: /*     $NetBSD: if_sip.c,v 1.124 2007/12/16 21:17:00 dyoung Exp $      */
1.28      thorpej     2:
                      3: /*-
1.45      thorpej     4:  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
1.28      thorpej     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
1.1       thorpej    38:
                     39: /*-
                     40:  * Copyright (c) 1999 Network Computer, Inc.
                     41:  * All rights reserved.
                     42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
                     51:  * 3. Neither the name of Network Computer, Inc. nor the names of its
                     52:  *    contributors may be used to endorse or promote products derived
                     53:  *    from this software without specific prior written permission.
                     54:  *
                     55:  * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS
                     56:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     57:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     58:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     59:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     60:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     61:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     62:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     63:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     64:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     65:  * POSSIBILITY OF SUCH DAMAGE.
                     66:  */
                     67:
                     68: /*
1.29      thorpej    69:  * Device driver for the Silicon Integrated Systems SiS 900,
                     70:  * SiS 7016 10/100, National Semiconductor DP83815 10/100, and
                     71:  * National Semiconductor DP83820 10/100/1000 PCI Ethernet
                     72:  * controllers.
1.101     perry      73:  *
1.32      thorpej    74:  * Originally written to support the SiS 900 by Jason R. Thorpe for
                     75:  * Network Computer, Inc.
1.29      thorpej    76:  *
                     77:  * TODO:
                     78:  *
1.58      thorpej    79:  *     - Reduce the Rx interrupt load.
1.1       thorpej    80:  */
1.43      lukem      81:
                     82: #include <sys/cdefs.h>
1.115.4.1! ad         83: __KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.124 2007/12/16 21:17:00 dyoung Exp $");
1.1       thorpej    84:
                     85: #include "bpfilter.h"
1.65      itojun     86: #include "rnd.h"
1.1       thorpej    87:
                     88: #include <sys/param.h>
                     89: #include <sys/systm.h>
1.9       thorpej    90: #include <sys/callout.h>
1.1       thorpej    91: #include <sys/mbuf.h>
                     92: #include <sys/malloc.h>
                     93: #include <sys/kernel.h>
                     94: #include <sys/socket.h>
                     95: #include <sys/ioctl.h>
                     96: #include <sys/errno.h>
                     97: #include <sys/device.h>
                     98: #include <sys/queue.h>
                     99:
1.12      mrg       100: #include <uvm/uvm_extern.h>            /* for PAGE_SIZE */
1.1       thorpej   101:
1.65      itojun    102: #if NRND > 0
                    103: #include <sys/rnd.h>
                    104: #endif
                    105:
1.1       thorpej   106: #include <net/if.h>
                    107: #include <net/if_dl.h>
                    108: #include <net/if_media.h>
                    109: #include <net/if_ether.h>
                    110:
                    111: #if NBPFILTER > 0
                    112: #include <net/bpf.h>
                    113: #endif
                    114:
1.115     ad        115: #include <sys/bus.h>
                    116: #include <sys/intr.h>
1.14      tsutsui   117: #include <machine/endian.h>
1.1       thorpej   118:
1.15      thorpej   119: #include <dev/mii/mii.h>
1.1       thorpej   120: #include <dev/mii/miivar.h>
1.29      thorpej   121: #include <dev/mii/mii_bitbang.h>
1.1       thorpej   122:
                    123: #include <dev/pci/pcireg.h>
                    124: #include <dev/pci/pcivar.h>
                    125: #include <dev/pci/pcidevs.h>
                    126:
                    127: #include <dev/pci/if_sipreg.h>
                    128:
                    129: /*
                    130:  * Transmit descriptor list size.  This is arbitrary, but allocate
1.30      thorpej   131:  * enough descriptors for 128 pending transmissions, and 8 segments
1.88      thorpej   132:  * per packet (64 for DP83820 for jumbo frames).
                    133:  *
                    134:  * This MUST work out to a power of 2.
1.1       thorpej   135:  */
1.115.4.1! ad        136: #define        GSIP_NTXSEGS_ALLOC 16
        !           137: #define        SIP_NTXSEGS_ALLOC 8
1.1       thorpej   138:
1.30      thorpej   139: #define        SIP_TXQUEUELEN          256
1.115.4.1! ad        140: #define        MAX_SIP_NTXDESC \
        !           141:     (SIP_TXQUEUELEN * MAX(SIP_NTXSEGS_ALLOC, GSIP_NTXSEGS_ALLOC))
1.46      thorpej   142:
1.1       thorpej   143: /*
                    144:  * Receive descriptor list size.  We have one Rx buffer per incoming
                    145:  * packet, so this logic is a little simpler.
1.36      thorpej   146:  *
                    147:  * Actually, on the DP83820, we allow the packet to consume more than
                    148:  * one buffer, in order to support jumbo Ethernet frames.  In that
                    149:  * case, a packet may consume up to 5 buffers (assuming a 2048 byte
                    150:  * mbuf cluster).  256 receive buffers is only 51 maximum size packets,
                    151:  * so we'd better be quick about handling receive interrupts.
1.1       thorpej   152:  */
1.115.4.1! ad        153: #define        GSIP_NRXDESC            256
1.30      thorpej   154: #define        SIP_NRXDESC             128
1.115.4.1! ad        155:
        !           156: #define        MAX_SIP_NRXDESC MAX(GSIP_NRXDESC, SIP_NRXDESC)
1.1       thorpej   157:
                    158: /*
                    159:  * Control structures are DMA'd to the SiS900 chip.  We allocate them in
                    160:  * a single clump that maps to a single DMA segment to make several things
                    161:  * easier.
                    162:  */
                    163: struct sip_control_data {
                    164:        /*
                    165:         * The transmit descriptors.
                    166:         */
1.115.4.1! ad        167:        struct sip_desc scd_txdescs[MAX_SIP_NTXDESC];
1.1       thorpej   168:
                    169:        /*
                    170:         * The receive descriptors.
                    171:         */
1.115.4.1! ad        172:        struct sip_desc scd_rxdescs[MAX_SIP_NRXDESC];
1.1       thorpej   173: };
                    174:
                    175: #define        SIP_CDOFF(x)    offsetof(struct sip_control_data, x)
                    176: #define        SIP_CDTXOFF(x)  SIP_CDOFF(scd_txdescs[(x)])
                    177: #define        SIP_CDRXOFF(x)  SIP_CDOFF(scd_rxdescs[(x)])
                    178:
                    179: /*
                    180:  * Software state for transmit jobs.
                    181:  */
                    182: struct sip_txsoft {
                    183:        struct mbuf *txs_mbuf;          /* head of our mbuf chain */
                    184:        bus_dmamap_t txs_dmamap;        /* our DMA map */
                    185:        int txs_firstdesc;              /* first descriptor in packet */
                    186:        int txs_lastdesc;               /* last descriptor in packet */
                    187:        SIMPLEQ_ENTRY(sip_txsoft) txs_q;
                    188: };
                    189:
                    190: SIMPLEQ_HEAD(sip_txsq, sip_txsoft);
                    191:
                    192: /*
                    193:  * Software state for receive jobs.
                    194:  */
                    195: struct sip_rxsoft {
                    196:        struct mbuf *rxs_mbuf;          /* head of our mbuf chain */
                    197:        bus_dmamap_t rxs_dmamap;        /* our DMA map */
                    198: };
                    199:
1.115.4.1! ad        200: enum sip_attach_stage {
        !           201:          SIP_ATTACH_FIN = 0
        !           202:        , SIP_ATTACH_CREATE_RXMAP
        !           203:        , SIP_ATTACH_CREATE_TXMAP
        !           204:        , SIP_ATTACH_LOAD_MAP
        !           205:        , SIP_ATTACH_CREATE_MAP
        !           206:        , SIP_ATTACH_MAP_MEM
        !           207:        , SIP_ATTACH_ALLOC_MEM
        !           208:        , SIP_ATTACH_INTR
        !           209:        , SIP_ATTACH_MAP
        !           210: };
        !           211:
1.1       thorpej   212: /*
                    213:  * Software state per device.
                    214:  */
                    215: struct sip_softc {
                    216:        struct device sc_dev;           /* generic device information */
                    217:        bus_space_tag_t sc_st;          /* bus space tag */
                    218:        bus_space_handle_t sc_sh;       /* bus space handle */
1.115.4.1! ad        219:        bus_size_t sc_sz;               /* bus space size */
1.1       thorpej   220:        bus_dma_tag_t sc_dmat;          /* bus DMA tag */
1.115.4.1! ad        221:        pci_chipset_tag_t sc_pc;
        !           222:        bus_dma_segment_t sc_seg;
1.1       thorpej   223:        struct ethercom sc_ethercom;    /* ethernet common data */
                    224:        void *sc_sdhook;                /* shutdown hook */
1.15      thorpej   225:
                    226:        const struct sip_product *sc_model; /* which model are we? */
1.115.4.1! ad        227:        int sc_gigabit;                 /* 1: 83820, 0: other */
1.45      thorpej   228:        int sc_rev;                     /* chip revision */
1.1       thorpej   229:
                    230:        void *sc_ih;                    /* interrupt cookie */
                    231:
                    232:        struct mii_data sc_mii;         /* MII/media information */
                    233:
1.113     ad        234:        callout_t sc_tick_ch;           /* tick callout */
1.9       thorpej   235:
1.1       thorpej   236:        bus_dmamap_t sc_cddmamap;       /* control data DMA map */
                    237: #define        sc_cddma        sc_cddmamap->dm_segs[0].ds_addr
                    238:
                    239:        /*
                    240:         * Software state for transmit and receive descriptors.
                    241:         */
                    242:        struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];
1.115.4.1! ad        243:        struct sip_rxsoft sc_rxsoft[MAX_SIP_NRXDESC];
1.1       thorpej   244:
                    245:        /*
                    246:         * Control data structures.
                    247:         */
                    248:        struct sip_control_data *sc_control_data;
                    249: #define        sc_txdescs      sc_control_data->scd_txdescs
                    250: #define        sc_rxdescs      sc_control_data->scd_rxdescs
                    251:
1.30      thorpej   252: #ifdef SIP_EVENT_COUNTERS
                    253:        /*
                    254:         * Event counters.
                    255:         */
                    256:        struct evcnt sc_ev_txsstall;    /* Tx stalled due to no txs */
                    257:        struct evcnt sc_ev_txdstall;    /* Tx stalled due to no txd */
1.56      thorpej   258:        struct evcnt sc_ev_txforceintr; /* Tx interrupts forced */
                    259:        struct evcnt sc_ev_txdintr;     /* Tx descriptor interrupts */
                    260:        struct evcnt sc_ev_txiintr;     /* Tx idle interrupts */
1.30      thorpej   261:        struct evcnt sc_ev_rxintr;      /* Rx interrupts */
1.62      thorpej   262:        struct evcnt sc_ev_hiberr;      /* HIBERR interrupts */
1.94      thorpej   263:        struct evcnt sc_ev_rxpause;     /* PAUSE received */
1.115.4.1! ad        264:        /* DP83820 only */
1.94      thorpej   265:        struct evcnt sc_ev_txpause;     /* PAUSE transmitted */
1.31      thorpej   266:        struct evcnt sc_ev_rxipsum;     /* IP checksums checked in-bound */
                    267:        struct evcnt sc_ev_rxtcpsum;    /* TCP checksums checked in-bound */
                    268:        struct evcnt sc_ev_rxudpsum;    /* UDP checksums checked in-boudn */
                    269:        struct evcnt sc_ev_txipsum;     /* IP checksums comp. out-bound */
                    270:        struct evcnt sc_ev_txtcpsum;    /* TCP checksums comp. out-bound */
                    271:        struct evcnt sc_ev_txudpsum;    /* UDP checksums comp. out-bound */
1.30      thorpej   272: #endif /* SIP_EVENT_COUNTERS */
                    273:
1.1       thorpej   274:        u_int32_t sc_txcfg;             /* prototype TXCFG register */
                    275:        u_int32_t sc_rxcfg;             /* prototype RXCFG register */
                    276:        u_int32_t sc_imr;               /* prototype IMR register */
                    277:        u_int32_t sc_rfcr;              /* prototype RFCR register */
                    278:
1.29      thorpej   279:        u_int32_t sc_cfg;               /* prototype CFG register */
                    280:
                    281:        u_int32_t sc_gpior;             /* prototype GPIOR register */
                    282:
1.1       thorpej   283:        u_int32_t sc_tx_fill_thresh;    /* transmit fill threshold */
                    284:        u_int32_t sc_tx_drain_thresh;   /* transmit drain threshold */
                    285:
                    286:        u_int32_t sc_rx_drain_thresh;   /* receive drain threshold */
                    287:
1.89      thorpej   288:        int     sc_flowflags;           /* 802.3x flow control flags */
                    289:        int     sc_rx_flow_thresh;      /* Rx FIFO threshold for flow control */
                    290:        int     sc_paused;              /* paused indication */
1.1       thorpej   291:
                    292:        int     sc_txfree;              /* number of free Tx descriptors */
                    293:        int     sc_txnext;              /* next ready Tx descriptor */
1.56      thorpej   294:        int     sc_txwin;               /* Tx descriptors since last intr */
1.1       thorpej   295:
                    296:        struct sip_txsq sc_txfreeq;     /* free Tx descsofts */
                    297:        struct sip_txsq sc_txdirtyq;    /* dirty Tx descsofts */
                    298:
1.106     pavel     299:        /* values of interface state at last init */
                    300:        struct {
                    301:                /* if_capenable */
                    302:                uint64_t        if_capenable;
                    303:                /* ec_capenable */
                    304:                int             ec_capenable;
                    305:                /* VLAN_ATTACHED */
                    306:                int             is_vlan;
                    307:        }       sc_prev;
                    308:
1.98      kim       309:        short   sc_if_flags;
                    310:
1.1       thorpej   311:        int     sc_rxptr;               /* next ready Rx descriptor/descsoft */
1.36      thorpej   312:        int     sc_rxdiscard;
                    313:        int     sc_rxlen;
                    314:        struct mbuf *sc_rxhead;
                    315:        struct mbuf *sc_rxtail;
                    316:        struct mbuf **sc_rxtailp;
1.115.4.1! ad        317:
        !           318:        int sc_ntxdesc;
        !           319:        int sc_ntxdesc_mask;
        !           320:
        !           321:        int sc_nrxdesc_mask;
        !           322:
        !           323:        const struct sip_parm {
        !           324:                const struct sip_regs {
        !           325:                        int r_rxcfg;
        !           326:                        int r_txcfg;
        !           327:                } p_regs;
        !           328:
        !           329:                const struct sip_bits {
        !           330:                        uint32_t b_txcfg_mxdma_8;
        !           331:                        uint32_t b_txcfg_mxdma_16;
        !           332:                        uint32_t b_txcfg_mxdma_32;
        !           333:                        uint32_t b_txcfg_mxdma_64;
        !           334:                        uint32_t b_txcfg_mxdma_128;
        !           335:                        uint32_t b_txcfg_mxdma_256;
        !           336:                        uint32_t b_txcfg_mxdma_512;
        !           337:                        uint32_t b_txcfg_flth_mask;
        !           338:                        uint32_t b_txcfg_drth_mask;
        !           339:
        !           340:                        uint32_t b_rxcfg_mxdma_8;
        !           341:                        uint32_t b_rxcfg_mxdma_16;
        !           342:                        uint32_t b_rxcfg_mxdma_32;
        !           343:                        uint32_t b_rxcfg_mxdma_64;
        !           344:                        uint32_t b_rxcfg_mxdma_128;
        !           345:                        uint32_t b_rxcfg_mxdma_256;
        !           346:                        uint32_t b_rxcfg_mxdma_512;
        !           347:
        !           348:                        uint32_t b_isr_txrcmp;
        !           349:                        uint32_t b_isr_rxrcmp;
        !           350:                        uint32_t b_isr_dperr;
        !           351:                        uint32_t b_isr_sserr;
        !           352:                        uint32_t b_isr_rmabt;
        !           353:                        uint32_t b_isr_rtabt;
        !           354:
        !           355:                        uint32_t b_cmdsts_size_mask;
        !           356:                } p_bits;
        !           357:                int             p_filtmem;
        !           358:                int             p_rxbuf_len;
        !           359:                bus_size_t      p_tx_dmamap_size;
        !           360:                int             p_ntxsegs;
        !           361:                int             p_ntxsegs_alloc;
        !           362:                int             p_nrxdesc;
        !           363:        } *sc_parm;
        !           364:
        !           365:        void (*sc_rxintr)(struct sip_softc *);
1.65      itojun    366:
                    367: #if NRND > 0
                    368:        rndsource_element_t rnd_source; /* random source */
                    369: #endif
1.1       thorpej   370: };
                    371:
1.115.4.1! ad        372: #define        sc_bits sc_parm->p_bits
        !           373: #define        sc_regs sc_parm->p_regs
        !           374:
        !           375: static const struct sip_parm sip_parm = {
        !           376:          .p_filtmem = OTHER_RFCR_NS_RFADDR_FILTMEM
        !           377:        , .p_rxbuf_len = MCLBYTES - 1   /* field width */
        !           378:        , .p_tx_dmamap_size = MCLBYTES
        !           379:        , .p_ntxsegs = 16
        !           380:        , .p_ntxsegs_alloc = SIP_NTXSEGS_ALLOC
        !           381:        , .p_nrxdesc = SIP_NRXDESC
        !           382:        , .p_bits = {
        !           383:                  .b_txcfg_mxdma_8      = 0x00200000    /*       8 bytes */
        !           384:                , .b_txcfg_mxdma_16     = 0x00300000    /*      16 bytes */
        !           385:                , .b_txcfg_mxdma_32     = 0x00400000    /*      32 bytes */
        !           386:                , .b_txcfg_mxdma_64     = 0x00500000    /*      64 bytes */
        !           387:                , .b_txcfg_mxdma_128    = 0x00600000    /*     128 bytes */
        !           388:                , .b_txcfg_mxdma_256    = 0x00700000    /*     256 bytes */
        !           389:                , .b_txcfg_mxdma_512    = 0x00000000    /*     512 bytes */
        !           390:                , .b_txcfg_flth_mask    = 0x00003f00    /* Tx fill threshold */
        !           391:                , .b_txcfg_drth_mask    = 0x0000003f    /* Tx drain threshold */
        !           392:
        !           393:                , .b_rxcfg_mxdma_8      = 0x00200000    /*       8 bytes */
        !           394:                , .b_rxcfg_mxdma_16     = 0x00300000    /*      16 bytes */
        !           395:                , .b_rxcfg_mxdma_32     = 0x00400000    /*      32 bytes */
        !           396:                , .b_rxcfg_mxdma_64     = 0x00500000    /*      64 bytes */
        !           397:                , .b_rxcfg_mxdma_128    = 0x00600000    /*     128 bytes */
        !           398:                , .b_rxcfg_mxdma_256    = 0x00700000    /*     256 bytes */
        !           399:                , .b_rxcfg_mxdma_512    = 0x00000000    /*     512 bytes */
        !           400:
        !           401:                , .b_isr_txrcmp = 0x02000000    /* transmit reset complete */
        !           402:                , .b_isr_rxrcmp = 0x01000000    /* receive reset complete */
        !           403:                , .b_isr_dperr  = 0x00800000    /* detected parity error */
        !           404:                , .b_isr_sserr  = 0x00400000    /* signalled system error */
        !           405:                , .b_isr_rmabt  = 0x00200000    /* received master abort */
        !           406:                , .b_isr_rtabt  = 0x00100000    /* received target abort */
        !           407:                , .b_cmdsts_size_mask = OTHER_CMDSTS_SIZE_MASK
        !           408:        }
        !           409:        , .p_regs = {
        !           410:                .r_rxcfg = OTHER_SIP_RXCFG,
        !           411:                .r_txcfg = OTHER_SIP_TXCFG
        !           412:        }
        !           413: }, gsip_parm = {
        !           414:          .p_filtmem = DP83820_RFCR_NS_RFADDR_FILTMEM
        !           415:        , .p_rxbuf_len = MCLBYTES - 8
        !           416:        , .p_tx_dmamap_size = ETHER_MAX_LEN_JUMBO
        !           417:        , .p_ntxsegs = 64
        !           418:        , .p_ntxsegs_alloc = GSIP_NTXSEGS_ALLOC
        !           419:        , .p_nrxdesc = GSIP_NRXDESC
        !           420:        , .p_bits = {
        !           421:                  .b_txcfg_mxdma_8      = 0x00100000    /*       8 bytes */
        !           422:                , .b_txcfg_mxdma_16     = 0x00200000    /*      16 bytes */
        !           423:                , .b_txcfg_mxdma_32     = 0x00300000    /*      32 bytes */
        !           424:                , .b_txcfg_mxdma_64     = 0x00400000    /*      64 bytes */
        !           425:                , .b_txcfg_mxdma_128    = 0x00500000    /*     128 bytes */
        !           426:                , .b_txcfg_mxdma_256    = 0x00600000    /*     256 bytes */
        !           427:                , .b_txcfg_mxdma_512    = 0x00700000    /*     512 bytes */
        !           428:                , .b_txcfg_flth_mask    = 0x0000ff00    /* Fx fill threshold */
        !           429:                , .b_txcfg_drth_mask    = 0x000000ff    /* Tx drain threshold */
        !           430:
        !           431:                , .b_rxcfg_mxdma_8      = 0x00100000    /*       8 bytes */
        !           432:                , .b_rxcfg_mxdma_16     = 0x00200000    /*      16 bytes */
        !           433:                , .b_rxcfg_mxdma_32     = 0x00300000    /*      32 bytes */
        !           434:                , .b_rxcfg_mxdma_64     = 0x00400000    /*      64 bytes */
        !           435:                , .b_rxcfg_mxdma_128    = 0x00500000    /*     128 bytes */
        !           436:                , .b_rxcfg_mxdma_256    = 0x00600000    /*     256 bytes */
        !           437:                , .b_rxcfg_mxdma_512    = 0x00700000    /*     512 bytes */
        !           438:
        !           439:                , .b_isr_txrcmp = 0x00400000    /* transmit reset complete */
        !           440:                , .b_isr_rxrcmp = 0x00200000    /* receive reset complete */
        !           441:                , .b_isr_dperr  = 0x00100000    /* detected parity error */
        !           442:                , .b_isr_sserr  = 0x00080000    /* signalled system error */
        !           443:                , .b_isr_rmabt  = 0x00040000    /* received master abort */
        !           444:                , .b_isr_rtabt  = 0x00020000    /* received target abort */
        !           445:                , .b_cmdsts_size_mask = DP83820_CMDSTS_SIZE_MASK
        !           446:        }
        !           447:        , .p_regs = {
        !           448:                .r_rxcfg = DP83820_SIP_RXCFG,
        !           449:                .r_txcfg = DP83820_SIP_TXCFG
        !           450:        }
        !           451: };
        !           452:
        !           453: static inline int
        !           454: sip_nexttx(const struct sip_softc *sc, int x)
        !           455: {
        !           456:        return (x + 1) & sc->sc_ntxdesc_mask;
        !           457: }
        !           458:
        !           459: static inline int
        !           460: sip_nextrx(const struct sip_softc *sc, int x)
        !           461: {
        !           462:        return (x + 1) & sc->sc_nrxdesc_mask;
        !           463: }
        !           464:
        !           465: /* 83820 only */
        !           466: static inline void
        !           467: sip_rxchain_reset(struct sip_softc *sc)
        !           468: {
        !           469:        sc->sc_rxtailp = &sc->sc_rxhead;
        !           470:        *sc->sc_rxtailp = NULL;
        !           471:        sc->sc_rxlen = 0;
        !           472: }
        !           473:
        !           474: /* 83820 only */
        !           475: static inline void
        !           476: sip_rxchain_link(struct sip_softc *sc, struct mbuf *m)
        !           477: {
        !           478:        *sc->sc_rxtailp = sc->sc_rxtail = m;
        !           479:        sc->sc_rxtailp = &m->m_next;
        !           480: }
1.36      thorpej   481:
1.30      thorpej   482: #ifdef SIP_EVENT_COUNTERS
                    483: #define        SIP_EVCNT_INCR(ev)      (ev)->ev_count++
                    484: #else
                    485: #define        SIP_EVCNT_INCR(ev)      /* nothing */
                    486: #endif
                    487:
1.1       thorpej   488: #define        SIP_CDTXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDTXOFF((x)))
                    489: #define        SIP_CDRXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDRXOFF((x)))
                    490:
1.115.4.1! ad        491: static inline void
        !           492: sip_cdtxsync(struct sip_softc *sc, const int x0, const int n0, const int ops)
        !           493: {
        !           494:        int x, n;
        !           495:
        !           496:        x = x0;
        !           497:        n = n0;
        !           498:
        !           499:        /* If it will wrap around, sync to the end of the ring. */
        !           500:        if (x + n > sc->sc_ntxdesc) {
        !           501:                bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
        !           502:                    SIP_CDTXOFF(x), sizeof(struct sip_desc) *
        !           503:                    (sc->sc_ntxdesc - x), ops);
        !           504:                n -= (sc->sc_ntxdesc - x);
        !           505:                x = 0;
        !           506:        }
        !           507:
        !           508:        /* Now sync whatever is left. */
        !           509:        bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
        !           510:            SIP_CDTXOFF(x), sizeof(struct sip_desc) * n, ops);
        !           511: }
        !           512:
        !           513: static inline void
        !           514: sip_cdrxsync(struct sip_softc *sc, int x, int ops)
        !           515: {
        !           516:        bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
        !           517:            SIP_CDRXOFF(x), sizeof(struct sip_desc), ops);
        !           518: }
1.1       thorpej   519:
1.115.4.1! ad        520: #if 0
1.31      thorpej   521: #ifdef DP83820
1.115.4.1! ad        522:        u_int32_t       sipd_bufptr;    /* pointer to DMA segment */
        !           523:        u_int32_t       sipd_cmdsts;    /* command/status word */
1.31      thorpej   524: #else
1.115.4.1! ad        525:        u_int32_t       sipd_cmdsts;    /* command/status word */
        !           526:        u_int32_t       sipd_bufptr;    /* pointer to DMA segment */
        !           527: #endif /* DP83820 */
        !           528: #endif /* 0 */
        !           529:
        !           530: static inline volatile uint32_t *
        !           531: sipd_cmdsts(struct sip_softc *sc, struct sip_desc *sipd)
        !           532: {
        !           533:        return &sipd->sipd_cbs[(sc->sc_gigabit) ? 1 : 0];
        !           534: }
        !           535:
        !           536: static inline volatile uint32_t *
        !           537: sipd_bufptr(struct sip_softc *sc, struct sip_desc *sipd)
        !           538: {
        !           539:        return &sipd->sipd_cbs[(sc->sc_gigabit) ? 0 : 1];
        !           540: }
        !           541:
        !           542: static inline void
        !           543: sip_init_rxdesc(struct sip_softc *sc, int x)
        !           544: {
        !           545:        struct sip_rxsoft *rxs = &sc->sc_rxsoft[x];
        !           546:        struct sip_desc *sipd = &sc->sc_rxdescs[x];
        !           547:
        !           548:        sipd->sipd_link = htole32(SIP_CDRXADDR(sc, sip_nextrx(sc, x)));
        !           549:        *sipd_bufptr(sc, sipd) = htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr);
        !           550:        *sipd_cmdsts(sc, sipd) = htole32(CMDSTS_INTR |
        !           551:            (sc->sc_parm->p_rxbuf_len & sc->sc_bits.b_cmdsts_size_mask));
        !           552:        sipd->sipd_extsts = 0;
        !           553:        sip_cdrxsync(sc, x, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !           554: }
1.1       thorpej   555:
1.45      thorpej   556: #define        SIP_CHIP_VERS(sc, v, p, r)                                      \
                    557:        ((sc)->sc_model->sip_vendor == (v) &&                           \
                    558:         (sc)->sc_model->sip_product == (p) &&                          \
                    559:         (sc)->sc_rev == (r))
                    560:
                    561: #define        SIP_CHIP_MODEL(sc, v, p)                                        \
                    562:        ((sc)->sc_model->sip_vendor == (v) &&                           \
                    563:         (sc)->sc_model->sip_product == (p))
                    564:
                    565: #define        SIP_SIS900_REV(sc, rev)                                         \
                    566:        SIP_CHIP_VERS((sc), PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, (rev))
                    567:
1.14      tsutsui   568: #define SIP_TIMEOUT 1000
                    569:
1.115.4.1! ad        570: static void    sipcom_start(struct ifnet *);
        !           571: static void    sipcom_watchdog(struct ifnet *);
        !           572: static int     sipcom_ioctl(struct ifnet *, u_long, void *);
        !           573: static int     sipcom_init(struct ifnet *);
        !           574: static void    sipcom_stop(struct ifnet *, int);
        !           575:
        !           576: static void    sipcom_shutdown(void *);
        !           577:
        !           578: static bool    sipcom_reset(struct sip_softc *);
        !           579: static void    sipcom_rxdrain(struct sip_softc *);
        !           580: static int     sipcom_add_rxbuf(struct sip_softc *, int);
        !           581: static void    sipcom_read_eeprom(struct sip_softc *, int, int,
1.95      thorpej   582:                                      u_int16_t *);
1.115.4.1! ad        583: static void    sipcom_tick(void *);
1.1       thorpej   584:
1.115.4.1! ad        585: static void    sipcom_sis900_set_filter(struct sip_softc *);
        !           586: static void    sipcom_dp83815_set_filter(struct sip_softc *);
1.15      thorpej   587:
1.115.4.1! ad        588: static void    sipcom_dp83820_read_macaddr(struct sip_softc *,
1.95      thorpej   589:                    const struct pci_attach_args *, u_int8_t *);
1.115.4.1! ad        590: static void    sipcom_sis900_eeprom_delay(struct sip_softc *sc);
        !           591: static void    sipcom_sis900_read_macaddr(struct sip_softc *,
1.95      thorpej   592:                    const struct pci_attach_args *, u_int8_t *);
1.115.4.1! ad        593: static void    sipcom_dp83815_read_macaddr(struct sip_softc *,
1.95      thorpej   594:                    const struct pci_attach_args *, u_int8_t *);
1.25      briggs    595:
1.115.4.1! ad        596: static int     sipcom_intr(void *);
        !           597: static void    sipcom_txintr(struct sip_softc *);
        !           598: static void    sip_rxintr(struct sip_softc *);
        !           599: static void    gsip_rxintr(struct sip_softc *);
        !           600:
        !           601: static int     sipcom_dp83820_mii_readreg(struct device *, int, int);
        !           602: static void    sipcom_dp83820_mii_writereg(struct device *, int, int, int);
        !           603: static void    sipcom_dp83820_mii_statchg(struct device *);
        !           604:
        !           605: static int     sipcom_sis900_mii_readreg(struct device *, int, int);
        !           606: static void    sipcom_sis900_mii_writereg(struct device *, int, int, int);
        !           607: static void    sipcom_sis900_mii_statchg(struct device *);
        !           608:
        !           609: static int     sipcom_dp83815_mii_readreg(struct device *, int, int);
        !           610: static void    sipcom_dp83815_mii_writereg(struct device *, int, int, int);
        !           611: static void    sipcom_dp83815_mii_statchg(struct device *);
        !           612:
        !           613: static int     sipcom_mediachange(struct ifnet *);
        !           614: static void    sipcom_mediastatus(struct ifnet *, struct ifmediareq *);
        !           615:
        !           616: static int     sipcom_match(struct device *, struct cfdata *, void *);
        !           617: static void    sipcom_attach(struct device *, struct device *, void *);
        !           618: static void    sipcom_do_detach(device_t, enum sip_attach_stage);
        !           619: static int     sipcom_detach(device_t, int);
        !           620: static bool    sipcom_resume(device_t);
1.1       thorpej   621:
1.115.4.1! ad        622: int    gsip_copy_small = 0;
        !           623: int    sip_copy_small = 0;
1.2       thorpej   624:
1.71      thorpej   625: CFATTACH_DECL(gsip, sizeof(struct sip_softc),
1.115.4.1! ad        626:     sipcom_match, sipcom_attach, sipcom_detach, NULL);
1.71      thorpej   627: CFATTACH_DECL(sip, sizeof(struct sip_softc),
1.115.4.1! ad        628:     sipcom_match, sipcom_attach, sipcom_detach, NULL);
1.1       thorpej   629:
1.15      thorpej   630: /*
                    631:  * Descriptions of the variants of the SiS900.
                    632:  */
                    633: struct sip_variant {
1.28      thorpej   634:        int     (*sipv_mii_readreg)(struct device *, int, int);
                    635:        void    (*sipv_mii_writereg)(struct device *, int, int, int);
                    636:        void    (*sipv_mii_statchg)(struct device *);
                    637:        void    (*sipv_set_filter)(struct sip_softc *);
1.101     perry     638:        void    (*sipv_read_macaddr)(struct sip_softc *,
1.44      thorpej   639:                    const struct pci_attach_args *, u_int8_t *);
1.15      thorpej   640: };
                    641:
1.115.4.1! ad        642: static u_int32_t sipcom_mii_bitbang_read(struct device *);
        !           643: static void    sipcom_mii_bitbang_write(struct device *, u_int32_t);
1.29      thorpej   644:
1.115.4.1! ad        645: static const struct mii_bitbang_ops sipcom_mii_bitbang_ops = {
        !           646:        sipcom_mii_bitbang_read,
        !           647:        sipcom_mii_bitbang_write,
1.29      thorpej   648:        {
                    649:                EROMAR_MDIO,            /* MII_BIT_MDO */
                    650:                EROMAR_MDIO,            /* MII_BIT_MDI */
                    651:                EROMAR_MDC,             /* MII_BIT_MDC */
                    652:                EROMAR_MDDIR,           /* MII_BIT_DIR_HOST_PHY */
                    653:                0,                      /* MII_BIT_DIR_PHY_HOST */
                    654:        }
                    655: };
                    656:
1.115.4.1! ad        657: static const struct sip_variant sipcom_variant_dp83820 = {
        !           658:        sipcom_dp83820_mii_readreg,
        !           659:        sipcom_dp83820_mii_writereg,
        !           660:        sipcom_dp83820_mii_statchg,
        !           661:        sipcom_dp83815_set_filter,
        !           662:        sipcom_dp83820_read_macaddr,
1.29      thorpej   663: };
1.115.4.1! ad        664:
        !           665: static const struct sip_variant sipcom_variant_sis900 = {
        !           666:        sipcom_sis900_mii_readreg,
        !           667:        sipcom_sis900_mii_writereg,
        !           668:        sipcom_sis900_mii_statchg,
        !           669:        sipcom_sis900_set_filter,
        !           670:        sipcom_sis900_read_macaddr,
1.15      thorpej   671: };
                    672:
1.115.4.1! ad        673: static const struct sip_variant sipcom_variant_dp83815 = {
        !           674:        sipcom_dp83815_mii_readreg,
        !           675:        sipcom_dp83815_mii_writereg,
        !           676:        sipcom_dp83815_mii_statchg,
        !           677:        sipcom_dp83815_set_filter,
        !           678:        sipcom_dp83815_read_macaddr,
1.15      thorpej   679: };
1.115.4.1! ad        680:
1.15      thorpej   681:
                    682: /*
                    683:  * Devices supported by this driver.
                    684:  */
1.95      thorpej   685: static const struct sip_product {
1.15      thorpej   686:        pci_vendor_id_t         sip_vendor;
                    687:        pci_product_id_t        sip_product;
                    688:        const char              *sip_name;
                    689:        const struct sip_variant *sip_variant;
1.115.4.1! ad        690:        int                     sip_gigabit;
        !           691: } sipcom_products[] = {
1.29      thorpej   692:        { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83820,
                    693:          "NatSemi DP83820 Gigabit Ethernet",
1.115.4.1! ad        694:          &sipcom_variant_dp83820, 1 },
1.15      thorpej   695:        { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_900,
                    696:          "SiS 900 10/100 Ethernet",
1.115.4.1! ad        697:          &sipcom_variant_sis900, 0 },
1.15      thorpej   698:        { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_7016,
                    699:          "SiS 7016 10/100 Ethernet",
1.115.4.1! ad        700:          &sipcom_variant_sis900, 0 },
1.15      thorpej   701:
                    702:        { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83815,
                    703:          "NatSemi DP83815 10/100 Ethernet",
1.115.4.1! ad        704:          &sipcom_variant_dp83815, 0 },
1.15      thorpej   705:
                    706:        { 0,                    0,
                    707:          NULL,
1.115.4.1! ad        708:          NULL, 0 },
1.15      thorpej   709: };
                    710:
1.28      thorpej   711: static const struct sip_product *
1.115.4.1! ad        712: sipcom_lookup(const struct pci_attach_args *pa, bool gigabit)
1.1       thorpej   713: {
                    714:        const struct sip_product *sip;
                    715:
1.115.4.1! ad        716:        for (sip = sipcom_products; sip->sip_name != NULL; sip++) {
1.1       thorpej   717:                if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor &&
1.115.4.1! ad        718:                    PCI_PRODUCT(pa->pa_id) == sip->sip_product &&
        !           719:                    sip->sip_gigabit == gigabit)
        !           720:                        return sip;
1.1       thorpej   721:        }
1.115.4.1! ad        722:        return NULL;
1.1       thorpej   723: }
                    724:
1.60      thorpej   725: /*
                    726:  * I really hate stupid hardware vendors.  There's a bit in the EEPROM
                    727:  * which indicates if the card can do 64-bit data transfers.  Unfortunately,
                    728:  * several vendors of 32-bit cards fail to clear this bit in the EEPROM,
                    729:  * which means we try to use 64-bit data transfers on those cards if we
                    730:  * happen to be plugged into a 32-bit slot.
                    731:  *
                    732:  * What we do is use this table of cards known to be 64-bit cards.  If
                    733:  * you have a 64-bit card who's subsystem ID is not listed in this table,
                    734:  * send the output of "pcictl dump ..." of the device to me so that your
                    735:  * card will use the 64-bit data path when plugged into a 64-bit slot.
                    736:  *
1.85      keihan    737:  *     -- Jason R. Thorpe <thorpej@NetBSD.org>
1.60      thorpej   738:  *        June 30, 2002
                    739:  */
                    740: static int
1.115.4.1! ad        741: sipcom_check_64bit(const struct pci_attach_args *pa)
1.60      thorpej   742: {
                    743:        static const struct {
                    744:                pci_vendor_id_t c64_vendor;
                    745:                pci_product_id_t c64_product;
                    746:        } card64[] = {
                    747:                /* Asante GigaNIX */
                    748:                { 0x128a,       0x0002 },
1.61      thorpej   749:
                    750:                /* Accton EN1407-T, Planex GN-1000TE */
                    751:                { 0x1113,       0x1407 },
1.60      thorpej   752:
1.69      thorpej   753:                /* Netgear GA-621 */
                    754:                { 0x1385,       0x621a },
1.77      briggs    755:
                    756:                /* SMC EZ Card */
                    757:                { 0x10b8,       0x9462 },
1.69      thorpej   758:
1.60      thorpej   759:                { 0, 0}
                    760:        };
                    761:        pcireg_t subsys;
                    762:        int i;
                    763:
                    764:        subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
                    765:
                    766:        for (i = 0; card64[i].c64_vendor != 0; i++) {
                    767:                if (PCI_VENDOR(subsys) == card64[i].c64_vendor &&
                    768:                    PCI_PRODUCT(subsys) == card64[i].c64_product)
                    769:                        return (1);
                    770:        }
                    771:
                    772:        return (0);
                    773: }
                    774:
1.95      thorpej   775: static int
1.115.4.1! ad        776: sipcom_match(struct device *parent, struct cfdata *cf, void *aux)
1.1       thorpej   777: {
                    778:        struct pci_attach_args *pa = aux;
                    779:
1.115.4.1! ad        780:        if (sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0) != NULL)
        !           781:                return 1;
1.1       thorpej   782:
1.115.4.1! ad        783:        return 0;
        !           784: }
        !           785:
        !           786: static void
        !           787: sipcom_dp83820_attach(struct sip_softc *sc, struct pci_attach_args *pa)
        !           788: {
        !           789:        u_int32_t reg;
        !           790:        int i;
        !           791:
        !           792:        /*
        !           793:         * Cause the chip to load configuration data from the EEPROM.
        !           794:         */
        !           795:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_PTSCR, PTSCR_EELOAD_EN);
        !           796:        for (i = 0; i < 10000; i++) {
        !           797:                delay(10);
        !           798:                if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &
        !           799:                    PTSCR_EELOAD_EN) == 0)
        !           800:                        break;
        !           801:        }
        !           802:        if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &
        !           803:            PTSCR_EELOAD_EN) {
        !           804:                printf("%s: timeout loading configuration from EEPROM\n",
        !           805:                    sc->sc_dev.dv_xname);
        !           806:                return;
        !           807:        }
        !           808:
        !           809:        sc->sc_gpior = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_GPIOR);
        !           810:
        !           811:        reg = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG);
        !           812:        if (reg & CFG_PCI64_DET) {
        !           813:                printf("%s: 64-bit PCI slot detected", sc->sc_dev.dv_xname);
        !           814:                /*
        !           815:                 * Check to see if this card is 64-bit.  If so, enable 64-bit
        !           816:                 * data transfers.
        !           817:                 *
        !           818:                 * We can't use the DATA64_EN bit in the EEPROM, because
        !           819:                 * vendors of 32-bit cards fail to clear that bit in many
        !           820:                 * cases (yet the card still detects that it's in a 64-bit
        !           821:                 * slot; go figure).
        !           822:                 */
        !           823:                if (sipcom_check_64bit(pa)) {
        !           824:                        sc->sc_cfg |= CFG_DATA64_EN;
        !           825:                        printf(", using 64-bit data transfers");
        !           826:                }
        !           827:                printf("\n");
        !           828:        }
        !           829:
        !           830:        /*
        !           831:         * XXX Need some PCI flags indicating support for
        !           832:         * XXX 64-bit addressing.
        !           833:         */
        !           834: #if 0
        !           835:        if (reg & CFG_M64ADDR)
        !           836:                sc->sc_cfg |= CFG_M64ADDR;
        !           837:        if (reg & CFG_T64ADDR)
        !           838:                sc->sc_cfg |= CFG_T64ADDR;
        !           839: #endif
        !           840:
        !           841:        if (reg & (CFG_TBI_EN|CFG_EXT_125)) {
        !           842:                const char *sep = "";
        !           843:                printf("%s: using ", sc->sc_dev.dv_xname);
        !           844:                if (reg & CFG_EXT_125) {
        !           845:                        sc->sc_cfg |= CFG_EXT_125;
        !           846:                        printf("%s125MHz clock", sep);
        !           847:                        sep = ", ";
        !           848:                }
        !           849:                if (reg & CFG_TBI_EN) {
        !           850:                        sc->sc_cfg |= CFG_TBI_EN;
        !           851:                        printf("%sten-bit interface", sep);
        !           852:                        sep = ", ";
        !           853:                }
        !           854:                printf("\n");
        !           855:        }
        !           856:        if ((pa->pa_flags & PCI_FLAGS_MRM_OKAY) == 0 ||
        !           857:            (reg & CFG_MRM_DIS) != 0)
        !           858:                sc->sc_cfg |= CFG_MRM_DIS;
        !           859:        if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0 ||
        !           860:            (reg & CFG_MWI_DIS) != 0)
        !           861:                sc->sc_cfg |= CFG_MWI_DIS;
        !           862:
        !           863:        /*
        !           864:         * Use the extended descriptor format on the DP83820.  This
        !           865:         * gives us an interface to VLAN tagging and IPv4/TCP/UDP
        !           866:         * checksumming.
        !           867:         */
        !           868:        sc->sc_cfg |= CFG_EXTSTS_EN;
        !           869: }
        !           870:
        !           871: static int
        !           872: sipcom_detach(device_t self, int flags)
        !           873: {
        !           874:        int s;
        !           875:
        !           876:        s = splnet();
        !           877:        sipcom_do_detach(self, SIP_ATTACH_FIN);
        !           878:        splx(s);
        !           879:
        !           880:        return 0;
        !           881: }
        !           882:
        !           883: static void
        !           884: sipcom_do_detach(device_t self, enum sip_attach_stage stage)
        !           885: {
        !           886:        int i;
        !           887:        struct sip_softc *sc = device_private(self);
        !           888:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        !           889:
        !           890:        /*
        !           891:         * Free any resources we've allocated during attach.
        !           892:         * Do this in reverse order and fall through.
        !           893:         */
        !           894:        switch (stage) {
        !           895:        case SIP_ATTACH_FIN:
        !           896:                sipcom_stop(ifp, 1);
        !           897:                pmf_device_deregister(self);
        !           898: #ifdef SIP_EVENT_COUNTERS
        !           899:                /*
        !           900:                 * Attach event counters.
        !           901:                 */
        !           902:                evcnt_detach(&sc->sc_ev_txforceintr);
        !           903:                evcnt_detach(&sc->sc_ev_txdstall);
        !           904:                evcnt_detach(&sc->sc_ev_txsstall);
        !           905:                evcnt_detach(&sc->sc_ev_hiberr);
        !           906:                evcnt_detach(&sc->sc_ev_rxintr);
        !           907:                evcnt_detach(&sc->sc_ev_txiintr);
        !           908:                evcnt_detach(&sc->sc_ev_txdintr);
        !           909:                if (!sc->sc_gigabit) {
        !           910:                        evcnt_detach(&sc->sc_ev_rxpause);
        !           911:                } else {
        !           912:                        evcnt_detach(&sc->sc_ev_txudpsum);
        !           913:                        evcnt_detach(&sc->sc_ev_txtcpsum);
        !           914:                        evcnt_detach(&sc->sc_ev_txipsum);
        !           915:                        evcnt_detach(&sc->sc_ev_rxudpsum);
        !           916:                        evcnt_detach(&sc->sc_ev_rxtcpsum);
        !           917:                        evcnt_detach(&sc->sc_ev_rxipsum);
        !           918:                        evcnt_detach(&sc->sc_ev_txpause);
        !           919:                        evcnt_detach(&sc->sc_ev_rxpause);
        !           920:                }
        !           921: #endif /* SIP_EVENT_COUNTERS */
        !           922:
        !           923: #if NRND > 0
        !           924:                rnd_detach_source(&sc->rnd_source);
        !           925: #endif
        !           926:
        !           927:                ether_ifdetach(ifp);
        !           928:                if_detach(ifp);
        !           929:                mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
        !           930:
        !           931:                if (sc->sc_sdhook != NULL)
        !           932:                        shutdownhook_disestablish(sc->sc_sdhook);
        !           933:
        !           934:                /*FALLTHROUGH*/
        !           935:        case SIP_ATTACH_CREATE_RXMAP:
        !           936:                for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
        !           937:                        if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
        !           938:                                bus_dmamap_destroy(sc->sc_dmat,
        !           939:                                    sc->sc_rxsoft[i].rxs_dmamap);
        !           940:                }
        !           941:                /*FALLTHROUGH*/
        !           942:        case SIP_ATTACH_CREATE_TXMAP:
        !           943:                for (i = 0; i < SIP_TXQUEUELEN; i++) {
        !           944:                        if (sc->sc_txsoft[i].txs_dmamap != NULL)
        !           945:                                bus_dmamap_destroy(sc->sc_dmat,
        !           946:                                    sc->sc_txsoft[i].txs_dmamap);
        !           947:                }
        !           948:                /*FALLTHROUGH*/
        !           949:        case SIP_ATTACH_LOAD_MAP:
        !           950:                bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
        !           951:                /*FALLTHROUGH*/
        !           952:        case SIP_ATTACH_CREATE_MAP:
        !           953:                bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
        !           954:                /*FALLTHROUGH*/
        !           955:        case SIP_ATTACH_MAP_MEM:
        !           956:                bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data,
        !           957:                    sizeof(struct sip_control_data));
        !           958:                /*FALLTHROUGH*/
        !           959:        case SIP_ATTACH_ALLOC_MEM:
        !           960:                bus_dmamem_free(sc->sc_dmat, &sc->sc_seg, 1);
        !           961:                /* FALLTHROUGH*/
        !           962:        case SIP_ATTACH_INTR:
        !           963:                pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
        !           964:                /* FALLTHROUGH*/
        !           965:        case SIP_ATTACH_MAP:
        !           966:                bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
        !           967:                break;
        !           968:        default:
        !           969:                break;
        !           970:        }
        !           971:        return;
        !           972: }
        !           973:
        !           974: static bool
        !           975: sipcom_resume(device_t self)
        !           976: {
        !           977:        struct sip_softc *sc = device_private(self);
        !           978:
        !           979:        return sipcom_reset(sc);
1.1       thorpej   980: }
                    981:
1.95      thorpej   982: static void
1.115.4.1! ad        983: sipcom_attach(device_t parent, device_t self, void *aux)
1.1       thorpej   984: {
                    985:        struct sip_softc *sc = (struct sip_softc *) self;
                    986:        struct pci_attach_args *pa = aux;
                    987:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                    988:        pci_chipset_tag_t pc = pa->pa_pc;
                    989:        pci_intr_handle_t ih;
                    990:        const char *intrstr = NULL;
                    991:        bus_space_tag_t iot, memt;
                    992:        bus_space_handle_t ioh, memh;
1.115.4.1! ad        993:        bus_size_t iosz, memsz;
1.1       thorpej   994:        int ioh_valid, memh_valid;
                    995:        int i, rseg, error;
                    996:        const struct sip_product *sip;
1.14      tsutsui   997:        u_int8_t enaddr[ETHER_ADDR_LEN];
1.108     christos  998:        pcireg_t pmreg;
1.29      thorpej   999:        pcireg_t memtype;
1.115.4.1! ad       1000:        bus_size_t tx_dmamap_size;
        !          1001:        int ntxsegs_alloc;
        !          1002:        cfdata_t cf = device_cfdata(self);
1.1       thorpej  1003:
1.113     ad       1004:        callout_init(&sc->sc_tick_ch, 0);
1.9       thorpej  1005:
1.115.4.1! ad       1006:        sip = sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0);
1.1       thorpej  1007:        if (sip == NULL) {
                   1008:                printf("\n");
1.115.4.1! ad       1009:                panic("%s: impossible", __func__);
        !          1010:        }
        !          1011:        sc->sc_gigabit = sip->sip_gigabit;
        !          1012:
        !          1013:        sc->sc_pc = pc;
        !          1014:
        !          1015:        if (sc->sc_gigabit) {
        !          1016:                sc->sc_rxintr = gsip_rxintr;
        !          1017:                sc->sc_parm = &gsip_parm;
        !          1018:        } else {
        !          1019:                sc->sc_rxintr = sip_rxintr;
        !          1020:                sc->sc_parm = &sip_parm;
1.1       thorpej  1021:        }
1.115.4.1! ad       1022:        tx_dmamap_size = sc->sc_parm->p_tx_dmamap_size;
        !          1023:        ntxsegs_alloc = sc->sc_parm->p_ntxsegs_alloc;
        !          1024:        sc->sc_ntxdesc = SIP_TXQUEUELEN * ntxsegs_alloc;
        !          1025:        sc->sc_ntxdesc_mask = sc->sc_ntxdesc - 1;
        !          1026:        sc->sc_nrxdesc_mask = sc->sc_parm->p_nrxdesc - 1;
        !          1027:
1.45      thorpej  1028:        sc->sc_rev = PCI_REVISION(pa->pa_class);
1.1       thorpej  1029:
1.50      briggs   1030:        printf(": %s, rev %#02x\n", sip->sip_name, sc->sc_rev);
1.1       thorpej  1031:
1.15      thorpej  1032:        sc->sc_model = sip;
1.5       thorpej  1033:
1.1       thorpej  1034:        /*
1.46      thorpej  1035:         * XXX Work-around broken PXE firmware on some boards.
                   1036:         *
                   1037:         * The DP83815 shares an address decoder with the MEM BAR
                   1038:         * and the ROM BAR.  Make sure the ROM BAR is disabled,
                   1039:         * so that memory mapped access works.
                   1040:         */
                   1041:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM,
                   1042:            pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM) &
                   1043:            ~PCI_MAPREG_ROM_ENABLE);
                   1044:
                   1045:        /*
1.1       thorpej  1046:         * Map the device.
                   1047:         */
                   1048:        ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA,
                   1049:            PCI_MAPREG_TYPE_IO, 0,
1.115.4.1! ad       1050:            &iot, &ioh, NULL, &iosz) == 0);
        !          1051:        if (sc->sc_gigabit) {
        !          1052:                memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIP_PCI_CFGMA);
        !          1053:                switch (memtype) {
        !          1054:                case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !          1055:                case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !          1056:                        memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
        !          1057:                            memtype, 0, &memt, &memh, NULL, &memsz) == 0);
        !          1058:                        break;
        !          1059:                default:
        !          1060:                        memh_valid = 0;
        !          1061:                }
        !          1062:        } else {
1.29      thorpej  1063:                memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
1.115.4.1! ad       1064:                    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
        !          1065:                    &memt, &memh, NULL, &memsz) == 0);
1.29      thorpej  1066:        }
                   1067:
1.1       thorpej  1068:        if (memh_valid) {
                   1069:                sc->sc_st = memt;
                   1070:                sc->sc_sh = memh;
1.115.4.1! ad       1071:                sc->sc_sz = memsz;
1.1       thorpej  1072:        } else if (ioh_valid) {
                   1073:                sc->sc_st = iot;
                   1074:                sc->sc_sh = ioh;
1.115.4.1! ad       1075:                sc->sc_sz = iosz;
1.1       thorpej  1076:        } else {
                   1077:                printf("%s: unable to map device registers\n",
                   1078:                    sc->sc_dev.dv_xname);
                   1079:                return;
                   1080:        }
                   1081:
                   1082:        sc->sc_dmat = pa->pa_dmat;
                   1083:
1.48      thorpej  1084:        /*
                   1085:         * Make sure bus mastering is enabled.  Also make sure
                   1086:         * Write/Invalidate is enabled if we're allowed to use it.
                   1087:         */
                   1088:        pmreg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
                   1089:        if (pa->pa_flags & PCI_FLAGS_MWI_OKAY)
                   1090:                pmreg |= PCI_COMMAND_INVALIDATE_ENABLE;
1.1       thorpej  1091:        pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
1.48      thorpej  1092:            pmreg | PCI_COMMAND_MASTER_ENABLE);
1.1       thorpej  1093:
1.108     christos 1094:        /* power up chip */
                   1095:        if ((error = pci_activate(pa->pa_pc, pa->pa_tag, sc,
                   1096:            NULL)) && error != EOPNOTSUPP) {
                   1097:                aprint_error("%s: cannot activate %d\n", sc->sc_dev.dv_xname,
                   1098:                    error);
                   1099:                return;
1.1       thorpej  1100:        }
                   1101:
                   1102:        /*
                   1103:         * Map and establish our interrupt.
                   1104:         */
1.23      sommerfe 1105:        if (pci_intr_map(pa, &ih)) {
1.1       thorpej  1106:                printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname);
                   1107:                return;
                   1108:        }
                   1109:        intrstr = pci_intr_string(pc, ih);
1.115.4.1! ad       1110:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sipcom_intr, sc);
1.1       thorpej  1111:        if (sc->sc_ih == NULL) {
                   1112:                printf("%s: unable to establish interrupt",
                   1113:                    sc->sc_dev.dv_xname);
                   1114:                if (intrstr != NULL)
                   1115:                        printf(" at %s", intrstr);
                   1116:                printf("\n");
1.115.4.1! ad       1117:                return sipcom_do_detach(self, SIP_ATTACH_MAP);
1.1       thorpej  1118:        }
                   1119:        printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
                   1120:
                   1121:        SIMPLEQ_INIT(&sc->sc_txfreeq);
                   1122:        SIMPLEQ_INIT(&sc->sc_txdirtyq);
                   1123:
                   1124:        /*
                   1125:         * Allocate the control data structures, and create and load the
                   1126:         * DMA map for it.
                   1127:         */
                   1128:        if ((error = bus_dmamem_alloc(sc->sc_dmat,
1.115.4.1! ad       1129:            sizeof(struct sip_control_data), PAGE_SIZE, 0, &sc->sc_seg, 1,
        !          1130:            &rseg, 0)) != 0) {
1.1       thorpej  1131:                printf("%s: unable to allocate control data, error = %d\n",
                   1132:                    sc->sc_dev.dv_xname, error);
1.115.4.1! ad       1133:                return sipcom_do_detach(self, SIP_ATTACH_INTR);
1.1       thorpej  1134:        }
                   1135:
1.115.4.1! ad       1136:        if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, rseg,
1.111     christos 1137:            sizeof(struct sip_control_data), (void **)&sc->sc_control_data,
1.115.4.1! ad       1138:            BUS_DMA_COHERENT|BUS_DMA_NOCACHE)) != 0) {
1.1       thorpej  1139:                printf("%s: unable to map control data, error = %d\n",
                   1140:                    sc->sc_dev.dv_xname, error);
1.115.4.1! ad       1141:                sipcom_do_detach(self, SIP_ATTACH_ALLOC_MEM);
1.1       thorpej  1142:        }
                   1143:
                   1144:        if ((error = bus_dmamap_create(sc->sc_dmat,
                   1145:            sizeof(struct sip_control_data), 1,
                   1146:            sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
                   1147:                printf("%s: unable to create control data DMA map, "
                   1148:                    "error = %d\n", sc->sc_dev.dv_xname, error);
1.115.4.1! ad       1149:                sipcom_do_detach(self, SIP_ATTACH_MAP_MEM);
1.1       thorpej  1150:        }
                   1151:
                   1152:        if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
                   1153:            sc->sc_control_data, sizeof(struct sip_control_data), NULL,
                   1154:            0)) != 0) {
                   1155:                printf("%s: unable to load control data DMA map, error = %d\n",
                   1156:                    sc->sc_dev.dv_xname, error);
1.115.4.1! ad       1157:                sipcom_do_detach(self, SIP_ATTACH_CREATE_MAP);
1.1       thorpej  1158:        }
                   1159:
                   1160:        /*
                   1161:         * Create the transmit buffer DMA maps.
                   1162:         */
                   1163:        for (i = 0; i < SIP_TXQUEUELEN; i++) {
1.115.4.1! ad       1164:                if ((error = bus_dmamap_create(sc->sc_dmat, tx_dmamap_size,
        !          1165:                    sc->sc_parm->p_ntxsegs, MCLBYTES, 0, 0,
1.1       thorpej  1166:                    &sc->sc_txsoft[i].txs_dmamap)) != 0) {
                   1167:                        printf("%s: unable to create tx DMA map %d, "
                   1168:                            "error = %d\n", sc->sc_dev.dv_xname, i, error);
1.115.4.1! ad       1169:                        sipcom_do_detach(self, SIP_ATTACH_CREATE_TXMAP);
1.1       thorpej  1170:                }
                   1171:        }
                   1172:
                   1173:        /*
                   1174:         * Create the receive buffer DMA maps.
                   1175:         */
1.115.4.1! ad       1176:        for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
1.1       thorpej  1177:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
                   1178:                    MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
                   1179:                        printf("%s: unable to create rx DMA map %d, "
                   1180:                            "error = %d\n", sc->sc_dev.dv_xname, i, error);
1.115.4.1! ad       1181:                        sipcom_do_detach(self, SIP_ATTACH_CREATE_RXMAP);
1.1       thorpej  1182:                }
1.2       thorpej  1183:                sc->sc_rxsoft[i].rxs_mbuf = NULL;
1.1       thorpej  1184:        }
                   1185:
                   1186:        /*
                   1187:         * Reset the chip to a known state.
                   1188:         */
1.115.4.1! ad       1189:        sipcom_reset(sc);
1.1       thorpej  1190:
                   1191:        /*
1.29      thorpej  1192:         * Read the Ethernet address from the EEPROM.  This might
1.115.4.1! ad       1193:         * also fetch other stuff from the EEPROM and stash it
        !          1194:         * in the softc.
        !          1195:         */
        !          1196:        sc->sc_cfg = 0;
        !          1197:        if (!sc->sc_gigabit) {
        !          1198:                if (SIP_SIS900_REV(sc,SIS_REV_635) ||
        !          1199:                    SIP_SIS900_REV(sc,SIS_REV_900B))
        !          1200:                        sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT);
        !          1201:
        !          1202:                if (SIP_SIS900_REV(sc,SIS_REV_635) ||
        !          1203:                    SIP_SIS900_REV(sc,SIS_REV_960) ||
        !          1204:                    SIP_SIS900_REV(sc,SIS_REV_900B))
        !          1205:                        sc->sc_cfg |=
        !          1206:                            (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG) &
        !          1207:                             CFG_EDBMASTEN);
        !          1208:        }
        !          1209:
        !          1210:        (*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr);
        !          1211:
        !          1212:        printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
        !          1213:            ether_sprintf(enaddr));
1.29      thorpej  1214:
                   1215:        /*
1.115.4.1! ad       1216:         * Initialize the configuration register: aggressive PCI
        !          1217:         * bus request algorithm, default backoff, default OW timer,
        !          1218:         * default parity error detection.
        !          1219:         *
        !          1220:         * NOTE: "Big endian mode" is useless on the SiS900 and
        !          1221:         * friends -- it affects packet data, not descriptors.
1.29      thorpej  1222:         */
1.115.4.1! ad       1223:        if (sc->sc_gigabit)
        !          1224:                sipcom_dp83820_attach(sc, pa);
1.29      thorpej  1225:
                   1226:        /*
1.1       thorpej  1227:         * Initialize our media structures and probe the MII.
                   1228:         */
                   1229:        sc->sc_mii.mii_ifp = ifp;
1.15      thorpej  1230:        sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg;
                   1231:        sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg;
                   1232:        sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg;
1.115.4.1! ad       1233:        ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, sipcom_mediachange,
        !          1234:            sipcom_mediastatus);
1.63      thorpej  1235:
1.89      thorpej  1236:        /*
                   1237:         * XXX We cannot handle flow control on the DP83815.
                   1238:         */
                   1239:        if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815))
                   1240:                mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
                   1241:                           MII_OFFSET_ANY, 0);
                   1242:        else
                   1243:                mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
                   1244:                           MII_OFFSET_ANY, MIIF_DOPAUSE);
1.1       thorpej  1245:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
                   1246:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
                   1247:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
                   1248:        } else
                   1249:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
                   1250:
                   1251:        ifp = &sc->sc_ethercom.ec_if;
                   1252:        strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
                   1253:        ifp->if_softc = sc;
                   1254:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1.98      kim      1255:        sc->sc_if_flags = ifp->if_flags;
1.115.4.1! ad       1256:        ifp->if_ioctl = sipcom_ioctl;
        !          1257:        ifp->if_start = sipcom_start;
        !          1258:        ifp->if_watchdog = sipcom_watchdog;
        !          1259:        ifp->if_init = sipcom_init;
        !          1260:        ifp->if_stop = sipcom_stop;
1.21      thorpej  1261:        IFQ_SET_READY(&ifp->if_snd);
1.1       thorpej  1262:
                   1263:        /*
1.29      thorpej  1264:         * We can support 802.1Q VLAN-sized frames.
                   1265:         */
                   1266:        sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
                   1267:
1.115.4.1! ad       1268:        if (sc->sc_gigabit) {
        !          1269:                /*
        !          1270:                 * And the DP83820 can do VLAN tagging in hardware, and
        !          1271:                 * support the jumbo Ethernet MTU.
        !          1272:                 */
        !          1273:                sc->sc_ethercom.ec_capabilities |=
        !          1274:                    ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;
1.31      thorpej  1275:
1.115.4.1! ad       1276:                /*
        !          1277:                 * The DP83820 can do IPv4, TCPv4, and UDPv4 checksums
        !          1278:                 * in hardware.
        !          1279:                 */
        !          1280:                ifp->if_capabilities |=
        !          1281:                    IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
        !          1282:                    IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
        !          1283:                    IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
        !          1284:        }
1.29      thorpej  1285:
                   1286:        /*
1.1       thorpej  1287:         * Attach the interface.
                   1288:         */
                   1289:        if_attach(ifp);
1.14      tsutsui  1290:        ether_ifattach(ifp, enaddr);
1.106     pavel    1291:        sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable;
                   1292:        sc->sc_prev.is_vlan = VLAN_ATTACHED(&(sc)->sc_ethercom);
                   1293:        sc->sc_prev.if_capenable = ifp->if_capenable;
1.65      itojun   1294: #if NRND > 0
                   1295:        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
                   1296:            RND_TYPE_NET, 0);
                   1297: #endif
1.1       thorpej  1298:
1.46      thorpej  1299:        /*
                   1300:         * The number of bytes that must be available in
                   1301:         * the Tx FIFO before the bus master can DMA more
                   1302:         * data into the FIFO.
                   1303:         */
                   1304:        sc->sc_tx_fill_thresh = 64 / 32;
                   1305:
                   1306:        /*
                   1307:         * Start at a drain threshold of 512 bytes.  We will
                   1308:         * increase it if a DMA underrun occurs.
                   1309:         *
                   1310:         * XXX The minimum value of this variable should be
                   1311:         * tuned.  We may be able to improve performance
                   1312:         * by starting with a lower value.  That, however,
                   1313:         * may trash the first few outgoing packets if the
                   1314:         * PCI bus is saturated.
                   1315:         */
1.115.4.1! ad       1316:        if (sc->sc_gigabit)
        !          1317:                sc->sc_tx_drain_thresh = 6400 / 32; /* from FreeBSD nge(4) */
        !          1318:        else
        !          1319:                sc->sc_tx_drain_thresh = 1504 / 32;
1.46      thorpej  1320:
                   1321:        /*
1.47      thorpej  1322:         * Initialize the Rx FIFO drain threshold.
                   1323:         *
1.46      thorpej  1324:         * This is in units of 8 bytes.
                   1325:         *
                   1326:         * We should never set this value lower than 2; 14 bytes are
                   1327:         * required to filter the packet.
                   1328:         */
1.47      thorpej  1329:        sc->sc_rx_drain_thresh = 128 / 8;
1.46      thorpej  1330:
1.30      thorpej  1331: #ifdef SIP_EVENT_COUNTERS
                   1332:        /*
                   1333:         * Attach event counters.
                   1334:         */
                   1335:        evcnt_attach_dynamic(&sc->sc_ev_txsstall, EVCNT_TYPE_MISC,
                   1336:            NULL, sc->sc_dev.dv_xname, "txsstall");
                   1337:        evcnt_attach_dynamic(&sc->sc_ev_txdstall, EVCNT_TYPE_MISC,
                   1338:            NULL, sc->sc_dev.dv_xname, "txdstall");
1.56      thorpej  1339:        evcnt_attach_dynamic(&sc->sc_ev_txforceintr, EVCNT_TYPE_INTR,
                   1340:            NULL, sc->sc_dev.dv_xname, "txforceintr");
                   1341:        evcnt_attach_dynamic(&sc->sc_ev_txdintr, EVCNT_TYPE_INTR,
                   1342:            NULL, sc->sc_dev.dv_xname, "txdintr");
                   1343:        evcnt_attach_dynamic(&sc->sc_ev_txiintr, EVCNT_TYPE_INTR,
                   1344:            NULL, sc->sc_dev.dv_xname, "txiintr");
1.30      thorpej  1345:        evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR,
                   1346:            NULL, sc->sc_dev.dv_xname, "rxintr");
1.62      thorpej  1347:        evcnt_attach_dynamic(&sc->sc_ev_hiberr, EVCNT_TYPE_INTR,
                   1348:            NULL, sc->sc_dev.dv_xname, "hiberr");
1.115.4.1! ad       1349:        if (!sc->sc_gigabit) {
        !          1350:                evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_INTR,
        !          1351:                    NULL, sc->sc_dev.dv_xname, "rxpause");
        !          1352:        } else {
        !          1353:                evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_MISC,
        !          1354:                    NULL, sc->sc_dev.dv_xname, "rxpause");
        !          1355:                evcnt_attach_dynamic(&sc->sc_ev_txpause, EVCNT_TYPE_MISC,
        !          1356:                    NULL, sc->sc_dev.dv_xname, "txpause");
        !          1357:                evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC,
        !          1358:                    NULL, sc->sc_dev.dv_xname, "rxipsum");
        !          1359:                evcnt_attach_dynamic(&sc->sc_ev_rxtcpsum, EVCNT_TYPE_MISC,
        !          1360:                    NULL, sc->sc_dev.dv_xname, "rxtcpsum");
        !          1361:                evcnt_attach_dynamic(&sc->sc_ev_rxudpsum, EVCNT_TYPE_MISC,
        !          1362:                    NULL, sc->sc_dev.dv_xname, "rxudpsum");
        !          1363:                evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC,
        !          1364:                    NULL, sc->sc_dev.dv_xname, "txipsum");
        !          1365:                evcnt_attach_dynamic(&sc->sc_ev_txtcpsum, EVCNT_TYPE_MISC,
        !          1366:                    NULL, sc->sc_dev.dv_xname, "txtcpsum");
        !          1367:                evcnt_attach_dynamic(&sc->sc_ev_txudpsum, EVCNT_TYPE_MISC,
        !          1368:                    NULL, sc->sc_dev.dv_xname, "txudpsum");
        !          1369:        }
1.30      thorpej  1370: #endif /* SIP_EVENT_COUNTERS */
                   1371:
1.115.4.1! ad       1372:        if (!pmf_device_register(self, NULL, sipcom_resume))
        !          1373:                aprint_error_dev(self, "couldn't establish power handler\n");
        !          1374:        else
        !          1375:                pmf_class_network_register(self, ifp);
        !          1376:
1.1       thorpej  1377:        /*
                   1378:         * Make sure the interface is shutdown during reboot.
                   1379:         */
1.115.4.1! ad       1380:        sc->sc_sdhook = shutdownhook_establish(sipcom_shutdown, sc);
1.1       thorpej  1381:        if (sc->sc_sdhook == NULL)
                   1382:                printf("%s: WARNING: unable to establish shutdown hook\n",
                   1383:                    sc->sc_dev.dv_xname);
                   1384: }
                   1385:
                   1386: /*
                   1387:  * sip_shutdown:
                   1388:  *
                   1389:  *     Make sure the interface is stopped at reboot time.
                   1390:  */
1.95      thorpej  1391: static void
1.115.4.1! ad       1392: sipcom_shutdown(void *arg)
1.1       thorpej  1393: {
                   1394:        struct sip_softc *sc = arg;
                   1395:
1.115.4.1! ad       1396:        sipcom_stop(&sc->sc_ethercom.ec_if, 1);
        !          1397: }
        !          1398:
        !          1399: static inline void
        !          1400: sipcom_set_extsts(struct sip_softc *sc, int lasttx, struct mbuf *m0,
        !          1401:     uint64_t capenable)
        !          1402: {
        !          1403:        struct m_tag *mtag;
        !          1404:        u_int32_t extsts;
        !          1405: #ifdef DEBUG
        !          1406:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        !          1407: #endif
        !          1408:        /*
        !          1409:         * If VLANs are enabled and the packet has a VLAN tag, set
        !          1410:         * up the descriptor to encapsulate the packet for us.
        !          1411:         *
        !          1412:         * This apparently has to be on the last descriptor of
        !          1413:         * the packet.
        !          1414:         */
        !          1415:
        !          1416:        /*
        !          1417:         * Byte swapping is tricky. We need to provide the tag
        !          1418:         * in a network byte order. On a big-endian machine,
        !          1419:         * the byteorder is correct, but we need to swap it
        !          1420:         * anyway, because this will be undone by the outside
        !          1421:         * htole32(). That's why there must be an
        !          1422:         * unconditional swap instead of htons() inside.
        !          1423:         */
        !          1424:        if ((mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m0)) != NULL) {
        !          1425:                sc->sc_txdescs[lasttx].sipd_extsts |=
        !          1426:                    htole32(EXTSTS_VPKT |
        !          1427:                                (bswap16(VLAN_TAG_VALUE(mtag)) &
        !          1428:                                 EXTSTS_VTCI));
        !          1429:        }
        !          1430:
        !          1431:        /*
        !          1432:         * If the upper-layer has requested IPv4/TCPv4/UDPv4
        !          1433:         * checksumming, set up the descriptor to do this work
        !          1434:         * for us.
        !          1435:         *
        !          1436:         * This apparently has to be on the first descriptor of
        !          1437:         * the packet.
        !          1438:         *
        !          1439:         * Byte-swap constants so the compiler can optimize.
        !          1440:         */
        !          1441:        extsts = 0;
        !          1442:        if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) {
        !          1443:                KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx);
        !          1444:                SIP_EVCNT_INCR(&sc->sc_ev_txipsum);
        !          1445:                extsts |= htole32(EXTSTS_IPPKT);
        !          1446:        }
        !          1447:        if (m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) {
        !          1448:                KDASSERT(ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx);
        !          1449:                SIP_EVCNT_INCR(&sc->sc_ev_txtcpsum);
        !          1450:                extsts |= htole32(EXTSTS_TCPPKT);
        !          1451:        } else if (m0->m_pkthdr.csum_flags & M_CSUM_UDPv4) {
        !          1452:                KDASSERT(ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx);
        !          1453:                SIP_EVCNT_INCR(&sc->sc_ev_txudpsum);
        !          1454:                extsts |= htole32(EXTSTS_UDPPKT);
        !          1455:        }
        !          1456:        sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts;
1.1       thorpej  1457: }
                   1458:
                   1459: /*
                   1460:  * sip_start:          [ifnet interface function]
                   1461:  *
                   1462:  *     Start packet transmission on the interface.
                   1463:  */
1.95      thorpej  1464: static void
1.115.4.1! ad       1465: sipcom_start(struct ifnet *ifp)
1.1       thorpej  1466: {
                   1467:        struct sip_softc *sc = ifp->if_softc;
1.83      mycroft  1468:        struct mbuf *m0;
                   1469:        struct mbuf *m;
1.1       thorpej  1470:        struct sip_txsoft *txs;
                   1471:        bus_dmamap_t dmamap;
1.57      thorpej  1472:        int error, nexttx, lasttx, seg;
                   1473:        int ofree = sc->sc_txfree;
                   1474: #if 0
                   1475:        int firsttx = sc->sc_txnext;
                   1476: #endif
1.1       thorpej  1477:
                   1478:        /*
                   1479:         * If we've been told to pause, don't transmit any more packets.
                   1480:         */
1.115.4.1! ad       1481:        if (!sc->sc_gigabit && sc->sc_paused)
1.1       thorpej  1482:                ifp->if_flags |= IFF_OACTIVE;
                   1483:
                   1484:        if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
                   1485:                return;
                   1486:
                   1487:        /*
                   1488:         * Loop through the send queue, setting up transmit descriptors
                   1489:         * until we drain the queue, or use up all available transmit
                   1490:         * descriptors.
                   1491:         */
1.30      thorpej  1492:        for (;;) {
                   1493:                /* Get a work queue entry. */
                   1494:                if ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) == NULL) {
                   1495:                        SIP_EVCNT_INCR(&sc->sc_ev_txsstall);
                   1496:                        break;
                   1497:                }
                   1498:
1.1       thorpej  1499:                /*
                   1500:                 * Grab a packet off the queue.
                   1501:                 */
1.21      thorpej  1502:                IFQ_POLL(&ifp->if_snd, m0);
1.1       thorpej  1503:                if (m0 == NULL)
                   1504:                        break;
1.22      thorpej  1505:                m = NULL;
1.1       thorpej  1506:
                   1507:                dmamap = txs->txs_dmamap;
                   1508:
1.36      thorpej  1509:                /*
                   1510:                 * Load the DMA map.  If this fails, the packet either
1.115.4.1! ad       1511:                 * didn't fit in the alloted number of segments, or we
        !          1512:                 * were short on resources.
1.36      thorpej  1513:                 */
                   1514:                error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
1.41      thorpej  1515:                    BUS_DMA_WRITE|BUS_DMA_NOWAIT);
1.115.4.1! ad       1516:                /* In the non-gigabit case, we'll copy and try again. */
        !          1517:                if (error != 0 && !sc->sc_gigabit) {
1.1       thorpej  1518:                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1519:                        if (m == NULL) {
                   1520:                                printf("%s: unable to allocate Tx mbuf\n",
                   1521:                                    sc->sc_dev.dv_xname);
                   1522:                                break;
                   1523:                        }
1.105     bouyer   1524:                        MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner);
1.1       thorpej  1525:                        if (m0->m_pkthdr.len > MHLEN) {
                   1526:                                MCLGET(m, M_DONTWAIT);
                   1527:                                if ((m->m_flags & M_EXT) == 0) {
                   1528:                                        printf("%s: unable to allocate Tx "
                   1529:                                            "cluster\n", sc->sc_dev.dv_xname);
                   1530:                                        m_freem(m);
                   1531:                                        break;
                   1532:                                }
                   1533:                        }
1.111     christos 1534:                        m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *));
1.1       thorpej  1535:                        m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
                   1536:                        error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
1.41      thorpej  1537:                            m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
1.1       thorpej  1538:                        if (error) {
                   1539:                                printf("%s: unable to load Tx buffer, "
                   1540:                                    "error = %d\n", sc->sc_dev.dv_xname, error);
                   1541:                                break;
                   1542:                        }
1.115.4.1! ad       1543:                } else if (error == EFBIG) {
        !          1544:                        /*
        !          1545:                         * For the too-many-segments case, we simply
        !          1546:                         * report an error and drop the packet,
        !          1547:                         * since we can't sanely copy a jumbo packet
        !          1548:                         * to a single buffer.
        !          1549:                         */
        !          1550:                        printf("%s: Tx packet consumes too many "
        !          1551:                            "DMA segments, dropping...\n", sc->sc_dev.dv_xname);
        !          1552:                        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          1553:                        m_freem(m0);
        !          1554:                        continue;
        !          1555:                } else if (error != 0) {
        !          1556:                        /*
        !          1557:                         * Short on resources, just stop for now.
        !          1558:                         */
        !          1559:                        break;
1.1       thorpej  1560:                }
1.21      thorpej  1561:
1.1       thorpej  1562:                /*
                   1563:                 * Ensure we have enough descriptors free to describe
1.30      thorpej  1564:                 * the packet.  Note, we always reserve one descriptor
                   1565:                 * at the end of the ring as a termination point, to
                   1566:                 * prevent wrap-around.
1.1       thorpej  1567:                 */
1.30      thorpej  1568:                if (dmamap->dm_nsegs > (sc->sc_txfree - 1)) {
1.1       thorpej  1569:                        /*
                   1570:                         * Not enough free descriptors to transmit this
                   1571:                         * packet.  We haven't committed anything yet,
                   1572:                         * so just unload the DMA map, put the packet
                   1573:                         * back on the queue, and punt.  Notify the upper
                   1574:                         * layer that there are not more slots left.
                   1575:                         *
                   1576:                         * XXX We could allocate an mbuf and copy, but
                   1577:                         * XXX is it worth it?
                   1578:                         */
                   1579:                        ifp->if_flags |= IFF_OACTIVE;
                   1580:                        bus_dmamap_unload(sc->sc_dmat, dmamap);
1.22      thorpej  1581:                        if (m != NULL)
                   1582:                                m_freem(m);
1.30      thorpej  1583:                        SIP_EVCNT_INCR(&sc->sc_ev_txdstall);
1.1       thorpej  1584:                        break;
1.22      thorpej  1585:                }
                   1586:
                   1587:                IFQ_DEQUEUE(&ifp->if_snd, m0);
                   1588:                if (m != NULL) {
                   1589:                        m_freem(m0);
                   1590:                        m0 = m;
1.1       thorpej  1591:                }
                   1592:
                   1593:                /*
                   1594:                 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
                   1595:                 */
                   1596:
                   1597:                /* Sync the DMA map. */
                   1598:                bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
                   1599:                    BUS_DMASYNC_PREWRITE);
                   1600:
                   1601:                /*
                   1602:                 * Initialize the transmit descriptors.
                   1603:                 */
1.74      scw      1604:                for (nexttx = lasttx = sc->sc_txnext, seg = 0;
1.1       thorpej  1605:                     seg < dmamap->dm_nsegs;
1.115.4.1! ad       1606:                     seg++, nexttx = sip_nexttx(sc, nexttx)) {
1.1       thorpej  1607:                        /*
                   1608:                         * If this is the first descriptor we're
                   1609:                         * enqueueing, don't set the OWN bit just
                   1610:                         * yet.  That could cause a race condition.
                   1611:                         * We'll do it below.
                   1612:                         */
1.115.4.1! ad       1613:                        *sipd_bufptr(sc, &sc->sc_txdescs[nexttx]) =
1.14      tsutsui  1614:                            htole32(dmamap->dm_segs[seg].ds_addr);
1.115.4.1! ad       1615:                        *sipd_cmdsts(sc, &sc->sc_txdescs[nexttx]) =
1.57      thorpej  1616:                            htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) |
1.14      tsutsui  1617:                            CMDSTS_MORE | dmamap->dm_segs[seg].ds_len);
1.29      thorpej  1618:                        sc->sc_txdescs[nexttx].sipd_extsts = 0;
1.1       thorpej  1619:                        lasttx = nexttx;
                   1620:                }
                   1621:
                   1622:                /* Clear the MORE bit on the last segment. */
1.115.4.1! ad       1623:                *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) &=
        !          1624:                    htole32(~CMDSTS_MORE);
1.1       thorpej  1625:
1.56      thorpej  1626:                /*
                   1627:                 * If we're in the interrupt delay window, delay the
                   1628:                 * interrupt.
                   1629:                 */
                   1630:                if (++sc->sc_txwin >= (SIP_TXQUEUELEN * 2 / 3)) {
                   1631:                        SIP_EVCNT_INCR(&sc->sc_ev_txforceintr);
1.115.4.1! ad       1632:                        *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) |=
1.56      thorpej  1633:                            htole32(CMDSTS_INTR);
                   1634:                        sc->sc_txwin = 0;
                   1635:                }
                   1636:
1.115.4.1! ad       1637:                if (sc->sc_gigabit)
        !          1638:                        sipcom_set_extsts(sc, lasttx, m0, ifp->if_capenable);
1.29      thorpej  1639:
1.1       thorpej  1640:                /* Sync the descriptors we're using. */
1.115.4.1! ad       1641:                sip_cdtxsync(sc, sc->sc_txnext, dmamap->dm_nsegs,
1.1       thorpej  1642:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                   1643:
                   1644:                /*
1.57      thorpej  1645:                 * The entire packet is set up.  Give the first descrptor
                   1646:                 * to the chip now.
                   1647:                 */
1.115.4.1! ad       1648:                *sipd_cmdsts(sc, &sc->sc_txdescs[sc->sc_txnext]) |=
1.57      thorpej  1649:                    htole32(CMDSTS_OWN);
1.115.4.1! ad       1650:                sip_cdtxsync(sc, sc->sc_txnext, 1,
1.57      thorpej  1651:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                   1652:
                   1653:                /*
1.1       thorpej  1654:                 * Store a pointer to the packet so we can free it later,
                   1655:                 * and remember what txdirty will be once the packet is
                   1656:                 * done.
                   1657:                 */
                   1658:                txs->txs_mbuf = m0;
                   1659:                txs->txs_firstdesc = sc->sc_txnext;
                   1660:                txs->txs_lastdesc = lasttx;
                   1661:
                   1662:                /* Advance the tx pointer. */
                   1663:                sc->sc_txfree -= dmamap->dm_nsegs;
                   1664:                sc->sc_txnext = nexttx;
                   1665:
1.54      lukem    1666:                SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
1.1       thorpej  1667:                SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
                   1668:
                   1669: #if NBPFILTER > 0
                   1670:                /*
                   1671:                 * Pass the packet to any BPF listeners.
                   1672:                 */
                   1673:                if (ifp->if_bpf)
                   1674:                        bpf_mtap(ifp->if_bpf, m0);
                   1675: #endif /* NBPFILTER > 0 */
                   1676:        }
                   1677:
                   1678:        if (txs == NULL || sc->sc_txfree == 0) {
                   1679:                /* No more slots left; notify upper layer. */
                   1680:                ifp->if_flags |= IFF_OACTIVE;
                   1681:        }
                   1682:
                   1683:        if (sc->sc_txfree != ofree) {
1.30      thorpej  1684:                /*
                   1685:                 * Start the transmit process.  Note, the manual says
                   1686:                 * that if there are no pending transmissions in the
                   1687:                 * chip's internal queue (indicated by TXE being clear),
                   1688:                 * then the driver software must set the TXDP to the
                   1689:                 * first descriptor to be transmitted.  However, if we
                   1690:                 * do this, it causes serious performance degredation on
                   1691:                 * the DP83820 under load, not setting TXDP doesn't seem
                   1692:                 * to adversely affect the SiS 900 or DP83815.
                   1693:                 *
                   1694:                 * Well, I guess it wouldn't be the first time a manual
                   1695:                 * has lied -- and they could be speaking of the NULL-
                   1696:                 * terminated descriptor list case, rather than OWN-
                   1697:                 * terminated rings.
                   1698:                 */
                   1699: #if 0
1.1       thorpej  1700:                if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR) &
                   1701:                     CR_TXE) == 0) {
                   1702:                        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP,
                   1703:                            SIP_CDTXADDR(sc, firsttx));
                   1704:                        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE);
                   1705:                }
1.30      thorpej  1706: #else
                   1707:                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE);
                   1708: #endif
1.1       thorpej  1709:
                   1710:                /* Set a watchdog timer in case the chip flakes out. */
1.88      thorpej  1711:                /* Gigabit autonegotiation takes 5 seconds. */
1.115.4.1! ad       1712:                ifp->if_timer = (sc->sc_gigabit) ? 10 : 5;
1.1       thorpej  1713:        }
                   1714: }
                   1715:
                   1716: /*
                   1717:  * sip_watchdog:       [ifnet interface function]
                   1718:  *
                   1719:  *     Watchdog timer handler.
                   1720:  */
1.95      thorpej  1721: static void
1.115.4.1! ad       1722: sipcom_watchdog(struct ifnet *ifp)
1.1       thorpej  1723: {
                   1724:        struct sip_softc *sc = ifp->if_softc;
                   1725:
                   1726:        /*
                   1727:         * The chip seems to ignore the CMDSTS_INTR bit sometimes!
                   1728:         * If we get a timeout, try and sweep up transmit descriptors.
                   1729:         * If we manage to sweep them all up, ignore the lack of
                   1730:         * interrupt.
                   1731:         */
1.115.4.1! ad       1732:        sipcom_txintr(sc);
1.1       thorpej  1733:
1.115.4.1! ad       1734:        if (sc->sc_txfree != sc->sc_ntxdesc) {
1.1       thorpej  1735:                printf("%s: device timeout\n", sc->sc_dev.dv_xname);
                   1736:                ifp->if_oerrors++;
                   1737:
                   1738:                /* Reset the interface. */
1.115.4.1! ad       1739:                (void) sipcom_init(ifp);
1.1       thorpej  1740:        } else if (ifp->if_flags & IFF_DEBUG)
                   1741:                printf("%s: recovered from device timeout\n",
                   1742:                    sc->sc_dev.dv_xname);
                   1743:
                   1744:        /* Try to get more packets going. */
1.115.4.1! ad       1745:        sipcom_start(ifp);
1.1       thorpej  1746: }
                   1747:
                   1748: /*
                   1749:  * sip_ioctl:          [ifnet interface function]
                   1750:  *
                   1751:  *     Handle control requests from the operator.
                   1752:  */
1.95      thorpej  1753: static int
1.115.4.1! ad       1754: sipcom_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.1       thorpej  1755: {
                   1756:        struct sip_softc *sc = ifp->if_softc;
                   1757:        struct ifreq *ifr = (struct ifreq *)data;
1.17      thorpej  1758:        int s, error;
1.1       thorpej  1759:
                   1760:        s = splnet();
                   1761:
                   1762:        switch (cmd) {
1.17      thorpej  1763:        case SIOCSIFMEDIA:
1.89      thorpej  1764:                /* Flow control requires full-duplex mode. */
                   1765:                if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||
                   1766:                    (ifr->ifr_media & IFM_FDX) == 0)
                   1767:                        ifr->ifr_media &= ~IFM_ETH_FMASK;
1.115.4.1! ad       1768:
1.89      thorpej  1769:                /* XXX */
                   1770:                if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815))
                   1771:                        ifr->ifr_media &= ~IFM_ETH_FMASK;
                   1772:                if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {
1.115.4.1! ad       1773:                        if (sc->sc_gigabit &&
        !          1774:                            (ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {
        !          1775:                                /* We can do both TXPAUSE and RXPAUSE. */
        !          1776:                                ifr->ifr_media |=
        !          1777:                                    IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
        !          1778:                        } else if (ifr->ifr_media & IFM_FLOW) {
1.89      thorpej  1779:                                /*
                   1780:                                 * Both TXPAUSE and RXPAUSE must be set.
                   1781:                                 * (SiS900 and DP83815 don't have PAUSE_ASYM
                   1782:                                 * feature.)
                   1783:                                 *
                   1784:                                 * XXX Can SiS900 and DP83815 send PAUSE?
                   1785:                                 */
                   1786:                                ifr->ifr_media |=
                   1787:                                    IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
                   1788:                        }
                   1789:                        sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK;
                   1790:                }
                   1791:                /* FALLTHROUGH */
1.17      thorpej  1792:        case SIOCGIFMEDIA:
                   1793:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1.1       thorpej  1794:                break;
1.98      kim      1795:        case SIOCSIFFLAGS:
                   1796:                /* If the interface is up and running, only modify the receive
                   1797:                 * filter when setting promiscuous or debug mode.  Otherwise
                   1798:                 * fall through to ether_ioctl, which will reset the chip.
                   1799:                 */
1.106     pavel    1800:
                   1801: #define COMPARE_EC(sc) (((sc)->sc_prev.ec_capenable                    \
                   1802:                         == (sc)->sc_ethercom.ec_capenable)             \
                   1803:                        && ((sc)->sc_prev.is_vlan ==                    \
                   1804:                            VLAN_ATTACHED(&(sc)->sc_ethercom) ))
                   1805:
                   1806: #define COMPARE_IC(sc, ifp) ((sc)->sc_prev.if_capenable == (ifp)->if_capenable)
                   1807:
1.98      kim      1808: #define RESETIGN (IFF_CANTCHANGE|IFF_DEBUG)
                   1809:                if (((ifp->if_flags & (IFF_UP|IFF_RUNNING))
                   1810:                    == (IFF_UP|IFF_RUNNING))
                   1811:                    && ((ifp->if_flags & (~RESETIGN))
1.106     pavel    1812:                    == (sc->sc_if_flags & (~RESETIGN)))
                   1813:                    && COMPARE_EC(sc) && COMPARE_IC(sc, ifp)) {
1.98      kim      1814:                        /* Set up the receive filter. */
                   1815:                        (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
1.99      cube     1816:                        error = 0;
1.98      kim      1817:                        break;
                   1818: #undef RESETIGN
                   1819:                }
                   1820:                /* FALLTHROUGH */
1.17      thorpej  1821:        default:
                   1822:                error = ether_ioctl(ifp, cmd, data);
1.101     perry    1823:                if (error == ENETRESET) {
1.1       thorpej  1824:                        /*
                   1825:                         * Multicast list has changed; set the hardware filter
                   1826:                         * accordingly.
                   1827:                         */
1.96      thorpej  1828:                        if (ifp->if_flags & IFF_RUNNING)
                   1829:                            (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
1.1       thorpej  1830:                        error = 0;
                   1831:                }
                   1832:                break;
                   1833:        }
                   1834:
                   1835:        /* Try to get more packets going. */
1.115.4.1! ad       1836:        sipcom_start(ifp);
1.1       thorpej  1837:
1.98      kim      1838:        sc->sc_if_flags = ifp->if_flags;
1.1       thorpej  1839:        splx(s);
                   1840:        return (error);
                   1841: }
                   1842:
                   1843: /*
                   1844:  * sip_intr:
                   1845:  *
                   1846:  *     Interrupt service routine.
                   1847:  */
1.95      thorpej  1848: static int
1.115.4.1! ad       1849: sipcom_intr(void *arg)
1.1       thorpej  1850: {
                   1851:        struct sip_softc *sc = arg;
                   1852:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   1853:        u_int32_t isr;
                   1854:        int handled = 0;
                   1855:
1.88      thorpej  1856:        /* Disable interrupts. */
                   1857:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, 0);
                   1858:
1.1       thorpej  1859:        for (;;) {
                   1860:                /* Reading clears interrupt. */
                   1861:                isr = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ISR);
                   1862:                if ((isr & sc->sc_imr) == 0)
                   1863:                        break;
1.65      itojun   1864:
                   1865: #if NRND > 0
1.66      itojun   1866:                if (RND_ENABLED(&sc->rnd_source))
                   1867:                        rnd_add_uint32(&sc->rnd_source, isr);
1.65      itojun   1868: #endif
1.1       thorpej  1869:
                   1870:                handled = 1;
                   1871:
                   1872:                if (isr & (ISR_RXORN|ISR_RXIDLE|ISR_RXDESC)) {
1.30      thorpej  1873:                        SIP_EVCNT_INCR(&sc->sc_ev_rxintr);
                   1874:
1.1       thorpej  1875:                        /* Grab any new packets. */
1.115.4.1! ad       1876:                        (*sc->sc_rxintr)(sc);
1.1       thorpej  1877:
                   1878:                        if (isr & ISR_RXORN) {
                   1879:                                printf("%s: receive FIFO overrun\n",
                   1880:                                    sc->sc_dev.dv_xname);
                   1881:
                   1882:                                /* XXX adjust rx_drain_thresh? */
                   1883:                        }
                   1884:
                   1885:                        if (isr & ISR_RXIDLE) {
                   1886:                                printf("%s: receive ring overrun\n",
                   1887:                                    sc->sc_dev.dv_xname);
                   1888:
                   1889:                                /* Get the receive process going again. */
                   1890:                                bus_space_write_4(sc->sc_st, sc->sc_sh,
                   1891:                                    SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
                   1892:                                bus_space_write_4(sc->sc_st, sc->sc_sh,
                   1893:                                    SIP_CR, CR_RXE);
                   1894:                        }
                   1895:                }
                   1896:
1.56      thorpej  1897:                if (isr & (ISR_TXURN|ISR_TXDESC|ISR_TXIDLE)) {
                   1898: #ifdef SIP_EVENT_COUNTERS
                   1899:                        if (isr & ISR_TXDESC)
                   1900:                                SIP_EVCNT_INCR(&sc->sc_ev_txdintr);
                   1901:                        else if (isr & ISR_TXIDLE)
                   1902:                                SIP_EVCNT_INCR(&sc->sc_ev_txiintr);
                   1903: #endif
1.30      thorpej  1904:
1.1       thorpej  1905:                        /* Sweep up transmit descriptors. */
1.115.4.1! ad       1906:                        sipcom_txintr(sc);
1.1       thorpej  1907:
                   1908:                        if (isr & ISR_TXURN) {
                   1909:                                u_int32_t thresh;
1.115.4.1! ad       1910:                                int txfifo_size = (sc->sc_gigabit)
        !          1911:                                    ? DP83820_SIP_TXFIFO_SIZE
        !          1912:                                    : OTHER_SIP_TXFIFO_SIZE;
1.1       thorpej  1913:
                   1914:                                printf("%s: transmit FIFO underrun",
                   1915:                                    sc->sc_dev.dv_xname);
                   1916:                                thresh = sc->sc_tx_drain_thresh + 1;
1.115.4.1! ad       1917:                                if (thresh <= __SHIFTOUT_MASK(sc->sc_bits.b_txcfg_drth_mask)
        !          1918:                                && (thresh * 32) <= (txfifo_size -
1.1       thorpej  1919:                                     (sc->sc_tx_fill_thresh * 32))) {
                   1920:                                        printf("; increasing Tx drain "
                   1921:                                            "threshold to %u bytes\n",
                   1922:                                            thresh * 32);
                   1923:                                        sc->sc_tx_drain_thresh = thresh;
1.115.4.1! ad       1924:                                        (void) sipcom_init(ifp);
1.1       thorpej  1925:                                } else {
1.115.4.1! ad       1926:                                        (void) sipcom_init(ifp);
1.1       thorpej  1927:                                        printf("\n");
                   1928:                                }
                   1929:                        }
                   1930:                }
                   1931:
                   1932:                if (sc->sc_imr & (ISR_PAUSE_END|ISR_PAUSE_ST)) {
                   1933:                        if (isr & ISR_PAUSE_ST) {
1.89      thorpej  1934:                                sc->sc_paused = 1;
1.94      thorpej  1935:                                SIP_EVCNT_INCR(&sc->sc_ev_rxpause);
1.1       thorpej  1936:                                ifp->if_flags |= IFF_OACTIVE;
                   1937:                        }
                   1938:                        if (isr & ISR_PAUSE_END) {
1.89      thorpej  1939:                                sc->sc_paused = 0;
1.1       thorpej  1940:                                ifp->if_flags &= ~IFF_OACTIVE;
                   1941:                        }
                   1942:                }
                   1943:
                   1944:                if (isr & ISR_HIBERR) {
1.62      thorpej  1945:                        int want_init = 0;
                   1946:
                   1947:                        SIP_EVCNT_INCR(&sc->sc_ev_hiberr);
                   1948:
1.1       thorpej  1949: #define        PRINTERR(bit, str)                                              \
1.62      thorpej  1950:                        do {                                            \
1.68      itojun   1951:                                if ((isr & (bit)) != 0) {               \
                   1952:                                        if ((ifp->if_flags & IFF_DEBUG) != 0) \
                   1953:                                                printf("%s: %s\n",      \
                   1954:                                                    sc->sc_dev.dv_xname, str); \
1.62      thorpej  1955:                                        want_init = 1;                  \
                   1956:                                }                                       \
                   1957:                        } while (/*CONSTCOND*/0)
                   1958:
1.115.4.1! ad       1959:                        PRINTERR(sc->sc_bits.b_isr_dperr, "parity error");
        !          1960:                        PRINTERR(sc->sc_bits.b_isr_sserr, "system error");
        !          1961:                        PRINTERR(sc->sc_bits.b_isr_rmabt, "master abort");
        !          1962:                        PRINTERR(sc->sc_bits.b_isr_rtabt, "target abort");
1.1       thorpej  1963:                        PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
1.62      thorpej  1964:                        /*
                   1965:                         * Ignore:
                   1966:                         *      Tx reset complete
                   1967:                         *      Rx reset complete
                   1968:                         */
                   1969:                        if (want_init)
1.115.4.1! ad       1970:                                (void) sipcom_init(ifp);
1.1       thorpej  1971: #undef PRINTERR
                   1972:                }
                   1973:        }
                   1974:
1.88      thorpej  1975:        /* Re-enable interrupts. */
                   1976:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, IER_IE);
                   1977:
1.1       thorpej  1978:        /* Try to get more packets going. */
1.115.4.1! ad       1979:        sipcom_start(ifp);
1.1       thorpej  1980:
                   1981:        return (handled);
                   1982: }
                   1983:
                   1984: /*
                   1985:  * sip_txintr:
                   1986:  *
                   1987:  *     Helper; handle transmit interrupts.
                   1988:  */
1.95      thorpej  1989: static void
1.115.4.1! ad       1990: sipcom_txintr(struct sip_softc *sc)
1.1       thorpej  1991: {
                   1992:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   1993:        struct sip_txsoft *txs;
                   1994:        u_int32_t cmdsts;
                   1995:
1.89      thorpej  1996:        if (sc->sc_paused == 0)
1.1       thorpej  1997:                ifp->if_flags &= ~IFF_OACTIVE;
                   1998:
                   1999:        /*
                   2000:         * Go through our Tx list and free mbufs for those
                   2001:         * frames which have been transmitted.
                   2002:         */
                   2003:        while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
1.115.4.1! ad       2004:                sip_cdtxsync(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,
1.1       thorpej  2005:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                   2006:
1.115.4.1! ad       2007:                cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc]));
1.1       thorpej  2008:                if (cmdsts & CMDSTS_OWN)
                   2009:                        break;
                   2010:
1.54      lukem    2011:                SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
1.1       thorpej  2012:
                   2013:                sc->sc_txfree += txs->txs_dmamap->dm_nsegs;
                   2014:
                   2015:                bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
                   2016:                    0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                   2017:                bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
                   2018:                m_freem(txs->txs_mbuf);
                   2019:                txs->txs_mbuf = NULL;
                   2020:
                   2021:                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
                   2022:
                   2023:                /*
                   2024:                 * Check for errors and collisions.
                   2025:                 */
                   2026:                if (cmdsts &
                   2027:                    (CMDSTS_Tx_TXA|CMDSTS_Tx_TFU|CMDSTS_Tx_ED|CMDSTS_Tx_EC)) {
1.34      simonb   2028:                        ifp->if_oerrors++;
                   2029:                        if (cmdsts & CMDSTS_Tx_EC)
                   2030:                                ifp->if_collisions += 16;
1.1       thorpej  2031:                        if (ifp->if_flags & IFF_DEBUG) {
1.34      simonb   2032:                                if (cmdsts & CMDSTS_Tx_ED)
1.1       thorpej  2033:                                        printf("%s: excessive deferral\n",
                   2034:                                            sc->sc_dev.dv_xname);
1.34      simonb   2035:                                if (cmdsts & CMDSTS_Tx_EC)
1.1       thorpej  2036:                                        printf("%s: excessive collisions\n",
                   2037:                                            sc->sc_dev.dv_xname);
                   2038:                        }
                   2039:                } else {
                   2040:                        /* Packet was transmitted successfully. */
                   2041:                        ifp->if_opackets++;
                   2042:                        ifp->if_collisions += CMDSTS_COLLISIONS(cmdsts);
                   2043:                }
                   2044:        }
                   2045:
                   2046:        /*
                   2047:         * If there are no more pending transmissions, cancel the watchdog
                   2048:         * timer.
                   2049:         */
1.56      thorpej  2050:        if (txs == NULL) {
1.1       thorpej  2051:                ifp->if_timer = 0;
1.56      thorpej  2052:                sc->sc_txwin = 0;
                   2053:        }
1.1       thorpej  2054: }
                   2055:
                   2056: /*
1.115.4.1! ad       2057:  * gsip_rxintr:
1.1       thorpej  2058:  *
1.115.4.1! ad       2059:  *     Helper; handle receive interrupts on gigabit parts.
1.1       thorpej  2060:  */
1.95      thorpej  2061: static void
1.115.4.1! ad       2062: gsip_rxintr(struct sip_softc *sc)
1.1       thorpej  2063: {
                   2064:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   2065:        struct sip_rxsoft *rxs;
1.97      thorpej  2066:        struct mbuf *m;
1.35      thorpej  2067:        u_int32_t cmdsts, extsts;
1.97      thorpej  2068:        int i, len;
1.1       thorpej  2069:
1.115.4.1! ad       2070:        for (i = sc->sc_rxptr;; i = sip_nextrx(sc, i)) {
1.1       thorpej  2071:                rxs = &sc->sc_rxsoft[i];
                   2072:
1.115.4.1! ad       2073:                sip_cdrxsync(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.1       thorpej  2074:
1.115.4.1! ad       2075:                cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_rxdescs[i]));
1.29      thorpej  2076:                extsts = le32toh(sc->sc_rxdescs[i].sipd_extsts);
1.115.4.1! ad       2077:                len = CMDSTS_SIZE(sc, cmdsts);
1.1       thorpej  2078:
                   2079:                /*
                   2080:                 * NOTE: OWN is set if owned by _consumer_.  We're the
                   2081:                 * consumer of the receive ring, so if the bit is clear,
                   2082:                 * we have processed all of the packets.
                   2083:                 */
                   2084:                if ((cmdsts & CMDSTS_OWN) == 0) {
                   2085:                        /*
                   2086:                         * We have processed all of the receive buffers.
                   2087:                         */
                   2088:                        break;
                   2089:                }
                   2090:
1.36      thorpej  2091:                if (__predict_false(sc->sc_rxdiscard)) {
1.115.4.1! ad       2092:                        sip_init_rxdesc(sc, i);
1.36      thorpej  2093:                        if ((cmdsts & CMDSTS_MORE) == 0) {
                   2094:                                /* Reset our state. */
                   2095:                                sc->sc_rxdiscard = 0;
                   2096:                        }
                   2097:                        continue;
                   2098:                }
                   2099:
                   2100:                bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   2101:                    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
                   2102:
                   2103:                m = rxs->rxs_mbuf;
                   2104:
                   2105:                /*
                   2106:                 * Add a new receive buffer to the ring.
                   2107:                 */
1.115.4.1! ad       2108:                if (sipcom_add_rxbuf(sc, i) != 0) {
1.36      thorpej  2109:                        /*
                   2110:                         * Failed, throw away what we've done so
                   2111:                         * far, and discard the rest of the packet.
                   2112:                         */
                   2113:                        ifp->if_ierrors++;
                   2114:                        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   2115:                            rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1.115.4.1! ad       2116:                        sip_init_rxdesc(sc, i);
1.36      thorpej  2117:                        if (cmdsts & CMDSTS_MORE)
                   2118:                                sc->sc_rxdiscard = 1;
                   2119:                        if (sc->sc_rxhead != NULL)
                   2120:                                m_freem(sc->sc_rxhead);
1.115.4.1! ad       2121:                        sip_rxchain_reset(sc);
1.36      thorpej  2122:                        continue;
                   2123:                }
                   2124:
1.115.4.1! ad       2125:                sip_rxchain_link(sc, m);
1.36      thorpej  2126:
1.97      thorpej  2127:                m->m_len = len;
                   2128:
1.36      thorpej  2129:                /*
                   2130:                 * If this is not the end of the packet, keep
                   2131:                 * looking.
                   2132:                 */
                   2133:                if (cmdsts & CMDSTS_MORE) {
1.97      thorpej  2134:                        sc->sc_rxlen += len;
1.36      thorpej  2135:                        continue;
                   2136:                }
                   2137:
1.1       thorpej  2138:                /*
1.97      thorpej  2139:                 * Okay, we have the entire packet now.  The chip includes
                   2140:                 * the FCS, so we need to trim it.
1.36      thorpej  2141:                 */
1.97      thorpej  2142:                m->m_len -= ETHER_CRC_LEN;
                   2143:
1.36      thorpej  2144:                *sc->sc_rxtailp = NULL;
1.104     thorpej  2145:                len = m->m_len + sc->sc_rxlen;
1.36      thorpej  2146:                m = sc->sc_rxhead;
                   2147:
1.115.4.1! ad       2148:                sip_rxchain_reset(sc);
1.36      thorpej  2149:
                   2150:                /*
                   2151:                 * If an error occurred, update stats and drop the packet.
1.1       thorpej  2152:                 */
1.36      thorpej  2153:                if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_RUNT|
1.1       thorpej  2154:                    CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
                   2155:                        ifp->if_ierrors++;
                   2156:                        if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
                   2157:                            (cmdsts & CMDSTS_Rx_RXO) == 0) {
                   2158:                                /* Receive overrun handled elsewhere. */
                   2159:                                printf("%s: receive descriptor error\n",
                   2160:                                    sc->sc_dev.dv_xname);
                   2161:                        }
                   2162: #define        PRINTERR(bit, str)                                              \
1.67      itojun   2163:                        if ((ifp->if_flags & IFF_DEBUG) != 0 &&         \
                   2164:                            (cmdsts & (bit)) != 0)                      \
1.1       thorpej  2165:                                printf("%s: %s\n", sc->sc_dev.dv_xname, str)
                   2166:                        PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
                   2167:                        PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
                   2168:                        PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
                   2169:                        PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
                   2170: #undef PRINTERR
1.36      thorpej  2171:                        m_freem(m);
1.1       thorpej  2172:                        continue;
                   2173:                }
                   2174:
                   2175:                /*
1.2       thorpej  2176:                 * If the packet is small enough to fit in a
                   2177:                 * single header mbuf, allocate one and copy
                   2178:                 * the data into it.  This greatly reduces
                   2179:                 * memory consumption when we receive lots
                   2180:                 * of small packets.
1.1       thorpej  2181:                 */
1.115.4.1! ad       2182:                if (gsip_copy_small != 0 && len <= (MHLEN - 2)) {
1.36      thorpej  2183:                        struct mbuf *nm;
                   2184:                        MGETHDR(nm, M_DONTWAIT, MT_DATA);
                   2185:                        if (nm == NULL) {
1.2       thorpej  2186:                                ifp->if_ierrors++;
1.36      thorpej  2187:                                m_freem(m);
1.2       thorpej  2188:                                continue;
                   2189:                        }
1.105     bouyer   2190:                        MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.36      thorpej  2191:                        nm->m_data += 2;
                   2192:                        nm->m_pkthdr.len = nm->m_len = len;
1.111     christos 2193:                        m_copydata(m, 0, len, mtod(nm, void *));
1.36      thorpej  2194:                        m_freem(m);
                   2195:                        m = nm;
1.1       thorpej  2196:                }
1.36      thorpej  2197: #ifndef __NO_STRICT_ALIGNMENT
                   2198:                else {
                   2199:                        /*
                   2200:                         * The DP83820's receive buffers must be 4-byte
                   2201:                         * aligned.  But this means that the data after
                   2202:                         * the Ethernet header is misaligned.  To compensate,
                   2203:                         * we have artificially shortened the buffer size
                   2204:                         * in the descriptor, and we do an overlapping copy
                   2205:                         * of the data two bytes further in (in the first
                   2206:                         * buffer of the chain only).
                   2207:                         */
1.112     yamt     2208:                        memmove(mtod(m, char *) + 2, mtod(m, void *),
1.36      thorpej  2209:                            m->m_len);
                   2210:                        m->m_data += 2;
1.1       thorpej  2211:                }
1.36      thorpej  2212: #endif /* ! __NO_STRICT_ALIGNMENT */
1.1       thorpej  2213:
1.29      thorpej  2214:                /*
                   2215:                 * If VLANs are enabled, VLAN packets have been unwrapped
                   2216:                 * for us.  Associate the tag with the packet.
                   2217:                 */
1.107     pavel    2218:
                   2219:                /*
                   2220:                 * Again, byte swapping is tricky. Hardware provided
                   2221:                 * the tag in the network byte order, but extsts was
                   2222:                 * passed through le32toh() in the meantime. On a
                   2223:                 * big-endian machine, we need to swap it again. On a
                   2224:                 * little-endian machine, we need to convert from the
                   2225:                 * network to host byte order. This means that we must
                   2226:                 * swap it in any case, so unconditional swap instead
                   2227:                 * of htons() is used.
                   2228:                 */
1.100     jdolecek 2229:                if ((extsts & EXTSTS_VPKT) != 0) {
1.107     pavel    2230:                        VLAN_INPUT_TAG(ifp, m, bswap16(extsts & EXTSTS_VTCI),
1.100     jdolecek 2231:                            continue);
1.29      thorpej  2232:                }
1.31      thorpej  2233:
                   2234:                /*
                   2235:                 * Set the incoming checksum information for the
                   2236:                 * packet.
                   2237:                 */
                   2238:                if ((extsts & EXTSTS_IPPKT) != 0) {
                   2239:                        SIP_EVCNT_INCR(&sc->sc_ev_rxipsum);
                   2240:                        m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
                   2241:                        if (extsts & EXTSTS_Rx_IPERR)
                   2242:                                m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
                   2243:                        if (extsts & EXTSTS_TCPPKT) {
                   2244:                                SIP_EVCNT_INCR(&sc->sc_ev_rxtcpsum);
                   2245:                                m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
                   2246:                                if (extsts & EXTSTS_Rx_TCPERR)
                   2247:                                        m->m_pkthdr.csum_flags |=
                   2248:                                            M_CSUM_TCP_UDP_BAD;
                   2249:                        } else if (extsts & EXTSTS_UDPPKT) {
                   2250:                                SIP_EVCNT_INCR(&sc->sc_ev_rxudpsum);
                   2251:                                m->m_pkthdr.csum_flags |= M_CSUM_UDPv4;
                   2252:                                if (extsts & EXTSTS_Rx_UDPERR)
                   2253:                                        m->m_pkthdr.csum_flags |=
                   2254:                                            M_CSUM_TCP_UDP_BAD;
                   2255:                        }
                   2256:                }
1.40      thorpej  2257:
                   2258:                ifp->if_ipackets++;
                   2259:                m->m_pkthdr.rcvif = ifp;
1.97      thorpej  2260:                m->m_pkthdr.len = len;
1.40      thorpej  2261:
                   2262: #if NBPFILTER > 0
                   2263:                /*
                   2264:                 * Pass this up to any BPF listeners, but only
                   2265:                 * pass if up the stack if it's for us.
                   2266:                 */
                   2267:                if (ifp->if_bpf)
                   2268:                        bpf_mtap(ifp->if_bpf, m);
                   2269: #endif /* NBPFILTER > 0 */
1.29      thorpej  2270:
1.1       thorpej  2271:                /* Pass it on. */
                   2272:                (*ifp->if_input)(ifp, m);
                   2273:        }
                   2274:
                   2275:        /* Update the receive pointer. */
                   2276:        sc->sc_rxptr = i;
                   2277: }
1.115.4.1! ad       2278:
1.35      thorpej  2279: /*
                   2280:  * sip_rxintr:
                   2281:  *
1.115.4.1! ad       2282:  *     Helper; handle receive interrupts on 10/100 parts.
1.35      thorpej  2283:  */
1.95      thorpej  2284: static void
1.115.4.1! ad       2285: sip_rxintr(struct sip_softc *sc)
1.35      thorpej  2286: {
                   2287:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   2288:        struct sip_rxsoft *rxs;
                   2289:        struct mbuf *m;
                   2290:        u_int32_t cmdsts;
                   2291:        int i, len;
                   2292:
1.115.4.1! ad       2293:        for (i = sc->sc_rxptr;; i = sip_nextrx(sc, i)) {
1.35      thorpej  2294:                rxs = &sc->sc_rxsoft[i];
                   2295:
1.115.4.1! ad       2296:                sip_cdrxsync(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.35      thorpej  2297:
1.115.4.1! ad       2298:                cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_rxdescs[i]));
1.35      thorpej  2299:
                   2300:                /*
                   2301:                 * NOTE: OWN is set if owned by _consumer_.  We're the
                   2302:                 * consumer of the receive ring, so if the bit is clear,
                   2303:                 * we have processed all of the packets.
                   2304:                 */
                   2305:                if ((cmdsts & CMDSTS_OWN) == 0) {
                   2306:                        /*
                   2307:                         * We have processed all of the receive buffers.
                   2308:                         */
                   2309:                        break;
                   2310:                }
                   2311:
                   2312:                /*
                   2313:                 * If any collisions were seen on the wire, count one.
                   2314:                 */
                   2315:                if (cmdsts & CMDSTS_Rx_COL)
                   2316:                        ifp->if_collisions++;
                   2317:
                   2318:                /*
                   2319:                 * If an error occurred, update stats, clear the status
                   2320:                 * word, and leave the packet buffer in place.  It will
                   2321:                 * simply be reused the next time the ring comes around.
                   2322:                 */
1.36      thorpej  2323:                if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_RUNT|
1.35      thorpej  2324:                    CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
                   2325:                        ifp->if_ierrors++;
                   2326:                        if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
                   2327:                            (cmdsts & CMDSTS_Rx_RXO) == 0) {
                   2328:                                /* Receive overrun handled elsewhere. */
                   2329:                                printf("%s: receive descriptor error\n",
                   2330:                                    sc->sc_dev.dv_xname);
                   2331:                        }
                   2332: #define        PRINTERR(bit, str)                                              \
1.67      itojun   2333:                        if ((ifp->if_flags & IFF_DEBUG) != 0 &&         \
                   2334:                            (cmdsts & (bit)) != 0)                      \
1.35      thorpej  2335:                                printf("%s: %s\n", sc->sc_dev.dv_xname, str)
                   2336:                        PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
                   2337:                        PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
                   2338:                        PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
                   2339:                        PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
                   2340: #undef PRINTERR
1.115.4.1! ad       2341:                        sip_init_rxdesc(sc, i);
1.35      thorpej  2342:                        continue;
                   2343:                }
                   2344:
                   2345:                bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   2346:                    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
                   2347:
                   2348:                /*
                   2349:                 * No errors; receive the packet.  Note, the SiS 900
                   2350:                 * includes the CRC with every packet.
                   2351:                 */
1.115.4.1! ad       2352:                len = CMDSTS_SIZE(sc, cmdsts) - ETHER_CRC_LEN;
1.35      thorpej  2353:
                   2354: #ifdef __NO_STRICT_ALIGNMENT
                   2355:                /*
                   2356:                 * If the packet is small enough to fit in a
                   2357:                 * single header mbuf, allocate one and copy
                   2358:                 * the data into it.  This greatly reduces
                   2359:                 * memory consumption when we receive lots
                   2360:                 * of small packets.
                   2361:                 *
                   2362:                 * Otherwise, we add a new buffer to the receive
                   2363:                 * chain.  If this fails, we drop the packet and
                   2364:                 * recycle the old buffer.
                   2365:                 */
1.115.4.1! ad       2366:                if (sip_copy_small != 0 && len <= MHLEN) {
1.35      thorpej  2367:                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   2368:                        if (m == NULL)
                   2369:                                goto dropit;
1.105     bouyer   2370:                        MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.111     christos 2371:                        memcpy(mtod(m, void *),
                   2372:                            mtod(rxs->rxs_mbuf, void *), len);
1.115.4.1! ad       2373:                        sip_init_rxdesc(sc, i);
1.35      thorpej  2374:                        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   2375:                            rxs->rxs_dmamap->dm_mapsize,
                   2376:                            BUS_DMASYNC_PREREAD);
                   2377:                } else {
                   2378:                        m = rxs->rxs_mbuf;
1.115.4.1! ad       2379:                        if (sipcom_add_rxbuf(sc, i) != 0) {
1.35      thorpej  2380:  dropit:
                   2381:                                ifp->if_ierrors++;
1.115.4.1! ad       2382:                                sip_init_rxdesc(sc, i);
1.35      thorpej  2383:                                bus_dmamap_sync(sc->sc_dmat,
                   2384:                                    rxs->rxs_dmamap, 0,
                   2385:                                    rxs->rxs_dmamap->dm_mapsize,
                   2386:                                    BUS_DMASYNC_PREREAD);
                   2387:                                continue;
                   2388:                        }
                   2389:                }
                   2390: #else
                   2391:                /*
                   2392:                 * The SiS 900's receive buffers must be 4-byte aligned.
                   2393:                 * But this means that the data after the Ethernet header
                   2394:                 * is misaligned.  We must allocate a new buffer and
                   2395:                 * copy the data, shifted forward 2 bytes.
                   2396:                 */
                   2397:                MGETHDR(m, M_DONTWAIT, MT_DATA);
                   2398:                if (m == NULL) {
                   2399:  dropit:
                   2400:                        ifp->if_ierrors++;
1.115.4.1! ad       2401:                        sip_init_rxdesc(sc, i);
1.35      thorpej  2402:                        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   2403:                            rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   2404:                        continue;
                   2405:                }
1.105     bouyer   2406:                MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.35      thorpej  2407:                if (len > (MHLEN - 2)) {
                   2408:                        MCLGET(m, M_DONTWAIT);
                   2409:                        if ((m->m_flags & M_EXT) == 0) {
                   2410:                                m_freem(m);
                   2411:                                goto dropit;
                   2412:                        }
                   2413:                }
                   2414:                m->m_data += 2;
                   2415:
                   2416:                /*
                   2417:                 * Note that we use clusters for incoming frames, so the
                   2418:                 * buffer is virtually contiguous.
                   2419:                 */
1.111     christos 2420:                memcpy(mtod(m, void *), mtod(rxs->rxs_mbuf, void *), len);
1.35      thorpej  2421:
                   2422:                /* Allow the receive descriptor to continue using its mbuf. */
1.115.4.1! ad       2423:                sip_init_rxdesc(sc, i);
1.35      thorpej  2424:                bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   2425:                    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   2426: #endif /* __NO_STRICT_ALIGNMENT */
                   2427:
                   2428:                ifp->if_ipackets++;
                   2429:                m->m_pkthdr.rcvif = ifp;
                   2430:                m->m_pkthdr.len = m->m_len = len;
                   2431:
                   2432: #if NBPFILTER > 0
                   2433:                /*
                   2434:                 * Pass this up to any BPF listeners, but only
                   2435:                 * pass if up the stack if it's for us.
                   2436:                 */
                   2437:                if (ifp->if_bpf)
                   2438:                        bpf_mtap(ifp->if_bpf, m);
                   2439: #endif /* NBPFILTER > 0 */
                   2440:
                   2441:                /* Pass it on. */
                   2442:                (*ifp->if_input)(ifp, m);
                   2443:        }
                   2444:
                   2445:        /* Update the receive pointer. */
                   2446:        sc->sc_rxptr = i;
                   2447: }
1.1       thorpej  2448:
                   2449: /*
                   2450:  * sip_tick:
                   2451:  *
                   2452:  *     One second timer, used to tick the MII.
                   2453:  */
1.95      thorpej  2454: static void
1.115.4.1! ad       2455: sipcom_tick(void *arg)
1.1       thorpej  2456: {
                   2457:        struct sip_softc *sc = arg;
                   2458:        int s;
                   2459:
                   2460:        s = splnet();
1.94      thorpej  2461: #ifdef SIP_EVENT_COUNTERS
1.115.4.1! ad       2462:        if (sc->sc_gigabit) {
        !          2463:                /* Read PAUSE related counts from MIB registers. */
        !          2464:                sc->sc_ev_rxpause.ev_count +=
        !          2465:                    bus_space_read_4(sc->sc_st, sc->sc_sh,
        !          2466:                                     SIP_NS_MIB(MIB_RXPauseFrames)) & 0xffff;
        !          2467:                sc->sc_ev_txpause.ev_count +=
        !          2468:                    bus_space_read_4(sc->sc_st, sc->sc_sh,
        !          2469:                                     SIP_NS_MIB(MIB_TXPauseFrames)) & 0xffff;
        !          2470:                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_MIBC, MIBC_ACLR);
        !          2471:        }
1.94      thorpej  2472: #endif /* SIP_EVENT_COUNTERS */
1.1       thorpej  2473:        mii_tick(&sc->sc_mii);
                   2474:        splx(s);
                   2475:
1.115.4.1! ad       2476:        callout_reset(&sc->sc_tick_ch, hz, sipcom_tick, sc);
1.1       thorpej  2477: }
                   2478:
                   2479: /*
                   2480:  * sip_reset:
                   2481:  *
                   2482:  *     Perform a soft reset on the SiS 900.
                   2483:  */
1.115.4.1! ad       2484: static bool
        !          2485: sipcom_reset(struct sip_softc *sc)
1.1       thorpej  2486: {
                   2487:        bus_space_tag_t st = sc->sc_st;
                   2488:        bus_space_handle_t sh = sc->sc_sh;
                   2489:        int i;
                   2490:
1.45      thorpej  2491:        bus_space_write_4(st, sh, SIP_IER, 0);
                   2492:        bus_space_write_4(st, sh, SIP_IMR, 0);
                   2493:        bus_space_write_4(st, sh, SIP_RFCR, 0);
1.1       thorpej  2494:        bus_space_write_4(st, sh, SIP_CR, CR_RST);
                   2495:
1.14      tsutsui  2496:        for (i = 0; i < SIP_TIMEOUT; i++) {
                   2497:                if ((bus_space_read_4(st, sh, SIP_CR) & CR_RST) == 0)
                   2498:                        break;
1.1       thorpej  2499:                delay(2);
                   2500:        }
                   2501:
1.115.4.1! ad       2502:        if (i == SIP_TIMEOUT) {
1.14      tsutsui  2503:                printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
1.115.4.1! ad       2504:                return false;
        !          2505:        }
1.14      tsutsui  2506:
                   2507:        delay(1000);
1.29      thorpej  2508:
1.115.4.1! ad       2509:        if (sc->sc_gigabit) {
        !          2510:                /*
        !          2511:                 * Set the general purpose I/O bits.  Do it here in case we
        !          2512:                 * need to have GPIO set up to talk to the media interface.
        !          2513:                 */
        !          2514:                bus_space_write_4(st, sh, SIP_GPIOR, sc->sc_gpior);
        !          2515:                delay(1000);
        !          2516:        }
        !          2517:        return true;
        !          2518: }
        !          2519:
        !          2520: static void
        !          2521: sipcom_dp83820_init(struct sip_softc *sc, uint64_t capenable)
        !          2522: {
        !          2523:        u_int32_t reg;
        !          2524:        bus_space_tag_t st = sc->sc_st;
        !          2525:        bus_space_handle_t sh = sc->sc_sh;
        !          2526:        /*
        !          2527:         * Initialize the VLAN/IP receive control register.
        !          2528:         * We enable checksum computation on all incoming
        !          2529:         * packets, and do not reject packets w/ bad checksums.
        !          2530:         */
        !          2531:        reg = 0;
        !          2532:        if (capenable &
        !          2533:            (IFCAP_CSUM_IPv4_Rx|IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx))
        !          2534:                reg |= VRCR_IPEN;
        !          2535:        if (VLAN_ATTACHED(&sc->sc_ethercom))
        !          2536:                reg |= VRCR_VTDEN|VRCR_VTREN;
        !          2537:        bus_space_write_4(st, sh, SIP_VRCR, reg);
        !          2538:
1.29      thorpej  2539:        /*
1.115.4.1! ad       2540:         * Initialize the VLAN/IP transmit control register.
        !          2541:         * We enable outgoing checksum computation on a
        !          2542:         * per-packet basis.
1.29      thorpej  2543:         */
1.115.4.1! ad       2544:        reg = 0;
        !          2545:        if (capenable &
        !          2546:            (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_UDPv4_Tx))
        !          2547:                reg |= VTCR_PPCHK;
        !          2548:        if (VLAN_ATTACHED(&sc->sc_ethercom))
        !          2549:                reg |= VTCR_VPPTI;
        !          2550:        bus_space_write_4(st, sh, SIP_VTCR, reg);
        !          2551:
        !          2552:        /*
        !          2553:         * If we're using VLANs, initialize the VLAN data register.
        !          2554:         * To understand why we bswap the VLAN Ethertype, see section
        !          2555:         * 4.2.36 of the DP83820 manual.
        !          2556:         */
        !          2557:        if (VLAN_ATTACHED(&sc->sc_ethercom))
        !          2558:                bus_space_write_4(st, sh, SIP_VDR, bswap16(ETHERTYPE_VLAN));
1.1       thorpej  2559: }
                   2560:
                   2561: /*
1.17      thorpej  2562:  * sip_init:           [ ifnet interface function ]
1.1       thorpej  2563:  *
                   2564:  *     Initialize the interface.  Must be called at splnet().
                   2565:  */
1.95      thorpej  2566: static int
1.115.4.1! ad       2567: sipcom_init(struct ifnet *ifp)
1.1       thorpej  2568: {
1.17      thorpej  2569:        struct sip_softc *sc = ifp->if_softc;
1.1       thorpej  2570:        bus_space_tag_t st = sc->sc_st;
                   2571:        bus_space_handle_t sh = sc->sc_sh;
                   2572:        struct sip_txsoft *txs;
1.2       thorpej  2573:        struct sip_rxsoft *rxs;
1.1       thorpej  2574:        struct sip_desc *sipd;
1.2       thorpej  2575:        int i, error = 0;
1.1       thorpej  2576:
1.115.4.1! ad       2577:        if (!device_has_power(&sc->sc_dev))
        !          2578:                return EBUSY;
        !          2579:
1.1       thorpej  2580:        /*
                   2581:         * Cancel any pending I/O.
                   2582:         */
1.115.4.1! ad       2583:        sipcom_stop(ifp, 0);
1.1       thorpej  2584:
                   2585:        /*
                   2586:         * Reset the chip to a known state.
                   2587:         */
1.115.4.1! ad       2588:        if (!sipcom_reset(sc))
        !          2589:                return EBUSY;
1.1       thorpej  2590:
1.45      thorpej  2591:        if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815)) {
1.25      briggs   2592:                /*
                   2593:                 * DP83815 manual, page 78:
                   2594:                 *    4.4 Recommended Registers Configuration
                   2595:                 *    For optimum performance of the DP83815, version noted
                   2596:                 *    as DP83815CVNG (SRR = 203h), the listed register
                   2597:                 *    modifications must be followed in sequence...
                   2598:                 *
                   2599:                 * It's not clear if this should be 302h or 203h because that
                   2600:                 * chip name is listed as SRR 302h in the description of the
1.26      briggs   2601:                 * SRR register.  However, my revision 302h DP83815 on the
                   2602:                 * Netgear FA311 purchased in 02/2001 needs these settings
                   2603:                 * to avoid tons of errors in AcceptPerfectMatch (non-
                   2604:                 * IFF_PROMISC) mode.  I do not know if other revisions need
                   2605:                 * this set or not.  [briggs -- 09 March 2001]
                   2606:                 *
                   2607:                 * Note that only the low-order 12 bits of 0xe4 are documented
                   2608:                 * and that this sets reserved bits in that register.
1.25      briggs   2609:                 */
1.78      thorpej  2610:                bus_space_write_4(st, sh, 0x00cc, 0x0001);
                   2611:
                   2612:                bus_space_write_4(st, sh, 0x00e4, 0x189C);
                   2613:                bus_space_write_4(st, sh, 0x00fc, 0x0000);
                   2614:                bus_space_write_4(st, sh, 0x00f4, 0x5040);
                   2615:                bus_space_write_4(st, sh, 0x00f8, 0x008c);
                   2616:
                   2617:                bus_space_write_4(st, sh, 0x00cc, 0x0000);
1.25      briggs   2618:        }
                   2619:
1.1       thorpej  2620:        /*
                   2621:         * Initialize the transmit descriptor ring.
                   2622:         */
1.115.4.1! ad       2623:        for (i = 0; i < sc->sc_ntxdesc; i++) {
1.1       thorpej  2624:                sipd = &sc->sc_txdescs[i];
                   2625:                memset(sipd, 0, sizeof(struct sip_desc));
1.115.4.1! ad       2626:                sipd->sipd_link = htole32(SIP_CDTXADDR(sc, sip_nexttx(sc, i)));
1.1       thorpej  2627:        }
1.115.4.1! ad       2628:        sip_cdtxsync(sc, 0, sc->sc_ntxdesc,
1.1       thorpej  2629:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1.115.4.1! ad       2630:        sc->sc_txfree = sc->sc_ntxdesc;
1.1       thorpej  2631:        sc->sc_txnext = 0;
1.56      thorpej  2632:        sc->sc_txwin = 0;
1.1       thorpej  2633:
                   2634:        /*
                   2635:         * Initialize the transmit job descriptors.
                   2636:         */
                   2637:        SIMPLEQ_INIT(&sc->sc_txfreeq);
                   2638:        SIMPLEQ_INIT(&sc->sc_txdirtyq);
                   2639:        for (i = 0; i < SIP_TXQUEUELEN; i++) {
                   2640:                txs = &sc->sc_txsoft[i];
                   2641:                txs->txs_mbuf = NULL;
                   2642:                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
                   2643:        }
                   2644:
                   2645:        /*
                   2646:         * Initialize the receive descriptor and receive job
1.2       thorpej  2647:         * descriptor rings.
1.1       thorpej  2648:         */
1.115.4.1! ad       2649:        for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
1.2       thorpej  2650:                rxs = &sc->sc_rxsoft[i];
                   2651:                if (rxs->rxs_mbuf == NULL) {
1.115.4.1! ad       2652:                        if ((error = sipcom_add_rxbuf(sc, i)) != 0) {
1.2       thorpej  2653:                                printf("%s: unable to allocate or map rx "
                   2654:                                    "buffer %d, error = %d\n",
                   2655:                                    sc->sc_dev.dv_xname, i, error);
                   2656:                                /*
                   2657:                                 * XXX Should attempt to run with fewer receive
                   2658:                                 * XXX buffers instead of just failing.
                   2659:                                 */
1.115.4.1! ad       2660:                                sipcom_rxdrain(sc);
1.2       thorpej  2661:                                goto out;
                   2662:                        }
1.42      thorpej  2663:                } else
1.115.4.1! ad       2664:                        sip_init_rxdesc(sc, i);
1.2       thorpej  2665:        }
1.1       thorpej  2666:        sc->sc_rxptr = 0;
1.36      thorpej  2667:        sc->sc_rxdiscard = 0;
1.115.4.1! ad       2668:        sip_rxchain_reset(sc);
1.1       thorpej  2669:
                   2670:        /*
1.29      thorpej  2671:         * Set the configuration register; it's already initialized
                   2672:         * in sip_attach().
1.1       thorpej  2673:         */
1.29      thorpej  2674:        bus_space_write_4(st, sh, SIP_CFG, sc->sc_cfg);
1.1       thorpej  2675:
                   2676:        /*
                   2677:         * Initialize the prototype TXCFG register.
                   2678:         */
1.115.4.1! ad       2679:        if (sc->sc_gigabit) {
        !          2680:                sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_512;
        !          2681:                sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_512;
        !          2682:        } else if ((SIP_SIS900_REV(sc, SIS_REV_635) ||
1.87      cube     2683:             SIP_SIS900_REV(sc, SIS_REV_960) ||
1.45      thorpej  2684:             SIP_SIS900_REV(sc, SIS_REV_900B)) &&
1.89      thorpej  2685:            (sc->sc_cfg & CFG_EDBMASTEN)) {
1.115.4.1! ad       2686:                sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_64;
        !          2687:                sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_64;
1.45      thorpej  2688:        } else {
1.115.4.1! ad       2689:                sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_512;
        !          2690:                sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_512;
1.45      thorpej  2691:        }
                   2692:
                   2693:        sc->sc_txcfg |= TXCFG_ATP |
1.115.4.1! ad       2694:            __SHIFTIN(sc->sc_tx_fill_thresh, sc->sc_bits.b_txcfg_flth_mask) |
1.1       thorpej  2695:            sc->sc_tx_drain_thresh;
1.115.4.1! ad       2696:        bus_space_write_4(st, sh, sc->sc_regs.r_txcfg, sc->sc_txcfg);
1.1       thorpej  2697:
                   2698:        /*
                   2699:         * Initialize the receive drain threshold if we have never
                   2700:         * done so.
                   2701:         */
                   2702:        if (sc->sc_rx_drain_thresh == 0) {
                   2703:                /*
                   2704:                 * XXX This value should be tuned.  This is set to the
                   2705:                 * maximum of 248 bytes, and we may be able to improve
                   2706:                 * performance by decreasing it (although we should never
                   2707:                 * set this value lower than 2; 14 bytes are required to
                   2708:                 * filter the packet).
                   2709:                 */
1.115.4.1! ad       2710:                sc->sc_rx_drain_thresh = __SHIFTOUT_MASK(RXCFG_DRTH_MASK);
1.1       thorpej  2711:        }
                   2712:
                   2713:        /*
                   2714:         * Initialize the prototype RXCFG register.
                   2715:         */
1.115.4.1! ad       2716:        sc->sc_rxcfg |= __SHIFTIN(sc->sc_rx_drain_thresh, RXCFG_DRTH_MASK);
1.88      thorpej  2717:        /*
                   2718:         * Accept long packets (including FCS) so we can handle
                   2719:         * 802.1q-tagged frames and jumbo frames properly.
                   2720:         */
1.115.4.1! ad       2721:        if ((sc->sc_gigabit && ifp->if_mtu > ETHERMTU) ||
1.88      thorpej  2722:            (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU))
                   2723:                sc->sc_rxcfg |= RXCFG_ALP;
                   2724:
                   2725:        /*
                   2726:         * Checksum offloading is disabled if the user selects an MTU
                   2727:         * larger than 8109.  (FreeBSD says 8152, but there is emperical
                   2728:         * evidence that >8109 does not work on some boards, such as the
                   2729:         * Planex GN-1000TE).
                   2730:         */
1.115.4.1! ad       2731:        if (sc->sc_gigabit && ifp->if_mtu > 8109 &&
1.88      thorpej  2732:            (ifp->if_capenable &
1.102     yamt     2733:             (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|
                   2734:              IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|
                   2735:              IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx))) {
1.88      thorpej  2736:                printf("%s: Checksum offloading does not work if MTU > 8109 - "
                   2737:                       "disabled.\n", sc->sc_dev.dv_xname);
1.102     yamt     2738:                ifp->if_capenable &=
                   2739:                    ~(IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|
                   2740:                     IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|
                   2741:                     IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx);
1.88      thorpej  2742:                ifp->if_csum_flags_tx = 0;
                   2743:                ifp->if_csum_flags_rx = 0;
                   2744:        }
1.29      thorpej  2745:
1.115.4.1! ad       2746:        bus_space_write_4(st, sh, sc->sc_regs.r_rxcfg, sc->sc_rxcfg);
1.29      thorpej  2747:
1.115.4.1! ad       2748:        if (sc->sc_gigabit)
        !          2749:                sipcom_dp83820_init(sc, ifp->if_capenable);
1.29      thorpej  2750:
1.1       thorpej  2751:        /*
                   2752:         * Give the transmit and receive rings to the chip.
                   2753:         */
                   2754:        bus_space_write_4(st, sh, SIP_TXDP, SIP_CDTXADDR(sc, sc->sc_txnext));
                   2755:        bus_space_write_4(st, sh, SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
                   2756:
                   2757:        /*
                   2758:         * Initialize the interrupt mask.
                   2759:         */
1.115.4.1! ad       2760:        sc->sc_imr = sc->sc_bits.b_isr_dperr |
        !          2761:                     sc->sc_bits.b_isr_sserr |
        !          2762:                     sc->sc_bits.b_isr_rmabt |
        !          2763:                     sc->sc_bits.b_isr_rtabt | ISR_RXSOVR |
1.56      thorpej  2764:            ISR_TXURN|ISR_TXDESC|ISR_TXIDLE|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;
1.1       thorpej  2765:        bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);
                   2766:
1.45      thorpej  2767:        /* Set up the receive filter. */
                   2768:        (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
                   2769:
1.89      thorpej  2770:        /*
                   2771:         * Tune sc_rx_flow_thresh.
                   2772:         * XXX "More than 8KB" is too short for jumbo frames.
                   2773:         * XXX TODO: Threshold value should be user-settable.
                   2774:         */
                   2775:        sc->sc_rx_flow_thresh = (PCR_PS_STHI_8 | PCR_PS_STLO_4 |
                   2776:                                 PCR_PS_FFHI_8 | PCR_PS_FFLO_4 |
                   2777:                                 (PCR_PAUSE_CNT & PCR_PAUSE_CNT_MASK));
                   2778:
1.1       thorpej  2779:        /*
                   2780:         * Set the current media.  Do this after initializing the prototype
                   2781:         * IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow
                   2782:         * control.
                   2783:         */
                   2784:        mii_mediachg(&sc->sc_mii);
                   2785:
1.88      thorpej  2786:        /*
                   2787:         * Set the interrupt hold-off timer to 100us.
                   2788:         */
1.115.4.1! ad       2789:        if (sc->sc_gigabit)
        !          2790:                bus_space_write_4(st, sh, SIP_IHR, 0x01);
1.88      thorpej  2791:
1.1       thorpej  2792:        /*
                   2793:         * Enable interrupts.
                   2794:         */
                   2795:        bus_space_write_4(st, sh, SIP_IER, IER_IE);
                   2796:
                   2797:        /*
                   2798:         * Start the transmit and receive processes.
                   2799:         */
                   2800:        bus_space_write_4(st, sh, SIP_CR, CR_RXE | CR_TXE);
                   2801:
                   2802:        /*
                   2803:         * Start the one second MII clock.
                   2804:         */
1.115.4.1! ad       2805:        callout_reset(&sc->sc_tick_ch, hz, sipcom_tick, sc);
1.1       thorpej  2806:
                   2807:        /*
                   2808:         * ...all done!
                   2809:         */
                   2810:        ifp->if_flags |= IFF_RUNNING;
                   2811:        ifp->if_flags &= ~IFF_OACTIVE;
1.98      kim      2812:        sc->sc_if_flags = ifp->if_flags;
1.106     pavel    2813:        sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable;
                   2814:        sc->sc_prev.is_vlan = VLAN_ATTACHED(&(sc)->sc_ethercom);
                   2815:        sc->sc_prev.if_capenable = ifp->if_capenable;
1.2       thorpej  2816:
                   2817:  out:
                   2818:        if (error)
                   2819:                printf("%s: interface not running\n", sc->sc_dev.dv_xname);
                   2820:        return (error);
                   2821: }
                   2822:
                   2823: /*
                   2824:  * sip_drain:
                   2825:  *
                   2826:  *     Drain the receive queue.
                   2827:  */
1.95      thorpej  2828: static void
1.115.4.1! ad       2829: sipcom_rxdrain(struct sip_softc *sc)
1.2       thorpej  2830: {
                   2831:        struct sip_rxsoft *rxs;
                   2832:        int i;
                   2833:
1.115.4.1! ad       2834:        for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
1.2       thorpej  2835:                rxs = &sc->sc_rxsoft[i];
                   2836:                if (rxs->rxs_mbuf != NULL) {
                   2837:                        bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
                   2838:                        m_freem(rxs->rxs_mbuf);
                   2839:                        rxs->rxs_mbuf = NULL;
                   2840:                }
                   2841:        }
1.1       thorpej  2842: }
                   2843:
                   2844: /*
1.17      thorpej  2845:  * sip_stop:           [ ifnet interface function ]
1.1       thorpej  2846:  *
                   2847:  *     Stop transmission on the interface.
                   2848:  */
1.95      thorpej  2849: static void
1.115.4.1! ad       2850: sipcom_stop(struct ifnet *ifp, int disable)
1.1       thorpej  2851: {
1.17      thorpej  2852:        struct sip_softc *sc = ifp->if_softc;
1.1       thorpej  2853:        bus_space_tag_t st = sc->sc_st;
                   2854:        bus_space_handle_t sh = sc->sc_sh;
                   2855:        struct sip_txsoft *txs;
                   2856:        u_int32_t cmdsts = 0;           /* DEBUG */
                   2857:
                   2858:        /*
                   2859:         * Stop the one second clock.
                   2860:         */
1.9       thorpej  2861:        callout_stop(&sc->sc_tick_ch);
1.4       thorpej  2862:
                   2863:        /* Down the MII. */
                   2864:        mii_down(&sc->sc_mii);
1.1       thorpej  2865:
                   2866:        /*
                   2867:         * Disable interrupts.
                   2868:         */
                   2869:        bus_space_write_4(st, sh, SIP_IER, 0);
                   2870:
                   2871:        /*
                   2872:         * Stop receiver and transmitter.
                   2873:         */
                   2874:        bus_space_write_4(st, sh, SIP_CR, CR_RXD | CR_TXD);
                   2875:
                   2876:        /*
                   2877:         * Release any queued transmit buffers.
                   2878:         */
                   2879:        while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
                   2880:                if ((ifp->if_flags & IFF_DEBUG) != 0 &&
                   2881:                    SIMPLEQ_NEXT(txs, txs_q) == NULL &&
1.115.4.1! ad       2882:                    (le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc])) &
1.1       thorpej  2883:                     CMDSTS_INTR) == 0)
                   2884:                        printf("%s: sip_stop: last descriptor does not "
                   2885:                            "have INTR bit set\n", sc->sc_dev.dv_xname);
1.54      lukem    2886:                SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
1.1       thorpej  2887: #ifdef DIAGNOSTIC
                   2888:                if (txs->txs_mbuf == NULL) {
                   2889:                        printf("%s: dirty txsoft with no mbuf chain\n",
                   2890:                            sc->sc_dev.dv_xname);
                   2891:                        panic("sip_stop");
                   2892:                }
                   2893: #endif
                   2894:                cmdsts |=               /* DEBUG */
1.115.4.1! ad       2895:                    le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc]));
1.1       thorpej  2896:                bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
                   2897:                m_freem(txs->txs_mbuf);
                   2898:                txs->txs_mbuf = NULL;
                   2899:                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
1.2       thorpej  2900:        }
                   2901:
1.17      thorpej  2902:        if (disable)
1.115.4.1! ad       2903:                sipcom_rxdrain(sc);
1.1       thorpej  2904:
                   2905:        /*
                   2906:         * Mark the interface down and cancel the watchdog timer.
                   2907:         */
                   2908:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                   2909:        ifp->if_timer = 0;
                   2910:
                   2911:        if ((ifp->if_flags & IFF_DEBUG) != 0 &&
1.115.4.1! ad       2912:            (cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != sc->sc_ntxdesc)
1.1       thorpej  2913:                printf("%s: sip_stop: no INTR bits set in dirty tx "
                   2914:                    "descriptors\n", sc->sc_dev.dv_xname);
                   2915: }
                   2916:
                   2917: /*
                   2918:  * sip_read_eeprom:
                   2919:  *
                   2920:  *     Read data from the serial EEPROM.
                   2921:  */
1.95      thorpej  2922: static void
1.115.4.1! ad       2923: sipcom_read_eeprom(struct sip_softc *sc, int word, int wordcnt,
1.28      thorpej  2924:     u_int16_t *data)
1.1       thorpej  2925: {
                   2926:        bus_space_tag_t st = sc->sc_st;
                   2927:        bus_space_handle_t sh = sc->sc_sh;
                   2928:        u_int16_t reg;
                   2929:        int i, x;
                   2930:
                   2931:        for (i = 0; i < wordcnt; i++) {
                   2932:                /* Send CHIP SELECT. */
                   2933:                reg = EROMAR_EECS;
                   2934:                bus_space_write_4(st, sh, SIP_EROMAR, reg);
                   2935:
                   2936:                /* Shift in the READ opcode. */
                   2937:                for (x = 3; x > 0; x--) {
                   2938:                        if (SIP_EEPROM_OPC_READ & (1 << (x - 1)))
                   2939:                                reg |= EROMAR_EEDI;
                   2940:                        else
                   2941:                                reg &= ~EROMAR_EEDI;
                   2942:                        bus_space_write_4(st, sh, SIP_EROMAR, reg);
                   2943:                        bus_space_write_4(st, sh, SIP_EROMAR,
                   2944:                            reg | EROMAR_EESK);
                   2945:                        delay(4);
                   2946:                        bus_space_write_4(st, sh, SIP_EROMAR, reg);
                   2947:                        delay(4);
                   2948:                }
1.101     perry    2949:
1.1       thorpej  2950:                /* Shift in address. */
                   2951:                for (x = 6; x > 0; x--) {
                   2952:                        if ((word + i) & (1 << (x - 1)))
                   2953:                                reg |= EROMAR_EEDI;
                   2954:                        else
1.101     perry    2955:                                reg &= ~EROMAR_EEDI;
1.1       thorpej  2956:                        bus_space_write_4(st, sh, SIP_EROMAR, reg);
                   2957:                        bus_space_write_4(st, sh, SIP_EROMAR,
                   2958:                            reg | EROMAR_EESK);
                   2959:                        delay(4);
                   2960:                        bus_space_write_4(st, sh, SIP_EROMAR, reg);
                   2961:                        delay(4);
                   2962:                }
                   2963:
                   2964:                /* Shift out data. */
                   2965:                reg = EROMAR_EECS;
                   2966:                data[i] = 0;
                   2967:                for (x = 16; x > 0; x--) {
                   2968:                        bus_space_write_4(st, sh, SIP_EROMAR,
                   2969:                            reg | EROMAR_EESK);
                   2970:                        delay(4);
                   2971:                        if (bus_space_read_4(st, sh, SIP_EROMAR) & EROMAR_EEDO)
                   2972:                                data[i] |= (1 << (x - 1));
                   2973:                        bus_space_write_4(st, sh, SIP_EROMAR, reg);
1.13      tsutsui  2974:                        delay(4);
1.1       thorpej  2975:                }
                   2976:
                   2977:                /* Clear CHIP SELECT. */
                   2978:                bus_space_write_4(st, sh, SIP_EROMAR, 0);
                   2979:                delay(4);
                   2980:        }
                   2981: }
                   2982:
                   2983: /*
1.115.4.1! ad       2984:  * sipcom_add_rxbuf:
1.1       thorpej  2985:  *
                   2986:  *     Add a receive buffer to the indicated descriptor.
                   2987:  */
1.95      thorpej  2988: static int
1.115.4.1! ad       2989: sipcom_add_rxbuf(struct sip_softc *sc, int idx)
1.1       thorpej  2990: {
                   2991:        struct sip_rxsoft *rxs = &sc->sc_rxsoft[idx];
                   2992:        struct mbuf *m;
                   2993:        int error;
                   2994:
                   2995:        MGETHDR(m, M_DONTWAIT, MT_DATA);
1.101     perry    2996:        if (m == NULL)
1.1       thorpej  2997:                return (ENOBUFS);
1.105     bouyer   2998:        MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
1.1       thorpej  2999:
                   3000:        MCLGET(m, M_DONTWAIT);
                   3001:        if ((m->m_flags & M_EXT) == 0) {
                   3002:                m_freem(m);
                   3003:                return (ENOBUFS);
                   3004:        }
1.36      thorpej  3005:
1.115.4.1! ad       3006:        /* XXX I don't believe this is necessary. --dyoung */
        !          3007:        if (sc->sc_gigabit)
        !          3008:                m->m_len = sc->sc_parm->p_rxbuf_len;
1.1       thorpej  3009:
                   3010:        if (rxs->rxs_mbuf != NULL)
                   3011:                bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
                   3012:
                   3013:        rxs->rxs_mbuf = m;
                   3014:
                   3015:        error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
1.41      thorpej  3016:            m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
                   3017:            BUS_DMA_READ|BUS_DMA_NOWAIT);
1.1       thorpej  3018:        if (error) {
                   3019:                printf("%s: can't load rx DMA map %d, error = %d\n",
                   3020:                    sc->sc_dev.dv_xname, idx, error);
1.115.4.1! ad       3021:                panic("%s", __func__);          /* XXX */
1.1       thorpej  3022:        }
                   3023:
                   3024:        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   3025:            rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   3026:
1.115.4.1! ad       3027:        sip_init_rxdesc(sc, idx);
1.1       thorpej  3028:
                   3029:        return (0);
                   3030: }
                   3031:
                   3032: /*
1.15      thorpej  3033:  * sip_sis900_set_filter:
1.1       thorpej  3034:  *
                   3035:  *     Set up the receive filter.
                   3036:  */
1.95      thorpej  3037: static void
1.115.4.1! ad       3038: sipcom_sis900_set_filter(struct sip_softc *sc)
1.1       thorpej  3039: {
                   3040:        bus_space_tag_t st = sc->sc_st;
                   3041:        bus_space_handle_t sh = sc->sc_sh;
                   3042:        struct ethercom *ec = &sc->sc_ethercom;
                   3043:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   3044:        struct ether_multi *enm;
1.114     dyoung   3045:        const u_int8_t *cp;
1.1       thorpej  3046:        struct ether_multistep step;
1.45      thorpej  3047:        u_int32_t crc, mchash[16];
1.1       thorpej  3048:
                   3049:        /*
                   3050:         * Initialize the prototype RFCR.
                   3051:         */
                   3052:        sc->sc_rfcr = RFCR_RFEN;
                   3053:        if (ifp->if_flags & IFF_BROADCAST)
                   3054:                sc->sc_rfcr |= RFCR_AAB;
                   3055:        if (ifp->if_flags & IFF_PROMISC) {
                   3056:                sc->sc_rfcr |= RFCR_AAP;
                   3057:                goto allmulti;
                   3058:        }
                   3059:
                   3060:        /*
                   3061:         * Set up the multicast address filter by passing all multicast
                   3062:         * addresses through a CRC generator, and then using the high-order
                   3063:         * 6 bits as an index into the 128 bit multicast hash table (only
                   3064:         * the lower 16 bits of each 32 bit multicast hash register are
                   3065:         * valid).  The high order bits select the register, while the
                   3066:         * rest of the bits select the bit within the register.
                   3067:         */
                   3068:
                   3069:        memset(mchash, 0, sizeof(mchash));
                   3070:
1.92      thorpej  3071:        /*
                   3072:         * SiS900 (at least SiS963) requires us to register the address of
                   3073:         * the PAUSE packet (01:80:c2:00:00:01) into the address filter.
                   3074:         */
                   3075:        crc = 0x0ed423f9;
                   3076:
                   3077:        if (SIP_SIS900_REV(sc, SIS_REV_635) ||
                   3078:            SIP_SIS900_REV(sc, SIS_REV_960) ||
                   3079:            SIP_SIS900_REV(sc, SIS_REV_900B)) {
                   3080:                /* Just want the 8 most significant bits. */
                   3081:                crc >>= 24;
                   3082:        } else {
                   3083:                /* Just want the 7 most significant bits. */
                   3084:                crc >>= 25;
                   3085:        }
                   3086:
                   3087:        /* Set the corresponding bit in the hash table. */
                   3088:        mchash[crc >> 4] |= 1 << (crc & 0xf);
                   3089:
1.1       thorpej  3090:        ETHER_FIRST_MULTI(step, ec, enm);
                   3091:        while (enm != NULL) {
1.37      thorpej  3092:                if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1.1       thorpej  3093:                        /*
                   3094:                         * We must listen to a range of multicast addresses.
                   3095:                         * For now, just accept all multicasts, rather than
                   3096:                         * trying to set only those filter bits needed to match
                   3097:                         * the range.  (At this time, the only use of address
                   3098:                         * ranges is for IP multicast routing, for which the
                   3099:                         * range is big enough to require all bits set.)
                   3100:                         */
                   3101:                        goto allmulti;
                   3102:                }
                   3103:
1.45      thorpej  3104:                crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
1.11      thorpej  3105:
1.45      thorpej  3106:                if (SIP_SIS900_REV(sc, SIS_REV_635) ||
1.84      cube     3107:                    SIP_SIS900_REV(sc, SIS_REV_960) ||
1.45      thorpej  3108:                    SIP_SIS900_REV(sc, SIS_REV_900B)) {
                   3109:                        /* Just want the 8 most significant bits. */
                   3110:                        crc >>= 24;
                   3111:                } else {
                   3112:                        /* Just want the 7 most significant bits. */
                   3113:                        crc >>= 25;
                   3114:                }
1.1       thorpej  3115:
                   3116:                /* Set the corresponding bit in the hash table. */
                   3117:                mchash[crc >> 4] |= 1 << (crc & 0xf);
                   3118:
                   3119:                ETHER_NEXT_MULTI(step, enm);
                   3120:        }
                   3121:
                   3122:        ifp->if_flags &= ~IFF_ALLMULTI;
                   3123:        goto setit;
                   3124:
                   3125:  allmulti:
                   3126:        ifp->if_flags |= IFF_ALLMULTI;
                   3127:        sc->sc_rfcr |= RFCR_AAM;
                   3128:
                   3129:  setit:
                   3130: #define        FILTER_EMIT(addr, data)                                         \
                   3131:        bus_space_write_4(st, sh, SIP_RFCR, (addr));                    \
1.14      tsutsui  3132:        delay(1);                                                       \
                   3133:        bus_space_write_4(st, sh, SIP_RFDR, (data));                    \
                   3134:        delay(1)
1.1       thorpej  3135:
                   3136:        /*
                   3137:         * Disable receive filter, and program the node address.
                   3138:         */
1.114     dyoung   3139:        cp = CLLADDR(ifp->if_sadl);
1.1       thorpej  3140:        FILTER_EMIT(RFCR_RFADDR_NODE0, (cp[1] << 8) | cp[0]);
                   3141:        FILTER_EMIT(RFCR_RFADDR_NODE2, (cp[3] << 8) | cp[2]);
                   3142:        FILTER_EMIT(RFCR_RFADDR_NODE4, (cp[5] << 8) | cp[4]);
                   3143:
                   3144:        if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
                   3145:                /*
                   3146:                 * Program the multicast hash table.
                   3147:                 */
                   3148:                FILTER_EMIT(RFCR_RFADDR_MC0, mchash[0]);
                   3149:                FILTER_EMIT(RFCR_RFADDR_MC1, mchash[1]);
                   3150:                FILTER_EMIT(RFCR_RFADDR_MC2, mchash[2]);
                   3151:                FILTER_EMIT(RFCR_RFADDR_MC3, mchash[3]);
                   3152:                FILTER_EMIT(RFCR_RFADDR_MC4, mchash[4]);
                   3153:                FILTER_EMIT(RFCR_RFADDR_MC5, mchash[5]);
                   3154:                FILTER_EMIT(RFCR_RFADDR_MC6, mchash[6]);
                   3155:                FILTER_EMIT(RFCR_RFADDR_MC7, mchash[7]);
1.45      thorpej  3156:                if (SIP_SIS900_REV(sc, SIS_REV_635) ||
1.84      cube     3157:                    SIP_SIS900_REV(sc, SIS_REV_960) ||
1.45      thorpej  3158:                    SIP_SIS900_REV(sc, SIS_REV_900B)) {
                   3159:                        FILTER_EMIT(RFCR_RFADDR_MC8, mchash[8]);
                   3160:                        FILTER_EMIT(RFCR_RFADDR_MC9, mchash[9]);
                   3161:                        FILTER_EMIT(RFCR_RFADDR_MC10, mchash[10]);
                   3162:                        FILTER_EMIT(RFCR_RFADDR_MC11, mchash[11]);
                   3163:                        FILTER_EMIT(RFCR_RFADDR_MC12, mchash[12]);
                   3164:                        FILTER_EMIT(RFCR_RFADDR_MC13, mchash[13]);
                   3165:                        FILTER_EMIT(RFCR_RFADDR_MC14, mchash[14]);
                   3166:                        FILTER_EMIT(RFCR_RFADDR_MC15, mchash[15]);
                   3167:                }
1.1       thorpej  3168:        }
                   3169: #undef FILTER_EMIT
                   3170:
                   3171:        /*
                   3172:         * Re-enable the receiver filter.
                   3173:         */
                   3174:        bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
                   3175: }
                   3176:
                   3177: /*
1.15      thorpej  3178:  * sip_dp83815_set_filter:
                   3179:  *
                   3180:  *     Set up the receive filter.
                   3181:  */
1.95      thorpej  3182: static void
1.115.4.1! ad       3183: sipcom_dp83815_set_filter(struct sip_softc *sc)
1.15      thorpej  3184: {
                   3185:        bus_space_tag_t st = sc->sc_st;
                   3186:        bus_space_handle_t sh = sc->sc_sh;
                   3187:        struct ethercom *ec = &sc->sc_ethercom;
1.101     perry    3188:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.15      thorpej  3189:        struct ether_multi *enm;
1.114     dyoung   3190:        const u_int8_t *cp;
1.101     perry    3191:        struct ether_multistep step;
1.29      thorpej  3192:        u_int32_t crc, hash, slot, bit;
1.115.4.1! ad       3193: #define        MCHASH_NWORDS_83820     128
        !          3194: #define        MCHASH_NWORDS_83815     32
        !          3195: #define        MCHASH_NWORDS   MAX(MCHASH_NWORDS_83820, MCHASH_NWORDS_83815)
1.29      thorpej  3196:        u_int16_t mchash[MCHASH_NWORDS];
1.15      thorpej  3197:        int i;
                   3198:
                   3199:        /*
                   3200:         * Initialize the prototype RFCR.
1.27      briggs   3201:         * Enable the receive filter, and accept on
                   3202:         *    Perfect (destination address) Match
1.26      briggs   3203:         * If IFF_BROADCAST, also accept all broadcast packets.
                   3204:         * If IFF_PROMISC, accept all unicast packets (and later, set
                   3205:         *    IFF_ALLMULTI and accept all multicast, too).
1.15      thorpej  3206:         */
1.27      briggs   3207:        sc->sc_rfcr = RFCR_RFEN | RFCR_APM;
1.15      thorpej  3208:        if (ifp->if_flags & IFF_BROADCAST)
                   3209:                sc->sc_rfcr |= RFCR_AAB;
                   3210:        if (ifp->if_flags & IFF_PROMISC) {
                   3211:                sc->sc_rfcr |= RFCR_AAP;
                   3212:                goto allmulti;
                   3213:        }
                   3214:
1.29      thorpej  3215:        /*
1.115.4.1! ad       3216:          * Set up the DP83820/DP83815 multicast address filter by
        !          3217:          * passing all multicast addresses through a CRC generator,
        !          3218:          * and then using the high-order 11/9 bits as an index into
        !          3219:          * the 2048/512 bit multicast hash table.  The high-order
        !          3220:          * 7/5 bits select the slot, while the low-order 4 bits
        !          3221:          * select the bit within the slot.  Note that only the low
        !          3222:          * 16-bits of each filter word are used, and there are
        !          3223:          * 128/32 filter words.
1.15      thorpej  3224:         */
                   3225:
                   3226:        memset(mchash, 0, sizeof(mchash));
                   3227:
1.26      briggs   3228:        ifp->if_flags &= ~IFF_ALLMULTI;
1.15      thorpej  3229:        ETHER_FIRST_MULTI(step, ec, enm);
1.38      thorpej  3230:        if (enm == NULL)
                   3231:                goto setit;
                   3232:        while (enm != NULL) {
1.39      thorpej  3233:                if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1.15      thorpej  3234:                        /*
                   3235:                         * We must listen to a range of multicast addresses.
                   3236:                         * For now, just accept all multicasts, rather than
                   3237:                         * trying to set only those filter bits needed to match
                   3238:                         * the range.  (At this time, the only use of address
                   3239:                         * ranges is for IP multicast routing, for which the
                   3240:                         * range is big enough to require all bits set.)
                   3241:                         */
1.38      thorpej  3242:                        goto allmulti;
                   3243:                }
1.26      briggs   3244:
1.38      thorpej  3245:                crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
1.29      thorpej  3246:
1.115.4.1! ad       3247:                if (sc->sc_gigabit) {
        !          3248:                        /* Just want the 11 most significant bits. */
        !          3249:                        hash = crc >> 21;
        !          3250:                } else {
        !          3251:                        /* Just want the 9 most significant bits. */
        !          3252:                        hash = crc >> 23;
        !          3253:                }
1.49      is       3254:
1.38      thorpej  3255:                slot = hash >> 4;
                   3256:                bit = hash & 0xf;
1.15      thorpej  3257:
1.38      thorpej  3258:                /* Set the corresponding bit in the hash table. */
                   3259:                mchash[slot] |= 1 << bit;
1.15      thorpej  3260:
1.38      thorpej  3261:                ETHER_NEXT_MULTI(step, enm);
1.15      thorpej  3262:        }
1.38      thorpej  3263:        sc->sc_rfcr |= RFCR_MHEN;
1.15      thorpej  3264:        goto setit;
                   3265:
                   3266:  allmulti:
                   3267:        ifp->if_flags |= IFF_ALLMULTI;
                   3268:        sc->sc_rfcr |= RFCR_AAM;
                   3269:
                   3270:  setit:
                   3271: #define        FILTER_EMIT(addr, data)                                         \
                   3272:        bus_space_write_4(st, sh, SIP_RFCR, (addr));                    \
                   3273:        delay(1);                                                       \
                   3274:        bus_space_write_4(st, sh, SIP_RFDR, (data));                    \
1.39      thorpej  3275:        delay(1)
1.15      thorpej  3276:
                   3277:        /*
                   3278:         * Disable receive filter, and program the node address.
                   3279:         */
1.114     dyoung   3280:        cp = CLLADDR(ifp->if_sadl);
1.26      briggs   3281:        FILTER_EMIT(RFCR_NS_RFADDR_PMATCH0, (cp[1] << 8) | cp[0]);
                   3282:        FILTER_EMIT(RFCR_NS_RFADDR_PMATCH2, (cp[3] << 8) | cp[2]);
                   3283:        FILTER_EMIT(RFCR_NS_RFADDR_PMATCH4, (cp[5] << 8) | cp[4]);
1.15      thorpej  3284:
                   3285:        if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
1.115.4.1! ad       3286:                int nwords =
        !          3287:                    sc->sc_gigabit ? MCHASH_NWORDS_83820 : MCHASH_NWORDS_83815;
1.15      thorpej  3288:                /*
                   3289:                 * Program the multicast hash table.
                   3290:                 */
1.115.4.1! ad       3291:                for (i = 0; i < nwords; i++) {
        !          3292:                        FILTER_EMIT(sc->sc_parm->p_filtmem + (i * 2), mchash[i]);
1.39      thorpej  3293:                }
1.15      thorpej  3294:        }
                   3295: #undef FILTER_EMIT
1.29      thorpej  3296: #undef MCHASH_NWORDS
1.115.4.1! ad       3297: #undef MCHASH_NWORDS_83815
        !          3298: #undef MCHASH_NWORDS_83820
1.15      thorpej  3299:
                   3300:        /*
                   3301:         * Re-enable the receiver filter.
                   3302:         */
                   3303:        bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
1.101     perry    3304: }
1.29      thorpej  3305:
                   3306: /*
                   3307:  * sip_dp83820_mii_readreg:    [mii interface function]
                   3308:  *
                   3309:  *     Read a PHY register on the MII of the DP83820.
                   3310:  */
1.95      thorpej  3311: static int
1.115.4.1! ad       3312: sipcom_dp83820_mii_readreg(struct device *self, int phy, int reg)
1.29      thorpej  3313: {
1.63      thorpej  3314:        struct sip_softc *sc = (void *) self;
                   3315:
                   3316:        if (sc->sc_cfg & CFG_TBI_EN) {
                   3317:                bus_addr_t tbireg;
                   3318:                int rv;
                   3319:
                   3320:                if (phy != 0)
                   3321:                        return (0);
                   3322:
                   3323:                switch (reg) {
                   3324:                case MII_BMCR:          tbireg = SIP_TBICR; break;
                   3325:                case MII_BMSR:          tbireg = SIP_TBISR; break;
                   3326:                case MII_ANAR:          tbireg = SIP_TANAR; break;
                   3327:                case MII_ANLPAR:        tbireg = SIP_TANLPAR; break;
                   3328:                case MII_ANER:          tbireg = SIP_TANER; break;
1.64      thorpej  3329:                case MII_EXTSR:
                   3330:                        /*
                   3331:                         * Don't even bother reading the TESR register.
                   3332:                         * The manual documents that the device has
                   3333:                         * 1000baseX full/half capability, but the
                   3334:                         * register itself seems read back 0 on some
                   3335:                         * boards.  Just hard-code the result.
                   3336:                         */
                   3337:                        return (EXTSR_1000XFDX|EXTSR_1000XHDX);
                   3338:
1.63      thorpej  3339:                default:
                   3340:                        return (0);
                   3341:                }
                   3342:
                   3343:                rv = bus_space_read_4(sc->sc_st, sc->sc_sh, tbireg) & 0xffff;
                   3344:                if (tbireg == SIP_TBISR) {
                   3345:                        /* LINK and ACOMP are switched! */
                   3346:                        int val = rv;
                   3347:
                   3348:                        rv = 0;
                   3349:                        if (val & TBISR_MR_LINK_STATUS)
                   3350:                                rv |= BMSR_LINK;
                   3351:                        if (val & TBISR_MR_AN_COMPLETE)
                   3352:                                rv |= BMSR_ACOMP;
1.64      thorpej  3353:
                   3354:                        /*
                   3355:                         * The manual claims this register reads back 0
                   3356:                         * on hard and soft reset.  But we want to let
                   3357:                         * the gentbi driver know that we support auto-
                   3358:                         * negotiation, so hard-code this bit in the
                   3359:                         * result.
                   3360:                         */
1.69      thorpej  3361:                        rv |= BMSR_ANEG | BMSR_EXTSTAT;
1.63      thorpej  3362:                }
                   3363:
                   3364:                return (rv);
                   3365:        }
1.29      thorpej  3366:
1.115.4.1! ad       3367:        return mii_bitbang_readreg(self, &sipcom_mii_bitbang_ops, phy, reg);
1.29      thorpej  3368: }
                   3369:
                   3370: /*
                   3371:  * sip_dp83820_mii_writereg:   [mii interface function]
                   3372:  *
                   3373:  *     Write a PHY register on the MII of the DP83820.
                   3374:  */
1.95      thorpej  3375: static void
1.115.4.1! ad       3376: sipcom_dp83820_mii_writereg(struct device *self, int phy, int reg, int val)
1.29      thorpej  3377: {
1.63      thorpej  3378:        struct sip_softc *sc = (void *) self;
                   3379:
                   3380:        if (sc->sc_cfg & CFG_TBI_EN) {
                   3381:                bus_addr_t tbireg;
                   3382:
                   3383:                if (phy != 0)
                   3384:                        return;
                   3385:
                   3386:                switch (reg) {
                   3387:                case MII_BMCR:          tbireg = SIP_TBICR; break;
                   3388:                case MII_ANAR:          tbireg = SIP_TANAR; break;
                   3389:                case MII_ANLPAR:        tbireg = SIP_TANLPAR; break;
                   3390:                default:
                   3391:                        return;
                   3392:                }
                   3393:
                   3394:                bus_space_write_4(sc->sc_st, sc->sc_sh, tbireg, val);
                   3395:                return;
                   3396:        }
1.29      thorpej  3397:
1.115.4.1! ad       3398:        mii_bitbang_writereg(self, &sipcom_mii_bitbang_ops, phy, reg, val);
1.29      thorpej  3399: }
                   3400:
                   3401: /*
1.88      thorpej  3402:  * sip_dp83820_mii_statchg:    [mii interface function]
1.29      thorpej  3403:  *
                   3404:  *     Callback from MII layer when media changes.
                   3405:  */
1.95      thorpej  3406: static void
1.115.4.1! ad       3407: sipcom_dp83820_mii_statchg(struct device *self)
1.29      thorpej  3408: {
                   3409:        struct sip_softc *sc = (struct sip_softc *) self;
1.89      thorpej  3410:        struct mii_data *mii = &sc->sc_mii;
                   3411:        u_int32_t cfg, pcr;
                   3412:
                   3413:        /*
                   3414:         * Get flow control negotiation result.
                   3415:         */
                   3416:        if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO &&
                   3417:            (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) {
                   3418:                sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK;
                   3419:                mii->mii_media_active &= ~IFM_ETH_FMASK;
                   3420:        }
1.29      thorpej  3421:
                   3422:        /*
                   3423:         * Update TXCFG for full-duplex operation.
                   3424:         */
1.89      thorpej  3425:        if ((mii->mii_media_active & IFM_FDX) != 0)
1.29      thorpej  3426:                sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
                   3427:        else
                   3428:                sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
                   3429:
                   3430:        /*
                   3431:         * Update RXCFG for full-duplex or loopback.
                   3432:         */
1.89      thorpej  3433:        if ((mii->mii_media_active & IFM_FDX) != 0 ||
                   3434:            IFM_SUBTYPE(mii->mii_media_active) == IFM_LOOP)
1.29      thorpej  3435:                sc->sc_rxcfg |= RXCFG_ATX;
                   3436:        else
                   3437:                sc->sc_rxcfg &= ~RXCFG_ATX;
                   3438:
                   3439:        /*
                   3440:         * Update CFG for MII/GMII.
                   3441:         */
                   3442:        if (sc->sc_ethercom.ec_if.if_baudrate == IF_Mbps(1000))
                   3443:                cfg = sc->sc_cfg | CFG_MODE_1000;
                   3444:        else
                   3445:                cfg = sc->sc_cfg;
                   3446:
                   3447:        /*
1.89      thorpej  3448:         * 802.3x flow control.
1.29      thorpej  3449:         */
1.89      thorpej  3450:        pcr = 0;
                   3451:        if (sc->sc_flowflags & IFM_FLOW) {
                   3452:                if (sc->sc_flowflags & IFM_ETH_TXPAUSE)
                   3453:                        pcr |= sc->sc_rx_flow_thresh;
                   3454:                if (sc->sc_flowflags & IFM_ETH_RXPAUSE)
1.93      thorpej  3455:                        pcr |= PCR_PSEN | PCR_PS_MCAST;
1.89      thorpej  3456:        }
1.29      thorpej  3457:
                   3458:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CFG, cfg);
1.115.4.1! ad       3459:        bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
        !          3460:            sc->sc_txcfg);
        !          3461:        bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
        !          3462:            sc->sc_rxcfg);
1.89      thorpej  3463:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_PCR, pcr);
1.15      thorpej  3464: }
                   3465:
                   3466: /*
1.86      cube     3467:  * sip_mii_bitbang_read: [mii bit-bang interface function]
1.29      thorpej  3468:  *
                   3469:  *     Read the MII serial port for the MII bit-bang module.
                   3470:  */
1.95      thorpej  3471: static u_int32_t
1.115.4.1! ad       3472: sipcom_mii_bitbang_read(struct device *self)
1.29      thorpej  3473: {
                   3474:        struct sip_softc *sc = (void *) self;
                   3475:
                   3476:        return (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR));
                   3477: }
                   3478:
                   3479: /*
1.86      cube     3480:  * sip_mii_bitbang_write: [mii big-bang interface function]
1.29      thorpej  3481:  *
                   3482:  *     Write the MII serial port for the MII bit-bang module.
                   3483:  */
1.95      thorpej  3484: static void
1.115.4.1! ad       3485: sipcom_mii_bitbang_write(struct device *self, u_int32_t val)
1.29      thorpej  3486: {
                   3487:        struct sip_softc *sc = (void *) self;
                   3488:
                   3489:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, val);
                   3490: }
1.84      cube     3491:
1.29      thorpej  3492: /*
1.15      thorpej  3493:  * sip_sis900_mii_readreg:     [mii interface function]
1.1       thorpej  3494:  *
                   3495:  *     Read a PHY register on the MII.
                   3496:  */
1.95      thorpej  3497: static int
1.115.4.1! ad       3498: sipcom_sis900_mii_readreg(struct device *self, int phy, int reg)
1.1       thorpej  3499: {
                   3500:        struct sip_softc *sc = (struct sip_softc *) self;
1.86      cube     3501:        u_int32_t enphy;
1.1       thorpej  3502:
                   3503:        /*
1.86      cube     3504:         * The PHY of recent SiS chipsets is accessed through bitbang
                   3505:         * operations.
1.1       thorpej  3506:         */
1.91      fair     3507:        if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900)
1.115.4.1! ad       3508:                return mii_bitbang_readreg(self, &sipcom_mii_bitbang_ops,
        !          3509:                    phy, reg);
1.84      cube     3510:
1.91      fair     3511: #ifndef SIS900_MII_RESTRICT
1.84      cube     3512:        /*
1.86      cube     3513:         * The SiS 900 has only an internal PHY on the MII.  Only allow
                   3514:         * MII address 0.
1.84      cube     3515:         */
1.86      cube     3516:        if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 && phy != 0)
                   3517:                return (0);
1.91      fair     3518: #endif
1.84      cube     3519:
1.86      cube     3520:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
                   3521:            (phy << ENPHY_PHYADDR_SHIFT) | (reg << ENPHY_REGADDR_SHIFT) |
                   3522:            ENPHY_RWCMD | ENPHY_ACCESS);
                   3523:        do {
                   3524:                enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
                   3525:        } while (enphy & ENPHY_ACCESS);
                   3526:        return ((enphy & ENPHY_PHYDATA) >> ENPHY_DATA_SHIFT);
1.1       thorpej  3527: }
                   3528:
                   3529: /*
1.15      thorpej  3530:  * sip_sis900_mii_writereg:    [mii interface function]
1.1       thorpej  3531:  *
                   3532:  *     Write a PHY register on the MII.
                   3533:  */
1.95      thorpej  3534: static void
1.115.4.1! ad       3535: sipcom_sis900_mii_writereg(struct device *self, int phy, int reg, int val)
1.1       thorpej  3536: {
                   3537:        struct sip_softc *sc = (struct sip_softc *) self;
                   3538:        u_int32_t enphy;
1.86      cube     3539:
1.91      fair     3540:        if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900) {
1.115.4.1! ad       3541:                mii_bitbang_writereg(self, &sipcom_mii_bitbang_ops,
1.86      cube     3542:                    phy, reg, val);
                   3543:                return;
                   3544:        }
1.1       thorpej  3545:
1.91      fair     3546: #ifndef SIS900_MII_RESTRICT
1.1       thorpej  3547:        /*
                   3548:         * The SiS 900 has only an internal PHY on the MII.  Only allow
                   3549:         * MII address 0.
                   3550:         */
1.86      cube     3551:        if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 && phy != 0)
1.1       thorpej  3552:                return;
1.91      fair     3553: #endif
1.84      cube     3554:
1.86      cube     3555:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
                   3556:            (val << ENPHY_DATA_SHIFT) | (phy << ENPHY_PHYADDR_SHIFT) |
                   3557:            (reg << ENPHY_REGADDR_SHIFT) | ENPHY_ACCESS);
                   3558:        do {
                   3559:                enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
                   3560:        } while (enphy & ENPHY_ACCESS);
1.1       thorpej  3561: }
                   3562:
                   3563: /*
1.15      thorpej  3564:  * sip_sis900_mii_statchg:     [mii interface function]
1.1       thorpej  3565:  *
                   3566:  *     Callback from MII layer when media changes.
                   3567:  */
1.95      thorpej  3568: static void
1.115.4.1! ad       3569: sipcom_sis900_mii_statchg(struct device *self)
1.1       thorpej  3570: {
                   3571:        struct sip_softc *sc = (struct sip_softc *) self;
1.89      thorpej  3572:        struct mii_data *mii = &sc->sc_mii;
1.1       thorpej  3573:        u_int32_t flowctl;
                   3574:
                   3575:        /*
1.89      thorpej  3576:         * Get flow control negotiation result.
                   3577:         */
                   3578:        if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO &&
                   3579:            (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) {
                   3580:                sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK;
                   3581:                mii->mii_media_active &= ~IFM_ETH_FMASK;
                   3582:        }
                   3583:
                   3584:        /*
1.1       thorpej  3585:         * Update TXCFG for full-duplex operation.
                   3586:         */
1.89      thorpej  3587:        if ((mii->mii_media_active & IFM_FDX) != 0)
1.1       thorpej  3588:                sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
                   3589:        else
                   3590:                sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
                   3591:
                   3592:        /*
                   3593:         * Update RXCFG for full-duplex or loopback.
                   3594:         */
1.89      thorpej  3595:        if ((mii->mii_media_active & IFM_FDX) != 0 ||
                   3596:            IFM_SUBTYPE(mii->mii_media_active) == IFM_LOOP)
1.1       thorpej  3597:                sc->sc_rxcfg |= RXCFG_ATX;
                   3598:        else
                   3599:                sc->sc_rxcfg &= ~RXCFG_ATX;
                   3600:
                   3601:        /*
                   3602:         * Update IMR for use of 802.3x flow control.
                   3603:         */
1.89      thorpej  3604:        if (sc->sc_flowflags & IFM_FLOW) {
1.1       thorpej  3605:                sc->sc_imr |= (ISR_PAUSE_END|ISR_PAUSE_ST);
                   3606:                flowctl = FLOWCTL_FLOWEN;
                   3607:        } else {
                   3608:                sc->sc_imr &= ~(ISR_PAUSE_END|ISR_PAUSE_ST);
                   3609:                flowctl = 0;
                   3610:        }
                   3611:
1.115.4.1! ad       3612:        bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
        !          3613:            sc->sc_txcfg);
        !          3614:        bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
        !          3615:            sc->sc_rxcfg);
1.1       thorpej  3616:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);
                   3617:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);
1.15      thorpej  3618: }
                   3619:
                   3620: /*
                   3621:  * sip_dp83815_mii_readreg:    [mii interface function]
                   3622:  *
                   3623:  *     Read a PHY register on the MII.
                   3624:  */
1.95      thorpej  3625: static int
1.115.4.1! ad       3626: sipcom_dp83815_mii_readreg(struct device *self, int phy, int reg)
1.15      thorpej  3627: {
                   3628:        struct sip_softc *sc = (struct sip_softc *) self;
                   3629:        u_int32_t val;
                   3630:
                   3631:        /*
                   3632:         * The DP83815 only has an internal PHY.  Only allow
                   3633:         * MII address 0.
                   3634:         */
                   3635:        if (phy != 0)
                   3636:                return (0);
                   3637:
                   3638:        /*
                   3639:         * Apparently, after a reset, the DP83815 can take a while
                   3640:         * to respond.  During this recovery period, the BMSR returns
                   3641:         * a value of 0.  Catch this -- it's not supposed to happen
                   3642:         * (the BMSR has some hardcoded-to-1 bits), and wait for the
                   3643:         * PHY to come back to life.
                   3644:         *
                   3645:         * This works out because the BMSR is the first register
                   3646:         * read during the PHY probe process.
                   3647:         */
                   3648:        do {
                   3649:                val = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_NS_PHY(reg));
                   3650:        } while (reg == MII_BMSR && val == 0);
                   3651:
                   3652:        return (val & 0xffff);
                   3653: }
                   3654:
                   3655: /*
                   3656:  * sip_dp83815_mii_writereg:   [mii interface function]
                   3657:  *
                   3658:  *     Write a PHY register to the MII.
                   3659:  */
1.95      thorpej  3660: static void
1.115.4.1! ad       3661: sipcom_dp83815_mii_writereg(struct device *self, int phy, int reg, int val)
1.15      thorpej  3662: {
                   3663:        struct sip_softc *sc = (struct sip_softc *) self;
                   3664:
                   3665:        /*
                   3666:         * The DP83815 only has an internal PHY.  Only allow
                   3667:         * MII address 0.
                   3668:         */
                   3669:        if (phy != 0)
                   3670:                return;
                   3671:
                   3672:        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_PHY(reg), val);
                   3673: }
                   3674:
                   3675: /*
                   3676:  * sip_dp83815_mii_statchg:    [mii interface function]
                   3677:  *
                   3678:  *     Callback from MII layer when media changes.
                   3679:  */
1.95      thorpej  3680: static void
1.115.4.1! ad       3681: sipcom_dp83815_mii_statchg(struct device *self)
1.15      thorpej  3682: {
                   3683:        struct sip_softc *sc = (struct sip_softc *) self;
                   3684:
                   3685:        /*
                   3686:         * Update TXCFG for full-duplex operation.
                   3687:         */
                   3688:        if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0)
                   3689:                sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
                   3690:        else
                   3691:                sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
                   3692:
                   3693:        /*
                   3694:         * Update RXCFG for full-duplex or loopback.
                   3695:         */
                   3696:        if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0 ||
                   3697:            IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_LOOP)
                   3698:                sc->sc_rxcfg |= RXCFG_ATX;
                   3699:        else
                   3700:                sc->sc_rxcfg &= ~RXCFG_ATX;
                   3701:
                   3702:        /*
                   3703:         * XXX 802.3x flow control.
                   3704:         */
                   3705:
1.115.4.1! ad       3706:        bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
        !          3707:            sc->sc_txcfg);
        !          3708:        bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
        !          3709:            sc->sc_rxcfg);
1.78      thorpej  3710:
                   3711:        /*
                   3712:         * Some DP83815s experience problems when used with short
                   3713:         * (< 30m/100ft) Ethernet cables in 100BaseTX mode.  This
                   3714:         * sequence adjusts the DSP's signal attenuation to fix the
                   3715:         * problem.
                   3716:         */
                   3717:        if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_100_TX) {
                   3718:                uint32_t reg;
                   3719:
                   3720:                bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00cc, 0x0001);
                   3721:
                   3722:                reg = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x00f4);
                   3723:                reg &= 0x0fff;
                   3724:                bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00f4, reg | 0x1000);
                   3725:                delay(100);
                   3726:                reg = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x00fc);
                   3727:                reg &= 0x00ff;
                   3728:                if ((reg & 0x0080) == 0 || (reg >= 0x00d8)) {
                   3729:                        bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00fc,
                   3730:                            0x00e8);
                   3731:                        reg = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x00f4);
                   3732:                        bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00f4,
                   3733:                            reg | 0x20);
                   3734:                }
                   3735:
                   3736:                bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00cc, 0);
                   3737:        }
1.25      briggs   3738: }
1.29      thorpej  3739:
1.95      thorpej  3740: static void
1.115.4.1! ad       3741: sipcom_dp83820_read_macaddr(struct sip_softc *sc,
1.110     christos 3742:     const struct pci_attach_args *pa, u_int8_t *enaddr)
1.29      thorpej  3743: {
                   3744:        u_int16_t eeprom_data[SIP_DP83820_EEPROM_LENGTH / 2];
                   3745:        u_int8_t cksum, *e, match;
                   3746:        int i;
                   3747:
                   3748:        /*
                   3749:         * EEPROM data format for the DP83820 can be found in
                   3750:         * the DP83820 manual, section 4.2.4.
                   3751:         */
1.25      briggs   3752:
1.115.4.1! ad       3753:        sipcom_read_eeprom(sc, 0, __arraycount(eeprom_data), eeprom_data);
1.29      thorpej  3754:
                   3755:        match = eeprom_data[SIP_DP83820_EEPROM_CHECKSUM / 2] >> 8;
                   3756:        match = ~(match - 1);
                   3757:
                   3758:        cksum = 0x55;
                   3759:        e = (u_int8_t *) eeprom_data;
                   3760:        for (i = 0; i < SIP_DP83820_EEPROM_CHECKSUM; i++)
                   3761:                cksum += *e++;
                   3762:
                   3763:        if (cksum != match)
                   3764:                printf("%s: Checksum (%x) mismatch (%x)",
                   3765:                    sc->sc_dev.dv_xname, cksum, match);
                   3766:
                   3767:        enaddr[0] = eeprom_data[SIP_DP83820_EEPROM_PMATCH2 / 2] & 0xff;
                   3768:        enaddr[1] = eeprom_data[SIP_DP83820_EEPROM_PMATCH2 / 2] >> 8;
                   3769:        enaddr[2] = eeprom_data[SIP_DP83820_EEPROM_PMATCH1 / 2] & 0xff;
                   3770:        enaddr[3] = eeprom_data[SIP_DP83820_EEPROM_PMATCH1 / 2] >> 8;
                   3771:        enaddr[4] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] & 0xff;
                   3772:        enaddr[5] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] >> 8;
                   3773: }
1.115.4.1! ad       3774:
1.84      cube     3775: static void
1.115.4.1! ad       3776: sipcom_sis900_eeprom_delay(struct sip_softc *sc)
1.84      cube     3777: {
                   3778:        int i;
                   3779:
                   3780:        /*
                   3781:         * FreeBSD goes from (300/33)+1 [10] to 0.  There must be
                   3782:         * a reason, but I don't know it.
                   3783:         */
                   3784:        for (i = 0; i < 10; i++)
                   3785:                bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR);
                   3786: }
                   3787:
1.95      thorpej  3788: static void
1.115.4.1! ad       3789: sipcom_sis900_read_macaddr(struct sip_softc *sc,
1.110     christos 3790:     const struct pci_attach_args *pa, u_int8_t *enaddr)
1.25      briggs   3791: {
                   3792:        u_int16_t myea[ETHER_ADDR_LEN / 2];
                   3793:
1.50      briggs   3794:        switch (sc->sc_rev) {
1.44      thorpej  3795:        case SIS_REV_630S:
                   3796:        case SIS_REV_630E:
                   3797:        case SIS_REV_630EA1:
1.51      briggs   3798:        case SIS_REV_630ET:
1.45      thorpej  3799:        case SIS_REV_635:
1.44      thorpej  3800:                /*
                   3801:                 * The MAC address for the on-board Ethernet of
                   3802:                 * the SiS 630 chipset is in the NVRAM.  Kick
                   3803:                 * the chip into re-loading it from NVRAM, and
                   3804:                 * read the MAC address out of the filter registers.
                   3805:                 */
                   3806:                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_RLD);
                   3807:
                   3808:                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RFCR,
                   3809:                    RFCR_RFADDR_NODE0);
                   3810:                myea[0] = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_RFDR) &
                   3811:                    0xffff;
                   3812:
                   3813:                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RFCR,
                   3814:                    RFCR_RFADDR_NODE2);
                   3815:                myea[1] = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_RFDR) &
                   3816:                    0xffff;
                   3817:
                   3818:                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RFCR,
                   3819:                    RFCR_RFADDR_NODE4);
                   3820:                myea[2] = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_RFDR) &
                   3821:                    0xffff;
                   3822:                break;
1.84      cube     3823:
                   3824:        case SIS_REV_960:
                   3825:                {
1.86      cube     3826: #define        SIS_SET_EROMAR(x,y)     bus_space_write_4(x->sc_st, x->sc_sh, SIP_EROMAR,       \
                   3827:                                    bus_space_read_4(x->sc_st, x->sc_sh, SIP_EROMAR) | (y))
                   3828:
                   3829: #define        SIS_CLR_EROMAR(x,y)     bus_space_write_4(x->sc_st, x->sc_sh, SIP_EROMAR,       \
                   3830:                                    bus_space_read_4(x->sc_st, x->sc_sh, SIP_EROMAR) & ~(y))
                   3831:
1.84      cube     3832:                        int waittime, i;
                   3833:
                   3834:                        /* Allow to read EEPROM from LAN. It is shared
                   3835:                         * between a 1394 controller and the NIC and each
                   3836:                         * time we access it, we need to set SIS_EECMD_REQ.
                   3837:                         */
                   3838:                        SIS_SET_EROMAR(sc, EROMAR_REQ);
                   3839:
                   3840:                        for (waittime = 0; waittime < 1000; waittime++) { /* 1 ms max */
                   3841:                                /* Force EEPROM to idle state. */
                   3842:
                   3843:                                /*
                   3844:                                 * XXX-cube This is ugly.  I'll look for docs about it.
                   3845:                                 */
                   3846:                                SIS_SET_EROMAR(sc, EROMAR_EECS);
1.115.4.1! ad       3847:                                sipcom_sis900_eeprom_delay(sc);
1.84      cube     3848:                                for (i = 0; i <= 25; i++) { /* Yes, 26 times. */
                   3849:                                        SIS_SET_EROMAR(sc, EROMAR_EESK);
1.115.4.1! ad       3850:                                        sipcom_sis900_eeprom_delay(sc);
1.84      cube     3851:                                        SIS_CLR_EROMAR(sc, EROMAR_EESK);
1.115.4.1! ad       3852:                                        sipcom_sis900_eeprom_delay(sc);
1.84      cube     3853:                                }
                   3854:                                SIS_CLR_EROMAR(sc, EROMAR_EECS);
1.115.4.1! ad       3855:                                sipcom_sis900_eeprom_delay(sc);
1.84      cube     3856:                                bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, 0);
                   3857:
                   3858:                                if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR) & EROMAR_GNT) {
1.115.4.1! ad       3859:                                        sipcom_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
1.84      cube     3860:                                            sizeof(myea) / sizeof(myea[0]), myea);
                   3861:                                        break;
                   3862:                                }
                   3863:                                DELAY(1);
                   3864:                        }
                   3865:
                   3866:                        /*
                   3867:                         * Set SIS_EECTL_CLK to high, so a other master
                   3868:                         * can operate on the i2c bus.
                   3869:                         */
                   3870:                        SIS_SET_EROMAR(sc, EROMAR_EESK);
                   3871:
                   3872:                        /* Refuse EEPROM access by LAN */
                   3873:                        SIS_SET_EROMAR(sc, EROMAR_DONE);
                   3874:                } break;
1.44      thorpej  3875:
                   3876:        default:
1.115.4.1! ad       3877:                sipcom_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
1.44      thorpej  3878:                    sizeof(myea) / sizeof(myea[0]), myea);
                   3879:        }
1.25      briggs   3880:
                   3881:        enaddr[0] = myea[0] & 0xff;
                   3882:        enaddr[1] = myea[0] >> 8;
                   3883:        enaddr[2] = myea[1] & 0xff;
                   3884:        enaddr[3] = myea[1] >> 8;
                   3885:        enaddr[4] = myea[2] & 0xff;
                   3886:        enaddr[5] = myea[2] >> 8;
                   3887: }
                   3888:
1.29      thorpej  3889: /* Table and macro to bit-reverse an octet. */
                   3890: static const u_int8_t bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
1.25      briggs   3891: #define bbr(v) ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])
                   3892:
1.95      thorpej  3893: static void
1.115.4.1! ad       3894: sipcom_dp83815_read_macaddr(struct sip_softc *sc,
1.110     christos 3895:     const struct pci_attach_args *pa, u_int8_t *enaddr)
1.25      briggs   3896: {
                   3897:        u_int16_t eeprom_data[SIP_DP83815_EEPROM_LENGTH / 2], *ea;
                   3898:        u_int8_t cksum, *e, match;
                   3899:        int i;
                   3900:
1.115.4.1! ad       3901:        sipcom_read_eeprom(sc, 0, sizeof(eeprom_data) /
1.29      thorpej  3902:            sizeof(eeprom_data[0]), eeprom_data);
1.25      briggs   3903:
                   3904:        match = eeprom_data[SIP_DP83815_EEPROM_CHECKSUM/2] >> 8;
                   3905:        match = ~(match - 1);
                   3906:
                   3907:        cksum = 0x55;
                   3908:        e = (u_int8_t *) eeprom_data;
                   3909:        for (i=0 ; i<SIP_DP83815_EEPROM_CHECKSUM ; i++) {
                   3910:                cksum += *e++;
                   3911:        }
                   3912:        if (cksum != match) {
                   3913:                printf("%s: Checksum (%x) mismatch (%x)",
                   3914:                    sc->sc_dev.dv_xname, cksum, match);
                   3915:        }
                   3916:
                   3917:        /*
                   3918:         * Unrolled because it makes slightly more sense this way.
                   3919:         * The DP83815 stores the MAC address in bit 0 of word 6
                   3920:         * through bit 15 of word 8.
                   3921:         */
                   3922:        ea = &eeprom_data[6];
                   3923:        enaddr[0] = ((*ea & 0x1) << 7);
                   3924:        ea++;
                   3925:        enaddr[0] |= ((*ea & 0xFE00) >> 9);
                   3926:        enaddr[1] = ((*ea & 0x1FE) >> 1);
                   3927:        enaddr[2] = ((*ea & 0x1) << 7);
                   3928:        ea++;
                   3929:        enaddr[2] |= ((*ea & 0xFE00) >> 9);
                   3930:        enaddr[3] = ((*ea & 0x1FE) >> 1);
                   3931:        enaddr[4] = ((*ea & 0x1) << 7);
                   3932:        ea++;
                   3933:        enaddr[4] |= ((*ea & 0xFE00) >> 9);
                   3934:        enaddr[5] = ((*ea & 0x1FE) >> 1);
                   3935:
                   3936:        /*
                   3937:         * In case that's not weird enough, we also need to reverse
                   3938:         * the bits in each byte.  This all actually makes more sense
                   3939:         * if you think about the EEPROM storage as an array of bits
                   3940:         * being shifted into bytes, but that's not how we're looking
                   3941:         * at it here...
                   3942:         */
1.28      thorpej  3943:        for (i = 0; i < 6 ;i++)
1.25      briggs   3944:                enaddr[i] = bbr(enaddr[i]);
1.1       thorpej  3945: }
                   3946:
                   3947: /*
                   3948:  * sip_mediastatus:    [ifmedia interface function]
                   3949:  *
                   3950:  *     Get the current interface media status.
                   3951:  */
1.95      thorpej  3952: static void
1.115.4.1! ad       3953: sipcom_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1.1       thorpej  3954: {
                   3955:        struct sip_softc *sc = ifp->if_softc;
                   3956:
                   3957:        mii_pollstat(&sc->sc_mii);
                   3958:        ifmr->ifm_status = sc->sc_mii.mii_media_status;
1.89      thorpej  3959:        ifmr->ifm_active = (sc->sc_mii.mii_media_active & ~IFM_ETH_FMASK) |
                   3960:                           sc->sc_flowflags;
1.1       thorpej  3961: }
                   3962:
                   3963: /*
                   3964:  * sip_mediachange:    [ifmedia interface function]
                   3965:  *
                   3966:  *     Set hardware to newly-selected media.
                   3967:  */
1.95      thorpej  3968: static int
1.115.4.1! ad       3969: sipcom_mediachange(struct ifnet *ifp)
1.1       thorpej  3970: {
                   3971:        struct sip_softc *sc = ifp->if_softc;
                   3972:
                   3973:        if (ifp->if_flags & IFF_UP)
                   3974:                mii_mediachg(&sc->sc_mii);
                   3975:        return (0);
                   3976: }

CVSweb <webmaster@jp.NetBSD.org>