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

Annotation of src/sys/dev/pci/if_kse.c, Revision 1.31.14.2

1.31.14.2! pgoyette    1: /*     $NetBSD$        */
1.1       nisimura    2:
1.15      nisimura    3: /*-
                      4:  * Copyright (c) 2006 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Tohru Nishimura.
1.1       nisimura    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:  *
1.15      nisimura   19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
1.1       nisimura   30:  */
                     31:
                     32: #include <sys/cdefs.h>
1.31.14.2! pgoyette   33: __KERNEL_RCSID(0, "$NetBSD$");
1.1       nisimura   34:
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/callout.h>
                     39: #include <sys/mbuf.h>
                     40: #include <sys/malloc.h>
                     41: #include <sys/kernel.h>
                     42: #include <sys/ioctl.h>
                     43: #include <sys/errno.h>
                     44: #include <sys/device.h>
                     45: #include <sys/queue.h>
                     46:
                     47: #include <machine/endian.h>
1.10      ad         48: #include <sys/bus.h>
                     49: #include <sys/intr.h>
1.1       nisimura   50:
                     51: #include <net/if.h>
                     52: #include <net/if_media.h>
                     53: #include <net/if_dl.h>
                     54: #include <net/if_ether.h>
                     55:
                     56: #include <net/bpf.h>
                     57:
                     58: #include <dev/pci/pcivar.h>
                     59: #include <dev/pci/pcireg.h>
                     60: #include <dev/pci/pcidevs.h>
                     61:
                     62: #define CSR_READ_4(sc, off) \
                     63:            bus_space_read_4(sc->sc_st, sc->sc_sh, off)
                     64: #define CSR_WRITE_4(sc, off, val) \
                     65:            bus_space_write_4(sc->sc_st, sc->sc_sh, off, val)
                     66: #define CSR_READ_2(sc, off) \
                     67:            bus_space_read_2(sc->sc_st, sc->sc_sh, off)
                     68: #define CSR_WRITE_2(sc, off, val) \
                     69:            bus_space_write_2(sc->sc_st, sc->sc_sh, off, val)
                     70:
                     71: #define MDTXC  0x000   /* DMA transmit control */
                     72: #define MDRXC  0x004   /* DMA receive control */
                     73: #define MDTSC  0x008   /* DMA transmit start */
                     74: #define MDRSC  0x00c   /* DMA receive start */
                     75: #define TDLB   0x010   /* transmit descriptor list base */
                     76: #define RDLB   0x014   /* receive descriptor list base */
1.7       nisimura   77: #define MTR0   0x020   /* multicast table 31:0 */
                     78: #define MTR1   0x024   /* multicast table 63:32 */
1.1       nisimura   79: #define INTEN  0x028   /* interrupt enable */
                     80: #define INTST  0x02c   /* interrupt status */
                     81: #define MARL   0x200   /* MAC address low */
                     82: #define MARM   0x202   /* MAC address middle */
                     83: #define MARH   0x204   /* MAC address high */
                     84: #define GRR    0x216   /* global reset */
                     85: #define CIDR   0x400   /* chip ID and enable */
                     86: #define CGCR   0x40a   /* chip global control */
1.8       nisimura   87: #define IACR   0x4a0   /* indirect access control */
                     88: #define IADR1  0x4a2   /* indirect access data 66:63 */
                     89: #define IADR2  0x4a4   /* indirect access data 47:32 */
                     90: #define IADR3  0x4a6   /* indirect access data 63:48 */
                     91: #define IADR4  0x4a8   /* indirect access data 15:0 */
                     92: #define IADR5  0x4aa   /* indirect access data 31:16 */
1.1       nisimura   93: #define P1CR4  0x512   /* port 1 control 4 */
                     94: #define P1SR   0x514   /* port 1 status */
1.8       nisimura   95: #define P2CR4  0x532   /* port 2 control 4 */
                     96: #define P2SR   0x534   /* port 2 status */
1.1       nisimura   97:
                     98: #define TXC_BS_MSK     0x3f000000      /* burst size */
                     99: #define TXC_BS_SFT     (24)            /* 1,2,4,8,16,32 or 0 for unlimited */
                    100: #define TXC_UCG                (1U<<18)        /* generate UDP checksum */
                    101: #define TXC_TCG                (1U<<17)        /* generate TCP checksum */
                    102: #define TXC_ICG                (1U<<16)        /* generate IP checksum */
                    103: #define TXC_FCE                (1U<<9)         /* enable flowcontrol */
                    104: #define TXC_EP         (1U<<2)         /* enable automatic padding */
                    105: #define TXC_AC         (1U<<1)         /* add CRC to frame */
                    106: #define TXC_TEN                (1)             /* enable DMA to run */
                    107:
                    108: #define RXC_BS_MSK     0x3f000000      /* burst size */
                    109: #define RXC_BS_SFT     (24)            /* 1,2,4,8,16,32 or 0 for unlimited */
1.6       nisimura  110: #define RXC_IHAE       (1U<<19)        /* IP header alignment enable */
1.5       nisimura  111: #define RXC_UCC                (1U<<18)        /* run UDP checksum */
                    112: #define RXC_TCC                (1U<<17)        /* run TDP checksum */
                    113: #define RXC_ICC                (1U<<16)        /* run IP checksum */
1.1       nisimura  114: #define RXC_FCE                (1U<<9)         /* enable flowcontrol */
                    115: #define RXC_RB         (1U<<6)         /* receive broadcast frame */
                    116: #define RXC_RM         (1U<<5)         /* receive multicast frame */
                    117: #define RXC_RU         (1U<<4)         /* receive unicast frame */
                    118: #define RXC_RE         (1U<<3)         /* accept error frame */
                    119: #define RXC_RA         (1U<<2)         /* receive all frame */
1.6       nisimura  120: #define RXC_MHTE       (1U<<1)         /* use multicast hash table */
1.1       nisimura  121: #define RXC_REN                (1)             /* enable DMA to run */
                    122:
                    123: #define INT_DMLCS      (1U<<31)        /* link status change */
                    124: #define INT_DMTS       (1U<<30)        /* sending desc. has posted Tx done */
                    125: #define INT_DMRS       (1U<<29)        /* frame was received */
                    126: #define INT_DMRBUS     (1U<<27)        /* Rx descriptor pool is full */
                    127:
                    128: #define T0_OWN         (1U<<31)        /* desc is ready to Tx */
                    129:
                    130: #define R0_OWN         (1U<<31)        /* desc is empty */
                    131: #define R0_FS          (1U<<30)        /* first segment of frame */
                    132: #define R0_LS          (1U<<29)        /* last segment of frame */
                    133: #define R0_IPE         (1U<<28)        /* IP checksum error */
                    134: #define R0_TCPE                (1U<<27)        /* TCP checksum error */
                    135: #define R0_UDPE                (1U<<26)        /* UDP checksum error */
                    136: #define R0_ES          (1U<<25)        /* error summary */
                    137: #define R0_MF          (1U<<24)        /* multicast frame */
1.5       nisimura  138: #define R0_SPN         0x00300000      /* 21:20 switch port 1/2 */
                    139: #define R0_ALIGN       0x00300000      /* 21:20 (KSZ8692P) Rx align amount */
                    140: #define R0_RE          (1U<<19)        /* MII reported error */
                    141: #define R0_TL          (1U<<18)        /* frame too long, beyond 1518 */
1.1       nisimura  142: #define R0_RF          (1U<<17)        /* damaged runt frame */
                    143: #define R0_CE          (1U<<16)        /* CRC error */
                    144: #define R0_FT          (1U<<15)        /* frame type */
                    145: #define R0_FL_MASK     0x7ff           /* frame length 10:0 */
                    146:
                    147: #define T1_IC          (1U<<31)        /* post interrupt on complete */
                    148: #define T1_FS          (1U<<30)        /* first segment of frame */
                    149: #define T1_LS          (1U<<29)        /* last segment of frame */
                    150: #define T1_IPCKG       (1U<<28)        /* generate IP checksum */
                    151: #define T1_TCPCKG      (1U<<27)        /* generate TCP checksum */
                    152: #define T1_UDPCKG      (1U<<26)        /* generate UDP checksum */
                    153: #define T1_TER         (1U<<25)        /* end of ring */
1.5       nisimura  154: #define T1_SPN         0x00300000      /* 21:20 switch port 1/2 */
1.1       nisimura  155: #define T1_TBS_MASK    0x7ff           /* segment size 10:0 */
                    156:
                    157: #define R1_RER         (1U<<25)        /* end of ring */
1.8       nisimura  158: #define R1_RBS_MASK    0x7fc           /* segment size 10:0 */
1.1       nisimura  159:
                    160: #define KSE_NTXSEGS            16
                    161: #define KSE_TXQUEUELEN         64
                    162: #define KSE_TXQUEUELEN_MASK    (KSE_TXQUEUELEN - 1)
                    163: #define KSE_TXQUEUE_GC         (KSE_TXQUEUELEN / 4)
                    164: #define KSE_NTXDESC            256
                    165: #define KSE_NTXDESC_MASK       (KSE_NTXDESC - 1)
                    166: #define KSE_NEXTTX(x)          (((x) + 1) & KSE_NTXDESC_MASK)
                    167: #define KSE_NEXTTXS(x)         (((x) + 1) & KSE_TXQUEUELEN_MASK)
                    168:
                    169: #define KSE_NRXDESC            64
                    170: #define KSE_NRXDESC_MASK       (KSE_NRXDESC - 1)
                    171: #define KSE_NEXTRX(x)          (((x) + 1) & KSE_NRXDESC_MASK)
                    172:
                    173: struct tdes {
1.2       tsutsui   174:        uint32_t t0, t1, t2, t3;
1.1       nisimura  175: };
                    176:
                    177: struct rdes {
1.2       tsutsui   178:        uint32_t r0, r1, r2, r3;
1.1       nisimura  179: };
                    180:
                    181: struct kse_control_data {
                    182:        struct tdes kcd_txdescs[KSE_NTXDESC];
                    183:        struct rdes kcd_rxdescs[KSE_NRXDESC];
                    184: };
                    185: #define KSE_CDOFF(x)           offsetof(struct kse_control_data, x)
                    186: #define KSE_CDTXOFF(x)         KSE_CDOFF(kcd_txdescs[(x)])
                    187: #define KSE_CDRXOFF(x)         KSE_CDOFF(kcd_rxdescs[(x)])
                    188:
                    189: struct kse_txsoft {
                    190:        struct mbuf *txs_mbuf;          /* head of our mbuf chain */
                    191:        bus_dmamap_t txs_dmamap;        /* our DMA map */
                    192:        int txs_firstdesc;              /* first descriptor in packet */
                    193:        int txs_lastdesc;               /* last descriptor in packet */
                    194:        int txs_ndesc;                  /* # of descriptors used */
                    195: };
                    196:
                    197: struct kse_rxsoft {
                    198:        struct mbuf *rxs_mbuf;          /* head of our mbuf chain */
                    199:        bus_dmamap_t rxs_dmamap;        /* our DMA map */
                    200: };
                    201:
                    202: struct kse_softc {
1.23      chs       203:        device_t sc_dev;                /* generic device information */
1.1       nisimura  204:        bus_space_tag_t sc_st;          /* bus space tag */
                    205:        bus_space_handle_t sc_sh;       /* bus space handle */
                    206:        bus_dma_tag_t sc_dmat;          /* bus DMA tag */
                    207:        struct ethercom sc_ethercom;    /* Ethernet common data */
                    208:        void *sc_ih;                    /* interrupt cookie */
                    209:
                    210:        struct ifmedia sc_media;        /* ifmedia information */
                    211:        int sc_media_status;            /* PHY */
1.2       tsutsui   212:        int sc_media_active;            /* PHY */
1.9       nisimura  213:        callout_t  sc_callout;          /* MII tick callout */
                    214:        callout_t  sc_stat_ch;          /* statistics counter callout */
1.1       nisimura  215:
                    216:        bus_dmamap_t sc_cddmamap;       /* control data DMA map */
                    217: #define sc_cddma       sc_cddmamap->dm_segs[0].ds_addr
                    218:
                    219:        struct kse_control_data *sc_control_data;
1.8       nisimura  220: #define sc_txdescs     sc_control_data->kcd_txdescs
                    221: #define sc_rxdescs     sc_control_data->kcd_rxdescs
1.1       nisimura  222:
                    223:        struct kse_txsoft sc_txsoft[KSE_TXQUEUELEN];
                    224:        struct kse_rxsoft sc_rxsoft[KSE_NRXDESC];
                    225:        int sc_txfree;                  /* number of free Tx descriptors */
                    226:        int sc_txnext;                  /* next ready Tx descriptor */
                    227:        int sc_txsfree;                 /* number of free Tx jobs */
                    228:        int sc_txsnext;                 /* next ready Tx job */
                    229:        int sc_txsdirty;                /* dirty Tx jobs */
                    230:        int sc_rxptr;                   /* next ready Rx descriptor/descsoft */
                    231:
1.2       tsutsui   232:        uint32_t sc_txc, sc_rxc;
                    233:        uint32_t sc_t1csum;
                    234:        int sc_mcsum;
1.8       nisimura  235:        uint32_t sc_inten;
                    236:
1.2       tsutsui   237:        uint32_t sc_chip;
1.8       nisimura  238:        uint8_t sc_altmac[16][ETHER_ADDR_LEN];
                    239:        uint16_t sc_vlan[16];
                    240:
                    241: #ifdef KSE_EVENT_COUNTERS
                    242:        struct ksext {
                    243:                char evcntname[3][8];
                    244:                struct evcnt pev[3][34];
                    245:        } sc_ext;                       /* switch statistics */
                    246: #endif
1.1       nisimura  247: };
                    248:
                    249: #define KSE_CDTXADDR(sc, x)    ((sc)->sc_cddma + KSE_CDTXOFF((x)))
                    250: #define KSE_CDRXADDR(sc, x)    ((sc)->sc_cddma + KSE_CDRXOFF((x)))
                    251:
                    252: #define KSE_CDTXSYNC(sc, x, n, ops)                                    \
                    253: do {                                                                   \
                    254:        int __x, __n;                                                   \
                    255:                                                                        \
                    256:        __x = (x);                                                      \
                    257:        __n = (n);                                                      \
                    258:                                                                        \
                    259:        /* If it will wrap around, sync to the end of the ring. */      \
                    260:        if ((__x + __n) > KSE_NTXDESC) {                                \
                    261:                bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,       \
                    262:                    KSE_CDTXOFF(__x), sizeof(struct tdes) *             \
                    263:                    (KSE_NTXDESC - __x), (ops));                        \
                    264:                __n -= (KSE_NTXDESC - __x);                             \
                    265:                __x = 0;                                                \
                    266:        }                                                               \
                    267:                                                                        \
                    268:        /* Now sync whatever is left. */                                \
                    269:        bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,               \
                    270:            KSE_CDTXOFF(__x), sizeof(struct tdes) * __n, (ops));        \
                    271: } while (/*CONSTCOND*/0)
                    272:
                    273: #define KSE_CDRXSYNC(sc, x, ops)                                       \
                    274: do {                                                                   \
                    275:        bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,               \
                    276:            KSE_CDRXOFF((x)), sizeof(struct rdes), (ops));              \
                    277: } while (/*CONSTCOND*/0)
                    278:
                    279: #define KSE_INIT_RXDESC(sc, x)                                         \
                    280: do {                                                                   \
                    281:        struct kse_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)];               \
                    282:        struct rdes *__rxd = &(sc)->sc_rxdescs[(x)];                    \
                    283:        struct mbuf *__m = __rxs->rxs_mbuf;                             \
                    284:                                                                        \
                    285:        __m->m_data = __m->m_ext.ext_buf;                               \
                    286:        __rxd->r2 = __rxs->rxs_dmamap->dm_segs[0].ds_addr;              \
                    287:        __rxd->r1 = R1_RBS_MASK /* __m->m_ext.ext_size */;              \
                    288:        __rxd->r0 = R0_OWN;                                             \
                    289:        KSE_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
                    290: } while (/*CONSTCOND*/0)
                    291:
1.11      nisimura  292: u_int kse_burstsize = 8;       /* DMA burst length tuning knob */
1.1       nisimura  293:
                    294: #ifdef KSEDIAGNOSTIC
1.2       tsutsui   295: u_int kse_monitor_rxintr;      /* fragmented UDP csum HW bug hook */
1.1       nisimura  296: #endif
                    297:
1.18      cegger    298: static int kse_match(device_t, cfdata_t, void *);
                    299: static void kse_attach(device_t, device_t, void *);
1.1       nisimura  300:
1.23      chs       301: CFATTACH_DECL_NEW(kse, sizeof(struct kse_softc),
1.1       nisimura  302:     kse_match, kse_attach, NULL, NULL);
                    303:
1.3       christos  304: static int kse_ioctl(struct ifnet *, u_long, void *);
1.1       nisimura  305: static void kse_start(struct ifnet *);
                    306: static void kse_watchdog(struct ifnet *);
                    307: static int kse_init(struct ifnet *);
                    308: static void kse_stop(struct ifnet *, int);
                    309: static void kse_reset(struct kse_softc *);
                    310: static void kse_set_filter(struct kse_softc *);
                    311: static int add_rxbuf(struct kse_softc *, int);
                    312: static void rxdrain(struct kse_softc *);
                    313: static int kse_intr(void *);
                    314: static void rxintr(struct kse_softc *);
                    315: static void txreap(struct kse_softc *);
                    316: static void lnkchg(struct kse_softc *);
                    317: static int ifmedia_upd(struct ifnet *);
                    318: static void ifmedia_sts(struct ifnet *, struct ifmediareq *);
                    319: static void phy_tick(void *);
1.8       nisimura  320: static int ifmedia2_upd(struct ifnet *);
                    321: static void ifmedia2_sts(struct ifnet *, struct ifmediareq *);
                    322: #ifdef KSE_EVENT_COUNTERS
                    323: static void stat_tick(void *);
                    324: static void zerostats(struct kse_softc *);
                    325: #endif
1.1       nisimura  326:
                    327: static int
1.18      cegger    328: kse_match(device_t parent, cfdata_t match, void *aux)
1.1       nisimura  329: {
                    330:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    331:
                    332:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_MICREL &&
                    333:             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MICREL_KSZ8842 ||
                    334:              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_MICREL_KSZ8841) &&
                    335:            PCI_CLASS(pa->pa_class) == PCI_CLASS_NETWORK)
                    336:                return 1;
                    337:
                    338:        return 0;
                    339: }
                    340:
                    341: static void
1.18      cegger    342: kse_attach(device_t parent, device_t self, void *aux)
1.1       nisimura  343: {
1.19      cegger    344:        struct kse_softc *sc = device_private(self);
1.1       nisimura  345:        struct pci_attach_args *pa = aux;
                    346:        pci_chipset_tag_t pc = pa->pa_pc;
                    347:        pci_intr_handle_t ih;
                    348:        const char *intrstr;
                    349:        struct ifnet *ifp;
1.8       nisimura  350:        struct ifmedia *ifm;
1.1       nisimura  351:        uint8_t enaddr[ETHER_ADDR_LEN];
                    352:        bus_dma_segment_t seg;
1.25      nisimura  353:        int i, error, nseg;
1.1       nisimura  354:        pcireg_t pmode;
                    355:        int pmreg;
1.27      christos  356:        char intrbuf[PCI_INTRSTR_LEN];
1.1       nisimura  357:
                    358:        if (pci_mapreg_map(pa, 0x10,
                    359:            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
                    360:            0, &sc->sc_st, &sc->sc_sh, NULL, NULL) != 0) {
                    361:                printf(": unable to map device registers\n");
                    362:                return;
                    363:        }
                    364:
1.23      chs       365:        sc->sc_dev = self;
1.1       nisimura  366:        sc->sc_dmat = pa->pa_dmat;
                    367:
                    368:        /* Make sure bus mastering is enabled. */
                    369:        pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
                    370:            pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
                    371:            PCI_COMMAND_MASTER_ENABLE);
                    372:
                    373:        /* Get it out of power save mode, if needed. */
                    374:        if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
                    375:                pmode = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR) &
                    376:                    PCI_PMCSR_STATE_MASK;
                    377:                if (pmode == PCI_PMCSR_STATE_D3) {
                    378:                        /*
                    379:                         * The card has lost all configuration data in
                    380:                         * this state, so punt.
                    381:                         */
                    382:                        printf("%s: unable to wake from power state D3\n",
1.23      chs       383:                            device_xname(sc->sc_dev));
1.1       nisimura  384:                        return;
                    385:                }
                    386:                if (pmode != PCI_PMCSR_STATE_D0) {
                    387:                        printf("%s: waking up from power date D%d\n",
1.23      chs       388:                            device_xname(sc->sc_dev), pmode);
1.1       nisimura  389:                        pci_conf_write(pc, pa->pa_tag, pmreg + PCI_PMCSR,
                    390:                            PCI_PMCSR_STATE_D0);
                    391:                }
                    392:        }
                    393:
                    394:        sc->sc_chip = PCI_PRODUCT(pa->pa_id);
                    395:        printf(": Micrel KSZ%04x Ethernet (rev. 0x%02x)\n",
                    396:            sc->sc_chip, PCI_REVISION(pa->pa_class));
                    397:
                    398:        /*
                    399:         * Read the Ethernet address from the EEPROM.
                    400:         */
                    401:        i = CSR_READ_2(sc, MARL);
                    402:        enaddr[5] = i; enaddr[4] = i >> 8;
                    403:        i = CSR_READ_2(sc, MARM);
                    404:        enaddr[3] = i; enaddr[2] = i >> 8;
                    405:        i = CSR_READ_2(sc, MARH);
                    406:        enaddr[1] = i; enaddr[0] = i >> 8;
1.31.14.1  pgoyette  407:        printf("%s: Ethernet address %s\n",
1.23      chs       408:                device_xname(sc->sc_dev), ether_sprintf(enaddr));
1.1       nisimura  409:
                    410:        /*
                    411:         * Enable chip function.
                    412:         */
                    413:        CSR_WRITE_2(sc, CIDR, 1);
                    414:
                    415:        /*
                    416:         * Map and establish our interrupt.
                    417:         */
                    418:        if (pci_intr_map(pa, &ih)) {
1.23      chs       419:                aprint_error_dev(sc->sc_dev, "unable to map interrupt\n");
1.1       nisimura  420:                return;
                    421:        }
1.27      christos  422:        intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf));
1.31.14.2! pgoyette  423:        sc->sc_ih = pci_intr_establish_xname(pc, ih, IPL_NET, kse_intr, sc,
        !           424:            device_xname(self));
1.1       nisimura  425:        if (sc->sc_ih == NULL) {
1.23      chs       426:                aprint_error_dev(sc->sc_dev, "unable to establish interrupt");
1.1       nisimura  427:                if (intrstr != NULL)
1.20      njoly     428:                        aprint_error(" at %s", intrstr);
                    429:                aprint_error("\n");
1.1       nisimura  430:                return;
                    431:        }
1.23      chs       432:        aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
1.1       nisimura  433:
                    434:        /*
                    435:         * Allocate the control data structures, and create and load the
                    436:         * DMA map for it.
                    437:         */
                    438:        error = bus_dmamem_alloc(sc->sc_dmat,
                    439:            sizeof(struct kse_control_data), PAGE_SIZE, 0, &seg, 1, &nseg, 0);
                    440:        if (error != 0) {
1.23      chs       441:                aprint_error_dev(sc->sc_dev, "unable to allocate control data, error = %d\n", error);
1.1       nisimura  442:                goto fail_0;
                    443:        }
                    444:        error = bus_dmamem_map(sc->sc_dmat, &seg, nseg,
1.9       nisimura  445:            sizeof(struct kse_control_data), (void **)&sc->sc_control_data,
1.1       nisimura  446:            BUS_DMA_COHERENT);
                    447:        if (error != 0) {
1.23      chs       448:                aprint_error_dev(sc->sc_dev, "unable to map control data, error = %d\n", error);
1.1       nisimura  449:                goto fail_1;
                    450:        }
                    451:        error = bus_dmamap_create(sc->sc_dmat,
                    452:            sizeof(struct kse_control_data), 1,
                    453:            sizeof(struct kse_control_data), 0, 0, &sc->sc_cddmamap);
                    454:        if (error != 0) {
1.23      chs       455:                aprint_error_dev(sc->sc_dev, "unable to create control data DMA map, "
1.14      cegger    456:                    "error = %d\n", error);
1.1       nisimura  457:                goto fail_2;
                    458:        }
                    459:        error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
                    460:            sc->sc_control_data, sizeof(struct kse_control_data), NULL, 0);
                    461:        if (error != 0) {
1.23      chs       462:                aprint_error_dev(sc->sc_dev, "unable to load control data DMA map, error = %d\n",
1.14      cegger    463:                    error);
1.1       nisimura  464:                goto fail_3;
                    465:        }
                    466:        for (i = 0; i < KSE_TXQUEUELEN; i++) {
                    467:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
                    468:                    KSE_NTXSEGS, MCLBYTES, 0, 0,
                    469:                    &sc->sc_txsoft[i].txs_dmamap)) != 0) {
1.23      chs       470:                        aprint_error_dev(sc->sc_dev, "unable to create tx DMA map %d, "
1.14      cegger    471:                            "error = %d\n", i, error);
1.1       nisimura  472:                        goto fail_4;
                    473:                }
                    474:        }
                    475:        for (i = 0; i < KSE_NRXDESC; i++) {
                    476:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
                    477:                    1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
1.23      chs       478:                        aprint_error_dev(sc->sc_dev, "unable to create rx DMA map %d, "
1.14      cegger    479:                            "error = %d\n", i, error);
1.1       nisimura  480:                        goto fail_5;
                    481:                }
                    482:                sc->sc_rxsoft[i].rxs_mbuf = NULL;
                    483:        }
                    484:
1.4       ad        485:        callout_init(&sc->sc_callout, 0);
1.8       nisimura  486:        callout_init(&sc->sc_stat_ch, 0);
1.1       nisimura  487:
1.8       nisimura  488:        ifm = &sc->sc_media;
                    489:        if (sc->sc_chip == 0x8841) {
                    490:                ifmedia_init(ifm, 0, ifmedia_upd, ifmedia_sts);
                    491:                ifmedia_add(ifm, IFM_ETHER|IFM_10_T, 0, NULL);
                    492:                ifmedia_add(ifm, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
                    493:                ifmedia_add(ifm, IFM_ETHER|IFM_100_TX, 0, NULL);
                    494:                ifmedia_add(ifm, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
                    495:                ifmedia_add(ifm, IFM_ETHER|IFM_AUTO, 0, NULL);
                    496:                ifmedia_set(ifm, IFM_ETHER|IFM_AUTO);
                    497:        }
                    498:        else {
                    499:                ifmedia_init(ifm, 0, ifmedia2_upd, ifmedia2_sts);
                    500:                ifmedia_add(ifm, IFM_ETHER|IFM_AUTO, 0, NULL);
                    501:                ifmedia_set(ifm, IFM_ETHER|IFM_AUTO);
                    502:        }
1.1       nisimura  503:
                    504:        printf("%s: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto\n",
1.23      chs       505:            device_xname(sc->sc_dev));
1.1       nisimura  506:
                    507:        ifp = &sc->sc_ethercom.ec_if;
1.23      chs       508:        strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
1.1       nisimura  509:        ifp->if_softc = sc;
                    510:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    511:        ifp->if_ioctl = kse_ioctl;
                    512:        ifp->if_start = kse_start;
                    513:        ifp->if_watchdog = kse_watchdog;
                    514:        ifp->if_init = kse_init;
                    515:        ifp->if_stop = kse_stop;
                    516:        IFQ_SET_READY(&ifp->if_snd);
                    517:
                    518:        /*
                    519:         * KSZ8842 can handle 802.1Q VLAN-sized frames,
                    520:         * can do IPv4, TCPv4, and UDPv4 checksums in hardware.
                    521:         */
                    522:        sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
                    523:        ifp->if_capabilities |=
                    524:            IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
                    525:            IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
                    526:            IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
                    527:
                    528:        if_attach(ifp);
                    529:        ether_ifattach(ifp, enaddr);
1.8       nisimura  530:
                    531: #ifdef KSE_EVENT_COUNTERS
1.25      nisimura  532:        int p = (sc->sc_chip == 0x8842) ? 3 : 1;
1.8       nisimura  533:        for (i = 0; i < p; i++) {
                    534:                struct ksext *ee = &sc->sc_ext;
1.26      christos  535:                snprintf(ee->evcntname[i], sizeof(ee->evcntname[i]),
                    536:                    "%s.%d", device_xname(sc->sc_dev), i+1);
1.8       nisimura  537:                evcnt_attach_dynamic(&ee->pev[i][0], EVCNT_TYPE_MISC,
                    538:                    NULL, ee->evcntname[i], "RxLoPriotyByte");
                    539:                evcnt_attach_dynamic(&ee->pev[i][1], EVCNT_TYPE_MISC,
                    540:                    NULL, ee->evcntname[i], "RxHiPriotyByte");
                    541:                evcnt_attach_dynamic(&ee->pev[i][2], EVCNT_TYPE_MISC,
                    542:                    NULL, ee->evcntname[i], "RxUndersizePkt");
                    543:                evcnt_attach_dynamic(&ee->pev[i][3], EVCNT_TYPE_MISC,
                    544:                    NULL, ee->evcntname[i], "RxFragments");
                    545:                evcnt_attach_dynamic(&ee->pev[i][4], EVCNT_TYPE_MISC,
                    546:                    NULL, ee->evcntname[i], "RxOversize");
                    547:                evcnt_attach_dynamic(&ee->pev[i][5], EVCNT_TYPE_MISC,
                    548:                    NULL, ee->evcntname[i], "RxJabbers");
                    549:                evcnt_attach_dynamic(&ee->pev[i][6], EVCNT_TYPE_MISC,
                    550:                    NULL, ee->evcntname[i], "RxSymbolError");
                    551:                evcnt_attach_dynamic(&ee->pev[i][7], EVCNT_TYPE_MISC,
                    552:                    NULL, ee->evcntname[i], "RxCRCError");
                    553:                evcnt_attach_dynamic(&ee->pev[i][8], EVCNT_TYPE_MISC,
                    554:                    NULL, ee->evcntname[i], "RxAlignmentError");
                    555:                evcnt_attach_dynamic(&ee->pev[i][9], EVCNT_TYPE_MISC,
1.9       nisimura  556:                    NULL, ee->evcntname[i], "RxControl8808Pkts");
1.8       nisimura  557:                evcnt_attach_dynamic(&ee->pev[i][10], EVCNT_TYPE_MISC,
                    558:                    NULL, ee->evcntname[i], "RxPausePkts");
                    559:                evcnt_attach_dynamic(&ee->pev[i][11], EVCNT_TYPE_MISC,
                    560:                    NULL, ee->evcntname[i], "RxBroadcast");
                    561:                evcnt_attach_dynamic(&ee->pev[i][12], EVCNT_TYPE_MISC,
                    562:                    NULL, ee->evcntname[i], "RxMulticast");
                    563:                evcnt_attach_dynamic(&ee->pev[i][13], EVCNT_TYPE_MISC,
                    564:                    NULL, ee->evcntname[i], "RxUnicast");
                    565:                evcnt_attach_dynamic(&ee->pev[i][14], EVCNT_TYPE_MISC,
                    566:                    NULL, ee->evcntname[i], "Rx64Octets");
                    567:                evcnt_attach_dynamic(&ee->pev[i][15], EVCNT_TYPE_MISC,
                    568:                    NULL, ee->evcntname[i], "Rx65To127Octets");
                    569:                evcnt_attach_dynamic(&ee->pev[i][16], EVCNT_TYPE_MISC,
                    570:                    NULL, ee->evcntname[i], "Rx128To255Octets");
                    571:                evcnt_attach_dynamic(&ee->pev[i][17], EVCNT_TYPE_MISC,
                    572:                    NULL, ee->evcntname[i], "Rx255To511Octets");
                    573:                evcnt_attach_dynamic(&ee->pev[i][18], EVCNT_TYPE_MISC,
                    574:                    NULL, ee->evcntname[i], "Rx512To1023Octets");
                    575:                evcnt_attach_dynamic(&ee->pev[i][19], EVCNT_TYPE_MISC,
                    576:                    NULL, ee->evcntname[i], "Rx1024To1522Octets");
                    577:                evcnt_attach_dynamic(&ee->pev[i][20], EVCNT_TYPE_MISC,
                    578:                    NULL, ee->evcntname[i], "TxLoPriotyByte");
                    579:                evcnt_attach_dynamic(&ee->pev[i][21], EVCNT_TYPE_MISC,
                    580:                    NULL, ee->evcntname[i], "TxHiPriotyByte");
                    581:                evcnt_attach_dynamic(&ee->pev[i][22], EVCNT_TYPE_MISC,
                    582:                    NULL, ee->evcntname[i], "TxLateCollision");
                    583:                evcnt_attach_dynamic(&ee->pev[i][23], EVCNT_TYPE_MISC,
                    584:                    NULL, ee->evcntname[i], "TxPausePkts");
                    585:                evcnt_attach_dynamic(&ee->pev[i][24], EVCNT_TYPE_MISC,
                    586:                    NULL, ee->evcntname[i], "TxBroadcastPkts");
                    587:                evcnt_attach_dynamic(&ee->pev[i][25], EVCNT_TYPE_MISC,
                    588:                    NULL, ee->evcntname[i], "TxMulticastPkts");
                    589:                evcnt_attach_dynamic(&ee->pev[i][26], EVCNT_TYPE_MISC,
                    590:                    NULL, ee->evcntname[i], "TxUnicastPkts");
                    591:                evcnt_attach_dynamic(&ee->pev[i][27], EVCNT_TYPE_MISC,
                    592:                    NULL, ee->evcntname[i], "TxDeferred");
                    593:                evcnt_attach_dynamic(&ee->pev[i][28], EVCNT_TYPE_MISC,
                    594:                    NULL, ee->evcntname[i], "TxTotalCollision");
                    595:                evcnt_attach_dynamic(&ee->pev[i][29], EVCNT_TYPE_MISC,
                    596:                    NULL, ee->evcntname[i], "TxExcessiveCollision");
                    597:                evcnt_attach_dynamic(&ee->pev[i][30], EVCNT_TYPE_MISC,
                    598:                    NULL, ee->evcntname[i], "TxSingleCollision");
                    599:                evcnt_attach_dynamic(&ee->pev[i][31], EVCNT_TYPE_MISC,
                    600:                    NULL, ee->evcntname[i], "TxMultipleCollision");
                    601:                evcnt_attach_dynamic(&ee->pev[i][32], EVCNT_TYPE_MISC,
                    602:                    NULL, ee->evcntname[i], "TxDropPkts");
                    603:                evcnt_attach_dynamic(&ee->pev[i][33], EVCNT_TYPE_MISC,
                    604:                    NULL, ee->evcntname[i], "RxDropPkts");
                    605:        }
                    606: #endif
1.1       nisimura  607:        return;
                    608:
                    609:  fail_5:
                    610:        for (i = 0; i < KSE_NRXDESC; i++) {
                    611:                if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
                    612:                        bus_dmamap_destroy(sc->sc_dmat,
                    613:                            sc->sc_rxsoft[i].rxs_dmamap);
1.24      christos  614:        }
1.1       nisimura  615:  fail_4:
                    616:        for (i = 0; i < KSE_TXQUEUELEN; i++) {
                    617:                if (sc->sc_txsoft[i].txs_dmamap != NULL)
                    618:                        bus_dmamap_destroy(sc->sc_dmat,
                    619:                            sc->sc_txsoft[i].txs_dmamap);
                    620:        }
                    621:        bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
                    622:  fail_3:
                    623:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
                    624:  fail_2:
1.3       christos  625:        bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data,
1.1       nisimura  626:            sizeof(struct kse_control_data));
                    627:  fail_1:
                    628:        bus_dmamem_free(sc->sc_dmat, &seg, nseg);
                    629:  fail_0:
                    630:        return;
                    631: }
                    632:
                    633: static int
1.3       christos  634: kse_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1.1       nisimura  635: {
                    636:        struct kse_softc *sc = ifp->if_softc;
                    637:        struct ifreq *ifr = (struct ifreq *)data;
                    638:        int s, error;
                    639:
                    640:        s = splnet();
                    641:
                    642:        switch (cmd) {
                    643:        case SIOCSIFMEDIA:
                    644:        case SIOCGIFMEDIA:
                    645:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                    646:                break;
                    647:
                    648:        default:
1.12      dyoung    649:                if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
                    650:                        break;
                    651:
                    652:                error = 0;
                    653:
                    654:                if (cmd == SIOCSIFCAP)
                    655:                        error = (*ifp->if_init)(ifp);
                    656:                if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
                    657:                        ;
                    658:                else if (ifp->if_flags & IFF_RUNNING) {
1.1       nisimura  659:                        /*
                    660:                         * Multicast list has changed; set the hardware filter
                    661:                         * accordingly.
                    662:                         */
1.12      dyoung    663:                        kse_set_filter(sc);
1.1       nisimura  664:                }
                    665:                break;
                    666:        }
                    667:
                    668:        kse_start(ifp);
                    669:
                    670:        splx(s);
                    671:        return error;
                    672: }
                    673:
                    674: static int
                    675: kse_init(struct ifnet *ifp)
                    676: {
                    677:        struct kse_softc *sc = ifp->if_softc;
1.2       tsutsui   678:        uint32_t paddr;
1.1       nisimura  679:        int i, error = 0;
                    680:
                    681:        /* cancel pending I/O */
                    682:        kse_stop(ifp, 0);
                    683:
                    684:        /* reset all registers but PCI configuration */
                    685:        kse_reset(sc);
                    686:
                    687:        /* craft Tx descriptor ring */
                    688:        memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
                    689:        for (i = 0, paddr = KSE_CDTXADDR(sc, 1); i < KSE_NTXDESC - 1; i++) {
                    690:                sc->sc_txdescs[i].t3 = paddr;
                    691:                paddr += sizeof(struct tdes);
                    692:        }
                    693:        sc->sc_txdescs[KSE_NTXDESC - 1].t3 = KSE_CDTXADDR(sc, 0);
                    694:        KSE_CDTXSYNC(sc, 0, KSE_NTXDESC,
                    695:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    696:        sc->sc_txfree = KSE_NTXDESC;
                    697:        sc->sc_txnext = 0;
                    698:
                    699:        for (i = 0; i < KSE_TXQUEUELEN; i++)
                    700:                sc->sc_txsoft[i].txs_mbuf = NULL;
                    701:        sc->sc_txsfree = KSE_TXQUEUELEN;
                    702:        sc->sc_txsnext = 0;
                    703:        sc->sc_txsdirty = 0;
                    704:
                    705:        /* craft Rx descriptor ring */
                    706:        memset(sc->sc_rxdescs, 0, sizeof(sc->sc_rxdescs));
                    707:        for (i = 0, paddr = KSE_CDRXADDR(sc, 1); i < KSE_NRXDESC - 1; i++) {
                    708:                sc->sc_rxdescs[i].r3 = paddr;
                    709:                paddr += sizeof(struct rdes);
                    710:        }
                    711:        sc->sc_rxdescs[KSE_NRXDESC - 1].r3 = KSE_CDRXADDR(sc, 0);
                    712:        for (i = 0; i < KSE_NRXDESC; i++) {
                    713:                if (sc->sc_rxsoft[i].rxs_mbuf == NULL) {
                    714:                        if ((error = add_rxbuf(sc, i)) != 0) {
                    715:                                printf("%s: unable to allocate or map rx "
                    716:                                    "buffer %d, error = %d\n",
1.23      chs       717:                                     device_xname(sc->sc_dev), i, error);
1.1       nisimura  718:                                rxdrain(sc);
                    719:                                goto out;
                    720:                        }
                    721:                }
                    722:                else
                    723:                        KSE_INIT_RXDESC(sc, i);
                    724:        }
                    725:        sc->sc_rxptr = 0;
                    726:
                    727:        /* hand Tx/Rx rings to HW */
                    728:        CSR_WRITE_4(sc, TDLB, KSE_CDTXADDR(sc, 0));
                    729:        CSR_WRITE_4(sc, RDLB, KSE_CDRXADDR(sc, 0));
                    730:
                    731:        sc->sc_txc = TXC_TEN | TXC_EP | TXC_AC | TXC_FCE;
                    732:        sc->sc_rxc = RXC_REN | RXC_RU | RXC_FCE;
                    733:        if (ifp->if_flags & IFF_PROMISC)
                    734:                sc->sc_rxc |= RXC_RA;
                    735:        if (ifp->if_flags & IFF_BROADCAST)
                    736:                sc->sc_rxc |= RXC_RB;
                    737:        sc->sc_t1csum = sc->sc_mcsum = 0;
                    738:        if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx) {
1.5       nisimura  739:                sc->sc_rxc |= RXC_ICC;
1.1       nisimura  740:                sc->sc_mcsum |= M_CSUM_IPv4;
                    741:        }
                    742:        if (ifp->if_capenable & IFCAP_CSUM_IPv4_Tx) {
                    743:                sc->sc_txc |= TXC_ICG;
                    744:                sc->sc_t1csum |= T1_IPCKG;
                    745:        }
                    746:        if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) {
1.5       nisimura  747:                sc->sc_rxc |= RXC_TCC;
1.1       nisimura  748:                sc->sc_mcsum |= M_CSUM_TCPv4;
                    749:        }
                    750:        if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx) {
                    751:                sc->sc_txc |= TXC_TCG;
                    752:                sc->sc_t1csum |= T1_TCPCKG;
                    753:        }
                    754:        if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) {
1.5       nisimura  755:                sc->sc_rxc |= RXC_UCC;
1.1       nisimura  756:                sc->sc_mcsum |= M_CSUM_UDPv4;
                    757:        }
                    758:        if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx) {
                    759:                sc->sc_txc |= TXC_UCG;
                    760:                sc->sc_t1csum |= T1_UDPCKG;
                    761:        }
                    762:        sc->sc_txc |= (kse_burstsize << TXC_BS_SFT);
                    763:        sc->sc_rxc |= (kse_burstsize << RXC_BS_SFT);
                    764:
1.6       nisimura  765:        /* build multicast hash filter if necessary */
                    766:        kse_set_filter(sc);
                    767:
1.1       nisimura  768:        /* set current media */
                    769:        (void)ifmedia_upd(ifp);
                    770:
                    771:        /* enable transmitter and receiver */
                    772:        CSR_WRITE_4(sc, MDTXC, sc->sc_txc);
                    773:        CSR_WRITE_4(sc, MDRXC, sc->sc_rxc);
                    774:        CSR_WRITE_4(sc, MDRSC, 1);
                    775:
                    776:        /* enable interrupts */
1.8       nisimura  777:        sc->sc_inten = INT_DMTS|INT_DMRS|INT_DMRBUS;
                    778:        if (sc->sc_chip == 0x8841)
                    779:                sc->sc_inten |= INT_DMLCS;
1.1       nisimura  780:        CSR_WRITE_4(sc, INTST, ~0);
1.8       nisimura  781:        CSR_WRITE_4(sc, INTEN, sc->sc_inten);
1.1       nisimura  782:
                    783:        ifp->if_flags |= IFF_RUNNING;
                    784:        ifp->if_flags &= ~IFF_OACTIVE;
                    785:
1.8       nisimura  786:        if (sc->sc_chip == 0x8841) {
                    787:                /* start one second timer */
                    788:                callout_reset(&sc->sc_callout, hz, phy_tick, sc);
                    789:        }
                    790: #ifdef KSE_EVENT_COUNTERS
                    791:        /* start statistics gather 1 minute timer */
                    792:        zerostats(sc);
                    793:        callout_reset(&sc->sc_stat_ch, hz * 60, stat_tick, sc);
                    794: #endif
1.1       nisimura  795:
                    796:  out:
                    797:        if (error) {
                    798:                ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    799:                ifp->if_timer = 0;
1.23      chs       800:                printf("%s: interface not running\n", device_xname(sc->sc_dev));
1.1       nisimura  801:        }
                    802:        return error;
                    803: }
                    804:
                    805: static void
                    806: kse_stop(struct ifnet *ifp, int disable)
                    807: {
                    808:        struct kse_softc *sc = ifp->if_softc;
                    809:        struct kse_txsoft *txs;
                    810:        int i;
                    811:
1.8       nisimura  812:        if (sc->sc_chip == 0x8841)
                    813:                callout_stop(&sc->sc_callout);
                    814:        callout_stop(&sc->sc_stat_ch);
1.1       nisimura  815:
                    816:        sc->sc_txc &= ~TXC_TEN;
                    817:        sc->sc_rxc &= ~RXC_REN;
                    818:        CSR_WRITE_4(sc, MDTXC, sc->sc_txc);
                    819:        CSR_WRITE_4(sc, MDRXC, sc->sc_rxc);
                    820:
                    821:        for (i = 0; i < KSE_TXQUEUELEN; i++) {
                    822:                txs = &sc->sc_txsoft[i];
                    823:                if (txs->txs_mbuf != NULL) {
                    824:                        bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
                    825:                        m_freem(txs->txs_mbuf);
                    826:                        txs->txs_mbuf = NULL;
                    827:                }
                    828:        }
                    829:
1.13      dyoung    830:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    831:        ifp->if_timer = 0;
                    832:
1.1       nisimura  833:        if (disable)
                    834:                rxdrain(sc);
                    835: }
                    836:
                    837: static void
                    838: kse_reset(struct kse_softc *sc)
                    839: {
                    840:
                    841:        CSR_WRITE_2(sc, GRR, 1);
                    842:        delay(1000); /* PDF does not mention the delay amount */
                    843:        CSR_WRITE_2(sc, GRR, 0);
                    844:
                    845:        CSR_WRITE_2(sc, CIDR, 1);
                    846: }
                    847:
                    848: static void
                    849: kse_watchdog(struct ifnet *ifp)
                    850: {
                    851:        struct kse_softc *sc = ifp->if_softc;
                    852:
1.24      christos  853:        /*
1.1       nisimura  854:         * Since we're not interrupting every packet, sweep
                    855:         * up before we report an error.
                    856:         */
                    857:        txreap(sc);
                    858:
                    859:        if (sc->sc_txfree != KSE_NTXDESC) {
                    860:                printf("%s: device timeout (txfree %d txsfree %d txnext %d)\n",
1.23      chs       861:                    device_xname(sc->sc_dev), sc->sc_txfree, sc->sc_txsfree,
1.1       nisimura  862:                    sc->sc_txnext);
                    863:                ifp->if_oerrors++;
                    864:
                    865:                /* Reset the interface. */
                    866:                kse_init(ifp);
                    867:        }
                    868:        else if (ifp->if_flags & IFF_DEBUG)
                    869:                printf("%s: recovered from device timeout\n",
1.23      chs       870:                    device_xname(sc->sc_dev));
1.1       nisimura  871:
                    872:        /* Try to get more packets going. */
                    873:        kse_start(ifp);
                    874: }
                    875:
                    876: static void
                    877: kse_start(struct ifnet *ifp)
                    878: {
                    879:        struct kse_softc *sc = ifp->if_softc;
1.8       nisimura  880:        struct mbuf *m0, *m;
1.1       nisimura  881:        struct kse_txsoft *txs;
                    882:        bus_dmamap_t dmamap;
                    883:        int error, nexttx, lasttx, ofree, seg;
1.6       nisimura  884:        uint32_t tdes0;
1.1       nisimura  885:
                    886:        if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
                    887:                return;
                    888:
                    889:        /*
                    890:         * Remember the previous number of free descriptors.
                    891:         */
                    892:        ofree = sc->sc_txfree;
                    893:
                    894:        /*
                    895:         * Loop through the send queue, setting up transmit descriptors
                    896:         * until we drain the queue, or use up all available transmit
                    897:         * descriptors.
                    898:         */
                    899:        for (;;) {
                    900:                IFQ_POLL(&ifp->if_snd, m0);
                    901:                if (m0 == NULL)
                    902:                        break;
                    903:
                    904:                if (sc->sc_txsfree < KSE_TXQUEUE_GC) {
                    905:                        txreap(sc);
                    906:                        if (sc->sc_txsfree == 0)
                    907:                                break;
                    908:                }
                    909:                txs = &sc->sc_txsoft[sc->sc_txsnext];
                    910:                dmamap = txs->txs_dmamap;
                    911:
                    912:                error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
                    913:                    BUS_DMA_WRITE|BUS_DMA_NOWAIT);
                    914:                if (error) {
                    915:                        if (error == EFBIG) {
                    916:                                printf("%s: Tx packet consumes too many "
                    917:                                    "DMA segments, dropping...\n",
1.23      chs       918:                                    device_xname(sc->sc_dev));
1.1       nisimura  919:                                    IFQ_DEQUEUE(&ifp->if_snd, m0);
                    920:                                    m_freem(m0);
                    921:                                    continue;
                    922:                        }
                    923:                        /* Short on resources, just stop for now. */
                    924:                        break;
                    925:                }
                    926:
                    927:                if (dmamap->dm_nsegs > sc->sc_txfree) {
                    928:                        /*
                    929:                         * Not enough free descriptors to transmit this
                    930:                         * packet.  We haven't committed anything yet,
                    931:                         * so just unload the DMA map, put the packet
                    932:                         * back on the queue, and punt.  Notify the upper
                    933:                         * layer that there are not more slots left.
                    934:                         */
                    935:                        ifp->if_flags |= IFF_OACTIVE;
                    936:                        bus_dmamap_unload(sc->sc_dmat, dmamap);
                    937:                        break;
                    938:                }
                    939:
                    940:                IFQ_DEQUEUE(&ifp->if_snd, m0);
                    941:
                    942:                /*
                    943:                 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
                    944:                 */
                    945:
                    946:                bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
                    947:                    BUS_DMASYNC_PREWRITE);
                    948:
1.6       nisimura  949:                lasttx = -1; tdes0 = 0;
1.1       nisimura  950:                for (nexttx = sc->sc_txnext, seg = 0;
                    951:                     seg < dmamap->dm_nsegs;
                    952:                     seg++, nexttx = KSE_NEXTTX(nexttx)) {
                    953:                        struct tdes *tdes = &sc->sc_txdescs[nexttx];
                    954:                        /*
                    955:                         * If this is the first descriptor we're
                    956:                         * enqueueing, don't set the OWN bit just
                    957:                         * yet.  That could cause a race condition.
                    958:                         * We'll do it below.
                    959:                         */
                    960:                        tdes->t2 = dmamap->dm_segs[seg].ds_addr;
                    961:                        tdes->t1 = sc->sc_t1csum
                    962:                             | (dmamap->dm_segs[seg].ds_len & T1_TBS_MASK);
1.6       nisimura  963:                        tdes->t0 = tdes0;
                    964:                        tdes0 |= T0_OWN;
1.1       nisimura  965:                        lasttx = nexttx;
                    966:                }
1.8       nisimura  967:
1.1       nisimura  968:                /*
                    969:                 * Outgoing NFS mbuf must be unloaded when Tx completed.
                    970:                 * Without T1_IC NFS mbuf is left unack'ed for excessive
                    971:                 * time and NFS stops to proceed until kse_watchdog()
                    972:                 * calls txreap() to reclaim the unack'ed mbuf.
1.5       nisimura  973:                 * It's painful to traverse every mbuf chain to determine
1.1       nisimura  974:                 * whether someone is waiting for Tx completion.
                    975:                 */
1.8       nisimura  976:                m = m0;
1.1       nisimura  977:                do {
                    978:                        if ((m->m_flags & M_EXT) && m->m_ext.ext_free) {
                    979:                                sc->sc_txdescs[lasttx].t1 |= T1_IC;
                    980:                                break;
                    981:                        }
                    982:                } while ((m = m->m_next) != NULL);
                    983:
                    984:                /* write last T0_OWN bit of the 1st segment */
                    985:                sc->sc_txdescs[lasttx].t1 |= T1_LS;
                    986:                sc->sc_txdescs[sc->sc_txnext].t1 |= T1_FS;
                    987:                sc->sc_txdescs[sc->sc_txnext].t0 = T0_OWN;
                    988:                KSE_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,
                    989:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                    990:
                    991:                /* tell DMA start transmit */
                    992:                CSR_WRITE_4(sc, MDTSC, 1);
                    993:
                    994:                txs->txs_mbuf = m0;
                    995:                txs->txs_firstdesc = sc->sc_txnext;
                    996:                txs->txs_lastdesc = lasttx;
                    997:                txs->txs_ndesc = dmamap->dm_nsegs;
                    998:
                    999:                sc->sc_txfree -= txs->txs_ndesc;
                   1000:                sc->sc_txnext = nexttx;
                   1001:                sc->sc_txsfree--;
                   1002:                sc->sc_txsnext = KSE_NEXTTXS(sc->sc_txsnext);
                   1003:                /*
                   1004:                 * Pass the packet to any BPF listeners.
                   1005:                 */
1.31.14.1  pgoyette 1006:                bpf_mtap(ifp, m0, BPF_D_OUT);
1.1       nisimura 1007:        }
                   1008:
                   1009:        if (sc->sc_txsfree == 0 || sc->sc_txfree == 0) {
                   1010:                /* No more slots left; notify upper layer. */
                   1011:                ifp->if_flags |= IFF_OACTIVE;
                   1012:        }
                   1013:        if (sc->sc_txfree != ofree) {
                   1014:                /* Set a watchdog timer in case the chip flakes out. */
                   1015:                ifp->if_timer = 5;
                   1016:        }
                   1017: }
                   1018:
                   1019: static void
                   1020: kse_set_filter(struct kse_softc *sc)
                   1021: {
                   1022:        struct ether_multistep step;
                   1023:        struct ether_multi *enm;
                   1024:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.6       nisimura 1025:        uint32_t h, hashes[2];
                   1026:
                   1027:        sc->sc_rxc &= ~(RXC_MHTE | RXC_RM);
                   1028:        ifp->if_flags &= ~IFF_ALLMULTI;
                   1029:        if (ifp->if_flags & IFF_PROMISC)
                   1030:                return;
1.1       nisimura 1031:
                   1032:        ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
1.6       nisimura 1033:        if (enm == NULL)
                   1034:                return;
                   1035:        hashes[0] = hashes[1] = 0;
                   1036:        do {
                   1037:                if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
                   1038:                        /*
                   1039:                         * We must listen to a range of multicast addresses.
                   1040:                         * For now, just accept all multicasts, rather than
                   1041:                         * trying to set only those filter bits needed to match
                   1042:                         * the range.  (At this time, the only use of address
                   1043:                         * ranges is for IP multicast routing, for which the
                   1044:                         * range is big enough to require all bits set.)
                   1045:                         */
                   1046:                        goto allmulti;
1.1       nisimura 1047:                }
1.6       nisimura 1048:                h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
                   1049:                hashes[h >> 5] |= 1 << (h & 0x1f);
1.1       nisimura 1050:                ETHER_NEXT_MULTI(step, enm);
1.6       nisimura 1051:        } while (enm != NULL);
                   1052:        sc->sc_rxc |= RXC_MHTE;
                   1053:        CSR_WRITE_4(sc, MTR0, hashes[0]);
                   1054:        CSR_WRITE_4(sc, MTR1, hashes[1]);
1.1       nisimura 1055:        return;
1.6       nisimura 1056:  allmulti:
                   1057:        sc->sc_rxc |= RXC_RM;
                   1058:        ifp->if_flags |= IFF_ALLMULTI;
1.1       nisimura 1059: }
                   1060:
                   1061: static int
                   1062: add_rxbuf(struct kse_softc *sc, int idx)
                   1063: {
                   1064:        struct kse_rxsoft *rxs = &sc->sc_rxsoft[idx];
                   1065:        struct mbuf *m;
                   1066:        int error;
                   1067:
                   1068:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1069:        if (m == NULL)
                   1070:                return ENOBUFS;
                   1071:
                   1072:        MCLGET(m, M_DONTWAIT);
                   1073:        if ((m->m_flags & M_EXT) == 0) {
                   1074:                m_freem(m);
                   1075:                return ENOBUFS;
                   1076:        }
                   1077:
                   1078:        if (rxs->rxs_mbuf != NULL)
                   1079:                bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
                   1080:
                   1081:        rxs->rxs_mbuf = m;
                   1082:
                   1083:        error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
                   1084:            m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
                   1085:        if (error) {
                   1086:                printf("%s: can't load rx DMA map %d, error = %d\n",
1.23      chs      1087:                    device_xname(sc->sc_dev), idx, error);
1.1       nisimura 1088:                panic("kse_add_rxbuf");
                   1089:        }
                   1090:
                   1091:        bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   1092:            rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                   1093:
                   1094:        KSE_INIT_RXDESC(sc, idx);
                   1095:
                   1096:        return 0;
                   1097: }
                   1098:
                   1099: static void
                   1100: rxdrain(struct kse_softc *sc)
                   1101: {
                   1102:        struct kse_rxsoft *rxs;
                   1103:        int i;
                   1104:
                   1105:        for (i = 0; i < KSE_NRXDESC; i++) {
                   1106:                rxs = &sc->sc_rxsoft[i];
                   1107:                if (rxs->rxs_mbuf != NULL) {
                   1108:                        bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
                   1109:                        m_freem(rxs->rxs_mbuf);
                   1110:                        rxs->rxs_mbuf = NULL;
                   1111:                }
                   1112:        }
                   1113: }
                   1114:
                   1115: static int
                   1116: kse_intr(void *arg)
                   1117: {
                   1118:        struct kse_softc *sc = arg;
1.2       tsutsui  1119:        uint32_t isr;
1.1       nisimura 1120:
                   1121:        if ((isr = CSR_READ_4(sc, INTST)) == 0)
                   1122:                return 0;
                   1123:
                   1124:        if (isr & INT_DMRS)
                   1125:                rxintr(sc);
                   1126:        if (isr & INT_DMTS)
                   1127:                txreap(sc);
                   1128:        if (isr & INT_DMLCS)
                   1129:                lnkchg(sc);
                   1130:        if (isr & INT_DMRBUS)
1.23      chs      1131:                printf("%s: Rx descriptor full\n", device_xname(sc->sc_dev));
1.1       nisimura 1132:
                   1133:        CSR_WRITE_4(sc, INTST, isr);
                   1134:        return 1;
                   1135: }
                   1136:
                   1137: static void
                   1138: rxintr(struct kse_softc *sc)
                   1139: {
                   1140:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   1141:        struct kse_rxsoft *rxs;
                   1142:        struct mbuf *m;
1.2       tsutsui  1143:        uint32_t rxstat;
1.1       nisimura 1144:        int i, len;
                   1145:
                   1146:        for (i = sc->sc_rxptr; /*CONSTCOND*/ 1; i = KSE_NEXTRX(i)) {
                   1147:                rxs = &sc->sc_rxsoft[i];
                   1148:
                   1149:                KSE_CDRXSYNC(sc, i,
                   1150:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                   1151:
                   1152:                rxstat = sc->sc_rxdescs[i].r0;
1.24      christos 1153:
1.1       nisimura 1154:                if (rxstat & R0_OWN) /* desc is left empty */
                   1155:                        break;
                   1156:
                   1157:                /* R0_FS|R0_LS must have been marked for this desc */
                   1158:
                   1159:                if (rxstat & R0_ES) {
                   1160:                        ifp->if_ierrors++;
                   1161: #define PRINTERR(bit, str)                                             \
                   1162:                        if (rxstat & (bit))                             \
                   1163:                                printf("%s: receive error: %s\n",       \
1.23      chs      1164:                                    device_xname(sc->sc_dev), str)
1.1       nisimura 1165:                        PRINTERR(R0_TL, "frame too long");
                   1166:                        PRINTERR(R0_RF, "runt frame");
                   1167:                        PRINTERR(R0_CE, "bad FCS");
                   1168: #undef PRINTERR
                   1169:                        KSE_INIT_RXDESC(sc, i);
                   1170:                        continue;
                   1171:                }
                   1172:
                   1173:                /* HW errata; frame might be too small or too large */
                   1174:
                   1175:                bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                   1176:                    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
                   1177:
                   1178:                len = rxstat & R0_FL_MASK;
1.2       tsutsui  1179:                len -= ETHER_CRC_LEN;   /* trim CRC off */
1.1       nisimura 1180:                m = rxs->rxs_mbuf;
                   1181:
                   1182:                if (add_rxbuf(sc, i) != 0) {
                   1183:                        ifp->if_ierrors++;
                   1184:                        KSE_INIT_RXDESC(sc, i);
                   1185:                        bus_dmamap_sync(sc->sc_dmat,
                   1186:                            rxs->rxs_dmamap, 0,
                   1187:                            rxs->rxs_dmamap->dm_mapsize,
                   1188:                            BUS_DMASYNC_PREREAD);
                   1189:                        continue;
                   1190:                }
                   1191:
1.30      ozaki-r  1192:                m_set_rcvif(m, ifp);
1.1       nisimura 1193:                m->m_pkthdr.len = m->m_len = len;
                   1194:
                   1195:                if (sc->sc_mcsum) {
                   1196:                        m->m_pkthdr.csum_flags |= sc->sc_mcsum;
                   1197:                        if (rxstat & R0_IPE)
                   1198:                                m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
                   1199:                        if (rxstat & (R0_TCPE | R0_UDPE))
                   1200:                                m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
                   1201:                }
1.29      ozaki-r  1202:                if_percpuq_enqueue(ifp->if_percpuq, m);
1.1       nisimura 1203: #ifdef KSEDIAGNOSTIC
                   1204:                if (kse_monitor_rxintr > 0) {
                   1205:                        printf("m stat %x data %p len %d\n",
                   1206:                            rxstat, m->m_data, m->m_len);
                   1207:                }
                   1208: #endif
                   1209:        }
                   1210:        sc->sc_rxptr = i;
                   1211: }
                   1212:
                   1213: static void
                   1214: txreap(struct kse_softc *sc)
                   1215: {
                   1216:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                   1217:        struct kse_txsoft *txs;
1.2       tsutsui  1218:        uint32_t txstat;
1.1       nisimura 1219:        int i;
                   1220:
                   1221:        ifp->if_flags &= ~IFF_OACTIVE;
                   1222:
                   1223:        for (i = sc->sc_txsdirty; sc->sc_txsfree != KSE_TXQUEUELEN;
                   1224:             i = KSE_NEXTTXS(i), sc->sc_txsfree++) {
                   1225:                txs = &sc->sc_txsoft[i];
                   1226:
                   1227:                KSE_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_ndesc,
                   1228:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                   1229:
                   1230:                txstat = sc->sc_txdescs[txs->txs_lastdesc].t0;
                   1231:
                   1232:                if (txstat & T0_OWN) /* desc is still in use */
                   1233:                        break;
                   1234:
                   1235:                /* there is no way to tell transmission status per frame */
                   1236:
                   1237:                ifp->if_opackets++;
                   1238:
                   1239:                sc->sc_txfree += txs->txs_ndesc;
                   1240:                bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
                   1241:                    0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                   1242:                bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
                   1243:                m_freem(txs->txs_mbuf);
                   1244:                txs->txs_mbuf = NULL;
                   1245:        }
                   1246:        sc->sc_txsdirty = i;
                   1247:        if (sc->sc_txsfree == KSE_TXQUEUELEN)
                   1248:                ifp->if_timer = 0;
                   1249: }
                   1250:
                   1251: static void
                   1252: lnkchg(struct kse_softc *sc)
                   1253: {
                   1254:        struct ifmediareq ifmr;
                   1255:
                   1256: #if 0 /* rambling link status */
1.23      chs      1257:        printf("%s: link %s\n", device_xname(sc->sc_dev),
1.1       nisimura 1258:            (CSR_READ_2(sc, P1SR) & (1U << 5)) ? "up" : "down");
                   1259: #endif
                   1260:        ifmedia_sts(&sc->sc_ethercom.ec_if, &ifmr);
                   1261: }
                   1262:
                   1263: static int
                   1264: ifmedia_upd(struct ifnet *ifp)
                   1265: {
                   1266:        struct kse_softc *sc = ifp->if_softc;
                   1267:        struct ifmedia *ifm = &sc->sc_media;
1.2       tsutsui  1268:        uint16_t ctl;
1.1       nisimura 1269:
                   1270:        ctl = 0;
                   1271:        if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
                   1272:                ctl |= (1U << 13); /* restart AN */
                   1273:                ctl |= (1U << 7);  /* enable AN */
                   1274:                ctl |= (1U << 4);  /* advertise flow control pause */
                   1275:                ctl |= (1U << 3) | (1U << 2) | (1U << 1) | (1U << 0);
                   1276:        }
                   1277:        else {
                   1278:                if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX)
                   1279:                        ctl |= (1U << 6);
                   1280:                if (ifm->ifm_media & IFM_FDX)
                   1281:                        ctl |= (1U << 5);
                   1282:        }
                   1283:        CSR_WRITE_2(sc, P1CR4, ctl);
                   1284:
                   1285:        sc->sc_media_active = IFM_NONE;
                   1286:        sc->sc_media_status = IFM_AVALID;
                   1287:
                   1288:        return 0;
                   1289: }
                   1290:
                   1291: static void
                   1292: ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
                   1293: {
                   1294:        struct kse_softc *sc = ifp->if_softc;
                   1295:        struct ifmedia *ifm = &sc->sc_media;
1.2       tsutsui  1296:        uint16_t ctl, sts, result;
1.1       nisimura 1297:
                   1298:        ifmr->ifm_status = IFM_AVALID;
                   1299:        ifmr->ifm_active = IFM_ETHER;
                   1300:
                   1301:        ctl = CSR_READ_2(sc, P1CR4);
                   1302:        sts = CSR_READ_2(sc, P1SR);
                   1303:        if ((sts & (1U << 5)) == 0) {
                   1304:                ifmr->ifm_active |= IFM_NONE;
                   1305:                goto out; /* link is down */
                   1306:        }
                   1307:        ifmr->ifm_status |= IFM_ACTIVE;
                   1308:        if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
                   1309:                if ((sts & (1U << 6)) == 0) {
                   1310:                        ifmr->ifm_active |= IFM_NONE;
                   1311:                        goto out; /* negotiation in progress */
                   1312:                }
                   1313:                result = ctl & sts & 017;
                   1314:                if (result & (1U << 3))
                   1315:                        ifmr->ifm_active |= IFM_100_TX|IFM_FDX;
                   1316:                else if (result & (1U << 2))
1.28      msaitoh  1317:                        ifmr->ifm_active |= IFM_100_TX|IFM_HDX;
1.1       nisimura 1318:                else if (result & (1U << 1))
                   1319:                        ifmr->ifm_active |= IFM_10_T|IFM_FDX;
                   1320:                else if (result & (1U << 0))
1.28      msaitoh  1321:                        ifmr->ifm_active |= IFM_10_T|IFM_HDX;
1.1       nisimura 1322:                else
                   1323:                        ifmr->ifm_active |= IFM_NONE;
                   1324:                if (ctl & (1U << 4))
                   1325:                        ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE;
                   1326:                if (sts & (1U << 4))
                   1327:                        ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE;
                   1328:        }
                   1329:        else {
                   1330:                ifmr->ifm_active |= (sts & (1U << 10)) ? IFM_100_TX : IFM_10_T;
                   1331:                if (sts & (1U << 9))
                   1332:                        ifmr->ifm_active |= IFM_FDX;
                   1333:                if (sts & (1U << 12))
                   1334:                        ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE;
                   1335:                if (sts & (1U << 11))
                   1336:                        ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE;
                   1337:        }
                   1338:
                   1339:   out:
                   1340:        sc->sc_media_status = ifmr->ifm_status;
                   1341:        sc->sc_media_active = ifmr->ifm_active;
                   1342: }
                   1343:
                   1344: static void
                   1345: phy_tick(void *arg)
                   1346: {
                   1347:        struct kse_softc *sc = arg;
                   1348:        struct ifmediareq ifmr;
                   1349:        int s;
                   1350:
                   1351:        s = splnet();
                   1352:        ifmedia_sts(&sc->sc_ethercom.ec_if, &ifmr);
                   1353:        splx(s);
                   1354:
                   1355:        callout_reset(&sc->sc_callout, hz, phy_tick, sc);
                   1356: }
1.8       nisimura 1357:
                   1358: static int
                   1359: ifmedia2_upd(struct ifnet *ifp)
                   1360: {
                   1361:        struct kse_softc *sc = ifp->if_softc;
                   1362:
                   1363:        sc->sc_media_status = IFM_AVALID;
                   1364:        sc->sc_media_active = IFM_NONE;
                   1365:        return 0;
                   1366: }
                   1367:
                   1368: static void
                   1369: ifmedia2_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
                   1370: {
                   1371:        struct kse_softc *sc = ifp->if_softc;
                   1372:        int p1sts, p2sts;
                   1373:
                   1374:        ifmr->ifm_status = IFM_AVALID;
                   1375:        ifmr->ifm_active = IFM_ETHER;
                   1376:        p1sts = CSR_READ_2(sc, P1SR);
                   1377:        p2sts = CSR_READ_2(sc, P2SR);
                   1378:        if (((p1sts | p2sts) & (1U << 5)) == 0)
                   1379:                ifmr->ifm_active |= IFM_NONE;
                   1380:        else {
                   1381:                ifmr->ifm_status |= IFM_ACTIVE;
                   1382:                ifmr->ifm_active |= IFM_100_TX|IFM_FDX;
                   1383:                ifmr->ifm_active |= IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE;
                   1384:        }
                   1385:        sc->sc_media_status = ifmr->ifm_status;
                   1386:        sc->sc_media_active = ifmr->ifm_active;
                   1387: }
                   1388:
                   1389: #ifdef KSE_EVENT_COUNTERS
                   1390: static void
1.16      dsl      1391: stat_tick(void *arg)
1.8       nisimura 1392: {
                   1393:        struct kse_softc *sc = arg;
                   1394:        struct ksext *ee = &sc->sc_ext;
                   1395:        int nport, p, i, val;
                   1396:
                   1397:        nport = (sc->sc_chip == 0x8842) ? 3 : 1;
                   1398:        for (p = 0; p < nport; p++) {
1.9       nisimura 1399:                for (i = 0; i < 32; i++) {
1.8       nisimura 1400:                        val = 0x1c00 | (p * 0x20 + i);
                   1401:                        CSR_WRITE_2(sc, IACR, val);
                   1402:                        do {
                   1403:                                val = CSR_READ_2(sc, IADR5) << 16;
                   1404:                        } while ((val & (1U << 30)) == 0);
1.9       nisimura 1405:                        if (val & (1U << 31)) {
                   1406:                                (void)CSR_READ_2(sc, IADR4);
1.8       nisimura 1407:                                val = 0x3fffffff; /* has made overflow */
1.9       nisimura 1408:                        }
                   1409:                        else {
                   1410:                                val &= 0x3fff0000;              /* 29:16 */
                   1411:                                val |= CSR_READ_2(sc, IADR4);   /* 15:0 */
                   1412:                        }
1.8       nisimura 1413:                        ee->pev[p][i].ev_count += val; /* i (0-31) */
                   1414:                }
                   1415:                CSR_WRITE_2(sc, IACR, 0x1c00 + 0x100 + p);
                   1416:                ee->pev[p][32].ev_count = CSR_READ_2(sc, IADR4); /* 32 */
1.9       nisimura 1417:                CSR_WRITE_2(sc, IACR, 0x1c00 + 0x100 + p * 3 + 1);
1.8       nisimura 1418:                ee->pev[p][33].ev_count = CSR_READ_2(sc, IADR4); /* 33 */
                   1419:        }
                   1420:        callout_reset(&sc->sc_stat_ch, hz * 60, stat_tick, arg);
                   1421: }
                   1422:
                   1423: static void
                   1424: zerostats(struct kse_softc *sc)
                   1425: {
                   1426:        struct ksext *ee = &sc->sc_ext;
                   1427:        int nport, p, i, val;
                   1428:
                   1429:        /* make sure all the HW counters get zero */
                   1430:        nport = (sc->sc_chip == 0x8842) ? 3 : 1;
                   1431:        for (p = 0; p < nport; p++) {
                   1432:                for (i = 0; i < 31; i++) {
                   1433:                        val = 0x1c00 | (p * 0x20 + i);
                   1434:                        CSR_WRITE_2(sc, IACR, val);
                   1435:                        do {
                   1436:                                val = CSR_READ_2(sc, IADR5) << 16;
                   1437:                        } while ((val & (1U << 30)) == 0);
1.9       nisimura 1438:                        (void)CSR_READ_2(sc, IADR4);
1.8       nisimura 1439:                        ee->pev[p][i].ev_count = 0;
                   1440:                }
                   1441:        }
                   1442: }
                   1443: #endif

CVSweb <webmaster@jp.NetBSD.org>