[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.8.3

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

CVSweb <webmaster@jp.NetBSD.org>