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

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

CVSweb <webmaster@jp.NetBSD.org>