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

Annotation of src/sys/dev/pci/if_tl.c, Revision 1.16

1.16    ! eeh         1: /*     $NetBSD: if_tl.c,v 1.15 1998/08/11 00:09:26 thorpej Exp $       */
1.1       bouyer      2:
                      3: /*
                      4:  * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *  This product includes software developed by Manuel Bouyer.
                     17:  * 4. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
1.2       bouyer     33:  * Texas Instruments ThunderLAN ethernet controller
1.1       bouyer     34:  * ThunderLAN Programmer's Guide (TI Literature Number SPWU013A)
                     35:  * available from www.ti.com
                     36:  */
                     37:
                     38: #undef TLDEBUG
                     39: #define TL_PRIV_STATS
                     40: #undef TLDEBUG_RX
                     41: #undef TLDEBUG_TX
                     42: #undef TLDEBUG_ADDR
1.12      jonathan   43:
                     44: #include "opt_inet.h"
1.13      jonathan   45: #include "opt_ns.h"
1.1       bouyer     46:
                     47: #include <sys/param.h>
                     48: #include <sys/systm.h>
                     49: #include <sys/mbuf.h>
                     50: #include <sys/protosw.h>
                     51: #include <sys/socket.h>
                     52: #include <sys/ioctl.h>
                     53: #include <sys/errno.h>
                     54: #include <sys/malloc.h>
                     55: #include <sys/kernel.h>
                     56: #include <sys/proc.h>  /* only for declaration of wakeup() used by vm.h */
                     57: #include <sys/device.h>
                     58:
                     59: #include <net/if.h>
                     60: #if defined(SIOCSIFMEDIA)
                     61: #include <net/if_media.h>
                     62: #endif
                     63: #include <net/if_types.h>
                     64: #include <net/if_dl.h>
                     65: #include <net/route.h>
                     66: #include <net/netisr.h>
                     67:
                     68: #include "bpfilter.h"
                     69: #if NBPFILTER > 0
                     70: #include <net/bpf.h>
                     71: #include <net/bpfdesc.h>
                     72: #endif
                     73:
                     74: #ifdef INET
                     75: #include <netinet/in.h>
                     76: #include <netinet/in_systm.h>
                     77: #include <netinet/in_var.h>
                     78: #include <netinet/ip.h>
                     79: #endif
                     80:
                     81: #ifdef NS
                     82: #include <netns/ns.h>
                     83: #include <netns/ns_if.h>
                     84: #endif
                     85:
                     86: #include <vm/vm.h>
                     87: #include <vm/vm_param.h>
                     88: #include <vm/vm_kern.h>
                     89:
                     90: #if defined(__NetBSD__)
                     91: #include <net/if_ether.h>
                     92: #if defined(INET)
                     93: #include <netinet/if_inarp.h>
                     94: #endif
1.4       thorpej    95:
1.1       bouyer     96: #include <machine/bus.h>
                     97: #include <machine/intr.h>
1.4       thorpej    98:
1.1       bouyer     99: #include <dev/pci/pcireg.h>
                    100: #include <dev/pci/pcivar.h>
                    101: #include <dev/pci/pcidevs.h>
1.15      thorpej   102:
1.1       bouyer    103: #include <dev/i2c/i2c_bus.h>
                    104: #include <dev/i2c/i2c_eeprom.h>
1.15      thorpej   105:
                    106: #include <dev/mii/mii.h>
                    107: #include <dev/mii/miivar.h>
                    108:
                    109: #include <dev/mii/tlphyvar.h>
                    110:
1.1       bouyer    111: #include <dev/pci/if_tlregs.h>
1.15      thorpej   112: #include <dev/pci/if_tlvar.h>
1.1       bouyer    113: #endif /* __NetBSD__ */
                    114:
1.15      thorpej   115: #if defined(__NetBSD__) && defined(__alpha__)
                    116: /* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
                    117: #undef vtophys
                    118: #define        vtophys(va)     alpha_XXX_dmamap((vm_offset_t)(va))
                    119: #endif
                    120:
1.1       bouyer    121: /* number of transmit/receive buffers */
                    122: #ifndef TL_NBUF
                    123: #define TL_NBUF 10
                    124: #endif
                    125:
                    126: /* number of seconds the link can be idle */
                    127: #ifndef TL_IDLETIME
                    128: #define TL_IDLETIME 10
                    129: #endif
                    130:
1.7       drochner  131: static int tl_pci_match __P((struct device *, struct cfdata *, void *));
1.1       bouyer    132: static void tl_pci_attach __P((struct device *, struct device *, void *));
                    133: static int tl_intr __P((void *));
                    134:
                    135: static int tl_ifioctl __P((struct ifnet *, ioctl_cmd_t, caddr_t));
                    136: static int tl_mediachange __P((struct ifnet *));
                    137: static void tl_mediastatus __P((struct ifnet *, struct ifmediareq *));
                    138: static void tl_ifwatchdog __P((struct ifnet *));
                    139: static void tl_shutdown __P((void*));
                    140:
                    141: static void tl_ifstart __P((struct ifnet *));
                    142: static void tl_reset __P((tl_softc_t*));
                    143: static int  tl_init __P((tl_softc_t*));
                    144: static void tl_restart __P((void  *));
                    145: static int  tl_add_RxBuff __P((struct Rx_list*, struct mbuf*));
                    146: static void tl_read_stats __P((tl_softc_t*));
                    147: static void tl_ticks __P((void*));
                    148: static int tl_multicast_hash __P((u_int8_t*));
                    149: static void tl_addr_filter __P((tl_softc_t*));
                    150:
                    151: static u_int32_t tl_intreg_read __P((tl_softc_t*, u_int32_t));
                    152: static void tl_intreg_write __P((tl_softc_t*, u_int32_t, u_int32_t));
                    153: static u_int8_t tl_intreg_read_byte __P((tl_softc_t*, u_int32_t));
                    154: static void tl_intreg_write_byte __P((tl_softc_t*, u_int32_t, u_int8_t));
                    155:
1.15      thorpej   156: void   tl_mii_sync __P((struct tl_softc *));
                    157: void   tl_mii_sendbits __P((struct tl_softc *, u_int32_t, int));
                    158:
1.1       bouyer    159:
                    160: #if defined(TLDEBUG_RX)
                    161: static void ether_printheader __P((struct ether_header*));
                    162: #endif
                    163:
1.15      thorpej   164: int tl_mii_read __P((struct device *, int, int));
                    165: void tl_mii_write __P((struct device *, int, int, int));
                    166:
                    167: void tl_statchg __P((struct device *));
1.1       bouyer    168:
                    169: void tl_i2c_set __P((void*, u_int8_t));
                    170: void tl_i2c_clr __P((void*, u_int8_t));
                    171: int tl_i2c_read __P((void*, u_int8_t));
                    172:
                    173: static __inline void netsio_clr __P((tl_softc_t*, u_int8_t));
                    174: static __inline void netsio_set __P((tl_softc_t*, u_int8_t));
                    175: static __inline u_int8_t netsio_read __P((tl_softc_t*, u_int8_t));
                    176: static __inline void netsio_clr(sc, bits)
                    177:        tl_softc_t* sc;
                    178:        u_int8_t bits;
                    179: {
                    180:        tl_intreg_write_byte(sc, TL_INT_NET + TL_INT_NetSio,
                    181:                tl_intreg_read_byte(sc, TL_INT_NET + TL_INT_NetSio) & (~bits));
                    182: }
                    183: static __inline void netsio_set(sc, bits)
                    184:        tl_softc_t* sc;
                    185:        u_int8_t bits;
                    186: {
                    187:        tl_intreg_write_byte(sc, TL_INT_NET + TL_INT_NetSio,
                    188:                tl_intreg_read_byte(sc, TL_INT_NET + TL_INT_NetSio) | bits);
                    189: }
                    190: static __inline u_int8_t netsio_read(sc, bits)
                    191:        tl_softc_t* sc;
                    192:        u_int8_t bits;
                    193: {
1.4       thorpej   194:        return (tl_intreg_read_byte(sc, TL_INT_NET + TL_INT_NetSio) & bits);
1.1       bouyer    195: }
                    196:
                    197: struct cfattach tl_ca = {
1.4       thorpej   198:        sizeof(tl_softc_t), tl_pci_match, tl_pci_attach
1.1       bouyer    199: };
                    200:
1.4       thorpej   201: const struct tl_product_desc tl_compaq_products[] = {
1.15      thorpej   202:        { PCI_PRODUCT_COMPAQ_N100TX, TLPHY_MEDIA_NO_10_T,
1.10      thorpej   203:          0, "Compaq Netelligent 10/100 TX" },
1.15      thorpej   204:        { PCI_PRODUCT_COMPAQ_N10T, TLPHY_MEDIA_10_5,
1.10      thorpej   205:          0, "Compaq Netelligent 10 T" },
1.15      thorpej   206:        { PCI_PRODUCT_COMPAQ_IntNF3P, TLPHY_MEDIA_10_2,
1.10      thorpej   207:          0, "Compaq Integrated NetFlex 3/P" },
1.15      thorpej   208:        { PCI_PRODUCT_COMPAQ_IntPL100TX, TLPHY_MEDIA_10_2|TLPHY_MEDIA_NO_10_T,
1.10      thorpej   209:          0, "Compaq ProLiant Integrated Netelligent 10/100 TX" },
1.15      thorpej   210:        { PCI_PRODUCT_COMPAQ_DPNet100TX, TLPHY_MEDIA_10_5|TLPHY_MEDIA_NO_10_T,
1.10      thorpej   211:          0, "Compaq Dual Port Netelligent 10/100 TX" },
1.15      thorpej   212:        { PCI_PRODUCT_COMPAQ_DP4000, TLPHY_MEDIA_10_5,
1.10      thorpej   213:          0, "Compaq Deskpro 4000 5233MMX" },
1.15      thorpej   214:        { PCI_PRODUCT_COMPAQ_NF3P_BNC, TLPHY_MEDIA_10_2,
1.10      thorpej   215:          0, "Compaq NetFlex 3/P w/ BNC" },
1.15      thorpej   216:        { PCI_PRODUCT_COMPAQ_NF3P, TLPHY_MEDIA_10_5,
1.10      thorpej   217:          0, "Compaq NetFlex 3/P" },
1.4       thorpej   218:        { 0, 0, NULL },
                    219: };
                    220:
                    221: const struct tl_product_desc tl_ti_products[] = {
1.10      thorpej   222:        /*
                    223:         * Built-in Ethernet on the TI TravelMate 5000
                    224:         * docking station; better product description?
                    225:         * XXX Seems to have broken memory-mapped access.
                    226:         */
1.15      thorpej   227:        { PCI_PRODUCT_TI_TLAN, 0,
1.10      thorpej   228:          TPF_BROKEN_MEM, "Texas Instruments ThunderLAN" },
1.4       thorpej   229:        { 0, 0, NULL },
                    230: };
                    231:
                    232: struct tl_vendor_desc {
                    233:        u_int32_t tv_vendor;
                    234:        const struct tl_product_desc *tv_products;
                    235: };
                    236:
                    237: const struct tl_vendor_desc tl_vendors[] = {
                    238:        { PCI_VENDOR_COMPAQ, tl_compaq_products },
                    239:        { PCI_VENDOR_TI, tl_ti_products },
                    240:        { 0, NULL },
                    241: };
                    242:
                    243: const struct tl_product_desc *tl_lookup_product __P((u_int32_t));
                    244:
                    245: const struct tl_product_desc *
                    246: tl_lookup_product(id)
                    247:        u_int32_t id;
                    248: {
                    249:        const struct tl_product_desc *tp;
                    250:        const struct tl_vendor_desc *tv;
                    251:
                    252:        for (tv = tl_vendors; tv->tv_products != NULL; tv++)
                    253:                if (PCI_VENDOR(id) == tv->tv_vendor)
                    254:                        break;
                    255:
                    256:        if ((tp = tv->tv_products) == NULL)
                    257:                return (NULL);
                    258:
                    259:        for (; tp->tp_desc != NULL; tp++)
                    260:                if (PCI_PRODUCT(id) == tp->tp_product)
                    261:                        break;
                    262:
                    263:        if (tp->tp_desc == NULL)
                    264:                return (NULL);
                    265:
                    266:        return (tp);
                    267: }
                    268:
1.6       bouyer    269: static char *nullbuf = NULL;
1.1       bouyer    270:
                    271: static int
1.4       thorpej   272: tl_pci_match(parent, match, aux)
1.1       bouyer    273:        struct device *parent;
1.7       drochner  274:        struct cfdata *match;
1.1       bouyer    275:        void *aux;
                    276: {
                    277:        struct pci_attach_args *pa = (struct pci_attach_args *) aux;
                    278:
1.4       thorpej   279:        if (tl_lookup_product(pa->pa_id) != NULL)
                    280:                return (1);
                    281:
                    282:        return (0);
1.1       bouyer    283: }
                    284:
                    285: static void
                    286: tl_pci_attach(parent, self, aux)
                    287:        struct device * parent;
                    288:        struct device * self;
                    289:        void * aux;
                    290: {
                    291:        tl_softc_t *sc = (tl_softc_t *)self;
                    292:        struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
1.4       thorpej   293:        const struct tl_product_desc *tp;
1.1       bouyer    294:        struct ifnet * const ifp = &sc->tl_if;
                    295:        bus_space_tag_t iot, memt;
                    296:        bus_space_handle_t ioh, memh;
                    297:        pci_intr_handle_t intrhandle;
1.4       thorpej   298:        const char *intrstr;
                    299:        int i, tmp, ioh_valid, memh_valid;
                    300:        pcireg_t csr;
                    301:
                    302:        printf("\n");
                    303:
1.10      thorpej   304:        tp = tl_lookup_product(pa->pa_id);
                    305:        if (tp == NULL)
                    306:                panic("tl_pci_attach: impossible");
1.15      thorpej   307:        sc->tl_product = tp;
1.10      thorpej   308:
1.4       thorpej   309:        /* Map the card space. */
                    310:        ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
                    311:            &iot, &ioh, NULL, NULL) == 0);
                    312:        memh_valid = (pci_mapreg_map(pa, PCI_CBMA,
                    313:            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
                    314:            0, &memt, &memh, NULL, NULL) == 0);
                    315:
1.10      thorpej   316:        if (memh_valid && (tp->tp_flags & TPF_BROKEN_MEM) == 0) {
1.4       thorpej   317:                sc->tl_bustag = memt;
                    318:                sc->tl_bushandle = memh;
                    319:        } else if (ioh_valid) {
                    320:                sc->tl_bustag = iot;
                    321:                sc->tl_bushandle = ioh;
1.1       bouyer    322:        } else {
1.4       thorpej   323:                printf("%s: unable to map device registers\n",
                    324:                    sc->sc_dev.dv_xname);
                    325:                return;
1.1       bouyer    326:        }
                    327:
1.4       thorpej   328:        /* Enable the device. */
                    329:        csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
                    330:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
                    331:            csr | PCI_COMMAND_MASTER_ENABLE);
1.1       bouyer    332:
1.4       thorpej   333:        printf("%s: %s\n", sc->sc_dev.dv_xname, tp->tp_desc);
1.1       bouyer    334:
                    335:        tl_reset(sc);
                    336:
                    337:        /* fill in the i2c struct */
                    338:        sc->i2cbus.adapter_softc = sc;
                    339:        sc->i2cbus.set_bit = tl_i2c_set;
                    340:        sc->i2cbus.clr_bit = tl_i2c_clr;
                    341:        sc->i2cbus.read_bit = tl_i2c_read;
                    342:
                    343: #ifdef TLDEBUG
                    344:        printf("default values of INTreg: 0x%x\n",
                    345:                tl_intreg_read(sc, TL_INT_Defaults));
                    346: #endif
                    347:
                    348:        /* read mac addr */
                    349:        for (i=0; i<ETHER_ADDR_LEN; i++) {
                    350:                tmp = i2c_eeprom_read(&sc->i2cbus, 0x83 + i);
                    351:                if (tmp < 0) {
1.4       thorpej   352:                        printf("%s: error reading Ethernet adress\n",
                    353:                            sc->sc_dev.dv_xname);
1.1       bouyer    354:                        return;
                    355:                } else {
                    356:                        sc->tl_enaddr[i] = tmp;
                    357:                }
                    358:        }
1.4       thorpej   359:        printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
1.1       bouyer    360:                ether_sprintf(sc->tl_enaddr));
                    361:
1.4       thorpej   362:        /* Map and establish interrupts */
                    363:        if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
                    364:                pa->pa_intrline, &intrhandle)) {
                    365:                printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
                    366:                return;
                    367:        }
                    368:        intrstr = pci_intr_string(pa->pa_pc, intrhandle);
                    369:        sc->tl_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET,
                    370:                tl_intr, sc);
                    371:        if (sc->tl_ih == NULL) {
                    372:                printf("%s: couldn't establish interrupt",
                    373:                    sc->sc_dev.dv_xname);
                    374:                if (intrstr != NULL)
                    375:                        printf(" at %s", intrstr);
                    376:                printf("\n");
                    377:                return;
                    378:        }
                    379:        printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
                    380:
                    381:        /*
                    382:         * Add shutdown hook so that DMA is disabled prior to reboot. Not
                    383:         * doing do could allow DMA to corrupt kernel memory during the
                    384:         * reboot before the driver initializes.
                    385:         */
                    386:        (void) shutdownhook_establish(tl_shutdown, sc);
                    387:
1.15      thorpej   388:        /*
                    389:         * Initialize our media structures and probe the MII.
                    390:         *
                    391:         * Note that we don't care about the media instance.  We
                    392:         * are expecting to have multiple PHYs on the 10/100 cards,
                    393:         * and on those cards we exclude the internal PHY from providing
                    394:         * 10baseT.  By ignoring the instance, it allows us to not have
                    395:         * to specify it on the command line when switching media.
                    396:         */
                    397:        sc->tl_mii.mii_ifp = ifp;
                    398:        sc->tl_mii.mii_readreg = tl_mii_read;
                    399:        sc->tl_mii.mii_writereg = tl_mii_write;
                    400:        sc->tl_mii.mii_statchg = tl_statchg;
                    401:        ifmedia_init(&sc->tl_mii.mii_media, IFM_IMASK, tl_mediachange,
                    402:            tl_mediastatus);
                    403:        mii_phy_probe(self, &sc->tl_mii, 0xffffffff);
                    404: #ifdef notyet  /* XXX XXX XXX */
                    405:        if (LIST_FIRST(&sc->tl_mii.mii_phys) == NULL) {
                    406:                ifmedia_add(&sc->tl_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
                    407:                ifmedia_set(&sc->tl_mii.mii_media, IFM_ETHER|IFM_NONE);
                    408:        } else
                    409:                ifmedia_set(&sc->tl_mii.mii_media, IFM_ETHER|IFM_AUTO);
                    410: #else
                    411:        ifmedia_set(&sc->tl_mii.mii_media, IFM_ETHER|IFM_NONE);
                    412: #endif
1.1       bouyer    413:
                    414:        bcopy(sc->sc_dev.dv_xname, sc->tl_if.if_xname, IFNAMSIZ);
                    415:        sc->tl_if.if_softc = sc;
                    416:        ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
                    417:        ifp->if_ioctl = tl_ifioctl;
                    418:        ifp->if_start = tl_ifstart;
                    419:        ifp->if_watchdog = tl_ifwatchdog;
                    420:        ifp->if_timer = 0;
                    421:        if_attach(ifp);
                    422:        ether_ifattach(&(sc)->tl_if, (sc)->tl_enaddr);
                    423: #if NBPFILTER > 0
                    424:        bpfattach(&sc->tl_bpf, &sc->tl_if, DLT_EN10MB,
                    425:                sizeof(struct ether_header));
                    426: #endif
                    427: }
                    428:
                    429: static void
                    430: tl_reset(sc)
                    431:        tl_softc_t *sc;
                    432: {
                    433:        int i;
                    434:
                    435:        /* read stats */
                    436:        if (sc->tl_if.if_flags & IFF_RUNNING) {
                    437:                untimeout(tl_ticks, sc);
                    438:                tl_read_stats(sc);
                    439:        }
                    440:        /* Reset adapter */
                    441:        TL_HR_WRITE(sc, TL_HOST_CMD,
                    442:                TL_HR_READ(sc, TL_HOST_CMD) | HOST_CMD_Ad_Rst);
                    443:        DELAY(100000);
                    444:        /* Disable interrupts */
                    445:        TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_IntOff);
                    446:        /* setup aregs & hash */
                    447:        for (i = TL_INT_Areg0; i <= TL_INT_HASH2; i = i + 4)
                    448:                tl_intreg_write(sc, i, 0);
                    449: #ifdef TLDEBUG_ADDR
                    450:        printf("Areg & hash registers: \n");
                    451:        for (i = TL_INT_Areg0; i <= TL_INT_HASH2; i = i + 4)
                    452:                printf("    reg %x: %x\n", i, tl_intreg_read(sc, i));
                    453: #endif
                    454:        /* Setup NetConfig */
                    455:        tl_intreg_write(sc, TL_INT_NetConfig,
                    456:                TL_NETCONFIG_1F | TL_NETCONFIG_1chn | TL_NETCONFIG_PHY_EN);
                    457:        /* Bsize: accept default */
                    458:        /* TX commit in Acommit: accept default */
                    459:        /* Load Ld_tmr and Ld_thr */
                    460:        /* Ld_tmr = 3 */
                    461:        TL_HR_WRITE(sc, TL_HOST_CMD, 0x3 | HOST_CMD_LdTmr);
                    462:        /* Ld_thr = 0 */
                    463:        TL_HR_WRITE(sc, TL_HOST_CMD, 0x0 | HOST_CMD_LdThr);
                    464:        /* Unreset MII */
                    465:        netsio_set(sc, TL_NETSIO_NMRST);
                    466:        DELAY(100000);
1.15      thorpej   467:        sc->tl_mii.mii_media_status &= ~IFM_ACTIVE;
1.1       bouyer    468:        sc->tl_flags = 0;
                    469:        sc->opkt = 0;
                    470:        sc->stats_exesscoll = 0;
                    471: }
                    472:
                    473: static void tl_shutdown(v)
                    474:        void *v;
                    475: {
                    476:        tl_softc_t *sc = v;
                    477:        struct Tx_list *Tx;
                    478:        int i;
                    479:
                    480:        if ((sc->tl_if.if_flags & IFF_RUNNING) == 0)
                    481:                return;
                    482:        /* disable interrupts */
                    483:        TL_HR_WRITE(sc, TL_HOST_CMD,
                    484:                HOST_CMD_IntOff);
                    485:        /* stop TX and RX channels */
                    486:        TL_HR_WRITE(sc, TL_HOST_CMD,
                    487:                HOST_CMD_STOP | HOST_CMD_RT | HOST_CMD_Nes);
                    488:        TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_STOP);
                    489:        DELAY(100000);
                    490:
                    491:        /* stop statistics reading loop, read stats */
                    492:        untimeout(tl_ticks, sc);
                    493:        tl_read_stats(sc);
                    494:
                    495:        /* deallocate memory allocations */
                    496:        for (i=0; i< TL_NBUF; i++) {
                    497:                if (sc->Rx_list[i].m)
                    498:                        m_freem(sc->Rx_list[i].m);
                    499:                        sc->Rx_list[i].m = NULL;
                    500:        }
                    501:        free(sc->Rx_list, M_DEVBUF);
                    502:        sc->Rx_list = NULL;
                    503:        while ((Tx = sc->active_Tx) != NULL) {
                    504:                Tx->hw_list.stat = 0;
                    505:                m_freem(Tx->m);
                    506:                sc->active_Tx = Tx->next;
                    507:                Tx->next = sc->Free_Tx;
                    508:                sc->Free_Tx = Tx;
                    509:        }
                    510:        sc->last_Tx = NULL;
                    511:        free(sc->Tx_list, M_DEVBUF);
                    512:        sc->Tx_list = NULL;
                    513:        sc->tl_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1.15      thorpej   514:        sc->tl_mii.mii_media_status &= ~IFM_ACTIVE;
1.1       bouyer    515:        sc->tl_flags = 0;
                    516: }
                    517:
                    518: static void tl_restart(v)
                    519:        void *v;
                    520: {
                    521:        tl_init(v);
                    522: }
                    523:
                    524: static int tl_init(sc)
                    525:        tl_softc_t *sc;
                    526: {
                    527:        struct ifnet *ifp = &sc->tl_if;
                    528:        int i, s;
                    529:
1.14      mycroft   530:        s = splnet();
1.1       bouyer    531:        /* cancel any pending IO */
                    532:        tl_shutdown(sc);
                    533:        tl_reset(sc);
                    534:        if ((sc->tl_if.if_flags & IFF_UP) == 0) {
                    535:                splx(s);
                    536:                return 0;
                    537:        }
                    538:        /* Set various register to reasonable value */
                    539:        /* setup NetCmd in promisc mode if needed */
                    540:        i = (ifp->if_flags & IFF_PROMISC) ? TL_NETCOMMAND_CAF : 0;
                    541:        tl_intreg_write_byte(sc, TL_INT_NET + TL_INT_NetCmd,
                    542:                TL_NETCOMMAND_NRESET | TL_NETCOMMAND_NWRAP | i);
                    543:        /* Max receive size : MCLBYTES */
                    544:        tl_intreg_write_byte(sc, TL_INT_MISC + TL_MISC_MaxRxL, MCLBYTES & 0xff);
                    545:        tl_intreg_write_byte(sc, TL_INT_MISC + TL_MISC_MaxRxH,
                    546:                (MCLBYTES >> 8) & 0xff);
                    547:
                    548:        /* init MAC addr */
                    549:        for (i = 0; i < ETHER_ADDR_LEN; i++)
                    550:                tl_intreg_write_byte(sc, TL_INT_Areg0 + i , sc->tl_enaddr[i]);
                    551:        /* add multicast filters */
                    552:        tl_addr_filter(sc);
                    553: #ifdef TLDEBUG_ADDR
                    554:        printf("Wrote Mac addr, Areg & hash registers are now: \n");
                    555:        for (i = TL_INT_Areg0; i <= TL_INT_HASH2; i = i + 4)
                    556:                printf("    reg %x: %x\n", i, tl_intreg_read(sc, i));
                    557: #endif
                    558:
                    559:        /* Pre-allocate receivers mbuf, make the lists */
                    560:        sc->Rx_list = malloc(sizeof(struct Rx_list) * TL_NBUF, M_DEVBUF, M_NOWAIT);
                    561:        sc->Tx_list = malloc(sizeof(struct Tx_list) * TL_NBUF, M_DEVBUF, M_NOWAIT);
                    562:        if (sc->Rx_list == NULL || sc->Tx_list == NULL) {
                    563:                printf("%s: out of memory for lists\n", sc->sc_dev.dv_xname);
                    564:                sc->tl_if.if_flags &= ~IFF_UP;
                    565:                splx(s);
                    566:                return ENOMEM;
                    567:        }
                    568:        for (i=0; i< TL_NBUF; i++) {
                    569:                if(tl_add_RxBuff(&sc->Rx_list[i], NULL) == 0) {
                    570:                        printf("%s: out of mbuf for receive list\n", sc->sc_dev.dv_xname);
                    571:                        sc->tl_if.if_flags &= ~IFF_UP;
                    572:                        splx(s);
                    573:                        return ENOMEM;
                    574:                }
                    575:                if (i > 0) { /* chain the list */
                    576:                        sc->Rx_list[i-1].next = &sc->Rx_list[i];
                    577:                        sc->Rx_list[i-1].hw_list.fwd = vtophys(&sc->Rx_list[i].hw_list);
                    578: #ifdef DIAGNOSTIC
                    579:                        if (sc->Rx_list[i-1].hw_list.fwd & 0x7)
                    580:                                printf("%s: physical addr 0x%x of list not properly aligned\n",
                    581:                                        sc->sc_dev.dv_xname, sc->Rx_list[i-1].hw_list.fwd);
                    582: #endif
                    583:                        sc->Tx_list[i-1].next = &sc->Tx_list[i];
                    584:                }
                    585:        }
                    586:        sc->Rx_list[TL_NBUF-1].next = NULL;
                    587:        sc->Rx_list[TL_NBUF-1].hw_list.fwd = 0;
                    588:        sc->Tx_list[TL_NBUF-1].next = NULL;
                    589:
                    590:        sc->active_Rx = &sc->Rx_list[0];
                    591:        sc->last_Rx   = &sc->Rx_list[TL_NBUF-1];
                    592:        sc->active_Tx = sc->last_Tx = NULL;
                    593:        sc->Free_Tx   = &sc->Tx_list[0];
                    594:
1.6       bouyer    595:        if (nullbuf == NULL)
                    596:                nullbuf = malloc(ETHER_MIN_TX, M_DEVBUF, M_NOWAIT);
1.1       bouyer    597:        if (nullbuf == NULL) {
                    598:                printf("%s: can't allocate space for pad buffer\n",
                    599:                        sc->sc_dev.dv_xname);
                    600:                sc->tl_if.if_flags &= ~IFF_UP;
                    601:                splx(s);
                    602:                return ENOMEM;
                    603:        }
                    604:        bzero(nullbuf, ETHER_MIN_TX);
                    605:
1.15      thorpej   606:        /* set media */
                    607:        mii_mediachg(&sc->tl_mii);
1.1       bouyer    608:
                    609:        /* start ticks calls */
                    610:        timeout(tl_ticks, sc, hz);
                    611:        /* write adress of Rx list and enable interrupts */
                    612:        TL_HR_WRITE(sc, TL_HOST_CH_PARM, vtophys(&sc->Rx_list[0].hw_list));
                    613:        TL_HR_WRITE(sc, TL_HOST_CMD,
                    614:                HOST_CMD_GO | HOST_CMD_RT | HOST_CMD_Nes | HOST_CMD_IntOn);
                    615:        sc->tl_if.if_flags |= IFF_RUNNING;
                    616:        sc->tl_if.if_flags &= ~IFF_OACTIVE;
                    617:        return 0;
                    618: }
                    619:
                    620:
                    621: static u_int32_t
                    622: tl_intreg_read(sc, reg)
                    623:        tl_softc_t *sc;
                    624:        u_int32_t reg;
                    625: {
                    626:        TL_HR_WRITE(sc, TL_HOST_INTR_DIOADR, reg & TL_HOST_DIOADR_MASK);
                    627:        return TL_HR_READ(sc, TL_HOST_DIO_DATA);
                    628: }
                    629:
                    630: static u_int8_t
                    631: tl_intreg_read_byte(sc, reg)
                    632:        tl_softc_t *sc;
                    633:        u_int32_t reg;
                    634: {
                    635:        TL_HR_WRITE(sc, TL_HOST_INTR_DIOADR,
                    636:                (reg & (~0x07)) & TL_HOST_DIOADR_MASK);
                    637:        return TL_HR_READ_BYTE(sc, TL_HOST_DIO_DATA + (reg & 0x07));
                    638: }
                    639:
                    640: static void
                    641: tl_intreg_write(sc, reg, val)
                    642:        tl_softc_t *sc;
                    643:        u_int32_t reg;
                    644:        u_int32_t val;
                    645: {
                    646:        TL_HR_WRITE(sc, TL_HOST_INTR_DIOADR, reg & TL_HOST_DIOADR_MASK);
                    647:        TL_HR_WRITE(sc, TL_HOST_DIO_DATA, val);
                    648: }
                    649:
                    650: static void
                    651: tl_intreg_write_byte(sc, reg, val)
                    652:        tl_softc_t *sc;
                    653:        u_int32_t reg;
                    654:        u_int8_t val;
                    655: {
                    656:        TL_HR_WRITE(sc, TL_HOST_INTR_DIOADR,
                    657:                (reg & (~0x03)) & TL_HOST_DIOADR_MASK);
                    658:        TL_HR_WRITE_BYTE(sc, TL_HOST_DIO_DATA + (reg & 0x03), val);
                    659: }
                    660:
1.15      thorpej   661: void
                    662: tl_mii_sync(sc)
                    663:        struct tl_softc *sc;
1.1       bouyer    664: {
1.15      thorpej   665:        int i;
1.1       bouyer    666:
1.15      thorpej   667:        netsio_clr(sc, TL_NETSIO_MTXEN);
                    668:        for (i = 0; i < 32; i++) {
                    669:                netsio_clr(sc, TL_NETSIO_MCLK);
1.1       bouyer    670:                netsio_set(sc, TL_NETSIO_MCLK);
                    671:        }
                    672: }
                    673:
1.15      thorpej   674: void
                    675: tl_mii_sendbits(sc, data, nbits)
                    676:        struct tl_softc *sc;
                    677:        u_int32_t data;
                    678:        int nbits;
1.1       bouyer    679: {
1.15      thorpej   680:        int i;
1.1       bouyer    681:
1.15      thorpej   682:        netsio_set(sc, TL_NETSIO_MTXEN);
                    683:        for (i = 1 << (nbits - 1); i; i = i >>  1) {
1.1       bouyer    684:                netsio_clr(sc, TL_NETSIO_MCLK);
1.15      thorpej   685:                netsio_read(sc, TL_NETSIO_MCLK);
                    686:                if (data & i)
                    687:                        netsio_set(sc, TL_NETSIO_MDATA);
                    688:                else
                    689:                        netsio_clr(sc, TL_NETSIO_MDATA);
                    690:                netsio_set(sc, TL_NETSIO_MCLK);
                    691:                netsio_read(sc, TL_NETSIO_MCLK);
1.1       bouyer    692:        }
                    693: }
                    694:
1.15      thorpej   695: int
                    696: tl_mii_read(self, phy, reg)
                    697:        struct device *self;
                    698:        int phy, reg;
1.1       bouyer    699: {
1.15      thorpej   700:        struct tl_softc *sc = (struct tl_softc *)self;
                    701:        int val = 0, i, err;
                    702:
                    703:        /*
                    704:         * Read the PHY register by manually driving the MII control lines.
                    705:         */
1.1       bouyer    706:
1.15      thorpej   707:        tl_mii_sync(sc);
                    708:        tl_mii_sendbits(sc, MII_COMMAND_START, 2);
                    709:        tl_mii_sendbits(sc, MII_COMMAND_READ, 2);
                    710:        tl_mii_sendbits(sc, phy, 5);
                    711:        tl_mii_sendbits(sc, reg, 5);
                    712:
                    713:        netsio_clr(sc, TL_NETSIO_MTXEN);
                    714:        netsio_clr(sc, TL_NETSIO_MCLK);
                    715:        netsio_set(sc, TL_NETSIO_MCLK);
                    716:        netsio_clr(sc, TL_NETSIO_MCLK);
                    717:
                    718:        err = netsio_read(sc, TL_NETSIO_MDATA);
                    719:        netsio_set(sc, TL_NETSIO_MCLK);
                    720:
                    721:        /* Even if an error occurs, must still clock out the cycle. */
                    722:        for (i = 0; i < 16; i++) {
                    723:                val <<= 1;
                    724:                netsio_clr(sc, TL_NETSIO_MCLK);
                    725:                if (err == 0 && netsio_read(sc, TL_NETSIO_MDATA))
                    726:                        val |= 1;
                    727:                netsio_set(sc, TL_NETSIO_MCLK);
1.1       bouyer    728:        }
1.15      thorpej   729:        netsio_clr(sc, TL_NETSIO_MCLK);
                    730:        netsio_set(sc, TL_NETSIO_MCLK);
                    731:
                    732:        return (err ? 0 : val);
                    733: }
                    734:
                    735: void
                    736: tl_mii_write(self, phy, reg, val)
                    737:        struct device *self;
                    738:        int phy, reg, val;
                    739: {
                    740:        struct tl_softc *sc = (struct tl_softc *)self;
                    741:
                    742:        /*
                    743:         * Write the PHY register by manually driving the MII control lines.
                    744:         */
                    745:
                    746:        tl_mii_sync(sc);
                    747:        tl_mii_sendbits(sc, MII_COMMAND_START, 2);
                    748:        tl_mii_sendbits(sc, MII_COMMAND_WRITE, 2);
                    749:        tl_mii_sendbits(sc, phy, 5);
                    750:        tl_mii_sendbits(sc, reg, 5);
                    751:        tl_mii_sendbits(sc, MII_COMMAND_ACK, 2);
                    752:        tl_mii_sendbits(sc, val, 16);
                    753:
                    754:        netsio_clr(sc, TL_NETSIO_MCLK);
                    755:        netsio_set(sc, TL_NETSIO_MCLK);
                    756: }
                    757:
                    758: void
                    759: tl_statchg(self)
                    760:        struct device *self;
                    761: {
                    762:        tl_softc_t *sc = (struct tl_softc *)self;
                    763:        u_int32_t reg;
                    764:
                    765: #ifdef TLDEBUG
                    766:        printf("tl_statchg, media %x\n", sc->tl_ifmedia.ifm_media);
                    767: #endif
                    768:
                    769:        /*
                    770:         * We must keep the ThunderLAN and the PHY in sync as
                    771:         * to the status of full-duplex!
                    772:         */
                    773:        reg = tl_intreg_read_byte(sc, TL_INT_NET + TL_INT_NetCmd);
                    774:        if (sc->tl_mii.mii_media_active & IFM_FDX)
                    775:                reg |= TL_NETCOMMAND_DUPLEX;
                    776:        else
                    777:                reg &= ~TL_NETCOMMAND_DUPLEX;
                    778:        tl_intreg_write_byte(sc, TL_INT_NET + TL_INT_NetCmd, reg);
                    779:
                    780:        /* XXX Update ifp->if_baudrate */
1.1       bouyer    781: }
                    782:
                    783: void tl_i2c_set(v, bit)
                    784:        void *v;
                    785:        u_int8_t bit;
                    786: {
                    787:        tl_softc_t *sc = v;
                    788:
                    789:        switch (bit) {
                    790:        case I2C_DATA:
                    791:                netsio_set(sc, TL_NETSIO_EDATA);
                    792:                break;
                    793:        case I2C_CLOCK:
                    794:                netsio_set(sc, TL_NETSIO_ECLOCK);
                    795:                break;
                    796:        case I2C_TXEN:
                    797:                netsio_set(sc, TL_NETSIO_ETXEN);
                    798:                break;
                    799:        default:
                    800:                printf("tl_i2c_set: unknown bit %d\n", bit);
                    801:        }
                    802:        return;
                    803: }
                    804:
                    805: void tl_i2c_clr(v, bit)
                    806:        void *v;
                    807:        u_int8_t bit;
                    808: {
                    809:        tl_softc_t *sc = v;
                    810:
                    811:        switch (bit) {
                    812:        case I2C_DATA:
                    813:                netsio_clr(sc, TL_NETSIO_EDATA);
                    814:                break;
                    815:        case I2C_CLOCK:
                    816:                netsio_clr(sc, TL_NETSIO_ECLOCK);
                    817:                break;
                    818:        case I2C_TXEN:
                    819:                netsio_clr(sc, TL_NETSIO_ETXEN);
                    820:                break;
                    821:        default:
                    822:                printf("tl_i2c_clr: unknown bit %d\n", bit);
                    823:        }
                    824:        return;
                    825: }
                    826:
                    827: int tl_i2c_read(v, bit)
                    828:        void *v;
                    829:        u_int8_t bit;
                    830: {
                    831:        tl_softc_t *sc = v;
                    832:
                    833:        switch (bit) {
                    834:        case I2C_DATA:
                    835:                return netsio_read(sc, TL_NETSIO_EDATA);
                    836:                break;
                    837:        case I2C_CLOCK:
                    838:                return netsio_read(sc, TL_NETSIO_ECLOCK);
                    839:                break;
                    840:        case I2C_TXEN:
                    841:                return netsio_read(sc, TL_NETSIO_ETXEN);
                    842:                break;
                    843:        default:
                    844:                printf("tl_i2c_read: unknown bit %d\n", bit);
                    845:                return -1;
                    846:        }
                    847: }
                    848:
                    849: static int
                    850: tl_intr(v)
                    851:        void *v;
                    852: {
                    853:        tl_softc_t *sc = v;
                    854:        struct ifnet *ifp = &sc->tl_if;
                    855:        struct Rx_list *Rx;
                    856:        struct Tx_list *Tx;
                    857:        struct mbuf *m;
                    858:        u_int32_t int_type, int_reg;
                    859:        int ack = 0;
                    860:        int size;
                    861:
                    862:        int_reg = TL_HR_READ(sc, TL_HOST_INTR_DIOADR);
                    863:        int_type = int_reg  & TL_INTR_MASK;
                    864:        if (int_type == 0)
                    865:                return 0;
                    866: #if defined(TLDEBUG_RX) || defined(TLDEBUG_TX)
                    867:        printf("%s: interrupt type %x, intr_reg %x\n", sc->sc_dev.dv_xname,
                    868:                int_type, int_reg);
                    869: #endif
                    870:        /* disable interrupts */
                    871:        TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_IntOff);
                    872:        switch(int_type & TL_INTR_MASK) {
                    873:        case TL_INTR_RxEOF:
                    874:                while(sc->active_Rx->hw_list.stat & TL_RX_CSTAT_CPLT) {
                    875:                        /* dequeue and requeue at end of list */
                    876:                        ack++;
                    877:                        Rx = sc->active_Rx;
                    878:                        sc->active_Rx = Rx->next;
                    879:                        m = Rx->m;
                    880:                        size = Rx->hw_list.stat >> 16;
                    881: #ifdef TLDEBUG_RX
                    882:                        printf("tl_intr: RX list complete, Rx %p, size=%d\n", Rx, size);
                    883: #endif
                    884:                        if (tl_add_RxBuff(Rx, m ) == 0) {
                    885:                                /* No new mbuf, reuse the same. This means that this packet
                    886:                                        is lost */
                    887:                                m = NULL;
                    888: #ifdef TL_PRIV_STATS
                    889:                                sc->ierr_nomem++;
                    890: #endif
                    891: #ifdef TLDEBUG
                    892:                                printf("%s: out of mbuf, lost input packet\n",
                    893:                                        sc->sc_dev.dv_xname);
                    894: #endif
                    895:                        }
                    896:                        Rx->next = NULL;
                    897:                        Rx->hw_list.fwd = 0;
                    898:                        sc->last_Rx->hw_list.fwd = vtophys(&Rx->hw_list);
                    899: #ifdef DIAGNOSTIC
                    900:                        if (sc->last_Rx->hw_list.fwd & 0x7)
                    901:                                printf("%s: physical addr 0x%x of list not properly aligned\n",
                    902:                                        sc->sc_dev.dv_xname, sc->last_Rx->hw_list.fwd);
                    903: #endif
                    904:                        sc->last_Rx->next = Rx;
                    905:                        sc->last_Rx = Rx;
                    906:
                    907:                        /* deliver packet */
                    908:                        if (m) {
                    909:                                struct ether_header *eh;
                    910:                                if (size < sizeof(struct ether_header)) {
                    911:                                        m_freem(m);
                    912:                                        continue;
                    913:                                }
                    914:                                m->m_pkthdr.rcvif = ifp;
                    915:                                m->m_pkthdr.len = m->m_len =
                    916:                                        size - sizeof(struct ether_header);
                    917:                                eh = mtod(m, struct ether_header *);
                    918: #ifdef TLDEBUG_RX
                    919:                                printf("tl_intr: Rx packet:\n");
                    920:                                ether_printheader(eh);
                    921: #endif
                    922: #if NBPFILTER > 0
                    923:                                if (ifp->if_bpf) {
                    924:                                        bpf_tap(ifp->if_bpf,
                    925:                                                mtod(m, caddr_t),
                    926:                                                size);
                    927:                                        /*
                    928:                                        * Only pass this packet up
                    929:                                        * if it is for us.
                    930:                                        */
                    931:                                        if ((ifp->if_flags & IFF_PROMISC) &&
                    932:                                                (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
                    933:                                                bcmp(eh->ether_dhost, LLADDR(ifp->if_sadl),
                    934:                                                        sizeof(eh->ether_dhost)) != 0) {
                    935:                                                m_freem(m);
                    936:                                                continue;
                    937:                                        }
                    938:                                }
                    939: #endif /* NBPFILTER > 0 */
                    940:                                m->m_data += sizeof(struct ether_header);
                    941:                                ether_input(ifp, eh, m);
                    942:                        }
                    943:                }
                    944: #ifdef TLDEBUG_RX
                    945:                printf("TL_INTR_RxEOF: ack %d\n", ack);
                    946: #else
                    947:                if (ack == 0) {
                    948:                        printf("%s: EOF intr without anything to read !\n",
                    949:                                sc->sc_dev.dv_xname);
                    950:                        tl_reset(sc);
                    951:                        /* shedule reinit of the board */
                    952:                        timeout(tl_restart, sc, 1);
                    953:                        return(1);
                    954:                }
                    955: #endif
                    956:                break;
                    957:        case TL_INTR_RxEOC:
                    958:                ack++;
                    959: #ifdef TLDEBUG_RX
                    960:                printf("TL_INTR_RxEOC: ack %d\n", ack);
                    961: #endif
                    962: #ifdef DIAGNOSTIC
                    963:                if (sc->active_Rx->hw_list.stat & TL_RX_CSTAT_CPLT) {
                    964:                        printf("%s: Rx EOC interrupt and active Rx list not cleared\n",
                    965:                                sc->sc_dev.dv_xname);
                    966:                        return 0;
                    967:                } else
                    968: #endif
                    969:                {
                    970:                /* write adress of Rx list and send Rx GO command, ack interrupt
                    971:                 and enable interrupts in one command */
                    972:                TL_HR_WRITE(sc, TL_HOST_CH_PARM,
                    973:                        vtophys(&sc->active_Rx->hw_list));
                    974:                TL_HR_WRITE(sc, TL_HOST_CMD,
                    975:                        HOST_CMD_GO | HOST_CMD_RT | HOST_CMD_Nes | ack | int_type |
                    976:                        HOST_CMD_ACK | HOST_CMD_IntOn);
                    977:                return 1;
                    978:                }
                    979:        case TL_INTR_TxEOF:
                    980:        case TL_INTR_TxEOC:
                    981:                while ((Tx = sc->active_Tx) != NULL) {
                    982:                        if((Tx->hw_list.stat & TL_TX_CSTAT_CPLT) == 0)
                    983:                                break;
                    984:                        ack++;
                    985: #ifdef TLDEBUG_TX
                    986:                        printf("TL_INTR_TxEOC: list 0x%xp done\n", vtophys(&Tx->hw_list));
                    987: #endif
                    988:                        Tx->hw_list.stat = 0;
                    989:                        m_freem(Tx->m);
                    990:                        Tx->m = NULL;
                    991:                        sc->active_Tx = Tx->next;
                    992:                        if (sc->active_Tx == NULL)
                    993:                                sc->last_Tx = NULL;
                    994:                        Tx->next = sc->Free_Tx;
                    995:                        sc->Free_Tx = Tx;
                    996:                }
                    997:                /* if this was an EOC, ACK immediatly */
                    998:                if (int_type == TL_INTR_TxEOC) {
                    999: #ifdef TLDEBUG_TX
                   1000:                        printf("TL_INTR_TxEOC: ack %d (will be set to 1)\n", ack);
                   1001: #endif
                   1002:                        TL_HR_WRITE(sc, TL_HOST_CMD, 1 | int_type | HOST_CMD_ACK |
                   1003:                                HOST_CMD_IntOn);
                   1004:                        if ( sc->active_Tx != NULL) { /* needs a Tx go command */
                   1005:                                TL_HR_WRITE(sc, TL_HOST_CH_PARM,
                   1006:                                        vtophys(&sc->active_Tx->hw_list));
                   1007:                                TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_GO);
                   1008:                        }
                   1009:                        sc->tl_if.if_timer = 0;
                   1010:                        if (sc->tl_if.if_snd.ifq_head != NULL)
                   1011:                                tl_ifstart(&sc->tl_if);
                   1012:                        return 1;
                   1013:                }
                   1014: #ifdef TLDEBUG
                   1015:                else {
                   1016:                        printf("TL_INTR_TxEOF: ack %d\n", ack);
                   1017:                }
                   1018: #endif
                   1019:                sc->tl_if.if_timer = 0;
                   1020:                if (sc->tl_if.if_snd.ifq_head != NULL)
                   1021:                        tl_ifstart(&sc->tl_if);
                   1022:                break;
                   1023:        case TL_INTR_Stat:
                   1024:                ack++;
                   1025: #ifdef TLDEBUG
                   1026:                printf("TL_INTR_Stat: ack %d\n", ack);
                   1027: #endif
                   1028:                tl_read_stats(sc);
                   1029:                break;
                   1030:        case TL_INTR_Adc:
                   1031:                if (int_reg & TL_INTVec_MASK) {
                   1032:                        /* adapter check conditions */
                   1033:                        printf("%s: check condition, intvect=0x%x, ch_param=0x%x\n",
                   1034:                                sc->sc_dev.dv_xname, int_reg & TL_INTVec_MASK,
                   1035:                                TL_HR_READ(sc, TL_HOST_CH_PARM));
                   1036:                        tl_reset(sc);
                   1037:                        /* shedule reinit of the board */
                   1038:                        timeout(tl_restart, sc, 1);
                   1039:                        return(1);
                   1040:                } else {
                   1041:                        u_int8_t netstat;
                   1042:                        /* Network status */
                   1043:                        netstat = tl_intreg_read_byte(sc, TL_INT_NET+TL_INT_NetSts);
                   1044:                        printf("%s: network status, NetSts=%x\n",
                   1045:                                sc->sc_dev.dv_xname, netstat);
                   1046:                        /* Ack interrupts */
                   1047:                        tl_intreg_write_byte(sc, TL_INT_NET+TL_INT_NetSts, netstat);
                   1048:                        ack++;
                   1049:                }
                   1050:                break;
                   1051:        default:
                   1052:                printf("%s: unhandled interrupt code %x!\n",
                   1053:                        sc->sc_dev.dv_xname, int_type);
                   1054:                ack++;
                   1055:        }
                   1056:
                   1057:        if (ack) {
                   1058:                /* Ack the interrupt and enable interrupts */
                   1059:                TL_HR_WRITE(sc, TL_HOST_CMD, ack | int_type | HOST_CMD_ACK |
                   1060:                        HOST_CMD_IntOn);
                   1061:                return 1;
                   1062:        }
                   1063:        /* ack = 0 ; interrupt was perhaps not our. Just enable interrupts */
                   1064:        TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_IntOn);
                   1065:        return 0;
                   1066: }
                   1067:
                   1068: static int
                   1069: tl_ifioctl(ifp, cmd, data)
                   1070:     struct ifnet *ifp;
                   1071:        ioctl_cmd_t cmd;
                   1072:        caddr_t data;
                   1073: {
                   1074:        struct tl_softc *sc = ifp->if_softc;
                   1075:        struct ifreq *ifr = (struct ifreq *)data;
                   1076:        int s, error;
                   1077:
1.14      mycroft  1078:        s = splnet();
1.1       bouyer   1079:        switch(cmd) {
                   1080:        case SIOCSIFADDR: {
                   1081:                struct ifaddr *ifa = (struct ifaddr *)data;
                   1082:                sc->tl_if.if_flags |= IFF_UP;
                   1083:                if ((error = tl_init(sc)) != NULL) {
                   1084:                        sc->tl_if.if_flags &= ~IFF_UP;
                   1085:                        break;
                   1086:                }
                   1087:                switch (ifa->ifa_addr->sa_family) {
                   1088: #ifdef INET
                   1089:                case AF_INET:
                   1090:                        arp_ifinit(ifp, ifa);
                   1091:                        break;
                   1092: #endif
                   1093: #ifdef NS
                   1094:                case AF_NS: {
                   1095:                        struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
                   1096:
                   1097:                        if (ns_nullhost(*ina))
                   1098:                                ina->x_host  = *(union ns_host*) LLADDR(ifp->if_sadl);
                   1099:                        else
                   1100:                                bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
                   1101:                                        ifp->if_addrlen);
                   1102:                        break;
                   1103:                }
                   1104: #endif
                   1105:                default:
                   1106:                        break;
                   1107:                }
                   1108:        break;
                   1109:        }
                   1110:        case SIOCSIFFLAGS:
                   1111:        {
                   1112:                u_int8_t reg;
                   1113:                /*
                   1114:                 * If interface is marked up and not running, then start it.
                   1115:                 * If it is marked down and running, stop it.
                   1116:                 */
                   1117:                if (ifp->if_flags & IFF_UP) {
                   1118:                        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                   1119:                                error = tl_init(sc);
                   1120:                                /* all flags have been handled by init */
                   1121:                                break;
                   1122:                        }
                   1123:                        error = 0;
                   1124:                        reg = tl_intreg_read_byte(sc, TL_INT_NET + TL_INT_NetCmd);
                   1125:                        if (ifp->if_flags & IFF_PROMISC)
                   1126:                                reg |= TL_NETCOMMAND_CAF;
                   1127:                        else
                   1128:                                reg &= ~TL_NETCOMMAND_CAF;
                   1129:                        tl_intreg_write_byte(sc, TL_INT_NET + TL_INT_NetCmd, reg);
                   1130: #ifdef TL_PRIV_STATS
                   1131:                        if (ifp->if_flags & IFF_LINK0) {
                   1132:                                ifp->if_flags &= ~IFF_LINK0;
                   1133:                                printf("%s errors statistics\n", sc->sc_dev.dv_xname);
                   1134:                                printf("    %4d RX buffer overrun\n",sc->ierr_overr);
                   1135:                                printf("    %4d RX code error\n", sc->ierr_code);
                   1136:                                printf("    %4d RX crc error\n", sc->ierr_crc);
                   1137:                                printf("    %4d RX out of memory\n", sc->ierr_nomem);
                   1138:                                printf("    %4d TX buffer underrun\n", sc->oerr_underr);
                   1139:                                printf("    %4d TX deffered frames\n", sc->oerr_deffered);
                   1140:                                printf("    %4d TX single collisions\n", sc->oerr_coll);
                   1141:                                printf("    %4d TX multi collisions\n", sc->oerr_multicoll);
                   1142:                                printf("    %4d TX exessive collisions\n", sc->oerr_exesscoll);
                   1143:                                printf("    %4d TX late collisions\n", sc->oerr_latecoll);
                   1144:                                printf("    %4d TX carrier loss\n", sc->oerr_carrloss);
                   1145:                                printf("    %4d TX mbuf copy\n", sc->oerr_mcopy);
                   1146:                        }
                   1147: #endif
                   1148:                } else {
                   1149:                        if (ifp->if_flags & IFF_RUNNING)
                   1150:                                tl_shutdown(sc);
                   1151:                        error = 0;
                   1152:                }
                   1153:                break;
                   1154:        }
                   1155:        case SIOCADDMULTI:
                   1156:        case SIOCDELMULTI:
                   1157:                /*
                   1158:                 * Update multicast listeners
                   1159:                 */
                   1160:                if (cmd == SIOCADDMULTI)
                   1161:                        error = ether_addmulti(ifr, &sc->tl_ec);
                   1162:                else
                   1163:                        error = ether_delmulti(ifr, &sc->tl_ec);
                   1164:                if (error == ENETRESET) {
                   1165:                        tl_addr_filter(sc);
                   1166:                        error = 0;
                   1167:                }
                   1168:                break;
                   1169:        case SIOCSIFMEDIA:
                   1170:        case SIOCGIFMEDIA:
1.15      thorpej  1171:                error = ifmedia_ioctl(ifp, ifr, &sc->tl_mii.mii_media, cmd);
1.1       bouyer   1172:                break;
                   1173:        default:
                   1174:                error = EINVAL;
                   1175:        }
                   1176:        splx(s);
                   1177:        return error;
                   1178: }
                   1179:
                   1180: static void
                   1181: tl_ifstart(ifp)
                   1182:        struct ifnet *ifp;
                   1183: {
                   1184:        tl_softc_t *sc = ifp->if_softc;
                   1185:        struct mbuf *m, *mb_head;
                   1186:        struct Tx_list *Tx;
                   1187:        int segment, size;
                   1188:
                   1189: txloop:
                   1190:        /* If we don't have more space ... */
                   1191:        if (sc->Free_Tx == NULL) {
                   1192: #ifdef TLDEBUG
                   1193:                printf("tl_ifstart: No free TX list\n");
                   1194: #endif
                   1195:                return;
                   1196:        }
                   1197:        /* Grab a paquet for output */
                   1198:        IF_DEQUEUE(&ifp->if_snd, mb_head);
                   1199:        if (mb_head == NULL) {
                   1200: #ifdef TLDEBUG_TX
                   1201:                printf("tl_ifstart: nothing to send\n");
                   1202: #endif
                   1203:                return;
                   1204:        }
                   1205:        Tx = sc->Free_Tx;
                   1206:        sc->Free_Tx = Tx->next;
                   1207:        /*
                   1208:         * Go through each of the mbufs in the chain and initialize
                   1209:         * the transmit list descriptors with the physical address
                   1210:         * and size of the mbuf.
                   1211:         */
                   1212: tbdinit:
                   1213:        bzero(Tx, sizeof(struct Tx_list));
                   1214:        Tx->m = mb_head;
                   1215:        size = 0;
                   1216:        for (m = mb_head, segment = 0; m != NULL ; m = m->m_next) {
                   1217:                if (m->m_len != 0) {
                   1218:                        if (segment == TL_NSEG)
                   1219:                                break;
                   1220:                        size += m->m_len;
                   1221:                        Tx->hw_list.seg[segment].data_addr =
1.16    ! eeh      1222:                                vtophys(mtod(m, vaddr_t));
1.1       bouyer   1223:                        Tx->hw_list.seg[segment].data_count = m->m_len;
                   1224:                        segment++;
                   1225:                }
                   1226:        }
                   1227:        if (m != NULL || (size < ETHER_MIN_TX && segment == TL_NSEG)) {
                   1228:                /*
                   1229:                 * We ran out of segments, or we will. We have to recopy this mbuf
                   1230:                 * chain first.
                   1231:                 */
                   1232:                struct mbuf *mn;
                   1233: #ifdef TLDEBUG_TX
                   1234:                printf("tl_ifstart: need to copy mbuf\n");
                   1235: #endif
                   1236: #ifdef TL_PRIV_STATS
                   1237:                sc->oerr_mcopy++;
                   1238: #endif
                   1239:                MGETHDR(mn, M_DONTWAIT, MT_DATA);
                   1240:                if (mn == NULL) {
                   1241:                        m_freem(mb_head);
                   1242:                        goto bad;
                   1243:                }
                   1244:                if (mb_head->m_pkthdr.len > MHLEN) {
                   1245:                        MCLGET(mn, M_DONTWAIT);
                   1246:                        if ((mn->m_flags & M_EXT) == 0) {
                   1247:                                m_freem(mn);
                   1248:                                m_freem(mb_head);
                   1249:                                goto bad;
                   1250:                        }
                   1251:                }
                   1252:                m_copydata(mb_head, 0, mb_head->m_pkthdr.len,
                   1253:                        mtod(mn, caddr_t));
                   1254:                mn->m_pkthdr.len = mn->m_len = mb_head->m_pkthdr.len;
                   1255:                m_freem(mb_head);
                   1256:                mb_head = mn;
                   1257:                goto tbdinit;
                   1258:        }
                   1259:        /* We are at end of mbuf chain. check the size and
                   1260:         * see if it needs to be extended
                   1261:         */
                   1262:        if (size < ETHER_MIN_TX) {
                   1263: #ifdef DIAGNOSTIC
                   1264:                if (segment >= TL_NSEG) {
                   1265:                        panic("tl_ifstart: to much segmets (%d)\n", segment);
                   1266:                }
                   1267: #endif
                   1268:                /*
                   1269:                 * add the nullbuf in the seg
                   1270:                 */
                   1271:                Tx->hw_list.seg[segment].data_count =
                   1272:                        ETHER_MIN_TX - size;
                   1273:                Tx->hw_list.seg[segment].data_addr =
                   1274:                        vtophys(nullbuf);
                   1275:                size = ETHER_MIN_TX;
                   1276:                segment++;
                   1277:        }
                   1278:        /* The list is done, finish the list init */
                   1279:        Tx->hw_list.seg[segment-1].data_count |=
                   1280:                TL_LAST_SEG;
                   1281:        Tx->hw_list.stat = (size << 16) | 0x3000;
                   1282: #ifdef TLDEBUG_TX
                   1283:        printf("%s: sending, Tx : stat = 0x%x\n", sc->sc_dev.dv_xname,
                   1284:                Tx->hw_list.stat);
                   1285: #if 0
                   1286:        for(segment = 0; segment < TL_NSEG; segment++) {
                   1287:                printf("    seg %d addr 0x%x len 0x%x\n",
                   1288:                        segment,
                   1289:                        Tx->hw_list.seg[segment].data_addr,
                   1290:                        Tx->hw_list.seg[segment].data_count);
                   1291:        }
                   1292: #endif
                   1293: #endif
                   1294:        sc->opkt++;
                   1295:        if (sc->active_Tx == NULL) {
                   1296:                sc->active_Tx = sc->last_Tx = Tx;
                   1297: #ifdef TLDEBUG_TX
                   1298:                printf("%s: Tx GO, addr=0x%x\n", sc->sc_dev.dv_xname,
                   1299:                        vtophys(&Tx->hw_list));
                   1300: #endif
                   1301:                TL_HR_WRITE(sc, TL_HOST_CH_PARM, vtophys(&Tx->hw_list));
                   1302:                TL_HR_WRITE(sc, TL_HOST_CMD, HOST_CMD_GO);
                   1303:        } else {
                   1304: #ifdef TLDEBUG_TX
                   1305:                printf("%s: Tx addr=0x%x queued\n", sc->sc_dev.dv_xname,
                   1306:                        vtophys(&Tx->hw_list));
                   1307: #endif
                   1308:                sc->last_Tx->hw_list.fwd = vtophys(&Tx->hw_list);
                   1309:                sc->last_Tx->next = Tx;
                   1310:                sc->last_Tx = Tx;
                   1311: #ifdef DIAGNOSTIC
                   1312:                if (sc->last_Tx->hw_list.fwd & 0x7)
                   1313:                                printf("%s: physical addr 0x%x of list not properly aligned\n",
                   1314:                                        sc->sc_dev.dv_xname, sc->last_Rx->hw_list.fwd);
                   1315: #endif
                   1316:        }
                   1317: #if NBPFILTER > 0
                   1318:        /* Pass packet to bpf if there is a listener */
                   1319:        if (ifp->if_bpf)
                   1320:                bpf_mtap(ifp->if_bpf, mb_head);
                   1321: #endif
                   1322:        /* Set a 5 second timer just in case we don't hear from the card again. */
                   1323:        ifp->if_timer = 5;
                   1324:
                   1325:        goto txloop;
                   1326: bad:
                   1327: #ifdef TLDEBUG
                   1328:        printf("tl_ifstart: Out of mbuf, Tx pkt lost\n");
                   1329: #endif
                   1330:        Tx->next = sc->Free_Tx;
                   1331:        sc->Free_Tx = Tx;
                   1332:        return;
                   1333: }
                   1334:
                   1335: static void
                   1336: tl_ifwatchdog(ifp)
                   1337:        struct ifnet *ifp;
                   1338: {
                   1339:        tl_softc_t *sc = ifp->if_softc;
                   1340:
                   1341:        if ((ifp->if_flags & IFF_RUNNING) == 0)
                   1342:                return;
                   1343:        printf("%s: device timeout\n", sc->sc_dev.dv_xname);
                   1344:        ifp->if_oerrors++;
                   1345:        tl_init(sc);
                   1346: }
                   1347:
                   1348: static int
                   1349: tl_mediachange(ifp)
                   1350:        struct ifnet *ifp;
                   1351: {
1.15      thorpej  1352:
                   1353:        if (ifp->if_flags & IFF_UP)
                   1354:                tl_init(ifp->if_softc);
                   1355:        return (0);
1.1       bouyer   1356: }
                   1357:
                   1358: static void
                   1359: tl_mediastatus(ifp, ifmr)
                   1360:        struct ifnet *ifp;
                   1361:        struct ifmediareq *ifmr;
                   1362: {
                   1363:        tl_softc_t *sc = ifp->if_softc;
1.15      thorpej  1364:
                   1365:        mii_pollstat(&sc->tl_mii);
                   1366:        ifmr->ifm_active = sc->tl_mii.mii_media_active;
                   1367:        ifmr->ifm_status = sc->tl_mii.mii_media_status;
1.1       bouyer   1368: }
                   1369:
                   1370: static int tl_add_RxBuff(Rx, oldm)
                   1371:        struct Rx_list *Rx;
                   1372:        struct mbuf *oldm;
                   1373: {
                   1374:        struct mbuf *m;
                   1375:
                   1376:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1377:        if (m != NULL) {
                   1378:                MCLGET(m, M_DONTWAIT);
                   1379:                if ((m->m_flags & M_EXT) == 0) {
                   1380:                        m_freem(m);
                   1381:                        if (oldm == NULL)
                   1382:                                return 0;
                   1383:                        m = oldm;
                   1384:                        m->m_data = m->m_ext.ext_buf;
                   1385:                }
                   1386:        } else {
                   1387:                if (oldm == NULL)
                   1388:                        return 0;
                   1389:                m = oldm;
                   1390:                m->m_data = m->m_ext.ext_buf;
                   1391:        }
                   1392:        /*
                   1393:         * Move the data pointer up so that the incoming data packet
                   1394:         * will be 32-bit aligned.
                   1395:         */
                   1396:        m->m_data += 2;
                   1397:
                   1398:        /* (re)init the Rx_list struct */
                   1399:
                   1400:        Rx->m = m;
                   1401:        Rx->hw_list.stat = ((MCLBYTES -2) << 16) | 0x3000;
                   1402:        Rx->hw_list.seg.data_count = (MCLBYTES -2);
                   1403:        Rx->hw_list.seg.data_addr = vtophys(m->m_data);
                   1404:        return (m != oldm);
                   1405: }
                   1406:
                   1407: static void tl_ticks(v)
                   1408:        void *v;
                   1409: {
                   1410:        tl_softc_t *sc = v;
                   1411:
                   1412:        tl_read_stats(sc);
                   1413:        if (sc->opkt > 0) {
                   1414:                if (sc->oerr_exesscoll > sc->opkt / 100) { /* exess collisions */
                   1415:                        if (sc->tl_flags & TL_IFACT) /* only print once */
                   1416:                                                printf("%s: no carrier\n", sc->sc_dev.dv_xname);
                   1417:                                        sc->tl_flags &= ~TL_IFACT;
                   1418:                                } else
                   1419:                                        sc->tl_flags |= TL_IFACT;
                   1420:                                sc->oerr_exesscoll = sc->opkt = 0;
                   1421:                                sc->tl_lasttx = 0;
                   1422:                        } else {
                   1423:                                sc->tl_lasttx++;
                   1424:                                if (sc->tl_lasttx >= TL_IDLETIME) {
                   1425:                                        /*
                   1426:                                         * No TX activity in the last TL_IDLETIME seconds.
                   1427:                                         * sends a LLC Class1 TEST pkt
                   1428:                                         */
                   1429:                                        struct mbuf *m;
                   1430:                                        int s;
                   1431:                                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1432:                                        if (m != NULL) {
                   1433:                #ifdef TLDEBUG
                   1434:                                                printf("tl_ticks: sending LLC test pkt\n");
                   1435:                #endif
                   1436:                                                bcopy(sc->tl_enaddr,
                   1437:                                                        mtod(m, struct ether_header *)->ether_dhost, 6);
                   1438:                                                bcopy(sc->tl_enaddr,
                   1439:                                                        mtod(m, struct ether_header *)->ether_shost, 6);
                   1440:                                                mtod(m, struct ether_header *)->ether_type = htons(3);
                   1441:                                                mtod(m, unsigned char *)[14] = 0;
                   1442:                                                mtod(m, unsigned char *)[15] = 0;
                   1443:                                                mtod(m, unsigned char *)[16] = 0xE3;
                   1444:                                                                                                        /* LLC Class1 TEST (no poll) */
                   1445:                                                m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
                   1446:                                                s = splnet();
                   1447:                                                IF_PREPEND(&sc->tl_if.if_snd, m);
                   1448:                                                tl_ifstart(&sc->tl_if);
                   1449:                                                splx(s);
                   1450:                                        }
                   1451:                                }
                   1452:                        }
                   1453:
                   1454:                        /* read statistics every seconds */
                   1455:                        timeout(tl_ticks, v, hz);
                   1456:                }
                   1457:
                   1458:                static void
                   1459:                tl_read_stats(sc)
                   1460:                        tl_softc_t *sc;
                   1461:                {
                   1462:                        u_int32_t reg;
                   1463:                        int ierr_overr;
                   1464:                        int ierr_code;
                   1465:                        int ierr_crc;
                   1466:                        int oerr_underr;
                   1467:                        int oerr_deffered;
                   1468:                        int oerr_coll;
                   1469:                        int oerr_multicoll;
                   1470:                        int oerr_exesscoll;
                   1471:                        int oerr_latecoll;
                   1472:                        int oerr_carrloss;
                   1473:                        struct ifnet *ifp = &sc->tl_if;
                   1474:
                   1475:                        reg =  tl_intreg_read(sc, TL_INT_STATS_TX);
                   1476:                        ifp->if_opackets += reg & 0x00ffffff;
                   1477:                        oerr_underr = reg >> 24;
                   1478:
                   1479:                        reg =  tl_intreg_read(sc, TL_INT_STATS_RX);
                   1480:                        ifp->if_ipackets += reg & 0x00ffffff;
                   1481:                        ierr_overr = reg >> 24;
                   1482:
                   1483:                        reg =  tl_intreg_read(sc, TL_INT_STATS_FERR);
                   1484:                        ierr_crc = (reg & TL_FERR_CRC) >> 16;
                   1485:                        ierr_code = (reg & TL_FERR_CODE) >> 24;
                   1486:                        oerr_deffered = (reg & TL_FERR_DEF);
                   1487:
                   1488:                        reg =  tl_intreg_read(sc, TL_INT_STATS_COLL);
                   1489:                        oerr_multicoll = (reg & TL_COL_MULTI);
                   1490:                        oerr_coll = (reg & TL_COL_SINGLE) >> 16;
                   1491:
                   1492:                        reg =  tl_intreg_read(sc, TL_INT_LERR);
                   1493:                        oerr_exesscoll = (reg & TL_LERR_ECOLL);
                   1494:                        oerr_latecoll = (reg & TL_LERR_LCOLL) >> 8;
                   1495:                        oerr_carrloss = (reg & TL_LERR_CL) >> 16;
                   1496:
                   1497:
                   1498:                        sc->stats_exesscoll += oerr_exesscoll;
                   1499:                        ifp->if_oerrors += oerr_underr + oerr_exesscoll + oerr_latecoll +
                   1500:                                oerr_carrloss;
                   1501:                        ifp->if_collisions += oerr_coll + oerr_multicoll;
                   1502:                        ifp->if_ierrors += ierr_overr + ierr_code + ierr_crc;
                   1503:
                   1504:                        if (ierr_overr)
                   1505:                                printf("%s: receiver ring buffer overrun\n", sc->sc_dev.dv_xname);
                   1506:                        if (oerr_underr)
                   1507:                                printf("%s: transmit buffer underrun\n", sc->sc_dev.dv_xname);
                   1508:                #ifdef TL_PRIV_STATS
                   1509:                        sc->ierr_overr          += ierr_overr;
                   1510:                        sc->ierr_code           += ierr_code;
                   1511:                        sc->ierr_crc            += ierr_crc;
                   1512:                        sc->oerr_underr         += oerr_underr;
                   1513:                        sc->oerr_deffered       += oerr_deffered;
                   1514:                        sc->oerr_coll           += oerr_coll;
                   1515:                        sc->oerr_multicoll      += oerr_multicoll;
                   1516:                        sc->oerr_exesscoll      += oerr_exesscoll;
                   1517:                        sc->oerr_latecoll       += oerr_latecoll;
                   1518:                        sc->oerr_carrloss       += oerr_carrloss;
                   1519:                #endif
                   1520:                }
                   1521:
                   1522:                static void tl_addr_filter(sc)
                   1523:                        tl_softc_t *sc;
                   1524:                {
                   1525:                        struct ether_multistep step;
                   1526:                        struct ether_multi *enm;
                   1527:                        u_int32_t hash[2] = {0, 0};
                   1528:                        int i;
                   1529:
                   1530:                        sc->tl_if.if_flags &= ~IFF_ALLMULTI;
                   1531:                        ETHER_FIRST_MULTI(step, &sc->tl_ec, enm);
                   1532:                        while (enm != NULL) {
                   1533:                #ifdef TLDEBUG
                   1534:                                printf("tl_addr_filter: addrs %s %s\n", ether_sprintf(enm->enm_addrlo), ether_sprintf(enm->enm_addrhi));
                   1535:                #endif
                   1536:                                if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) == 0) {
                   1537:                                        i = tl_multicast_hash(enm->enm_addrlo);
                   1538:                                        hash[i/32] |= 1 << (i%32);
                   1539:                                } else {
                   1540:                                        hash[0] = hash[1] = 0xffffffff;
                   1541:                                        sc->tl_if.if_flags |= IFF_ALLMULTI;
                   1542:                                        break;
                   1543:                                }
                   1544:                                ETHER_NEXT_MULTI(step, enm);
                   1545:                        }
                   1546:                #ifdef TLDEBUG
                   1547:                        printf("tl_addr_filer: hash1 %x has2 %x\n", hash[0], hash[1]);
                   1548:                #endif
                   1549:                        tl_intreg_write(sc, TL_INT_HASH1, hash[0]);
                   1550:                        tl_intreg_write(sc, TL_INT_HASH2, hash[1]);
                   1551:                }
                   1552:
                   1553:                static int tl_multicast_hash(a)
                   1554:                        u_int8_t *a;
                   1555:                {
                   1556:                        int hash;
                   1557:
                   1558:                #define DA(addr,bit) (addr[5 - (bit/8)] & (1 << bit%8))
                   1559:                #define xor8(a,b,c,d,e,f,g,h) (((a != 0) + (b != 0) + (c != 0) + (d != 0) + (e != 0) + (f != 0) + (g != 0) + (h != 0)) & 1)
                   1560:
                   1561:                        hash  = xor8( DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24), DA(a,30),
                   1562:                                DA(a,36), DA(a,42));
                   1563:                        hash |= xor8( DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25), DA(a,31),
                   1564:                                DA(a,37), DA(a,43)) << 1;
                   1565:                        hash |= xor8( DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26), DA(a,32),
                   1566:                                DA(a,38), DA(a,44)) << 2;
                   1567:                        hash |= xor8( DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27), DA(a,33),
                   1568:                                DA(a,39), DA(a,45)) << 3;
                   1569:                        hash |= xor8( DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28), DA(a,34),
                   1570:                                DA(a,40), DA(a,46)) << 4;
                   1571:                        hash |= xor8( DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29), DA(a,35),
                   1572:                                DA(a,41), DA(a,47)) << 5;
                   1573:
                   1574:                        return hash;
                   1575:                }
                   1576:
                   1577:                #if defined(TLDEBUG_RX)
                   1578:                void ether_printheader(eh)
                   1579:                        struct ether_header *eh;
                   1580:                {
                   1581:                        u_char *c = (char*)eh;
                   1582:                        int i;
                   1583:                        for (i=0; i<sizeof(struct ether_header); i++)
                   1584:                                printf("%x ", (u_int)c[i]);
                   1585:                        printf("\n");
                   1586:                }
                   1587: #endif

CVSweb <webmaster@jp.NetBSD.org>