[BACK]Return to if_de.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/if_de.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_de.c,v 1.97 2007/02/14 00:53:48 jsg Exp $  */
                      2: /*     $NetBSD: if_de.c,v 1.58 1998/01/12 09:39:58 thorpej Exp $       */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  *
                     27:  * Id: if_de.c,v 1.89 1997/06/03 19:19:55 thomas Exp
                     28:  *
                     29:  */
                     30:
                     31: /*
                     32:  * DEC 21040 PCI Ethernet Controller
                     33:  *
                     34:  * Written by Matt Thomas
                     35:  * BPF support code stolen directly from if_ec.c
                     36:  *
                     37:  *   This driver supports the DEC DE435 or any other PCI
                     38:  *   board which support 21040, 21041, or 21140 (mostly).
                     39:  */
                     40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/mbuf.h>
                     44: #include <sys/protosw.h>
                     45: #include <sys/socket.h>
                     46: #include <sys/ioctl.h>
                     47: #include <sys/errno.h>
                     48: #include <sys/malloc.h>
                     49: #include <sys/kernel.h>
                     50: #include <sys/proc.h>  /* only for declaration of wakeup() used by vm.h */
                     51: #include <sys/device.h>
                     52: #include <sys/timeout.h>
                     53:
                     54: #include <net/if.h>
                     55: #include <net/if_media.h>
                     56: #include <net/if_types.h>
                     57: #include <net/if_dl.h>
                     58: #include <net/route.h>
                     59: #include <net/netisr.h>
                     60:
                     61: #include "bpfilter.h"
                     62: #if NBPFILTER > 0
                     63: #include <net/bpf.h>
                     64: #endif
                     65:
                     66: #ifdef INET
                     67: #include <netinet/in.h>
                     68: #include <netinet/in_systm.h>
                     69: #include <netinet/in_var.h>
                     70: #include <netinet/ip.h>
                     71: #endif
                     72:
                     73: #include <netinet/if_ether.h>
                     74:
                     75: #include <machine/bus.h>
                     76: #include <machine/intr.h>
                     77: #include <dev/pci/pcireg.h>
                     78: #include <dev/pci/pcivar.h>
                     79: #include <dev/pci/pcidevs.h>
                     80: #include <dev/ic/dc21040reg.h>
                     81:
                     82: /*
                     83:  * Intel CPUs should use I/O mapped access.
                     84:  */
                     85: #if defined(__i386__)
                     86: #define        TULIP_IOMAPPED
                     87: #endif
                     88:
                     89: #define        TULIP_HZ        10
                     90:
                     91: #define TULIP_SIAGEN_WATCHDOG  0
                     92:
                     93: #define TULIP_GPR_CMDBITS      (TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_TXTHRSHLDCTL)
                     94:
                     95: #define EMIT   do { TULIP_CSR_WRITE(sc, csr_srom_mii, csr); tulip_delay_300ns(sc); } while (0)
                     96: #define MII_EMIT       do { TULIP_CSR_WRITE(sc, csr_srom_mii, csr); tulip_delay_300ns(sc); } while (0)
                     97:
                     98: #define tulip_mchash(mca)      (ether_crc32_le(mca, 6) & 0x1FF)
                     99: #define tulip_srom_crcok(databuf)      ( \
                    100:     ((ether_crc32_le(databuf, 126) & 0xFFFFU) ^ 0xFFFFU) == \
                    101:      ((databuf)[126] | ((databuf)[127] << 8)))
                    102:
                    103: /*
                    104:  * This is the PCI configuration support.  Since the 21040 is available
                    105:  * on both EISA and PCI boards, one must be careful in how defines the
                    106:  * 21040 in the config file.
                    107:  */
                    108:
                    109: #define PCI_CFID       0x00    /* Configuration ID */
                    110: #define PCI_CFCS       0x04    /* Configurtion Command/Status */
                    111: #define PCI_CFRV       0x08    /* Configuration Revision */
                    112: #define PCI_CFLT       0x0c    /* Configuration Latency Timer */
                    113: #define PCI_CBIO       0x10    /* Configuration Base IO Address */
                    114: #define PCI_CBMA       0x14    /* Configuration Base Memory Address */
                    115: #define PCI_CFIT       0x3c    /* Configuration Interrupt */
                    116: #define PCI_CFDA       0x40    /* Configuration Driver Area */
                    117:
                    118: #define PCI_CONF_WRITE(r, v)   pci_conf_write(pa->pa_pc, pa->pa_tag, (r), (v))
                    119: #define PCI_CONF_READ(r)       pci_conf_read(pa->pa_pc, pa->pa_tag, (r))
                    120: #define PCI_GETBUSDEVINFO(sc)  do { \
                    121:        (sc)->tulip_pci_busno = parent; \
                    122:        (sc)->tulip_pci_devno = pa->pa_device; \
                    123:     } while (0)
                    124:
                    125: #include <dev/pci/if_devar.h>
                    126: /*
                    127:  * This module supports
                    128:  *     the DEC 21040 PCI Ethernet Controller.
                    129:  *     the DEC 21041 PCI Ethernet Controller.
                    130:  *     the DEC 21140 PCI Fast Ethernet Controller.
                    131:  */
                    132: int tulip_probe(struct device *parent, void *match, void *aux);
                    133: void tulip_attach(struct device * const parent, struct device * const self, void * const aux);
                    134:
                    135: struct cfattach de_ca = {
                    136:        sizeof(tulip_softc_t), tulip_probe, tulip_attach
                    137: };
                    138:
                    139: struct cfdriver de_cd = {
                    140:        0, "de", DV_IFNET
                    141: };
                    142:
                    143: void tulip_timeout_callback(void *arg);
                    144: void tulip_timeout(tulip_softc_t * const sc);
                    145: int tulip_txprobe(tulip_softc_t * const sc);
                    146: void tulip_media_set(tulip_softc_t * const sc, tulip_media_t media);
                    147: void tulip_linkup(tulip_softc_t * const sc, tulip_media_t media);
                    148: void tulip_media_print(tulip_softc_t * const sc);
                    149: tulip_link_status_t tulip_media_link_monitor(tulip_softc_t * const sc);
                    150: void tulip_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event);
                    151: void tulip_media_select(tulip_softc_t * const sc);
                    152:
                    153: void tulip_21040_mediainfo_init(tulip_softc_t * const sc, tulip_media_t media);
                    154: void tulip_21040_media_probe(tulip_softc_t * const sc);
                    155: void tulip_21040_10baset_only_media_probe(tulip_softc_t * const sc);
                    156: void tulip_21040_10baset_only_media_select(tulip_softc_t * const sc);
                    157: void tulip_21040_auibnc_only_media_probe(tulip_softc_t * const sc);
                    158: void tulip_21040_auibnc_only_media_select(tulip_softc_t * const sc);
                    159:
                    160: void tulip_21041_mediainfo_init(tulip_softc_t * const sc);
                    161: void tulip_21041_media_noprobe(tulip_softc_t * const sc);
                    162: void tulip_21041_media_probe(tulip_softc_t * const sc);
                    163: void tulip_21041_media_poll(tulip_softc_t * const sc, const tulip_mediapoll_event_t event);
                    164:
                    165: tulip_media_t tulip_mii_phy_readspecific(tulip_softc_t * const sc);
                    166: unsigned tulip_mii_get_phyaddr(tulip_softc_t * const sc, unsigned offset);
                    167: int tulip_mii_map_abilities(tulip_softc_t * const sc, unsigned abilities);
                    168: void tulip_mii_autonegotiate(tulip_softc_t * const sc, const unsigned phyaddr);
                    169:
                    170: void tulip_2114x_media_preset(tulip_softc_t * const sc);
                    171:
                    172: void tulip_null_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event);
                    173:
                    174: void tulip_21140_mediainit(tulip_softc_t * const sc, tulip_media_info_t * const mip,
                    175:     tulip_media_t const media, unsigned gpdata, unsigned cmdmode);
                    176: void tulip_21140_evalboard_media_probe(tulip_softc_t * const sc);
                    177: void tulip_21140_accton_media_probe(tulip_softc_t * const sc);
                    178: void tulip_21140_smc9332_media_probe(tulip_softc_t * const sc);
                    179: void tulip_21140_cogent_em100_media_probe(tulip_softc_t * const sc);
                    180: void tulip_21140_znyx_zx34x_media_probe(tulip_softc_t * const sc);
                    181:
                    182: void tulip_2114x_media_probe(tulip_softc_t * const sc);
                    183:
                    184: void tulip_delay_300ns(tulip_softc_t * const sc);
                    185: void tulip_srom_idle(tulip_softc_t * const sc);
                    186: void tulip_srom_read(tulip_softc_t * const sc);
                    187: void tulip_mii_writebits(tulip_softc_t * const sc, unsigned data, unsigned bits);
                    188: void tulip_mii_turnaround(tulip_softc_t * const sc, unsigned cmd);
                    189: unsigned tulip_mii_readbits(tulip_softc_t * const sc);
                    190: unsigned tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno);
                    191: void tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno,
                    192:     unsigned data);
                    193:
                    194: void tulip_identify_dec_nic(tulip_softc_t * const sc);
                    195: void tulip_identify_znyx_nic(tulip_softc_t * const sc);
                    196: void tulip_identify_smc_nic(tulip_softc_t * const sc);
                    197: void tulip_identify_cogent_nic(tulip_softc_t * const sc);
                    198: void tulip_identify_accton_nic(tulip_softc_t * const sc);
                    199: void tulip_identify_asante_nic(tulip_softc_t * const sc);
                    200: void tulip_identify_compex_nic(tulip_softc_t * const sc);
                    201:
                    202: int tulip_srom_decode(tulip_softc_t * const sc);
                    203: int tulip_read_macaddr(tulip_softc_t * const sc);
                    204: void tulip_ifmedia_add(tulip_softc_t * const sc);
                    205: int tulip_ifmedia_change(struct ifnet * const ifp);
                    206: void tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req);
                    207: void tulip_addr_filter(tulip_softc_t * const sc);
                    208: void tulip_reset(tulip_softc_t * const sc);
                    209: void tulip_init(tulip_softc_t * const sc);
                    210: void tulip_rx_intr(tulip_softc_t * const sc);
                    211: int tulip_tx_intr(tulip_softc_t * const sc);
                    212: void tulip_print_abnormal_interrupt(tulip_softc_t * const sc, u_int32_t csr);
                    213: void tulip_intr_handler(tulip_softc_t * const sc, int *progress_p);
                    214: int tulip_intr_shared(void *arg);
                    215: int tulip_intr_normal(void *arg);
                    216: struct mbuf *tulip_mbuf_compress(struct mbuf *m);
                    217: struct mbuf *tulip_txput(tulip_softc_t * const sc, struct mbuf *m);
                    218: void tulip_txput_setup(tulip_softc_t * const sc);
                    219: int tulip_ifioctl(struct ifnet * ifp, u_long cmd, caddr_t data);
                    220: void tulip_ifstart(struct ifnet *ifp);
                    221: void tulip_ifstart_one(struct ifnet *ifp);
                    222: void tulip_ifwatchdog(struct ifnet *ifp);
                    223: int tulip_busdma_allocmem(tulip_softc_t * const sc, size_t size,
                    224:     bus_dmamap_t *map_p, tulip_desc_t **desc_p);
                    225: int tulip_busdma_init(tulip_softc_t * const sc);
                    226: void tulip_initcsrs(tulip_softc_t * const sc, bus_addr_t csr_base, size_t csr_size);
                    227: void tulip_initring(tulip_softc_t * const sc, tulip_ringinfo_t * const ri,
                    228:     tulip_desc_t *descs, int ndescs);
                    229: void tulip_shutdown(void *arg);
                    230:
                    231:
                    232: void
                    233: tulip_timeout_callback(void *arg)
                    234: {
                    235:     tulip_softc_t * const sc = arg;
                    236:     int s;
                    237:
                    238:     s = splnet();
                    239:
                    240:     TULIP_PERFSTART(timeout)
                    241:
                    242:     sc->tulip_flags &= ~TULIP_TIMEOUTPENDING;
                    243:     sc->tulip_probe_timeout -= 1000 / TULIP_HZ;
                    244:     (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER);
                    245:
                    246:     TULIP_PERFEND(timeout);
                    247:     splx(s);
                    248: }
                    249:
                    250: void
                    251: tulip_timeout(tulip_softc_t * const sc)
                    252: {
                    253:     if (sc->tulip_flags & TULIP_TIMEOUTPENDING)
                    254:        return;
                    255:     sc->tulip_flags |= TULIP_TIMEOUTPENDING;
                    256:     timeout_add(&sc->tulip_stmo, (hz + TULIP_HZ / 2) / TULIP_HZ);
                    257: }
                    258:
                    259: int
                    260: tulip_txprobe(tulip_softc_t * const sc)
                    261: {
                    262:     struct mbuf *m;
                    263:
                    264:     /*
                    265:      * Before we are sure this is the right media we need
                    266:      * to send a small packet to make sure there's carrier.
                    267:      * Strangely, BNC and AUI will "see" receive data if
                    268:      * either is connected so the transmit is the only way
                    269:      * to verify the connectivity.
                    270:      */
                    271:     MGETHDR(m, M_DONTWAIT, MT_DATA);
                    272:     if (m == NULL)
                    273:        return (0);
                    274:     /*
                    275:      * Construct a LLC TEST message which will point to ourselves.
                    276:      */
                    277:     bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_dhost,
                    278:        ETHER_ADDR_LEN);
                    279:     bcopy(sc->tulip_enaddr, mtod(m, struct ether_header *)->ether_shost,
                    280:        ETHER_ADDR_LEN);
                    281:     mtod(m, struct ether_header *)->ether_type = htons(3);
                    282:     mtod(m, unsigned char *)[14] = 0;
                    283:     mtod(m, unsigned char *)[15] = 0;
                    284:     mtod(m, unsigned char *)[16] = 0xE3;       /* LLC Class1 TEST (no poll) */
                    285:     m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
                    286:     /*
                    287:      * send it!
                    288:      */
                    289:     sc->tulip_cmdmode |= TULIP_CMD_TXRUN;
                    290:     sc->tulip_intrmask |= TULIP_STS_TXINTR;
                    291:     sc->tulip_flags |= TULIP_TXPROBE_ACTIVE;
                    292:     TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                    293:     TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                    294:     if ((m = tulip_txput(sc, m)) != NULL)
                    295:        m_freem(m);
                    296:     sc->tulip_probe.probe_txprobes++;
                    297:     return (1);
                    298: }
                    299:
                    300: void
                    301: tulip_media_set(tulip_softc_t * const sc, tulip_media_t media)
                    302: {
                    303:     const tulip_media_info_t *mi = sc->tulip_mediums[media];
                    304:
                    305:     if (mi == NULL)
                    306:        return;
                    307:
                    308:     /* Reset the SIA first
                    309:      */
                    310:     if (mi->mi_type == TULIP_MEDIAINFO_SIA || (sc->tulip_features & TULIP_HAVE_SIANWAY))
                    311:        TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
                    312:
                    313:     /* Next, set full duplex if needed.
                    314:      */
                    315:     if (sc->tulip_flags & TULIP_FULLDUPLEX) {
                    316: #ifdef TULIP_DEBUG
                    317:        if (TULIP_CSR_READ(sc, csr_command) & (TULIP_CMD_RXRUN|TULIP_CMD_TXRUN))
                    318:            printf(TULIP_PRINTF_FMT ": warning: board is running (FD).\n", TULIP_PRINTF_ARGS);
                    319:        if ((TULIP_CSR_READ(sc, csr_command) & TULIP_CMD_FULLDUPLEX) == 0)
                    320:            printf(TULIP_PRINTF_FMT ": setting full duplex.\n", TULIP_PRINTF_ARGS);
                    321:                       TULIP_PRINTF_ARGS);
                    322: #endif
                    323:        sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
                    324:        TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode & ~(TULIP_CMD_RXRUN|TULIP_CMD_TXRUN));
                    325:     }
                    326:
                    327:     /* Now setup the media.
                    328:      *
                    329:      * If we are switching media, make sure we don't think there's
                    330:      * any stale RX activity
                    331:      */
                    332:     sc->tulip_flags &= ~TULIP_RXACT;
                    333:     if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
                    334:        TULIP_CSR_WRITE(sc, csr_sia_tx_rx,        mi->mi_sia_tx_rx);
                    335:        if (sc->tulip_features & TULIP_HAVE_SIAGP) {
                    336:            TULIP_CSR_WRITE(sc, csr_sia_general,  mi->mi_sia_gp_control|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
                    337:            DELAY(50);
                    338:            TULIP_CSR_WRITE(sc, csr_sia_general,  mi->mi_sia_gp_data|mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
                    339:        } else
                    340:            TULIP_CSR_WRITE(sc, csr_sia_general,  mi->mi_sia_general|TULIP_SIAGEN_WATCHDOG);
                    341:        TULIP_CSR_WRITE(sc, csr_sia_connectivity, mi->mi_sia_connectivity);
                    342:     } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {
                    343:        /*
                    344:         * If the cmdmode bits don't match the currently operating mode,
                    345:         * set the cmdmode appropriately and reset the chip.
                    346:         */
                    347:        if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {
                    348:            sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
                    349:            sc->tulip_cmdmode |= mi->mi_cmdmode;
                    350:            tulip_reset(sc);
                    351:        }
                    352:        TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);
                    353:        DELAY(10);
                    354:        TULIP_CSR_WRITE(sc, csr_gp, (u_int8_t) mi->mi_gpdata);
                    355:     } else if (mi->mi_type == TULIP_MEDIAINFO_SYM) {
                    356:        /*
                    357:         * If the cmdmode bits don't match the currently operating mode,
                    358:         * set the cmdmode appropriately and reset the chip.
                    359:         */
                    360:        if (((mi->mi_cmdmode ^ TULIP_CSR_READ(sc, csr_command)) & TULIP_GPR_CMDBITS) != 0) {
                    361:            sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
                    362:            sc->tulip_cmdmode |= mi->mi_cmdmode;
                    363:            tulip_reset(sc);
                    364:        }
                    365:        TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpcontrol);
                    366:        TULIP_CSR_WRITE(sc, csr_sia_general, mi->mi_gpdata);
                    367:     } else if (mi->mi_type == TULIP_MEDIAINFO_MII
                    368:               && sc->tulip_probe_state != TULIP_PROBE_INACTIVE) {
                    369:        int idx;
                    370:        if (sc->tulip_features & TULIP_HAVE_SIAGP) {
                    371:            const u_int8_t *dp;
                    372:            dp = &sc->tulip_rombuf[mi->mi_reset_offset];
                    373:            for (idx = 0; idx < mi->mi_reset_length; idx++, dp += 2) {
                    374:                DELAY(10);
                    375:                TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);
                    376:            }
                    377:            sc->tulip_phyaddr = mi->mi_phyaddr;
                    378:            dp = &sc->tulip_rombuf[mi->mi_gpr_offset];
                    379:            for (idx = 0; idx < mi->mi_gpr_length; idx++, dp += 2) {
                    380:                DELAY(10);
                    381:                TULIP_CSR_WRITE(sc, csr_sia_general, (dp[0] + 256 * dp[1]) << 16);
                    382:            }
                    383:        } else {
                    384:            for (idx = 0; idx < mi->mi_reset_length; idx++) {
                    385:                DELAY(10);
                    386:                TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx]);
                    387:            }
                    388:            sc->tulip_phyaddr = mi->mi_phyaddr;
                    389:            for (idx = 0; idx < mi->mi_gpr_length; idx++) {
                    390:                DELAY(10);
                    391:                TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx]);
                    392:            }
                    393:        }
                    394:
                    395:        if (sc->tulip_features & TULIP_HAVE_SIANWAY) {
                    396:            /* Set the SIA port into MII mode */
                    397:            TULIP_CSR_WRITE(sc, csr_sia_general, 1);
                    398:            TULIP_CSR_WRITE(sc, csr_sia_tx_rx, 0);
                    399:            TULIP_CSR_WRITE(sc, csr_sia_status, 0);
                    400:        }
                    401:
                    402:        if (sc->tulip_flags & TULIP_TRYNWAY)
                    403:            tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);
                    404:        else if ((sc->tulip_flags & TULIP_DIDNWAY) == 0) {
                    405:            u_int32_t data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_CONTROL);
                    406:            data &= ~(PHYCTL_SELECT_100MB|PHYCTL_FULL_DUPLEX|PHYCTL_AUTONEG_ENABLE);
                    407:            sc->tulip_flags &= ~TULIP_DIDNWAY;
                    408:            if (TULIP_IS_MEDIA_FD(media))
                    409:                data |= PHYCTL_FULL_DUPLEX;
                    410:            if (TULIP_IS_MEDIA_100MB(media))
                    411:                data |= PHYCTL_SELECT_100MB;
                    412:            tulip_mii_writereg(sc, sc->tulip_phyaddr, PHYREG_CONTROL, data);
                    413:        }
                    414:     }
                    415: }
                    416:
                    417: void
                    418: tulip_linkup(tulip_softc_t * const sc, tulip_media_t media)
                    419: {
                    420:     if ((sc->tulip_flags & TULIP_LINKUP) == 0)
                    421:        sc->tulip_flags |= TULIP_PRINTLINKUP;
                    422:     sc->tulip_flags |= TULIP_LINKUP;
                    423:     sc->tulip_if.if_flags &= ~IFF_OACTIVE;
                    424:     if (sc->tulip_media != media) {
                    425: #ifdef TULIP_DEBUG
                    426:        sc->tulip_dbg.dbg_last_media = sc->tulip_media;
                    427: #endif
                    428:        sc->tulip_media = media;
                    429:        sc->tulip_flags |= TULIP_PRINTMEDIA;
                    430:        if (TULIP_IS_MEDIA_FD(sc->tulip_media))
                    431:            sc->tulip_flags |= TULIP_FULLDUPLEX;
                    432:        else if (sc->tulip_chipid != TULIP_21041 || (sc->tulip_flags & TULIP_DIDNWAY) == 0)
                    433:            sc->tulip_flags &= ~TULIP_FULLDUPLEX;
                    434:     }
                    435:     /*
                    436:      * We could set probe_timeout to 0 but setting to 3000 puts this
                    437:      * in one central place and the only matters is tulip_link is
                    438:      * followed by a tulip_timeout.  Therefore setting it should not
                    439:      * result in aberrant behavour.
                    440:      */
                    441:     sc->tulip_probe_timeout = 3000;
                    442:     sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                    443:     sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_TRYNWAY);
                    444:     if (sc->tulip_flags & TULIP_INRESET)
                    445:        tulip_media_set(sc, sc->tulip_media);
                    446:     else if (sc->tulip_probe_media != sc->tulip_media) {
                    447:        /*
                    448:         * No reason to change media if we have the right media.
                    449:         */
                    450:        tulip_reset(sc);
                    451:     }
                    452:     tulip_init(sc);
                    453: }
                    454:
                    455: void
                    456: tulip_media_print(tulip_softc_t * const sc)
                    457: {
                    458:     if ((sc->tulip_flags & TULIP_LINKUP) == 0)
                    459:        return;
                    460:     if (sc->tulip_flags & TULIP_PRINTMEDIA) {
                    461: #ifdef TULIP_DEBUG
                    462:        printf(TULIP_PRINTF_FMT ": enabling %s port\n",
                    463:               TULIP_PRINTF_ARGS,
                    464:               tulip_mediums[sc->tulip_media]);
                    465: #endif
                    466:        sc->tulip_flags &= ~(TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);
                    467:     } else if (sc->tulip_flags & TULIP_PRINTLINKUP) {
                    468: #ifdef TULIP_DEBUG
                    469:        printf(TULIP_PRINTF_FMT ": link up\n", TULIP_PRINTF_ARGS);
                    470: #endif
                    471:        sc->tulip_flags &= ~TULIP_PRINTLINKUP;
                    472:     }
                    473: }
                    474:
                    475: tulip_link_status_t
                    476: tulip_media_link_monitor(tulip_softc_t * const sc)
                    477: {
                    478:     const tulip_media_info_t * const mi = sc->tulip_mediums[sc->tulip_media];
                    479:     tulip_link_status_t linkup = TULIP_LINK_DOWN;
                    480:
                    481:     if (mi == NULL) {
                    482: #if defined(TULIP_DEBUG)
                    483:        printf("tulip_media_link_monitor: %s: botch at line %d\n",
                    484:              tulip_mediums[sc->tulip_media],__LINE__);
                    485: #endif
                    486:        return (TULIP_LINK_UNKNOWN);
                    487:     }
                    488:
                    489:
                    490:     /*
                    491:      * Have we seen some packets?  If so, the link must be good.
                    492:      */
                    493:     if ((sc->tulip_flags & (TULIP_RXACT|TULIP_LINKUP)) == (TULIP_RXACT|TULIP_LINKUP)) {
                    494:        sc->tulip_flags &= ~TULIP_RXACT;
                    495:        sc->tulip_probe_timeout = 3000;
                    496:        return (TULIP_LINK_UP);
                    497:     }
                    498:
                    499:     sc->tulip_flags &= ~TULIP_RXACT;
                    500:     if (mi->mi_type == TULIP_MEDIAINFO_MII) {
                    501:        u_int32_t status;
                    502:        /*
                    503:         * Read the PHY status register.
                    504:         */
                    505:        status = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS)
                    506:                | tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS);
                    507:        if (status & PHYSTS_AUTONEG_DONE) {
                    508:            /*
                    509:             * If the PHY has completed autonegotiation, see the if the
                    510:             * remote systems abilities have changed.  If so, upgrade or
                    511:             * downgrade as appropriate.
                    512:             */
                    513:            u_int32_t abilities = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_AUTONEG_ABILITIES);
                    514:            abilities = (abilities << 6) & status;
                    515:            if (abilities != sc->tulip_abilities) {
                    516: #if defined(TULIP_DEBUG)
                    517:                printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation changed: 0x%04x -> 0x%04x\n",
                    518:                           TULIP_PRINTF_ARGS, sc->tulip_phyaddr,
                    519:                           sc->tulip_abilities, abilities);
                    520: #endif
                    521:                if (tulip_mii_map_abilities(sc, abilities)) {
                    522:                    tulip_linkup(sc, sc->tulip_probe_media);
                    523:                    return (TULIP_LINK_UP);
                    524:                }
                    525:                /*
                    526:                 * if we had selected media because of autonegotiation,
                    527:                 * we need to probe for the new media.
                    528:                 */
                    529:                sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                    530:                if (sc->tulip_flags & TULIP_DIDNWAY)
                    531:                    return (TULIP_LINK_DOWN);
                    532:            }
                    533:        }
                    534:        /*
                    535:         * The link is now up.  If was down, say its back up.
                    536:         */
                    537:        if ((status & (PHYSTS_LINK_UP|PHYSTS_REMOTE_FAULT)) == PHYSTS_LINK_UP)
                    538:            linkup = TULIP_LINK_UP;
                    539:     } else if (mi->mi_type == TULIP_MEDIAINFO_GPR) {
                    540:        /*
                    541:         * No activity sensor?  Assume all's well.
                    542:         */
                    543:        if (mi->mi_actmask == 0)
                    544:            return (TULIP_LINK_UNKNOWN);
                    545:        /*
                    546:         * Does the activity data match?
                    547:         */
                    548:        if ((TULIP_CSR_READ(sc, csr_gp) & mi->mi_actmask) == mi->mi_actdata)
                    549:            linkup = TULIP_LINK_UP;
                    550:     } else if (mi->mi_type == TULIP_MEDIAINFO_SIA) {
                    551:        /*
                    552:         * Assume non TP ok for now.
                    553:         */
                    554:        if (!TULIP_IS_MEDIA_TP(sc->tulip_media))
                    555:            return (TULIP_LINK_UNKNOWN);
                    556:        if ((TULIP_CSR_READ(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) == 0)
                    557:            linkup = TULIP_LINK_UP;
                    558: #if defined(TULIP_DEBUG)
                    559:        if (sc->tulip_probe_timeout <= 0)
                    560:            printf(TULIP_PRINTF_FMT ": sia status = 0x%08x\n", TULIP_PRINTF_ARGS, TULIP_CSR_READ(sc, csr_sia_status));
                    561: #endif
                    562:     } else if (mi->mi_type == TULIP_MEDIAINFO_SYM)
                    563:        return (TULIP_LINK_UNKNOWN);
                    564:     /*
                    565:      * We will wait for 3 seconds until the link goes into suspect mode.
                    566:      */
                    567:     if (sc->tulip_flags & TULIP_LINKUP) {
                    568:        if (linkup == TULIP_LINK_UP)
                    569:            sc->tulip_probe_timeout = 3000;
                    570:        if (sc->tulip_probe_timeout > 0)
                    571:            return (TULIP_LINK_UP);
                    572:
                    573:        sc->tulip_flags &= ~TULIP_LINKUP;
                    574:     }
                    575: #if defined(TULIP_DEBUG)
                    576:     sc->tulip_dbg.dbg_link_downed++;
                    577: #endif
                    578:     return (TULIP_LINK_DOWN);
                    579: }
                    580:
                    581: void
                    582: tulip_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event)
                    583: {
                    584: #if defined(TULIP_DEBUG)
                    585:     sc->tulip_dbg.dbg_events[event]++;
                    586: #endif
                    587:     if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE
                    588:            && event == TULIP_MEDIAPOLL_TIMER) {
                    589:        switch (tulip_media_link_monitor(sc)) {
                    590:            case TULIP_LINK_DOWN: {
                    591:                /*
                    592:                 * Link Monitor failed.  Probe for new media.
                    593:                 */
                    594:                event = TULIP_MEDIAPOLL_LINKFAIL;
                    595:                break;
                    596:            }
                    597:            case TULIP_LINK_UP: {
                    598:                /*
                    599:                 * Check again soon.
                    600:                 */
                    601:                tulip_timeout(sc);
                    602:                return;
                    603:            }
                    604:            case TULIP_LINK_UNKNOWN: {
                    605:                /*
                    606:                 * We can't tell so don't bother.
                    607:                 */
                    608:                return;
                    609:            }
                    610:        }
                    611:     }
                    612:
                    613:     if (event == TULIP_MEDIAPOLL_LINKFAIL) {
                    614:        if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE) {
                    615:            if (TULIP_DO_AUTOSENSE(sc)) {
                    616: #if defined(TULIP_DEBUG)
                    617:                sc->tulip_dbg.dbg_link_failures++;
                    618: #endif
                    619:                sc->tulip_media = TULIP_MEDIA_UNKNOWN;
                    620:                if (sc->tulip_if.if_flags & IFF_UP)
                    621:                    tulip_reset(sc);    /* restart probe */
                    622:            }
                    623:            return;
                    624:        }
                    625: #if defined(TULIP_DEBUG)
                    626:        sc->tulip_dbg.dbg_link_pollintrs++;
                    627: #endif
                    628:     }
                    629:
                    630:     if (event == TULIP_MEDIAPOLL_START) {
                    631:        sc->tulip_if.if_flags |= IFF_OACTIVE;
                    632:        if (sc->tulip_probe_state != TULIP_PROBE_INACTIVE)
                    633:            return;
                    634:        sc->tulip_probe_mediamask = 0;
                    635:        sc->tulip_probe_passes = 0;
                    636: #if defined(TULIP_DEBUG)
                    637:        sc->tulip_dbg.dbg_media_probes++;
                    638: #endif
                    639:        /*
                    640:         * If the SROM contained an explicit media to use, use it.
                    641:         */
                    642:        sc->tulip_cmdmode &= ~(TULIP_CMD_RXRUN|TULIP_CMD_FULLDUPLEX);
                    643:        sc->tulip_flags |= TULIP_TRYNWAY|TULIP_PROBE1STPASS;
                    644:        sc->tulip_flags &= ~(TULIP_DIDNWAY|TULIP_PRINTMEDIA|TULIP_PRINTLINKUP);
                    645:        /*
                    646:         * connidx is defaulted to a media_unknown type.
                    647:         */
                    648:        sc->tulip_probe_media = tulip_srom_conninfo[sc->tulip_connidx].sc_media;
                    649:        if (sc->tulip_probe_media != TULIP_MEDIA_UNKNOWN) {
                    650:            tulip_linkup(sc, sc->tulip_probe_media);
                    651:            tulip_timeout(sc);
                    652:            return;
                    653:        }
                    654:
                    655:        if (sc->tulip_features & TULIP_HAVE_GPR) {
                    656:            sc->tulip_probe_state = TULIP_PROBE_GPRTEST;
                    657:            sc->tulip_probe_timeout = 2000;
                    658:        } else {
                    659:            sc->tulip_probe_media = TULIP_MEDIA_MAX;
                    660:            sc->tulip_probe_timeout = 0;
                    661:            sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                    662:        }
                    663:     }
                    664:
                    665:     /*
                    666:      * Ignore txprobe failures or spurious callbacks.
                    667:      */
                    668:     if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED
                    669:            && sc->tulip_probe_state != TULIP_PROBE_MEDIATEST) {
                    670:        sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
                    671:        return;
                    672:     }
                    673:
                    674:     /*
                    675:      * If we really transmitted a packet, then that's the media we'll use.
                    676:      */
                    677:     if (event == TULIP_MEDIAPOLL_TXPROBE_OK || event == TULIP_MEDIAPOLL_LINKPASS) {
                    678:        if (event == TULIP_MEDIAPOLL_LINKPASS) {
                    679:            /* XXX Check media status just to be sure */
                    680:            sc->tulip_probe_media = TULIP_MEDIA_10BASET;
                    681: #if defined(TULIP_DEBUG)
                    682:        } else {
                    683:            sc->tulip_dbg.dbg_txprobes_ok[sc->tulip_probe_media]++;
                    684: #endif
                    685:        }
                    686:        tulip_linkup(sc, sc->tulip_probe_media);
                    687:        tulip_timeout(sc);
                    688:        return;
                    689:     }
                    690:
                    691:     if (sc->tulip_probe_state == TULIP_PROBE_GPRTEST) {
                    692:        /*
                    693:         * Brute force.  We cycle through each of the media types
                    694:         * and try to transmit a packet.
                    695:         */
                    696:        sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                    697:        sc->tulip_probe_media = TULIP_MEDIA_MAX;
                    698:        sc->tulip_probe_timeout = 0;
                    699:        tulip_timeout(sc);
                    700:        return;
                    701:     }
                    702:
                    703:     if (sc->tulip_probe_state != TULIP_PROBE_MEDIATEST
                    704:           && (sc->tulip_features & TULIP_HAVE_MII)) {
                    705:        tulip_media_t old_media = sc->tulip_probe_media;
                    706:        tulip_mii_autonegotiate(sc, sc->tulip_phyaddr);
                    707:        switch (sc->tulip_probe_state) {
                    708:            case TULIP_PROBE_FAILED:
                    709:            case TULIP_PROBE_MEDIATEST: {
                    710:                /*
                    711:                 * Try the next media.
                    712:                 */
                    713:                sc->tulip_probe_mediamask |= sc->tulip_mediums[sc->tulip_probe_media]->mi_mediamask;
                    714:                sc->tulip_probe_timeout = 0;
                    715:                break;
                    716:            }
                    717:            case TULIP_PROBE_PHYAUTONEG: {
                    718:                return;
                    719:            }
                    720:            case TULIP_PROBE_INACTIVE: {
                    721:                /*
                    722:                 * Only probe if we autonegotiated a media that hasn't failed.
                    723:                 */
                    724:                sc->tulip_probe_timeout = 0;
                    725:                if (sc->tulip_probe_mediamask & TULIP_BIT(sc->tulip_probe_media)) {
                    726:                    sc->tulip_probe_media = old_media;
                    727:                    break;
                    728:                }
                    729:                tulip_linkup(sc, sc->tulip_probe_media);
                    730:                tulip_timeout(sc);
                    731:                return;
                    732:            }
                    733:            default: {
                    734: #if defined(DIAGNOSTIC) || defined(TULIP_DEBUG)
                    735:                printf("tulip_media_poll: botch at line %d\n", __LINE__);
                    736: #endif
                    737:                break;
                    738:            }
                    739:        }
                    740:     }
                    741:
                    742:     if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED) {
                    743: #if defined(TULIP_DEBUG)
                    744:        sc->tulip_dbg.dbg_txprobes_failed[sc->tulip_probe_media]++;
                    745: #endif
                    746:        sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
                    747:        return;
                    748:     }
                    749:
                    750:     /*
                    751:      * Switch to another media if we tried this one enough.
                    752:      */
                    753:     if (/* event == TULIP_MEDIAPOLL_TXPROBE_FAILED || */ sc->tulip_probe_timeout <= 0) {
                    754: #if defined(TULIP_DEBUG)
                    755:        if (sc->tulip_probe_media == TULIP_MEDIA_UNKNOWN) {
                    756:            printf(TULIP_PRINTF_FMT ": poll media unknown!\n",
                    757:                   TULIP_PRINTF_ARGS);
                    758:            sc->tulip_probe_media = TULIP_MEDIA_MAX;
                    759:        }
                    760: #endif
                    761:        /*
                    762:         * Find the next media type to check for.  Full Duplex
                    763:         * types are not allowed.
                    764:         */
                    765:        do {
                    766:            sc->tulip_probe_media -= 1;
                    767:            if (sc->tulip_probe_media == TULIP_MEDIA_UNKNOWN) {
                    768:                if (++sc->tulip_probe_passes == 3) {
                    769:                    if ((sc->tulip_if.if_flags & IFF_UP) == 0) {
                    770:                        sc->tulip_if.if_flags &= ~IFF_RUNNING;
                    771:                        sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                    772:                        return;
                    773:                    }
                    774:                }
                    775:                sc->tulip_flags ^= TULIP_TRYNWAY;       /* XXX */
                    776:                sc->tulip_probe_mediamask = 0;
                    777:                sc->tulip_probe_media = TULIP_MEDIA_MAX - 1;
                    778:            }
                    779:        } while (sc->tulip_mediums[sc->tulip_probe_media] == NULL
                    780:                 || (sc->tulip_probe_mediamask & TULIP_BIT(sc->tulip_probe_media))
                    781:                 || TULIP_IS_MEDIA_FD(sc->tulip_probe_media));
                    782:
                    783: #if defined(TULIP_DEBUG)
                    784:        printf(TULIP_PRINTF_FMT ": %s: probing %s\n", TULIP_PRINTF_ARGS,
                    785:               event == TULIP_MEDIAPOLL_TXPROBE_FAILED ? "txprobe failed" : "timeout",
                    786:               tulip_mediums[sc->tulip_probe_media]);
                    787: #endif
                    788:        sc->tulip_probe_timeout = TULIP_IS_MEDIA_TP(sc->tulip_probe_media) ? 2500 : 1000;
                    789:        sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                    790:        sc->tulip_probe.probe_txprobes = 0;
                    791:        tulip_reset(sc);
                    792:        tulip_media_set(sc, sc->tulip_probe_media);
                    793:        sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
                    794:     }
                    795:     tulip_timeout(sc);
                    796:
                    797:     /*
                    798:      * If this is hanging off a phy, we know are doing NWAY and we have
                    799:      * forced the phy to a specific speed.  Wait for link up before
                    800:      * before sending a packet.
                    801:      */
                    802:     switch (sc->tulip_mediums[sc->tulip_probe_media]->mi_type) {
                    803:        case TULIP_MEDIAINFO_MII: {
                    804:            if (sc->tulip_probe_media != tulip_mii_phy_readspecific(sc))
                    805:                return;
                    806:            break;
                    807:        }
                    808:        case TULIP_MEDIAINFO_SIA: {
                    809:            if (TULIP_IS_MEDIA_TP(sc->tulip_probe_media)) {
                    810:                if (TULIP_CSR_READ(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL)
                    811:                    return;
                    812:                tulip_linkup(sc, sc->tulip_probe_media);
                    813:                return;
                    814:            }
                    815:            break;
                    816:        }
                    817:        case TULIP_MEDIAINFO_RESET:
                    818:        case TULIP_MEDIAINFO_SYM:
                    819:        case TULIP_MEDIAINFO_NONE:
                    820:        case TULIP_MEDIAINFO_GPR: {
                    821:            break;
                    822:        }
                    823:     }
                    824:     /*
                    825:      * Try to send a packet.
                    826:      */
                    827:     tulip_txprobe(sc);
                    828: }
                    829:
                    830: void
                    831: tulip_media_select(tulip_softc_t * const sc)
                    832: {
                    833:     if (sc->tulip_features & TULIP_HAVE_GPR) {
                    834:        TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit);
                    835:        DELAY(10);
                    836:        TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_gpdata);
                    837:     }
                    838:     /*
                    839:      * If this board has no media, just return
                    840:      */
                    841:     if (sc->tulip_features & TULIP_HAVE_NOMEDIA)
                    842:        return;
                    843:
                    844:     if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) {
                    845:        TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                    846:        (*sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_START);
                    847:     } else
                    848:        tulip_media_set(sc, sc->tulip_media);
                    849: }
                    850:
                    851: void
                    852: tulip_21040_mediainfo_init(tulip_softc_t * const sc, tulip_media_t media)
                    853: {
                    854:     sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_THRSHLD160
                    855:        |TULIP_CMD_BACKOFFCTR;
                    856:     sc->tulip_if.if_baudrate = 10000000;
                    857:
                    858:     if (media == TULIP_MEDIA_10BASET || media == TULIP_MEDIA_UNKNOWN) {
                    859:        TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[0], 21040, 10BASET);
                    860:        TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[1], 21040, 10BASET_FD);
                    861:        sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
                    862:     }
                    863:
                    864:     if (media == TULIP_MEDIA_AUIBNC || media == TULIP_MEDIA_UNKNOWN)
                    865:        TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[2], 21040, AUIBNC);
                    866:
                    867:     if (media == TULIP_MEDIA_UNKNOWN)
                    868:        TULIP_MEDIAINFO_SIA_INIT(sc, &sc->tulip_mediainfo[3], 21040, EXTSIA);
                    869: }
                    870:
                    871: void
                    872: tulip_21040_media_probe(tulip_softc_t * const sc)
                    873: {
                    874:     tulip_21040_mediainfo_init(sc, TULIP_MEDIA_UNKNOWN);
                    875: }
                    876:
                    877: void
                    878: tulip_21040_10baset_only_media_probe(tulip_softc_t * const sc)
                    879: {
                    880:     tulip_21040_mediainfo_init(sc, TULIP_MEDIA_10BASET);
                    881:     tulip_media_set(sc, TULIP_MEDIA_10BASET);
                    882:     sc->tulip_media = TULIP_MEDIA_10BASET;
                    883: }
                    884:
                    885: void
                    886: tulip_21040_10baset_only_media_select(tulip_softc_t * const sc)
                    887: {
                    888:     sc->tulip_flags |= TULIP_LINKUP;
                    889:     if (sc->tulip_media == TULIP_MEDIA_10BASET_FD) {
                    890:        sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX;
                    891:        sc->tulip_flags &= ~TULIP_SQETEST;
                    892:     } else {
                    893:        sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
                    894:        sc->tulip_flags |= TULIP_SQETEST;
                    895:     }
                    896:     tulip_media_set(sc, sc->tulip_media);
                    897: }
                    898:
                    899: void
                    900: tulip_21040_auibnc_only_media_probe(tulip_softc_t * const sc)
                    901: {
                    902:     tulip_21040_mediainfo_init(sc, TULIP_MEDIA_AUIBNC);
                    903:     sc->tulip_flags |= TULIP_SQETEST|TULIP_LINKUP;
                    904:     tulip_media_set(sc, TULIP_MEDIA_AUIBNC);
                    905:     sc->tulip_media = TULIP_MEDIA_AUIBNC;
                    906: }
                    907:
                    908: void
                    909: tulip_21040_auibnc_only_media_select(tulip_softc_t * const sc)
                    910: {
                    911:     tulip_media_set(sc, TULIP_MEDIA_AUIBNC);
                    912:     sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX;
                    913: }
                    914:
                    915: static const tulip_boardsw_t tulip_21040_boardsw = {
                    916:     TULIP_21040_GENERIC,
                    917:     tulip_21040_media_probe,
                    918:     tulip_media_select,
                    919:     tulip_media_poll,
                    920: };
                    921:
                    922: static const tulip_boardsw_t tulip_21040_10baset_only_boardsw = {
                    923:     TULIP_21040_GENERIC,
                    924:     tulip_21040_10baset_only_media_probe,
                    925:     tulip_21040_10baset_only_media_select,
                    926:     NULL,
                    927: };
                    928:
                    929: static const tulip_boardsw_t tulip_21040_auibnc_only_boardsw = {
                    930:     TULIP_21040_GENERIC,
                    931:     tulip_21040_auibnc_only_media_probe,
                    932:     tulip_21040_auibnc_only_media_select,
                    933:     NULL,
                    934: };
                    935:
                    936: void
                    937: tulip_21041_mediainfo_init(tulip_softc_t * const sc)
                    938: {
                    939:     tulip_media_info_t * const mi = sc->tulip_mediainfo;
                    940:
                    941:     TULIP_MEDIAINFO_SIA_INIT(sc, &mi[0], 21041, 10BASET);
                    942:     TULIP_MEDIAINFO_SIA_INIT(sc, &mi[1], 21041, 10BASET_FD);
                    943:     TULIP_MEDIAINFO_SIA_INIT(sc, &mi[2], 21041, AUI);
                    944:     TULIP_MEDIAINFO_SIA_INIT(sc, &mi[3], 21041, BNC);
                    945: }
                    946:
                    947: void
                    948: tulip_21041_media_noprobe(tulip_softc_t * const sc)
                    949: {
                    950:     sc->tulip_if.if_baudrate = 10000000;
                    951:     sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT
                    952:        |TULIP_CMD_THRSHLD160|TULIP_CMD_BACKOFFCTR;
                    953:     sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
                    954: }
                    955:
                    956: void
                    957: tulip_21041_media_probe(tulip_softc_t * const sc)
                    958: {
                    959:     sc->tulip_if.if_baudrate = 10000000;
                    960:     sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT
                    961:        |TULIP_CMD_THRSHLD160|TULIP_CMD_BACKOFFCTR;
                    962:     sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
                    963:     tulip_21041_mediainfo_init(sc);
                    964: }
                    965:
                    966: void
                    967: tulip_21041_media_poll(tulip_softc_t * const sc, const tulip_mediapoll_event_t event)
                    968: {
                    969:     u_int32_t sia_status;
                    970:
                    971: #if defined(TULIP_DEBUG)
                    972:     sc->tulip_dbg.dbg_events[event]++;
                    973: #endif
                    974:
                    975:     if (event == TULIP_MEDIAPOLL_LINKFAIL) {
                    976:        if (sc->tulip_probe_state != TULIP_PROBE_INACTIVE
                    977:                || !TULIP_DO_AUTOSENSE(sc))
                    978:            return;
                    979:        sc->tulip_media = TULIP_MEDIA_UNKNOWN;
                    980:        tulip_reset(sc);        /* start probe */
                    981:        return;
                    982:     }
                    983:
                    984:     /*
                    985:      * If we've been been asked to start a poll or link change interrupt
                    986:      * restart the probe (and reset the tulip to a known state).
                    987:      */
                    988:     if (event == TULIP_MEDIAPOLL_START) {
                    989:        sc->tulip_if.if_flags |= IFF_OACTIVE;
                    990:        sc->tulip_cmdmode &= ~(TULIP_CMD_FULLDUPLEX|TULIP_CMD_RXRUN);
                    991:        TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                    992:        sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                    993:        sc->tulip_probe_media = TULIP_MEDIA_10BASET;
                    994:        sc->tulip_probe_timeout = TULIP_21041_PROBE_10BASET_TIMEOUT;
                    995:        tulip_media_set(sc, TULIP_MEDIA_10BASET);
                    996:        tulip_timeout(sc);
                    997:        return;
                    998:     }
                    999:
                   1000:     if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE)
                   1001:        return;
                   1002:
                   1003:     if (event == TULIP_MEDIAPOLL_TXPROBE_OK) {
                   1004: #if defined(TULIP_DEBUG)
                   1005:        sc->tulip_dbg.dbg_txprobes_ok[sc->tulip_probe_media]++;
                   1006: #endif
                   1007:        tulip_linkup(sc, sc->tulip_probe_media);
                   1008:        return;
                   1009:     }
                   1010:
                   1011:     sia_status = TULIP_CSR_READ(sc, csr_sia_status);
                   1012:     TULIP_CSR_WRITE(sc, csr_sia_status, sia_status);
                   1013:     if ((sia_status & TULIP_SIASTS_LINKFAIL) == 0) {
                   1014:        if (sc->tulip_revinfo >= 0x20) {
                   1015:            if (sia_status & (PHYSTS_10BASET_FD << (16 - 6)))
                   1016:                sc->tulip_probe_media = TULIP_MEDIA_10BASET_FD;
                   1017:        }
                   1018:        /*
                   1019:         * If the link has passed LinkPass, 10baseT is the
                   1020:         * proper media to use.
                   1021:         */
                   1022:        tulip_linkup(sc, sc->tulip_probe_media);
                   1023:        return;
                   1024:     }
                   1025:
                   1026:     /*
                   1027:      * wait for up to 2.4 seconds for the link to reach pass state.
                   1028:      * Only then start scanning the other media for activity.
                   1029:      * choose media with receive activity over those without.
                   1030:      */
                   1031:     if (sc->tulip_probe_media == TULIP_MEDIA_10BASET) {
                   1032:        if (event != TULIP_MEDIAPOLL_TIMER)
                   1033:            return;
                   1034:        if (sc->tulip_probe_timeout > 0
                   1035:                && (sia_status & TULIP_SIASTS_OTHERRXACTIVITY) == 0) {
                   1036:            tulip_timeout(sc);
                   1037:            return;
                   1038:        }
                   1039:        sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
                   1040:        sc->tulip_flags |= TULIP_WANTRXACT;
                   1041:        if (sia_status & TULIP_SIASTS_OTHERRXACTIVITY)
                   1042:            sc->tulip_probe_media = TULIP_MEDIA_BNC;
                   1043:        else
                   1044:            sc->tulip_probe_media = TULIP_MEDIA_AUI;
                   1045:        tulip_media_set(sc, sc->tulip_probe_media);
                   1046:        tulip_timeout(sc);
                   1047:        return;
                   1048:     }
                   1049:
                   1050:     /*
                   1051:      * If we failed, clear the txprobe active flag.
                   1052:      */
                   1053:     if (event == TULIP_MEDIAPOLL_TXPROBE_FAILED)
                   1054:        sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
                   1055:
                   1056:
                   1057:     if (event == TULIP_MEDIAPOLL_TIMER) {
                   1058:        /*
                   1059:         * If we've received something, then that's our link!
                   1060:         */
                   1061:        if (sc->tulip_flags & TULIP_RXACT) {
                   1062:            tulip_linkup(sc, sc->tulip_probe_media);
                   1063:            return;
                   1064:        }
                   1065:        /*
                   1066:         * if no txprobe active
                   1067:         */
                   1068:        if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0
                   1069:                && ((sc->tulip_flags & TULIP_WANTRXACT) == 0
                   1070:                    || (sia_status & TULIP_SIASTS_RXACTIVITY))) {
                   1071:            sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
                   1072:            tulip_txprobe(sc);
                   1073:            tulip_timeout(sc);
                   1074:            return;
                   1075:        }
                   1076:        /*
                   1077:         * Take 2 passes through before deciding to not
                   1078:         * wait for receive activity.  Then take another
                   1079:         * two passes before spitting out a warning.
                   1080:         */
                   1081:        if (sc->tulip_probe_timeout <= 0) {
                   1082:            if (sc->tulip_flags & TULIP_WANTRXACT) {
                   1083:                sc->tulip_flags &= ~TULIP_WANTRXACT;
                   1084:                sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
                   1085:            } else {
                   1086:                if ((sc->tulip_if.if_flags & IFF_UP) == 0) {
                   1087:                    sc->tulip_if.if_flags &= ~IFF_RUNNING;
                   1088:                    sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                   1089:                    return;
                   1090:                }
                   1091:            }
                   1092:        }
                   1093:     }
                   1094:
                   1095:     /*
                   1096:      * Since this media failed to probe, try the other one.
                   1097:      */
                   1098:     sc->tulip_probe_timeout = TULIP_21041_PROBE_AUIBNC_TIMEOUT;
                   1099:     if (sc->tulip_probe_media == TULIP_MEDIA_AUI)
                   1100:        sc->tulip_probe_media = TULIP_MEDIA_BNC;
                   1101:     else
                   1102:        sc->tulip_probe_media = TULIP_MEDIA_AUI;
                   1103:     tulip_media_set(sc, sc->tulip_probe_media);
                   1104:     sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
                   1105:     tulip_timeout(sc);
                   1106: }
                   1107:
                   1108: static const tulip_boardsw_t tulip_21041_boardsw = {
                   1109:     TULIP_21041_GENERIC,
                   1110:     tulip_21041_media_probe,
                   1111:     tulip_media_select,
                   1112:     tulip_21041_media_poll
                   1113: };
                   1114:
                   1115: static const tulip_boardsw_t tulip_21041np_boardsw = {
                   1116:     TULIP_21041_GENERIC,
                   1117:     tulip_21041_media_noprobe,
                   1118:     tulip_media_select,
                   1119:     tulip_21041_media_poll
                   1120: };
                   1121:
                   1122: static const tulip_phy_attr_t tulip_mii_phy_attrlist[] = {
                   1123:     { 0x20005c00, 0,           /* 08-00-17 */
                   1124:       {
                   1125:        { 0x19, 0x0040, 0x0040 },       /* 10TX */
                   1126:        { 0x19, 0x0040, 0x0000 },       /* 100TX */
                   1127:       },
                   1128: #if defined(TULIP_DEBUG)
                   1129:       "NS DP83840",
                   1130: #endif
                   1131:     },
                   1132:     { 0x0281F400, 0,           /* 00-A0-7D */
                   1133:       {
                   1134:        { 0x12, 0x0010, 0x0000 },       /* 10T */
                   1135:        { 0 },                          /* 100TX */
                   1136:        { 0x12, 0x0010, 0x0010 },       /* 100T4 */
                   1137:        { 0x12, 0x0008, 0x0008 },       /* FULL_DUPLEX */
                   1138:       },
                   1139: #if defined(TULIP_DEBUG)
                   1140:       "Seeq 80C240"
                   1141: #endif
                   1142:     },
                   1143:     { 0x0281F400, 3,   /* 00-A0-7D */
                   1144:       {
                   1145:        { 0x12, 0x0080, 0x0000 },       /* 10T */
                   1146:        { 0x12, 0x0080, 0x0080 },       /* 100TX */
                   1147:        { 0 },                          /* 100T4 */
                   1148:        { 0x12, 0x0040, 0x0040 },       /* FULL_DUPLEX */
                   1149:       },
                   1150: #if defined(TULIP_DEBUG)
                   1151:       "Seeq 80225"
                   1152: #endif
                   1153:     },
                   1154:     { 0x0281F400, 0,           /* 00-A0-BE */
                   1155:       {
                   1156:        { 0x11, 0x8000, 0x0000 },       /* 10T */
                   1157:        { 0x11, 0x8000, 0x8000 },       /* 100TX */
                   1158:        { 0 },                          /* 100T4 */
                   1159:        { 0x11, 0x4000, 0x4000 },       /* FULL_DUPLEX */
                   1160:       },
                   1161: #if defined(TULIP_DEBUG)
                   1162:       "ICS 1890"
                   1163: #endif
                   1164:     },
                   1165:     { 0x78100000, 0,           /* 00-A0-CC */
                   1166:       {
                   1167:        { 0x14, 0x0800, 0x0000 },       /* 10TX */
                   1168:        { 0x14, 0x0800, 0x0800 },       /* 100TX */
                   1169:        { 0 },                          /* 100T4 */
                   1170:        { 0x14, 0x1000, 0x1000 },       /* FULL_DUPLEX */
                   1171:       },
                   1172: #if defined(TULIP_DEBUG)
                   1173:       "LEVEL1 LXT970"
                   1174: #endif
                   1175:     },
                   1176:     { 0 }
                   1177: };
                   1178:
                   1179: tulip_media_t
                   1180: tulip_mii_phy_readspecific(tulip_softc_t * const sc)
                   1181: {
                   1182:     const tulip_phy_attr_t *attr;
                   1183:     u_int16_t data;
                   1184:     u_int32_t id;
                   1185:     unsigned idx = 0;
                   1186:     static const tulip_media_t table[] = {
                   1187:        TULIP_MEDIA_UNKNOWN,
                   1188:        TULIP_MEDIA_10BASET,
                   1189:        TULIP_MEDIA_100BASETX,
                   1190:        TULIP_MEDIA_100BASET4,
                   1191:        TULIP_MEDIA_UNKNOWN,
                   1192:        TULIP_MEDIA_10BASET_FD,
                   1193:        TULIP_MEDIA_100BASETX_FD,
                   1194:        TULIP_MEDIA_UNKNOWN
                   1195:     };
                   1196:
                   1197:     /*
                   1198:      * Don't read phy specific registers if link is not up.
                   1199:      */
                   1200:     data = tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS)
                   1201:            | tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_STATUS);
                   1202:     if ((data & (PHYSTS_LINK_UP|PHYSTS_EXTENDED_REGS)) != (PHYSTS_LINK_UP|PHYSTS_EXTENDED_REGS))
                   1203:        return (TULIP_MEDIA_UNKNOWN);
                   1204:
                   1205:     id = (tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_IDLOW) << 16) |
                   1206:        tulip_mii_readreg(sc, sc->tulip_phyaddr, PHYREG_IDHIGH);
                   1207:     for (attr = tulip_mii_phy_attrlist;; attr++) {
                   1208:        if (attr->attr_id == 0)
                   1209:            return (TULIP_MEDIA_UNKNOWN);
                   1210:        if ((id & ~0x0F) == attr->attr_id)
                   1211:            break;
                   1212:     }
                   1213:
                   1214:     if (attr->attr_modes[PHY_MODE_100TX].pm_regno) {
                   1215:        const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_100TX];
                   1216:        data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
                   1217:        if ((data & pm->pm_mask) == pm->pm_value)
                   1218:            idx = 2;
                   1219:     }
                   1220:     if (idx == 0 && attr->attr_modes[PHY_MODE_100T4].pm_regno) {
                   1221:        const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_100T4];
                   1222:        data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
                   1223:        if ((data & pm->pm_mask) == pm->pm_value)
                   1224:            idx = 3;
                   1225:     }
                   1226:     if (idx == 0 && attr->attr_modes[PHY_MODE_10T].pm_regno) {
                   1227:        const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_10T];
                   1228:        data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
                   1229:        if ((data & pm->pm_mask) == pm->pm_value)
                   1230:            idx = 1;
                   1231:     }
                   1232:     if (idx != 0 && attr->attr_modes[PHY_MODE_FULLDUPLEX].pm_regno) {
                   1233:        const tulip_phy_modedata_t * const pm = &attr->attr_modes[PHY_MODE_FULLDUPLEX];
                   1234:        data = tulip_mii_readreg(sc, sc->tulip_phyaddr, pm->pm_regno);
                   1235:        idx += ((data & pm->pm_mask) == pm->pm_value ? 4 : 0);
                   1236:     }
                   1237:     return (table[idx]);
                   1238: }
                   1239:
                   1240: unsigned
                   1241: tulip_mii_get_phyaddr(tulip_softc_t * const sc, unsigned offset)
                   1242: {
                   1243:     unsigned phyaddr;
                   1244:
                   1245:     for (phyaddr = 1; phyaddr < 32; phyaddr++) {
                   1246:        unsigned status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
                   1247:        if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET)
                   1248:            continue;
                   1249:        if (offset == 0)
                   1250:            return (phyaddr);
                   1251:        offset--;
                   1252:     }
                   1253:     if (offset == 0) {
                   1254:        unsigned status = tulip_mii_readreg(sc, 0, PHYREG_STATUS);
                   1255:        if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET)
                   1256:            return (TULIP_MII_NOPHY);
                   1257:        return (0);
                   1258:     }
                   1259:     return (TULIP_MII_NOPHY);
                   1260: }
                   1261:
                   1262: int
                   1263: tulip_mii_map_abilities(tulip_softc_t * const sc, unsigned abilities)
                   1264: {
                   1265:     sc->tulip_abilities = abilities;
                   1266:     if (abilities & PHYSTS_100BASETX_FD)
                   1267:        sc->tulip_probe_media = TULIP_MEDIA_100BASETX_FD;
                   1268:     else if (abilities & PHYSTS_100BASET4)
                   1269:        sc->tulip_probe_media = TULIP_MEDIA_100BASET4;
                   1270:     else if (abilities & PHYSTS_100BASETX)
                   1271:        sc->tulip_probe_media = TULIP_MEDIA_100BASETX;
                   1272:     else if (abilities & PHYSTS_10BASET_FD)
                   1273:        sc->tulip_probe_media = TULIP_MEDIA_10BASET_FD;
                   1274:     else if (abilities & PHYSTS_10BASET)
                   1275:        sc->tulip_probe_media = TULIP_MEDIA_10BASET;
                   1276:     else {
                   1277:        sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                   1278:        return (0);
                   1279:     }
                   1280:     sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                   1281:     return (1);
                   1282: }
                   1283:
                   1284: void
                   1285: tulip_mii_autonegotiate(tulip_softc_t * const sc, const unsigned phyaddr)
                   1286: {
                   1287:     switch (sc->tulip_probe_state) {
                   1288:         case TULIP_PROBE_MEDIATEST:
                   1289:         case TULIP_PROBE_INACTIVE: {
                   1290:            sc->tulip_flags |= TULIP_DIDNWAY;
                   1291:            tulip_mii_writereg(sc, phyaddr, PHYREG_CONTROL, PHYCTL_RESET);
                   1292:            sc->tulip_probe_timeout = 3000;
                   1293:            sc->tulip_intrmask |= TULIP_STS_ABNRMLINTR|TULIP_STS_NORMALINTR;
                   1294:            sc->tulip_probe_state = TULIP_PROBE_PHYRESET;
                   1295:            /* FALLTHROUGH */
                   1296:        }
                   1297:         case TULIP_PROBE_PHYRESET: {
                   1298:            u_int32_t status;
                   1299:            u_int32_t data = tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL);
                   1300:            if (data & PHYCTL_RESET) {
                   1301:                if (sc->tulip_probe_timeout > 0) {
                   1302:                    tulip_timeout(sc);
                   1303:                    return;
                   1304:                }
                   1305: #ifdef TULIP_DEBUG
                   1306:                printf(TULIP_PRINTF_FMT "(phy%d): error: reset of PHY never completed!\n",
                   1307:                           TULIP_PRINTF_ARGS, phyaddr);
                   1308: #endif
                   1309:                sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE;
                   1310:                sc->tulip_probe_state = TULIP_PROBE_FAILED;
                   1311:                sc->tulip_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
                   1312:                return;
                   1313:            }
                   1314:            status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS)
                   1315:                    | tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
                   1316:            if ((status & PHYSTS_CAN_AUTONEG) == 0) {
                   1317: #if defined(TULIP_DEBUG)
                   1318:                printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation disabled\n",
                   1319:                           TULIP_PRINTF_ARGS, phyaddr);
                   1320: #endif
                   1321:                sc->tulip_flags &= ~TULIP_DIDNWAY;
                   1322:                sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                   1323:                return;
                   1324:            }
                   1325:            if (tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT) != ((status >> 6) | 0x01))
                   1326:                tulip_mii_writereg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT, (status >> 6) | 0x01);
                   1327:            tulip_mii_writereg(sc, phyaddr, PHYREG_CONTROL, data|PHYCTL_AUTONEG_RESTART|PHYCTL_AUTONEG_ENABLE);
                   1328:            data = tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL);
                   1329: #if defined(TULIP_DEBUG)
                   1330:            if ((data & PHYCTL_AUTONEG_ENABLE) == 0)
                   1331:                printf(TULIP_PRINTF_FMT "(phy%d): oops: enable autonegotiation failed: 0x%04x\n",
                   1332:                           TULIP_PRINTF_ARGS, phyaddr, data);
                   1333:            else
                   1334:                printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation restarted: 0x%04x (ad=0x%04x)\n",
                   1335:                           TULIP_PRINTF_ARGS, phyaddr, data,
                   1336:                           tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ADVERTISEMENT));
                   1337:            sc->tulip_dbg.dbg_nway_starts++;
                   1338: #endif
                   1339:            sc->tulip_probe_state = TULIP_PROBE_PHYAUTONEG;
                   1340:            sc->tulip_probe_timeout = 3000;
                   1341:            /* FALLTHROUGH */
                   1342:        }
                   1343:         case TULIP_PROBE_PHYAUTONEG: {
                   1344:            u_int32_t status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS)
                   1345:                            | tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS);
                   1346:            u_int32_t data;
                   1347:            if ((status & PHYSTS_AUTONEG_DONE) == 0) {
                   1348:                if (sc->tulip_probe_timeout > 0) {
                   1349:                    tulip_timeout(sc);
                   1350:                    return;
                   1351:                }
                   1352: #if defined(TULIP_DEBUG)
                   1353:                printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation timeout: sts=0x%04x, ctl=0x%04x\n",
                   1354:                           TULIP_PRINTF_ARGS, phyaddr, status,
                   1355:                           tulip_mii_readreg(sc, phyaddr, PHYREG_CONTROL));
                   1356: #endif
                   1357:                sc->tulip_flags &= ~TULIP_DIDNWAY;
                   1358:                sc->tulip_probe_state = TULIP_PROBE_MEDIATEST;
                   1359:                return;
                   1360:            }
                   1361:            data = tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ABILITIES)
                   1362:                | tulip_mii_readreg(sc, phyaddr, PHYREG_AUTONEG_ABILITIES);
                   1363: #if defined(TULIP_DEBUG)
                   1364:            printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation complete: 0x%04x (sts=0x%04x)\n",
                   1365:                       TULIP_PRINTF_ARGS, phyaddr, data, status);
                   1366: #endif
                   1367:            data = (data << 6) & status;
                   1368:            if (!tulip_mii_map_abilities(sc, data))
                   1369:                sc->tulip_flags &= ~TULIP_DIDNWAY;
                   1370:            return;
                   1371:        }
                   1372:        default: {
                   1373: #if defined(DIAGNOSTIC)
                   1374:            printf("tulip_media_poll: botch at line %d\n", __LINE__);
                   1375: #endif
                   1376:            break;
                   1377:        }
                   1378:     }
                   1379: #if defined(TULIP_DEBUG)
                   1380:     printf(TULIP_PRINTF_FMT "(phy%d): autonegotiation failure: state = %d\n",
                   1381:               TULIP_PRINTF_ARGS, phyaddr, sc->tulip_probe_state);
                   1382:            sc->tulip_dbg.dbg_nway_failures++;
                   1383: #endif
                   1384: }
                   1385:
                   1386: void
                   1387: tulip_2114x_media_preset(tulip_softc_t * const sc)
                   1388: {
                   1389:     const tulip_media_info_t *mi = NULL;
                   1390:     tulip_media_t media = sc->tulip_media;
                   1391:
                   1392:     if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE)
                   1393:        media = sc->tulip_media;
                   1394:     else
                   1395:        media = sc->tulip_probe_media;
                   1396:
                   1397:     sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT|TULIP_CMD_NOHEARTBEAT
                   1398:                |TULIP_CMD_FULLDUPLEX|TULIP_CMD_TXTHRSHLDCTL);
                   1399:     sc->tulip_flags &= ~(TULIP_SQETEST|TULIP_FULLDUPLEX);
                   1400:     if (media != TULIP_MEDIA_UNKNOWN && media != TULIP_MEDIA_MAX) {
                   1401: #if defined(TULIP_DEBUG)
                   1402:        if (media < TULIP_MEDIA_MAX && sc->tulip_mediums[media] != NULL) {
                   1403: #endif
                   1404:            mi = sc->tulip_mediums[media];
                   1405:            if (mi->mi_type == TULIP_MEDIAINFO_MII)
                   1406:                sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT;
                   1407:            else if (mi->mi_type == TULIP_MEDIAINFO_GPR
                   1408:                       || mi->mi_type == TULIP_MEDIAINFO_SYM) {
                   1409:                sc->tulip_cmdmode &= ~TULIP_GPR_CMDBITS;
                   1410:                sc->tulip_cmdmode |= mi->mi_cmdmode;
                   1411:            } else if (mi->mi_type == TULIP_MEDIAINFO_SIA)
                   1412:                TULIP_CSR_WRITE(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
                   1413: #if defined(TULIP_DEBUG)
                   1414:        } else {
                   1415:            printf(TULIP_PRINTF_FMT ": preset: bad media %d!\n",
                   1416:                   TULIP_PRINTF_ARGS, media);
                   1417:        }
                   1418: #endif
                   1419:     }
                   1420:     switch (media) {
                   1421:        case TULIP_MEDIA_BNC:
                   1422:        case TULIP_MEDIA_AUI:
                   1423:        case TULIP_MEDIA_10BASET: {
                   1424:            sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL;
                   1425:            sc->tulip_if.if_baudrate = 10000000;
                   1426:            sc->tulip_flags |= TULIP_SQETEST;
                   1427:            break;
                   1428:        }
                   1429:        case TULIP_MEDIA_10BASET_FD: {
                   1430:            sc->tulip_flags |= TULIP_FULLDUPLEX;
                   1431:            sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX;
                   1432:            sc->tulip_if.if_baudrate = 10000000;
                   1433:            break;
                   1434:        }
                   1435:        case TULIP_MEDIA_100BASEFX:
                   1436:        case TULIP_MEDIA_100BASET4:
                   1437:        case TULIP_MEDIA_100BASETX: {
                   1438:            sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT;
                   1439:            sc->tulip_if.if_baudrate = 100000000;
                   1440:            if (mi->mi_type == TULIP_MEDIAINFO_SYM
                   1441:                    || mi->mi_type == TULIP_MEDIAINFO_MII) {
                   1442:                sc->tulip_cmdmode |= TULIP_CMD_NOHEARTBEAT;
                   1443:            }
                   1444:            break;
                   1445:        }
                   1446:        case TULIP_MEDIA_100BASEFX_FD:
                   1447:        case TULIP_MEDIA_100BASETX_FD: {
                   1448:            sc->tulip_flags |= TULIP_FULLDUPLEX;
                   1449:            sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT|TULIP_CMD_FULLDUPLEX;
                   1450:            sc->tulip_if.if_baudrate = 100000000;
                   1451:            if (mi->mi_type == TULIP_MEDIAINFO_SYM
                   1452:                    || mi->mi_type == TULIP_MEDIAINFO_MII) {
                   1453:                sc->tulip_cmdmode |= TULIP_CMD_NOHEARTBEAT;
                   1454:            }
                   1455:            break;
                   1456:        }
                   1457:        default: {
                   1458:            break;
                   1459:        }
                   1460:     }
                   1461:     TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                   1462: }
                   1463:
                   1464: /*
                   1465:  ********************************************************************
                   1466:  *  Start of 21140/21140A support which does not use the MII interface
                   1467:  */
                   1468:
                   1469: void
                   1470: tulip_null_media_poll(tulip_softc_t * const sc, tulip_mediapoll_event_t event)
                   1471: {
                   1472: #if defined(TULIP_DEBUG)
                   1473:     sc->tulip_dbg.dbg_events[event]++;
                   1474: #endif
                   1475: #if defined(DIAGNOSTIC)
                   1476:     printf(TULIP_PRINTF_FMT ": botch(media_poll) at line %d\n",
                   1477:           TULIP_PRINTF_ARGS, __LINE__);
                   1478: #endif
                   1479: }
                   1480:
                   1481: void
                   1482: tulip_21140_mediainit(tulip_softc_t * const sc, tulip_media_info_t * const mip,
                   1483:     tulip_media_t const media, unsigned gpdata, unsigned cmdmode)
                   1484: {
                   1485:     sc->tulip_mediums[media] = mip;
                   1486:     mip->mi_type = TULIP_MEDIAINFO_GPR;
                   1487:     mip->mi_cmdmode = cmdmode;
                   1488:     mip->mi_gpdata = gpdata;
                   1489: }
                   1490:
                   1491: void
                   1492: tulip_21140_evalboard_media_probe(tulip_softc_t * const sc)
                   1493: {
                   1494:     tulip_media_info_t *mip = sc->tulip_mediainfo;
                   1495:
                   1496:     sc->tulip_gpinit = TULIP_GP_EB_PINS;
                   1497:     sc->tulip_gpdata = TULIP_GP_EB_INIT;
                   1498:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS);
                   1499:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_INIT);
                   1500:     TULIP_CSR_WRITE(sc, csr_command,
                   1501:        TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
                   1502:        TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
                   1503:     TULIP_CSR_WRITE(sc, csr_command,
                   1504:        TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
                   1505:     DELAY(1000000);
                   1506:     if ((TULIP_CSR_READ(sc, csr_gp) & TULIP_GP_EB_OK100) != 0)
                   1507:        sc->tulip_media = TULIP_MEDIA_10BASET;
                   1508:     else
                   1509:        sc->tulip_media = TULIP_MEDIA_100BASETX;
                   1510:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
                   1511:                          TULIP_GP_EB_INIT,
                   1512:                          TULIP_CMD_TXTHRSHLDCTL);
                   1513:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
                   1514:                          TULIP_GP_EB_INIT,
                   1515:                          TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
                   1516:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
                   1517:                          TULIP_GP_EB_INIT,
                   1518:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1519:                              |TULIP_CMD_SCRAMBLER);
                   1520:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
                   1521:                          TULIP_GP_EB_INIT,
                   1522:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1523:                              |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
                   1524: }
                   1525:
                   1526: static const tulip_boardsw_t tulip_21140_eb_boardsw = {
                   1527:     TULIP_21140_DEC_EB,
                   1528:     tulip_21140_evalboard_media_probe,
                   1529:     tulip_media_select,
                   1530:     tulip_null_media_poll,
                   1531:     tulip_2114x_media_preset,
                   1532: };
                   1533:
                   1534: void
                   1535: tulip_21140_accton_media_probe(tulip_softc_t * const sc)
                   1536: {
                   1537:     tulip_media_info_t *mip = sc->tulip_mediainfo;
                   1538:     unsigned gpdata;
                   1539:
                   1540:     sc->tulip_gpinit = TULIP_GP_EB_PINS;
                   1541:     sc->tulip_gpdata = TULIP_GP_EB_INIT;
                   1542:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS);
                   1543:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_INIT);
                   1544:     TULIP_CSR_WRITE(sc, csr_command,
                   1545:        TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
                   1546:        TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
                   1547:     TULIP_CSR_WRITE(sc, csr_command,
                   1548:        TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
                   1549:     DELAY(1000000);
                   1550:     gpdata = TULIP_CSR_READ(sc, csr_gp);
                   1551:     if ((gpdata & TULIP_GP_EN1207_UTP_INIT) == 0)
                   1552:        sc->tulip_media = TULIP_MEDIA_10BASET;
                   1553:     else {
                   1554:        if ((gpdata & TULIP_GP_EN1207_BNC_INIT) == 0)
                   1555:                sc->tulip_media = TULIP_MEDIA_BNC;
                   1556:         else
                   1557:                sc->tulip_media = TULIP_MEDIA_100BASETX;
                   1558:     }
                   1559:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_BNC,
                   1560:                          TULIP_GP_EN1207_BNC_INIT,
                   1561:                          TULIP_CMD_TXTHRSHLDCTL);
                   1562:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
                   1563:                          TULIP_GP_EN1207_UTP_INIT,
                   1564:                          TULIP_CMD_TXTHRSHLDCTL);
                   1565:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
                   1566:                          TULIP_GP_EN1207_UTP_INIT,
                   1567:                          TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
                   1568:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
                   1569:                          TULIP_GP_EN1207_100_INIT,
                   1570:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1571:                              |TULIP_CMD_SCRAMBLER);
                   1572:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
                   1573:                          TULIP_GP_EN1207_100_INIT,
                   1574:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1575:                              |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
                   1576: }
                   1577:
                   1578: static const tulip_boardsw_t tulip_21140_accton_boardsw = {
                   1579:     TULIP_21140_EN1207,
                   1580:     tulip_21140_accton_media_probe,
                   1581:     tulip_media_select,
                   1582:     tulip_null_media_poll,
                   1583:     tulip_2114x_media_preset,
                   1584: };
                   1585:
                   1586: void
                   1587: tulip_21140_smc9332_media_probe(tulip_softc_t * const sc)
                   1588: {
                   1589:     tulip_media_info_t *mip = sc->tulip_mediainfo;
                   1590:     int idx, cnt = 0;
                   1591:
                   1592:     TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT|TULIP_CMD_MUSTBEONE);
                   1593:     TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
                   1594:     DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
                   1595:                   33MHz that comes to two microseconds but wait a
                   1596:                   bit longer anyways) */
                   1597:     TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT |
                   1598:        TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
                   1599:     sc->tulip_gpinit = TULIP_GP_SMC_9332_PINS;
                   1600:     sc->tulip_gpdata = TULIP_GP_SMC_9332_INIT;
                   1601:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_SMC_9332_PINS|TULIP_GP_PINSET);
                   1602:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_SMC_9332_INIT);
                   1603:     DELAY(200000);
                   1604:     for (idx = 1000; idx > 0; idx--) {
                   1605:        u_int32_t csr = TULIP_CSR_READ(sc, csr_gp);
                   1606:        if ((csr & (TULIP_GP_SMC_9332_OK10|TULIP_GP_SMC_9332_OK100)) == (TULIP_GP_SMC_9332_OK10|TULIP_GP_SMC_9332_OK100)) {
                   1607:            if (++cnt > 100)
                   1608:                break;
                   1609:        } else if ((csr & TULIP_GP_SMC_9332_OK10) == 0)
                   1610:            break;
                   1611:        else
                   1612:            cnt = 0;
                   1613:        DELAY(1000);
                   1614:     }
                   1615:     sc->tulip_media = cnt > 100 ? TULIP_MEDIA_100BASETX : TULIP_MEDIA_10BASET;
                   1616:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
                   1617:                          TULIP_GP_SMC_9332_INIT,
                   1618:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1619:                              |TULIP_CMD_SCRAMBLER);
                   1620:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
                   1621:                          TULIP_GP_SMC_9332_INIT,
                   1622:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1623:                              |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
                   1624:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
                   1625:                          TULIP_GP_SMC_9332_INIT,
                   1626:                          TULIP_CMD_TXTHRSHLDCTL);
                   1627:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
                   1628:                          TULIP_GP_SMC_9332_INIT,
                   1629:                          TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
                   1630: }
                   1631:
                   1632: static const tulip_boardsw_t tulip_21140_smc9332_boardsw = {
                   1633:     TULIP_21140_SMC_9332,
                   1634:     tulip_21140_smc9332_media_probe,
                   1635:     tulip_media_select,
                   1636:     tulip_null_media_poll,
                   1637:     tulip_2114x_media_preset,
                   1638: };
                   1639:
                   1640: void
                   1641: tulip_21140_cogent_em100_media_probe(tulip_softc_t * const sc)
                   1642: {
                   1643:     tulip_media_info_t *mip = sc->tulip_mediainfo;
                   1644:     u_int32_t cmdmode = TULIP_CSR_READ(sc, csr_command);
                   1645:
                   1646:     sc->tulip_gpinit = TULIP_GP_EM100_PINS;
                   1647:     sc->tulip_gpdata = TULIP_GP_EM100_INIT;
                   1648:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_PINS);
                   1649:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_INIT);
                   1650:
                   1651:     cmdmode = TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION|TULIP_CMD_MUSTBEONE;
                   1652:     cmdmode &= ~(TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_SCRAMBLER);
                   1653:     if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
                   1654:        TULIP_CSR_WRITE(sc, csr_command, cmdmode);
                   1655:        sc->tulip_media = TULIP_MEDIA_100BASEFX;
                   1656:
                   1657:        tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASEFX,
                   1658:                          TULIP_GP_EM100_INIT,
                   1659:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION);
                   1660:        tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASEFX_FD,
                   1661:                          TULIP_GP_EM100_INIT,
                   1662:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1663:                              |TULIP_CMD_FULLDUPLEX);
                   1664:     } else {
                   1665:        TULIP_CSR_WRITE(sc, csr_command, cmdmode|TULIP_CMD_SCRAMBLER);
                   1666:        sc->tulip_media = TULIP_MEDIA_100BASETX;
                   1667:        tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
                   1668:                          TULIP_GP_EM100_INIT,
                   1669:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1670:                              |TULIP_CMD_SCRAMBLER);
                   1671:        tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
                   1672:                          TULIP_GP_EM100_INIT,
                   1673:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1674:                              |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
                   1675:     }
                   1676: }
                   1677:
                   1678: static const tulip_boardsw_t tulip_21140_cogent_em100_boardsw = {
                   1679:     TULIP_21140_COGENT_EM100,
                   1680:     tulip_21140_cogent_em100_media_probe,
                   1681:     tulip_media_select,
                   1682:     tulip_null_media_poll,
                   1683:     tulip_2114x_media_preset
                   1684: };
                   1685:
                   1686: void
                   1687: tulip_21140_znyx_zx34x_media_probe(tulip_softc_t * const sc)
                   1688: {
                   1689:     tulip_media_info_t *mip = sc->tulip_mediainfo;
                   1690:     int cnt10 = 0, cnt100 = 0, idx;
                   1691:
                   1692:     sc->tulip_gpinit = TULIP_GP_ZX34X_PINS;
                   1693:     sc->tulip_gpdata = TULIP_GP_ZX34X_INIT;
                   1694:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_PINS);
                   1695:     TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_INIT);
                   1696:     TULIP_CSR_WRITE(sc, csr_command,
                   1697:        TULIP_CSR_READ(sc, csr_command) | TULIP_CMD_PORTSELECT |
                   1698:        TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE);
                   1699:     TULIP_CSR_WRITE(sc, csr_command,
                   1700:        TULIP_CSR_READ(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL);
                   1701:
                   1702:     DELAY(200000);
                   1703:     for (idx = 1000; idx > 0; idx--) {
                   1704:        u_int32_t csr = TULIP_CSR_READ(sc, csr_gp);
                   1705:        if ((csr & (TULIP_GP_ZX34X_LNKFAIL|TULIP_GP_ZX34X_SYMDET|TULIP_GP_ZX34X_SIGDET)) == (TULIP_GP_ZX34X_LNKFAIL|TULIP_GP_ZX34X_SYMDET|TULIP_GP_ZX34X_SIGDET)) {
                   1706:            if (++cnt100 > 100)
                   1707:                break;
                   1708:        } else if ((csr & TULIP_GP_ZX34X_LNKFAIL) == 0) {
                   1709:            if (++cnt10 > 100)
                   1710:                break;
                   1711:        } else {
                   1712:            cnt10 = 0;
                   1713:            cnt100 = 0;
                   1714:        }
                   1715:        DELAY(1000);
                   1716:     }
                   1717:     sc->tulip_media = cnt100 > 100 ? TULIP_MEDIA_100BASETX : TULIP_MEDIA_10BASET;
                   1718:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET,
                   1719:                          TULIP_GP_ZX34X_INIT,
                   1720:                          TULIP_CMD_TXTHRSHLDCTL);
                   1721:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_10BASET_FD,
                   1722:                          TULIP_GP_ZX34X_INIT,
                   1723:                          TULIP_CMD_TXTHRSHLDCTL|TULIP_CMD_FULLDUPLEX);
                   1724:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX,
                   1725:                          TULIP_GP_ZX34X_INIT,
                   1726:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1727:                              |TULIP_CMD_SCRAMBLER);
                   1728:     tulip_21140_mediainit(sc, mip++, TULIP_MEDIA_100BASETX_FD,
                   1729:                          TULIP_GP_ZX34X_INIT,
                   1730:                          TULIP_CMD_PORTSELECT|TULIP_CMD_PCSFUNCTION
                   1731:                              |TULIP_CMD_SCRAMBLER|TULIP_CMD_FULLDUPLEX);
                   1732: }
                   1733:
                   1734: static const tulip_boardsw_t tulip_21140_znyx_zx34x_boardsw = {
                   1735:     TULIP_21140_ZNYX_ZX34X,
                   1736:     tulip_21140_znyx_zx34x_media_probe,
                   1737:     tulip_media_select,
                   1738:     tulip_null_media_poll,
                   1739:     tulip_2114x_media_preset,
                   1740: };
                   1741:
                   1742: void
                   1743: tulip_2114x_media_probe(tulip_softc_t * const sc)
                   1744: {
                   1745:     sc->tulip_cmdmode |= TULIP_CMD_MUSTBEONE
                   1746:        |TULIP_CMD_BACKOFFCTR|TULIP_CMD_THRSHLD72;
                   1747: }
                   1748:
                   1749: static const tulip_boardsw_t tulip_2114x_isv_boardsw = {
                   1750:     TULIP_21140_ISV,
                   1751:     tulip_2114x_media_probe,
                   1752:     tulip_media_select,
                   1753:     tulip_media_poll,
                   1754:     tulip_2114x_media_preset,
                   1755: };
                   1756:
                   1757: /*
                   1758:  * ******** END of chip-specific handlers. ***********
                   1759:  */
                   1760:
                   1761: /*
                   1762:  * Code the read the SROM and MII bit streams (I2C)
                   1763:  */
                   1764: void
                   1765: tulip_delay_300ns(tulip_softc_t * const sc)
                   1766: {
                   1767:     int idx;
                   1768:     for (idx = (300 / 33) + 1; idx > 0; idx--)
                   1769:        (void) TULIP_CSR_READ(sc, csr_busmode);
                   1770: }
                   1771:
                   1772: void
                   1773: tulip_srom_idle(tulip_softc_t * const sc)
                   1774: {
                   1775:     unsigned bit, csr;
                   1776:
                   1777:     csr  = SROMSEL ; EMIT;
                   1778:     csr  = SROMSEL | SROMRD; EMIT;
                   1779:     csr ^= SROMCS; EMIT;
                   1780:     csr ^= SROMCLKON; EMIT;
                   1781:
                   1782:     /*
                   1783:      * Write 25 cycles of 0 which will force the SROM to be idle.
                   1784:      */
                   1785:     for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
                   1786:         csr ^= SROMCLKOFF; EMIT;    /* clock low; data not valid */
                   1787:         csr ^= SROMCLKON; EMIT;     /* clock high; data valid */
                   1788:     }
                   1789:     csr ^= SROMCLKOFF; EMIT;
                   1790:     csr ^= SROMCS; EMIT;
                   1791:     csr  = 0; EMIT;
                   1792: }
                   1793:
                   1794: void
                   1795: tulip_srom_read(tulip_softc_t * const sc)
                   1796: {
                   1797:     unsigned idx;
                   1798:     const unsigned bitwidth = SROM_BITWIDTH;
                   1799:     const unsigned cmdmask = (SROMCMD_RD << bitwidth);
                   1800:     const unsigned msb = 1 << (bitwidth + 3 - 1);
                   1801:     unsigned lastidx = (1 << bitwidth) - 1;
                   1802:
                   1803:     tulip_srom_idle(sc);
                   1804:
                   1805:     for (idx = 0; idx <= lastidx; idx++) {
                   1806:         unsigned lastbit, data, bits, bit, csr;
                   1807:        csr  = SROMSEL ;                EMIT;
                   1808:         csr  = SROMSEL | SROMRD;        EMIT;
                   1809:         csr ^= SROMCSON;                EMIT;
                   1810:         csr ^=            SROMCLKON;    EMIT;
                   1811:
                   1812:         lastbit = 0;
                   1813:         for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1) {
                   1814:             const unsigned thisbit = bits & msb;
                   1815:             csr ^= SROMCLKOFF; EMIT;    /* clock low; data not valid */
                   1816:             if (thisbit != lastbit) {
                   1817:                 csr ^= SROMDOUT; EMIT;  /* clock low; invert data */
                   1818:             } else {
                   1819:                EMIT;
                   1820:             }
                   1821:             csr ^= SROMCLKON; EMIT;     /* clock high; data valid */
                   1822:             lastbit = thisbit;
                   1823:         }
                   1824:         csr ^= SROMCLKOFF; EMIT;
                   1825:
                   1826:         for (data = 0, bits = 0; bits < 16; bits++) {
                   1827:             data <<= 1;
                   1828:             csr ^= SROMCLKON; EMIT;     /* clock high; data valid */
                   1829:             data |= TULIP_CSR_READ(sc, csr_srom_mii) & SROMDIN ? 1 : 0;
                   1830:             csr ^= SROMCLKOFF; EMIT;    /* clock low; data not valid */
                   1831:         }
                   1832:        sc->tulip_rombuf[idx*2] = data & 0xFF;
                   1833:        sc->tulip_rombuf[idx*2+1] = data >> 8;
                   1834:        csr  = SROMSEL | SROMRD; EMIT;
                   1835:        csr  = 0; EMIT;
                   1836:     }
                   1837:     tulip_srom_idle(sc);
                   1838: }
                   1839:
                   1840: void
                   1841: tulip_mii_writebits(tulip_softc_t * const sc, unsigned data, unsigned bits)
                   1842: {
                   1843:     unsigned msb = 1 << (bits - 1);
                   1844:     unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                   1845:     unsigned lastbit = (csr & MII_DOUT) ? msb : 0;
                   1846:
                   1847:     csr |= MII_WR; MII_EMIT;           /* clock low; assert write */
                   1848:
                   1849:     for (; bits > 0; bits--, data <<= 1) {
                   1850:        const unsigned thisbit = data & msb;
                   1851:        if (thisbit != lastbit)
                   1852:            csr ^= MII_DOUT; MII_EMIT;  /* clock low; invert data */
                   1853:        csr ^= MII_CLKON; MII_EMIT;     /* clock high; data valid */
                   1854:        lastbit = thisbit;
                   1855:        csr ^= MII_CLKOFF; MII_EMIT;    /* clock low; data not valid */
                   1856:     }
                   1857: }
                   1858:
                   1859: void
                   1860: tulip_mii_turnaround(tulip_softc_t * const sc, unsigned cmd)
                   1861: {
                   1862:     unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                   1863:
                   1864:     if (cmd == MII_WRCMD) {
                   1865:        csr |= MII_DOUT; MII_EMIT;      /* clock low; change data */
                   1866:        csr ^= MII_CLKON; MII_EMIT;     /* clock high; data valid */
                   1867:        csr ^= MII_CLKOFF; MII_EMIT;    /* clock low; data not valid */
                   1868:        csr ^= MII_DOUT; MII_EMIT;      /* clock low; change data */
                   1869:     } else
                   1870:        csr |= MII_RD; MII_EMIT;        /* clock low; switch to read */
                   1871:     csr ^= MII_CLKON; MII_EMIT;                /* clock high; data valid */
                   1872:     csr ^= MII_CLKOFF; MII_EMIT;       /* clock low; data not valid */
                   1873: }
                   1874:
                   1875: unsigned
                   1876: tulip_mii_readbits(tulip_softc_t * const sc)
                   1877: {
                   1878:     unsigned data;
                   1879:     unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                   1880:     int idx;
                   1881:
                   1882:     for (idx = 0, data = 0; idx < 16; idx++) {
                   1883:        data <<= 1;     /* this is NOOP on the first pass through */
                   1884:        csr ^= MII_CLKON; MII_EMIT;     /* clock high; data valid */
                   1885:        if (TULIP_CSR_READ(sc, csr_srom_mii) & MII_DIN)
                   1886:            data |= 1;
                   1887:        csr ^= MII_CLKOFF; MII_EMIT;    /* clock low; data not valid */
                   1888:     }
                   1889:     csr ^= MII_RD; MII_EMIT;           /* clock low; turn off read */
                   1890:
                   1891:     return (data);
                   1892: }
                   1893:
                   1894: unsigned
                   1895: tulip_mii_readreg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno)
                   1896: {
                   1897:     unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                   1898:     unsigned data;
                   1899:
                   1900:     csr &= ~(MII_RD|MII_CLK); MII_EMIT;
                   1901:     tulip_mii_writebits(sc, MII_PREAMBLE, 32);
                   1902:     tulip_mii_writebits(sc, MII_RDCMD, 8);
                   1903:     tulip_mii_writebits(sc, devaddr, 5);
                   1904:     tulip_mii_writebits(sc, regno, 5);
                   1905:     tulip_mii_turnaround(sc, MII_RDCMD);
                   1906:
                   1907:     data = tulip_mii_readbits(sc);
                   1908: #if defined(TULIP_DEBUG)
                   1909:     sc->tulip_dbg.dbg_phyregs[regno][0] = data;
                   1910:     sc->tulip_dbg.dbg_phyregs[regno][1]++;
                   1911: #endif
                   1912:     return (data);
                   1913: }
                   1914:
                   1915: void
                   1916: tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr,
                   1917:     unsigned regno, unsigned data)
                   1918: {
                   1919:     unsigned csr;
                   1920:
                   1921:     csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                   1922:     csr &= ~(MII_RD|MII_CLK); MII_EMIT;
                   1923:     tulip_mii_writebits(sc, MII_PREAMBLE, 32);
                   1924:     tulip_mii_writebits(sc, MII_WRCMD, 8);
                   1925:     tulip_mii_writebits(sc, devaddr, 5);
                   1926:     tulip_mii_writebits(sc, regno, 5);
                   1927:     tulip_mii_turnaround(sc, MII_WRCMD);
                   1928:     tulip_mii_writebits(sc, data, 16);
                   1929: #if defined(TULIP_DEBUG)
                   1930:     sc->tulip_dbg.dbg_phyregs[regno][2] = data;
                   1931:     sc->tulip_dbg.dbg_phyregs[regno][3]++;
                   1932: #endif
                   1933: }
                   1934:
                   1935: void
                   1936: tulip_identify_dec_nic(tulip_softc_t * const sc)
                   1937: {
                   1938:     strlcpy(sc->tulip_boardid, "DEC ", sizeof(sc->tulip_boardid));
                   1939: #define D0     4
                   1940:     if (sc->tulip_chipid <= TULIP_DE425)
                   1941:        return;
                   1942:     if (bcmp(sc->tulip_rombuf + 29, "DE500", 5) == 0
                   1943:        || bcmp(sc->tulip_rombuf + 29, "DE450", 5) == 0) {
                   1944:        bcopy(sc->tulip_rombuf + 29, &sc->tulip_boardid[D0], 8);
                   1945:        sc->tulip_boardid[D0+8] = ' ';
                   1946:     }
                   1947: #undef D0
                   1948: }
                   1949:
                   1950: void
                   1951: tulip_identify_znyx_nic(tulip_softc_t * const sc)
                   1952: {
                   1953:     unsigned id = 0;
                   1954:     strlcpy(sc->tulip_boardid, "ZNYX ZX3XX ", sizeof(sc->tulip_boardid));
                   1955:     if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
                   1956:        unsigned znyx_ptr;
                   1957:        sc->tulip_boardid[8] = '4';
                   1958:        znyx_ptr = sc->tulip_rombuf[124] + 256 * sc->tulip_rombuf[125];
                   1959:        if (znyx_ptr < 26 || znyx_ptr > 116) {
                   1960:            sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
                   1961:            return;
                   1962:        }
                   1963:        /* ZX344 = 0010 .. 0013FF
                   1964:         */
                   1965:        if (sc->tulip_rombuf[znyx_ptr] == 0x4A
                   1966:                && sc->tulip_rombuf[znyx_ptr + 1] == 0x52
                   1967:                && sc->tulip_rombuf[znyx_ptr + 2] == 0x01) {
                   1968:            id = sc->tulip_rombuf[znyx_ptr + 5] + 256 * sc->tulip_rombuf[znyx_ptr + 4];
                   1969:            if ((id >> 8) == (TULIP_ZNYX_ID_ZX342 >> 8)) {
                   1970:                sc->tulip_boardid[9] = '2';
                   1971:                if (id == TULIP_ZNYX_ID_ZX342B) {
                   1972:                    sc->tulip_boardid[10] = 'B';
                   1973:                    sc->tulip_boardid[11] = ' ';
                   1974:                }
                   1975:                sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
                   1976:            } else if (id == TULIP_ZNYX_ID_ZX344) {
                   1977:                sc->tulip_boardid[10] = '4';
                   1978:                sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
                   1979:            } else if (id == TULIP_ZNYX_ID_ZX345) {
                   1980:                sc->tulip_boardid[9] = (sc->tulip_rombuf[19] > 1) ? '8' : '5';
                   1981:            } else if (id == TULIP_ZNYX_ID_ZX346) {
                   1982:                sc->tulip_boardid[9] = '6';
                   1983:            } else if (id == TULIP_ZNYX_ID_ZX351) {
                   1984:                sc->tulip_boardid[8] = '5';
                   1985:                sc->tulip_boardid[9] = '1';
                   1986:            }
                   1987:        }
                   1988:        if (id == 0) {
                   1989:            /*
                   1990:             * Assume it's a ZX342...
                   1991:             */
                   1992:            sc->tulip_boardsw = &tulip_21140_znyx_zx34x_boardsw;
                   1993:        }
                   1994:        return;
                   1995:     }
                   1996:     sc->tulip_boardid[8] = '1';
                   1997:     if (sc->tulip_chipid == TULIP_21041) {
                   1998:        sc->tulip_boardid[10] = '1';
                   1999:        return;
                   2000:     }
                   2001:     if (sc->tulip_rombuf[32] == 0x4A && sc->tulip_rombuf[33] == 0x52) {
                   2002:        id = sc->tulip_rombuf[37] + 256 * sc->tulip_rombuf[36];
                   2003:        if (id == TULIP_ZNYX_ID_ZX312T) {
                   2004:            sc->tulip_boardid[9] = '2';
                   2005:            sc->tulip_boardid[10] = 'T';
                   2006:            sc->tulip_boardid[11] = ' ';
                   2007:            sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
                   2008:        } else if (id == TULIP_ZNYX_ID_ZX314_INTA) {
                   2009:            sc->tulip_boardid[9] = '4';
                   2010:            sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
                   2011:            sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
                   2012:        } else if (id == TULIP_ZNYX_ID_ZX314) {
                   2013:            sc->tulip_boardid[9] = '4';
                   2014:            sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
                   2015:            sc->tulip_features |= TULIP_HAVE_BASEROM;
                   2016:        } else if (id == TULIP_ZNYX_ID_ZX315_INTA) {
                   2017:            sc->tulip_boardid[9] = '5';
                   2018:            sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
                   2019:        } else if (id == TULIP_ZNYX_ID_ZX315) {
                   2020:            sc->tulip_boardid[9] = '5';
                   2021:            sc->tulip_features |= TULIP_HAVE_BASEROM;
                   2022:        } else
                   2023:            id = 0;
                   2024:     }
                   2025:     if (id == 0) {
                   2026:        if ((sc->tulip_enaddr[3] & ~3) == 0xF0 && (sc->tulip_enaddr[5] & 3) == 0) {
                   2027:            sc->tulip_boardid[9] = '4';
                   2028:            sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
                   2029:            sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
                   2030:        } else if ((sc->tulip_enaddr[3] & ~3) == 0xF4 && (sc->tulip_enaddr[5] & 1) == 0) {
                   2031:            sc->tulip_boardid[9] = '5';
                   2032:            sc->tulip_boardsw = &tulip_21040_boardsw;
                   2033:            sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
                   2034:        } else if ((sc->tulip_enaddr[3] & ~3) == 0xEC) {
                   2035:            sc->tulip_boardid[9] = '2';
                   2036:            sc->tulip_boardsw = &tulip_21040_boardsw;
                   2037:        }
                   2038:     }
                   2039: }
                   2040:
                   2041: void
                   2042: tulip_identify_smc_nic(tulip_softc_t * const sc)
                   2043: {
                   2044:     u_int32_t id1, id2, ei;
                   2045:     int auibnc = 0, utp = 0;
                   2046:     char *cp;
                   2047:
                   2048:     strlcpy(sc->tulip_boardid, "SMC ", sizeof(sc->tulip_boardid));
                   2049:     if (sc->tulip_chipid == TULIP_21041)
                   2050:        return;
                   2051:     if (sc->tulip_chipid != TULIP_21040) {
                   2052:        if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw) {
                   2053:            strlcat(sc->tulip_boardid, "9332DST ", sizeof(sc->tulip_boardid));
                   2054:            sc->tulip_boardsw = &tulip_21140_smc9332_boardsw;
                   2055:        } else if (sc->tulip_features & (TULIP_HAVE_BASEROM|TULIP_HAVE_SLAVEDROM))
                   2056:            strlcat(sc->tulip_boardid, "9334BDT ", sizeof(sc->tulip_boardid));
                   2057:        else
                   2058:            strlcat(sc->tulip_boardid, "9332BDT ", sizeof(sc->tulip_boardid));
                   2059:        return;
                   2060:     }
                   2061:     id1 = sc->tulip_rombuf[0x60] | (sc->tulip_rombuf[0x61] << 8);
                   2062:     id2 = sc->tulip_rombuf[0x62] | (sc->tulip_rombuf[0x63] << 8);
                   2063:     ei  = sc->tulip_rombuf[0x66] | (sc->tulip_rombuf[0x67] << 8);
                   2064:
                   2065:     strlcat(sc->tulip_boardid, "8432", sizeof(sc->tulip_boardid));
                   2066:     cp = &sc->tulip_boardid[8];
                   2067:     if ((id1 & 1) == 0)
                   2068:        *cp++ = 'B', auibnc = 1;
                   2069:     if ((id1 & 0xFF) > 0x32)
                   2070:        *cp++ = 'T', utp = 1;
                   2071:     if ((id1 & 0x4000) == 0)
                   2072:        *cp++ = 'A', auibnc = 1;
                   2073:     if (id2 == 0x15) {
                   2074:        sc->tulip_boardid[7] = '4';
                   2075:        *cp++ = '-';
                   2076:        *cp++ = 'C';
                   2077:        *cp++ = 'H';
                   2078:        *cp++ = (ei ? '2' : '1');
                   2079:     }
                   2080:     *cp++ = ' ';
                   2081:     *cp = '\0';
                   2082:     if (utp && !auibnc)
                   2083:        sc->tulip_boardsw = &tulip_21040_10baset_only_boardsw;
                   2084:     else if (!utp && auibnc)
                   2085:        sc->tulip_boardsw = &tulip_21040_auibnc_only_boardsw;
                   2086: }
                   2087:
                   2088: void
                   2089: tulip_identify_cogent_nic(tulip_softc_t * const sc)
                   2090: {
                   2091:     strlcpy(sc->tulip_boardid, "Cogent ", sizeof(sc->tulip_boardid));
                   2092:     if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
                   2093:        if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100TX_ID) {
                   2094:            strlcat(sc->tulip_boardid, "EM100TX ", sizeof(sc->tulip_boardid));
                   2095:            sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
                   2096: #if defined(TULIP_COGENT_EM110TX_ID)
                   2097:        } else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM110TX_ID) {
                   2098:            strlcat(sc->tulip_boardid, "EM110TX ", sizeof(sc->tulip_boardid));
                   2099:            sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
                   2100: #endif
                   2101:        } else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
                   2102:            strlcat(sc->tulip_boardid, "EM100FX ", sizeof(sc->tulip_boardid));
                   2103:            sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
                   2104:        }
                   2105:        /*
                   2106:         * Magic number (0x24001109U) is the SubVendor (0x2400) and
                   2107:         * SubDevId (0x1109) for the ANA6944TX (EM440TX).
                   2108:         */
                   2109:        if (*(u_int32_t *) sc->tulip_rombuf == 0x24001109U
                   2110:                && (sc->tulip_features & TULIP_HAVE_BASEROM)) {
                   2111:            /*
                   2112:             * Cogent (Adaptec) is still mapping all INTs to INTA of
                   2113:             * first 21140.  Dumb!  Dumb!
                   2114:             */
                   2115:            strlcat(sc->tulip_boardid, "EM440TX ", sizeof(sc->tulip_boardid));
                   2116:            sc->tulip_features |= TULIP_HAVE_SHAREDINTR;
                   2117:        }
                   2118:     } else if (sc->tulip_chipid == TULIP_21040)
                   2119:        sc->tulip_features |= TULIP_HAVE_SHAREDINTR|TULIP_HAVE_BASEROM;
                   2120: }
                   2121:
                   2122: void
                   2123: tulip_identify_accton_nic(tulip_softc_t * const sc)
                   2124: {
                   2125:     strlcpy(sc->tulip_boardid, "ACCTON ", sizeof(sc->tulip_boardid));
                   2126:     switch (sc->tulip_chipid) {
                   2127:        case TULIP_21140A:
                   2128:            strlcat(sc->tulip_boardid, "EN1207 ", sizeof(sc->tulip_boardid));
                   2129:            if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw)
                   2130:                sc->tulip_boardsw = &tulip_21140_accton_boardsw;
                   2131:            break;
                   2132:        case TULIP_21140:
                   2133:            strlcat(sc->tulip_boardid, "EN1207TX ", sizeof(sc->tulip_boardid));
                   2134:            if (sc->tulip_boardsw != &tulip_2114x_isv_boardsw)
                   2135:                sc->tulip_boardsw = &tulip_21140_eb_boardsw;
                   2136:             break;
                   2137:         case TULIP_21040:
                   2138:            strlcat(sc->tulip_boardid, "EN1203 ", sizeof(sc->tulip_boardid));
                   2139:             sc->tulip_boardsw = &tulip_21040_boardsw;
                   2140:             break;
                   2141:         case TULIP_21041:
                   2142:            strlcat(sc->tulip_boardid, "EN1203 ", sizeof(sc->tulip_boardid));
                   2143:             sc->tulip_boardsw = &tulip_21041_boardsw;
                   2144:             break;
                   2145:        default:
                   2146:             sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
                   2147:             break;
                   2148:     }
                   2149: }
                   2150:
                   2151: void
                   2152: tulip_identify_asante_nic(tulip_softc_t * const sc)
                   2153: {
                   2154:     strlcpy(sc->tulip_boardid, "Asante ", sizeof(sc->tulip_boardid));
                   2155:     if ((sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A)
                   2156:            && sc->tulip_boardsw != &tulip_2114x_isv_boardsw) {
                   2157:        tulip_media_info_t *mi = sc->tulip_mediainfo;
                   2158:        int idx;
                   2159:        /*
                   2160:         * The Asante Fast Ethernet doesn't always ship with a valid
                   2161:         * new format SROM.  So if isn't in the new format, we cheat
                   2162:         * set it up as if we had.
                   2163:         */
                   2164:
                   2165:        sc->tulip_gpinit = TULIP_GP_ASANTE_PINS;
                   2166:        sc->tulip_gpdata = 0;
                   2167:
                   2168:        TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ASANTE_PINS|TULIP_GP_PINSET);
                   2169:        TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ASANTE_PHYRESET);
                   2170:        DELAY(100);
                   2171:        TULIP_CSR_WRITE(sc, csr_gp, 0);
                   2172:
                   2173:        mi->mi_type = TULIP_MEDIAINFO_MII;
                   2174:        mi->mi_gpr_length = 0;
                   2175:        mi->mi_gpr_offset = 0;
                   2176:        mi->mi_reset_length = 0;
                   2177:        mi->mi_reset_offset = 0;
                   2178:
                   2179:        mi->mi_phyaddr = TULIP_MII_NOPHY;
                   2180:        for (idx = 20; idx > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx--) {
                   2181:            DELAY(10000);
                   2182:            mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, 0);
                   2183:        }
                   2184:        if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
                   2185: #ifdef TULIP_DEBUG
                   2186:            printf(TULIP_PRINTF_FMT ": can't find phy 0\n", TULIP_PRINTF_ARGS);
                   2187: #endif
                   2188:            return;
                   2189:        }
                   2190:
                   2191:        sc->tulip_features |= TULIP_HAVE_MII;
                   2192:        mi->mi_capabilities  = PHYSTS_10BASET|PHYSTS_10BASET_FD|PHYSTS_100BASETX|PHYSTS_100BASETX_FD;
                   2193:        mi->mi_advertisement = PHYSTS_10BASET|PHYSTS_10BASET_FD|PHYSTS_100BASETX|PHYSTS_100BASETX_FD;
                   2194:        mi->mi_full_duplex   = PHYSTS_10BASET_FD|PHYSTS_100BASETX_FD;
                   2195:        mi->mi_tx_threshold  = PHYSTS_10BASET|PHYSTS_10BASET_FD;
                   2196:        TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
                   2197:        TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
                   2198:        TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
                   2199:        TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
                   2200:        TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
                   2201:        mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
                   2202:            tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
                   2203:
                   2204:        sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
                   2205:     }
                   2206: }
                   2207:
                   2208: void
                   2209: tulip_identify_compex_nic(tulip_softc_t * const sc)
                   2210: {
                   2211:     strlcpy(sc->tulip_boardid, "COMPEX ", sizeof(sc->tulip_boardid));
                   2212:     if (sc->tulip_chipid == TULIP_21140A) {
                   2213:        int root_unit;
                   2214:        tulip_softc_t *root_sc = NULL;
                   2215:
                   2216:        strlcat(sc->tulip_boardid, "400TX/PCI ", sizeof(sc->tulip_boardid));
                   2217:        /*
                   2218:         * All 4 chips on these boards share an interrupt.  This code
                   2219:         * copied from tulip_read_macaddr.
                   2220:         */
                   2221:        sc->tulip_features |= TULIP_HAVE_SHAREDINTR;
                   2222:        for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) {
                   2223:            root_sc = TULIP_UNIT_TO_SOFTC(root_unit);
                   2224:            if (root_sc == NULL
                   2225:                || !(root_sc->tulip_features & TULIP_HAVE_SLAVEDINTR))
                   2226:                break;
                   2227:            root_sc = NULL;
                   2228:        }
                   2229:        if (root_sc != NULL
                   2230:            && root_sc->tulip_chipid == sc->tulip_chipid
                   2231:            && root_sc->tulip_pci_busno == sc->tulip_pci_busno) {
                   2232:            sc->tulip_features |= TULIP_HAVE_SLAVEDINTR;
                   2233:            sc->tulip_slaves = root_sc->tulip_slaves;
                   2234:            root_sc->tulip_slaves = sc;
                   2235:        } else if(sc->tulip_features & TULIP_HAVE_SLAVEDINTR)
                   2236:            printf("\nCannot find master device for de%d interrupts", sc->tulip_unit);
                   2237:     } else
                   2238:        strlcat(sc->tulip_boardid, "unknown ", sizeof(sc->tulip_boardid));
                   2239:
                   2240:     /*      sc->tulip_boardsw = &tulip_21140_eb_boardsw; */
                   2241: }
                   2242:
                   2243: int
                   2244: tulip_srom_decode(tulip_softc_t * const sc)
                   2245: {
                   2246:     unsigned idx1, idx2, idx3;
                   2247:
                   2248:     const tulip_srom_header_t *shp = (tulip_srom_header_t *) &sc->tulip_rombuf[0];
                   2249:     const tulip_srom_adapter_info_t *saip = (tulip_srom_adapter_info_t *) (shp + 1);
                   2250:     tulip_srom_media_t srom_media;
                   2251:     tulip_media_info_t *mi = sc->tulip_mediainfo;
                   2252:     const u_int8_t *dp;
                   2253:     u_int32_t leaf_offset, blocks, data;
                   2254:
                   2255:     for (idx1 = 0; idx1 < shp->sh_adapter_count; idx1++, saip++) {
                   2256:        if (shp->sh_adapter_count == 1)
                   2257:            break;
                   2258:        if (saip->sai_device == sc->tulip_pci_devno)
                   2259:            break;
                   2260:     }
                   2261:     /*
                   2262:      * Didn't find the right media block for this card.
                   2263:      */
                   2264:     if (idx1 == shp->sh_adapter_count)
                   2265:        return (0);
                   2266:
                   2267:     /*
                   2268:      * Save the hardware address.
                   2269:      */
                   2270:     bcopy((caddr_t) shp->sh_ieee802_address, (caddr_t) sc->tulip_enaddr,
                   2271:        ETHER_ADDR_LEN);
                   2272:     /*
                   2273:      * If this is a multiple port card, add the adapter index to the last
                   2274:      * byte of the hardware address.  (if it isn't multiport, adding 0
                   2275:      * won't hurt.
                   2276:      */
                   2277:     sc->tulip_enaddr[5] += idx1;
                   2278:
                   2279:     leaf_offset = saip->sai_leaf_offset_lowbyte
                   2280:        + saip->sai_leaf_offset_highbyte * 256;
                   2281:     dp = sc->tulip_rombuf + leaf_offset;
                   2282:
                   2283:     sc->tulip_conntype = (tulip_srom_connection_t) (dp[0] + dp[1] * 256); dp += 2;
                   2284:
                   2285:     for (idx2 = 0;; idx2++) {
                   2286:        if (tulip_srom_conninfo[idx2].sc_type == sc->tulip_conntype
                   2287:                || tulip_srom_conninfo[idx2].sc_type == TULIP_SROM_CONNTYPE_NOT_USED)
                   2288:            break;
                   2289:     }
                   2290:     sc->tulip_connidx = idx2;
                   2291:
                   2292:     if (sc->tulip_chipid == TULIP_21041) {
                   2293:        blocks = *dp++;
                   2294:        for (idx2 = 0; idx2 < blocks; idx2++) {
                   2295:            tulip_media_t media;
                   2296:            data = *dp++;
                   2297:            srom_media = (tulip_srom_media_t) (data & 0x3F);
                   2298:            for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
                   2299:                if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
                   2300:                    break;
                   2301:            }
                   2302:            media = tulip_srom_mediums[idx3].sm_type;
                   2303:            if (media != TULIP_MEDIA_UNKNOWN) {
                   2304:                if (data & TULIP_SROM_21041_EXTENDED) {
                   2305:                    mi->mi_type = TULIP_MEDIAINFO_SIA;
                   2306:                    sc->tulip_mediums[media] = mi;
                   2307:                    mi->mi_sia_connectivity = dp[0] + dp[1] * 256;
                   2308:                    mi->mi_sia_tx_rx        = dp[2] + dp[3] * 256;
                   2309:                    mi->mi_sia_general      = dp[4] + dp[5] * 256;
                   2310:                    mi++;
                   2311:                } else {
                   2312:                    switch (media) {
                   2313:                        case TULIP_MEDIA_BNC: {
                   2314:                            TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, BNC);
                   2315:                            mi++;
                   2316:                            break;
                   2317:                        }
                   2318:                        case TULIP_MEDIA_AUI: {
                   2319:                            TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, AUI);
                   2320:                            mi++;
                   2321:                            break;
                   2322:                        }
                   2323:                        case TULIP_MEDIA_10BASET: {
                   2324:                            TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET);
                   2325:                            mi++;
                   2326:                            break;
                   2327:                        }
                   2328:                        case TULIP_MEDIA_10BASET_FD: {
                   2329:                            TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21041, 10BASET_FD);
                   2330:                            mi++;
                   2331:                            break;
                   2332:                        }
                   2333:                        default: {
                   2334:                            break;
                   2335:                        }
                   2336:                    }
                   2337:                }
                   2338:            }
                   2339:            if (data & TULIP_SROM_21041_EXTENDED)
                   2340:                dp += 6;
                   2341:        }
                   2342:     } else {
                   2343:        unsigned length, type;
                   2344:        tulip_media_t gp_media = TULIP_MEDIA_UNKNOWN;
                   2345:        if (sc->tulip_features & TULIP_HAVE_GPR)
                   2346:            sc->tulip_gpinit = *dp++;
                   2347:        blocks = *dp++;
                   2348:        for (idx2 = 0; idx2 < blocks; idx2++) {
                   2349:            const u_int8_t *ep;
                   2350:            if ((*dp & 0x80) == 0) {
                   2351:                length = 4;
                   2352:                type = 0;
                   2353:            } else {
                   2354:                length = (*dp++ & 0x7f) - 1;
                   2355:                type = *dp++ & 0x3f;
                   2356:            }
                   2357:            ep = dp + length;
                   2358:            switch (type & 0x3f) {
                   2359:                case 0: {       /* 21140[A] GPR block */
                   2360:                    tulip_media_t media;
                   2361:                    srom_media = (tulip_srom_media_t)(dp[0] & 0x3f);
                   2362:                    for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
                   2363:                        if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
                   2364:                            break;
                   2365:                    }
                   2366:                    media = tulip_srom_mediums[idx3].sm_type;
                   2367:                    if (media == TULIP_MEDIA_UNKNOWN)
                   2368:                        break;
                   2369:                    mi->mi_type = TULIP_MEDIAINFO_GPR;
                   2370:                    sc->tulip_mediums[media] = mi;
                   2371:                    mi->mi_gpdata = dp[1];
                   2372:                    if (media > gp_media && !TULIP_IS_MEDIA_FD(media)) {
                   2373:                        sc->tulip_gpdata = mi->mi_gpdata;
                   2374:                        gp_media = media;
                   2375:                    }
                   2376:                    data = dp[2] + dp[3] * 256;
                   2377:                    mi->mi_cmdmode = TULIP_SROM_2114X_CMDBITS(data);
                   2378:                    if (data & TULIP_SROM_2114X_NOINDICATOR)
                   2379:                        mi->mi_actmask = 0;
                   2380:                    else {
                   2381:                        mi->mi_actmask = TULIP_SROM_2114X_BITPOS(data);
                   2382:                        mi->mi_actdata = (data & TULIP_SROM_2114X_POLARITY) ? 0 : mi->mi_actmask;
                   2383:                    }
                   2384:                    mi++;
                   2385:                    break;
                   2386:                }
                   2387:                case 1: {       /* 21140[A] MII block */
                   2388:                    const unsigned phyno = *dp++;
                   2389:                    mi->mi_type = TULIP_MEDIAINFO_MII;
                   2390:                    mi->mi_gpr_length = *dp++;
                   2391:                    mi->mi_gpr_offset = dp - sc->tulip_rombuf;
                   2392:                    dp += mi->mi_gpr_length;
                   2393:                    mi->mi_reset_length = *dp++;
                   2394:                    mi->mi_reset_offset = dp - sc->tulip_rombuf;
                   2395:                    dp += mi->mi_reset_length;
                   2396:
                   2397:                    /*
                   2398:                     * Before we probe for a PHY, use the GPR information
                   2399:                     * to select it.  If we don't, it may be inaccessible.
                   2400:                     */
                   2401:                    TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_gpinit|TULIP_GP_PINSET);
                   2402:                    for (idx3 = 0; idx3 < mi->mi_reset_length; idx3++) {
                   2403:                        DELAY(10);
                   2404:                        TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_reset_offset + idx3]);
                   2405:                    }
                   2406:                    sc->tulip_phyaddr = mi->mi_phyaddr;
                   2407:                    for (idx3 = 0; idx3 < mi->mi_gpr_length; idx3++) {
                   2408:                        DELAY(10);
                   2409:                        TULIP_CSR_WRITE(sc, csr_gp, sc->tulip_rombuf[mi->mi_gpr_offset + idx3]);
                   2410:                    }
                   2411:
                   2412:                    /*
                   2413:                     * At least write something!
                   2414:                     */
                   2415:                    if (mi->mi_reset_length == 0 && mi->mi_gpr_length == 0)
                   2416:                        TULIP_CSR_WRITE(sc, csr_gp, 0);
                   2417:
                   2418:                    mi->mi_phyaddr = TULIP_MII_NOPHY;
                   2419:                    for (idx3 = 20; idx3 > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx3--) {
                   2420:                        DELAY(10000);
                   2421:                        mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, phyno);
                   2422:                    }
                   2423:                    if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
                   2424: #if defined(TULIP_DEBUG)
                   2425:                        printf(TULIP_PRINTF_FMT ": can't find phy %d\n",
                   2426:                               TULIP_PRINTF_ARGS, phyno);
                   2427: #endif
                   2428:                        break;
                   2429:                    }
                   2430:                    sc->tulip_features |= TULIP_HAVE_MII;
                   2431:                    mi->mi_capabilities  = dp[0] + dp[1] * 256; dp += 2;
                   2432:                    mi->mi_advertisement = dp[0] + dp[1] * 256; dp += 2;
                   2433:                    mi->mi_full_duplex   = dp[0] + dp[1] * 256; dp += 2;
                   2434:                    mi->mi_tx_threshold  = dp[0] + dp[1] * 256; dp += 2;
                   2435:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
                   2436:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
                   2437:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
                   2438:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
                   2439:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
                   2440:                    mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
                   2441:                        tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
                   2442:                    mi++;
                   2443:                    break;
                   2444:                }
                   2445:                case 2: {       /* 2114[23] SIA block */
                   2446:                    tulip_media_t media;
                   2447:                    srom_media = (tulip_srom_media_t)(dp[0] & 0x3f);
                   2448:                    for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
                   2449:                        if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
                   2450:                            break;
                   2451:                    }
                   2452:                    media = tulip_srom_mediums[idx3].sm_type;
                   2453:                    if (media == TULIP_MEDIA_UNKNOWN)
                   2454:                        break;
                   2455:                    mi->mi_type = TULIP_MEDIAINFO_SIA;
                   2456:                    sc->tulip_mediums[media] = mi;
                   2457:                    if (dp[0] & 0x40) {
                   2458:                        mi->mi_sia_connectivity = dp[1] + dp[2] * 256;
                   2459:                        mi->mi_sia_tx_rx        = dp[3] + dp[4] * 256;
                   2460:                        mi->mi_sia_general      = dp[5] + dp[6] * 256;
                   2461:                        dp += 6;
                   2462:                    } else {
                   2463:                        switch (media) {
                   2464:                            case TULIP_MEDIA_BNC: {
                   2465:                                TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, BNC);
                   2466:                                break;
                   2467:                            }
                   2468:                            case TULIP_MEDIA_AUI: {
                   2469:                                TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, AUI);
                   2470:                                break;
                   2471:                            }
                   2472:                            case TULIP_MEDIA_10BASET: {
                   2473:                                TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, 10BASET);
                   2474:                                sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
                   2475:                                break;
                   2476:                            }
                   2477:                            case TULIP_MEDIA_10BASET_FD: {
                   2478:                                TULIP_MEDIAINFO_SIA_INIT(sc, mi, 21142, 10BASET_FD);
                   2479:                                sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
                   2480:                                break;
                   2481:                            }
                   2482:                            default: {
                   2483:                                goto bad_media;
                   2484:                            }
                   2485:                        }
                   2486:                    }
                   2487:                    mi->mi_sia_gp_control = (dp[1] + dp[2] * 256) << 16;
                   2488:                    mi->mi_sia_gp_data    = (dp[3] + dp[4] * 256) << 16;
                   2489:                    mi++;
                   2490:                  bad_media:
                   2491:                    break;
                   2492:                }
                   2493:                case 3: {       /* 2114[23] MII PHY block */
                   2494:                    const unsigned phyno = *dp++;
                   2495:                    const u_int8_t *dp0;
                   2496:                    mi->mi_type = TULIP_MEDIAINFO_MII;
                   2497:                    mi->mi_gpr_length = *dp++;
                   2498:                    mi->mi_gpr_offset = dp - sc->tulip_rombuf;
                   2499:                    dp += 2 * mi->mi_gpr_length;
                   2500:                    mi->mi_reset_length = *dp++;
                   2501:                    mi->mi_reset_offset = dp - sc->tulip_rombuf;
                   2502:                    dp += 2 * mi->mi_reset_length;
                   2503:
                   2504:                    dp0 = &sc->tulip_rombuf[mi->mi_reset_offset];
                   2505:                    for (idx3 = 0; idx3 < mi->mi_reset_length; idx3++, dp0 += 2) {
                   2506:                        DELAY(10);
                   2507:                        TULIP_CSR_WRITE(sc, csr_sia_general, (dp0[0] + 256 * dp0[1]) << 16);
                   2508:                    }
                   2509:                    sc->tulip_phyaddr = mi->mi_phyaddr;
                   2510:                    dp0 = &sc->tulip_rombuf[mi->mi_gpr_offset];
                   2511:                    for (idx3 = 0; idx3 < mi->mi_gpr_length; idx3++, dp0 += 2) {
                   2512:                        DELAY(10);
                   2513:                        TULIP_CSR_WRITE(sc, csr_sia_general, (dp0[0] + 256 * dp0[1]) << 16);
                   2514:                    }
                   2515:
                   2516:                    if (mi->mi_reset_length == 0 && mi->mi_gpr_length == 0)
                   2517:                        TULIP_CSR_WRITE(sc, csr_sia_general, 0);
                   2518:
                   2519:                    mi->mi_phyaddr = TULIP_MII_NOPHY;
                   2520:                    for (idx3 = 20; idx3 > 0 && mi->mi_phyaddr == TULIP_MII_NOPHY; idx3--) {
                   2521:                        DELAY(10000);
                   2522:                        mi->mi_phyaddr = tulip_mii_get_phyaddr(sc, phyno);
                   2523:                    }
                   2524:                    if (mi->mi_phyaddr == TULIP_MII_NOPHY) {
                   2525: #if defined(TULIP_DEBUG)
                   2526:                        printf(TULIP_PRINTF_FMT ": can't find phy %d\n",
                   2527:                               TULIP_PRINTF_ARGS, phyno);
                   2528: #endif
                   2529:                        break;
                   2530:                    }
                   2531:                    sc->tulip_features |= TULIP_HAVE_MII;
                   2532:                    mi->mi_capabilities  = dp[0] + dp[1] * 256; dp += 2;
                   2533:                    mi->mi_advertisement = dp[0] + dp[1] * 256; dp += 2;
                   2534:                    mi->mi_full_duplex   = dp[0] + dp[1] * 256; dp += 2;
                   2535:                    mi->mi_tx_threshold  = dp[0] + dp[1] * 256; dp += 2;
                   2536:                    mi->mi_mii_interrupt = dp[0] + dp[1] * 256; dp += 2;
                   2537:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX_FD);
                   2538:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASETX);
                   2539:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 100BASET4);
                   2540:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET_FD);
                   2541:                    TULIP_MEDIAINFO_ADD_CAPABILITY(sc, mi, 10BASET);
                   2542:                    mi->mi_phyid = (tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDLOW) << 16) |
                   2543:                        tulip_mii_readreg(sc, mi->mi_phyaddr, PHYREG_IDHIGH);
                   2544:                    mi++;
                   2545:                    break;
                   2546:                }
                   2547:                case 4: {       /* 21143 SYM block */
                   2548:                    tulip_media_t media;
                   2549:                    srom_media = (tulip_srom_media_t) dp[0];
                   2550:                    for (idx3 = 0; tulip_srom_mediums[idx3].sm_type != TULIP_MEDIA_UNKNOWN; idx3++) {
                   2551:                        if (tulip_srom_mediums[idx3].sm_srom_type == srom_media)
                   2552:                            break;
                   2553:                    }
                   2554:                    media = tulip_srom_mediums[idx3].sm_type;
                   2555:                    if (media == TULIP_MEDIA_UNKNOWN)
                   2556:                        break;
                   2557:                    mi->mi_type = TULIP_MEDIAINFO_SYM;
                   2558:                    sc->tulip_mediums[media] = mi;
                   2559:                    mi->mi_gpcontrol = (dp[1] + dp[2] * 256) << 16;
                   2560:                    mi->mi_gpdata    = (dp[3] + dp[4] * 256) << 16;
                   2561:                    data = dp[5] + dp[6] * 256;
                   2562:                    mi->mi_cmdmode = TULIP_SROM_2114X_CMDBITS(data);
                   2563:                    if (data & TULIP_SROM_2114X_NOINDICATOR)
                   2564:                        mi->mi_actmask = 0;
                   2565:                    else {
                   2566:                        mi->mi_default = (data & TULIP_SROM_2114X_DEFAULT) != 0;
                   2567:                        mi->mi_actmask = TULIP_SROM_2114X_BITPOS(data);
                   2568:                        mi->mi_actdata = (data & TULIP_SROM_2114X_POLARITY) ? 0 : mi->mi_actmask;
                   2569:                    }
                   2570:                    if (TULIP_IS_MEDIA_TP(media))
                   2571:                        sc->tulip_intrmask |= TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL;
                   2572:                    mi++;
                   2573:                    break;
                   2574:                }
                   2575:                default: {
                   2576:                }
                   2577:            }
                   2578:            dp = ep;
                   2579:        }
                   2580:     }
                   2581:     return (mi - sc->tulip_mediainfo);
                   2582: }
                   2583:
                   2584: static const struct {
                   2585:     void (*vendor_identify_nic)(tulip_softc_t * const sc);
                   2586:     unsigned char vendor_oui[3];
                   2587: } tulip_vendors[] = {
                   2588:     { tulip_identify_dec_nic,          { 0x08, 0x00, 0x2B } },
                   2589:     { tulip_identify_dec_nic,          { 0x00, 0x00, 0xF8 } },
                   2590:     { tulip_identify_smc_nic,          { 0x00, 0x00, 0xC0 } },
                   2591:     { tulip_identify_smc_nic,          { 0x00, 0xE0, 0x29 } },
                   2592:     { tulip_identify_znyx_nic,         { 0x00, 0xC0, 0x95 } },
                   2593:     { tulip_identify_cogent_nic,       { 0x00, 0x00, 0x92 } },
                   2594:     { tulip_identify_cogent_nic,       { 0x00, 0x00, 0xD1 } },
                   2595:     { tulip_identify_asante_nic,       { 0x00, 0x00, 0x94 } },
                   2596:     { tulip_identify_accton_nic,       { 0x00, 0x00, 0xE8 } },
                   2597:     { tulip_identify_compex_nic,       { 0x00, 0x80, 0x48 } },
                   2598:     { NULL }
                   2599: };
                   2600:
                   2601: /*
                   2602:  * This deals with the vagaries of the address roms and the
                   2603:  * brain-deadness that various vendors commit in using them.
                   2604:  */
                   2605: int
                   2606: tulip_read_macaddr(tulip_softc_t * const sc)
                   2607: {
                   2608:     unsigned cksum, rom_cksum, idx;
                   2609:     u_int32_t csr;
                   2610:     unsigned char tmpbuf[8];
                   2611:     static const u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
                   2612:
                   2613:     sc->tulip_connidx = TULIP_SROM_LASTCONNIDX;
                   2614:
                   2615:     if (sc->tulip_chipid == TULIP_21040) {
                   2616:        TULIP_CSR_WRITE(sc, csr_enetrom, 1);
                   2617:        for (idx = 0; idx < sizeof(sc->tulip_rombuf); idx++) {
                   2618:            int cnt = 0;
                   2619:            while (((csr = TULIP_CSR_READ(sc, csr_enetrom)) & 0x80000000L) && cnt < 10000)
                   2620:                cnt++;
                   2621:            sc->tulip_rombuf[idx] = csr & 0xFF;
                   2622:        }
                   2623:        sc->tulip_boardsw = &tulip_21040_boardsw;
                   2624:     } else {
                   2625:        if (sc->tulip_chipid == TULIP_21041) {
                   2626:            /*
                   2627:             * Thankfully all 21041's act the same.
                   2628:             */
                   2629:            sc->tulip_boardsw = &tulip_21041_boardsw;
                   2630:        } else {
                   2631:            /*
                   2632:             * Assume all 21140 board are compatible with the
                   2633:             * DEC 10/100 evaluation board.  Not really valid but
                   2634:             * it's the best we can do until every one switches to
                   2635:             * the new SROM format.
                   2636:             */
                   2637:
                   2638:            sc->tulip_boardsw = &tulip_21140_eb_boardsw;
                   2639:        }
                   2640:        tulip_srom_read(sc);
                   2641:        if (tulip_srom_crcok(sc->tulip_rombuf)) {
                   2642:            /*
                   2643:             * SROM CRC is valid therefore it must be in the
                   2644:             * new format.
                   2645:             */
                   2646:            sc->tulip_features |= TULIP_HAVE_ISVSROM|TULIP_HAVE_OKSROM;
                   2647:        } else if (sc->tulip_rombuf[126] == 0xff && sc->tulip_rombuf[127] == 0xFF) {
                   2648:            /*
                   2649:             * No checksum is present.  See if the SROM id checks out;
                   2650:             * the first 18 bytes should be 0 followed by a 1 followed
                   2651:             * by the number of adapters (which we don't deal with yet).
                   2652:             */
                   2653:            for (idx = 0; idx < 18; idx++) {
                   2654:                if (sc->tulip_rombuf[idx] != 0)
                   2655:                    break;
                   2656:            }
                   2657:            if (idx == 18 && sc->tulip_rombuf[18] == 1 && sc->tulip_rombuf[19] != 0)
                   2658:                sc->tulip_features |= TULIP_HAVE_ISVSROM;
                   2659:        } else if (sc->tulip_chipid >= TULIP_21142) {
                   2660:            sc->tulip_features |= TULIP_HAVE_ISVSROM;
                   2661:            sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
                   2662:        }
                   2663:        if ((sc->tulip_features & TULIP_HAVE_ISVSROM) && tulip_srom_decode(sc)) {
                   2664:            if (sc->tulip_chipid != TULIP_21041)
                   2665:                sc->tulip_boardsw = &tulip_2114x_isv_boardsw;
                   2666:
                   2667:            /*
                   2668:             * If the SROM specifies more than one adapter, tag this as a
                   2669:             * BASE rom.
                   2670:             */
                   2671:            if (sc->tulip_rombuf[19] > 1)
                   2672:                sc->tulip_features |= TULIP_HAVE_BASEROM;
                   2673:            if (sc->tulip_boardsw == NULL)
                   2674:                return (-6);
                   2675:            goto check_oui;
                   2676:        }
                   2677:     }
                   2678:
                   2679:     if (bcmp(&sc->tulip_rombuf[0], &sc->tulip_rombuf[16], 8) != 0) {
                   2680:        /*
                   2681:         * Some folks don't use the standard ethernet rom format
                   2682:         * but instead just put the address in the first 6 bytes
                   2683:         * of the rom and let the rest be all 0xffs.  (Can we say
                   2684:         * ZNYX???) (well sometimes they put in a checksum so we'll
                   2685:         * start at 8).
                   2686:         */
                   2687:        for (idx = 8; idx < 32; idx++) {
                   2688:            if (sc->tulip_rombuf[idx] != 0xFF)
                   2689:                return (-4);
                   2690:        }
                   2691:        /*
                   2692:         * Make sure the address is not multicast or locally assigned
                   2693:         * that the OUI is not 00-00-00.
                   2694:         */
                   2695:        if ((sc->tulip_rombuf[0] & 3) != 0)
                   2696:            return (-4);
                   2697:        if (sc->tulip_rombuf[0] == 0 && sc->tulip_rombuf[1] == 0
                   2698:                && sc->tulip_rombuf[2] == 0)
                   2699:            return (-4);
                   2700:        bcopy(sc->tulip_rombuf, sc->tulip_enaddr, ETHER_ADDR_LEN);
                   2701:        sc->tulip_features |= TULIP_HAVE_OKROM;
                   2702:        goto check_oui;
                   2703:     } else {
                   2704:        /*
                   2705:         * A number of makers of multiport boards (ZNYX and Cogent)
                   2706:         * only put on one address ROM on their 21040 boards.  So
                   2707:         * if the ROM is all zeros (or all 0xFFs), look at the
                   2708:         * previous configured boards (as long as they are on the same
                   2709:         * PCI bus and the bus number is non-zero) until we find the
                   2710:         * master board with address ROM.  We then use its address ROM
                   2711:         * as the base for this board.  (we add our relative board
                   2712:         * to the last byte of its address).
                   2713:         */
                   2714:        for (idx = 0; idx < sizeof(sc->tulip_rombuf); idx++) {
                   2715:            if (sc->tulip_rombuf[idx] != 0 && sc->tulip_rombuf[idx] != 0xFF)
                   2716:                break;
                   2717:        }
                   2718:        if (idx == sizeof(sc->tulip_rombuf)) {
                   2719:            int root_unit;
                   2720:            tulip_softc_t *root_sc = NULL;
                   2721:            for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) {
                   2722:                root_sc = TULIP_UNIT_TO_SOFTC(root_unit);
                   2723:                if (root_sc == NULL || (root_sc->tulip_features & (TULIP_HAVE_OKROM|TULIP_HAVE_SLAVEDROM)) == TULIP_HAVE_OKROM)
                   2724:                    break;
                   2725:                root_sc = NULL;
                   2726:            }
                   2727:            if (root_sc != NULL && (root_sc->tulip_features & TULIP_HAVE_BASEROM)
                   2728:                    && root_sc->tulip_chipid == sc->tulip_chipid
                   2729:                    && root_sc->tulip_pci_busno == sc->tulip_pci_busno) {
                   2730:                sc->tulip_features |= TULIP_HAVE_SLAVEDROM;
                   2731:                sc->tulip_boardsw = root_sc->tulip_boardsw;
                   2732:                strlcpy(sc->tulip_boardid, root_sc->tulip_boardid,
                   2733:                    sizeof(sc->tulip_boardid));
                   2734:                if (sc->tulip_boardsw->bd_type == TULIP_21140_ISV) {
                   2735:                    bcopy(root_sc->tulip_rombuf, sc->tulip_rombuf,
                   2736:                          sizeof(sc->tulip_rombuf));
                   2737:                    if (!tulip_srom_decode(sc))
                   2738:                        return (-5);
                   2739:                } else {
                   2740:                    bcopy(root_sc->tulip_enaddr, sc->tulip_enaddr,
                   2741:                       ETHER_ADDR_LEN);
                   2742:                    sc->tulip_enaddr[5] += sc->tulip_unit - root_sc->tulip_unit;
                   2743:                }
                   2744:                /*
                   2745:                 * Now for a truly disgusting kludge: all 4 21040s on
                   2746:                 * the ZX314 share the same INTA line so the mapping
                   2747:                 * setup by the BIOS on the PCI bridge is worthless.
                   2748:                 * Rather than reprogramming the value in the config
                   2749:                 * register, we will handle this internally.
                   2750:                 */
                   2751:                if (root_sc->tulip_features & TULIP_HAVE_SHAREDINTR) {
                   2752:                    sc->tulip_slaves = root_sc->tulip_slaves;
                   2753:                    root_sc->tulip_slaves = sc;
                   2754:                    sc->tulip_features |= TULIP_HAVE_SLAVEDINTR;
                   2755:                }
                   2756:                return (0);
                   2757:            }
                   2758:        }
                   2759:     }
                   2760:
                   2761:     /*
                   2762:      * This is the standard DEC address ROM test.
                   2763:      */
                   2764:
                   2765:     if (bcmp(&sc->tulip_rombuf[24], testpat, 8) != 0)
                   2766:        return (-3);
                   2767:
                   2768:     tmpbuf[0] = sc->tulip_rombuf[15]; tmpbuf[1] = sc->tulip_rombuf[14];
                   2769:     tmpbuf[2] = sc->tulip_rombuf[13]; tmpbuf[3] = sc->tulip_rombuf[12];
                   2770:     tmpbuf[4] = sc->tulip_rombuf[11]; tmpbuf[5] = sc->tulip_rombuf[10];
                   2771:     tmpbuf[6] = sc->tulip_rombuf[9];  tmpbuf[7] = sc->tulip_rombuf[8];
                   2772:     if (bcmp(&sc->tulip_rombuf[0], tmpbuf, 8) != 0)
                   2773:        return (-2);
                   2774:
                   2775:     bcopy(sc->tulip_rombuf, sc->tulip_enaddr, ETHER_ADDR_LEN);
                   2776:
                   2777:     cksum = *(u_int16_t *) &sc->tulip_enaddr[0];
                   2778:     cksum *= 2;
                   2779:     if (cksum > 65535) cksum -= 65535;
                   2780:     cksum += *(u_int16_t *) &sc->tulip_enaddr[2];
                   2781:     if (cksum > 65535) cksum -= 65535;
                   2782:     cksum *= 2;
                   2783:     if (cksum > 65535) cksum -= 65535;
                   2784:     cksum += *(u_int16_t *) &sc->tulip_enaddr[4];
                   2785:     if (cksum >= 65535) cksum -= 65535;
                   2786:
                   2787:     rom_cksum = *(u_int16_t *) &sc->tulip_rombuf[6];
                   2788:
                   2789:     if (cksum != rom_cksum)
                   2790:        return (-1);
                   2791:
                   2792:   check_oui:
                   2793:     /*
                   2794:      * Check for various boards based on OUI.  Did I say braindead?
                   2795:      */
                   2796:     for (idx = 0; tulip_vendors[idx].vendor_identify_nic != NULL; idx++) {
                   2797:        if (bcmp((caddr_t) sc->tulip_enaddr,
                   2798:                 (caddr_t) tulip_vendors[idx].vendor_oui, 3) == 0) {
                   2799:            (*tulip_vendors[idx].vendor_identify_nic)(sc);
                   2800:            break;
                   2801:        }
                   2802:     }
                   2803:
                   2804:     sc->tulip_features |= TULIP_HAVE_OKROM;
                   2805:     return (0);
                   2806: }
                   2807:
                   2808: void
                   2809: tulip_ifmedia_add(tulip_softc_t * const sc)
                   2810: {
                   2811:     tulip_media_t media;
                   2812:     int medias = 0;
                   2813:
                   2814:     for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
                   2815:        if (sc->tulip_mediums[media] != NULL) {
                   2816:            ifmedia_add(&sc->tulip_ifmedia, tulip_media_to_ifmedia[media],
                   2817:                        0, 0);
                   2818:            medias++;
                   2819:        }
                   2820:     }
                   2821:     if (medias == 0) {
                   2822:        sc->tulip_features |= TULIP_HAVE_NOMEDIA;
                   2823:        ifmedia_add(&sc->tulip_ifmedia, IFM_ETHER | IFM_NONE, 0, 0);
                   2824:        ifmedia_set(&sc->tulip_ifmedia, IFM_ETHER | IFM_NONE);
                   2825:     } else if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) {
                   2826:        ifmedia_add(&sc->tulip_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
                   2827:        ifmedia_set(&sc->tulip_ifmedia, IFM_ETHER | IFM_AUTO);
                   2828:     } else {
                   2829:        ifmedia_set(&sc->tulip_ifmedia, tulip_media_to_ifmedia[sc->tulip_media]);
                   2830:        sc->tulip_flags |= TULIP_PRINTMEDIA;
                   2831:        tulip_linkup(sc, sc->tulip_media);
                   2832:     }
                   2833: }
                   2834:
                   2835: int
                   2836: tulip_ifmedia_change(struct ifnet * const ifp)
                   2837: {
                   2838:     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
                   2839:
                   2840:     sc->tulip_flags |= TULIP_NEEDRESET;
                   2841:     sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                   2842:     sc->tulip_media = TULIP_MEDIA_UNKNOWN;
                   2843:     if (IFM_SUBTYPE(sc->tulip_ifmedia.ifm_media) != IFM_AUTO) {
                   2844:        tulip_media_t media;
                   2845:        for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) {
                   2846:            if (sc->tulip_mediums[media] != NULL
                   2847:                && sc->tulip_ifmedia.ifm_media == tulip_media_to_ifmedia[media]) {
                   2848:                sc->tulip_flags |= TULIP_PRINTMEDIA;
                   2849:                sc->tulip_flags &= ~TULIP_DIDNWAY;
                   2850:                tulip_linkup(sc, media);
                   2851:                return (0);
                   2852:            }
                   2853:        }
                   2854:     }
                   2855:     sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_WANTRXACT);
                   2856:     tulip_reset(sc);
                   2857:     tulip_init(sc);
                   2858:     return (0);
                   2859: }
                   2860:
                   2861: /*
                   2862:  * Media status callback
                   2863:  */
                   2864: void
                   2865: tulip_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req)
                   2866: {
                   2867:     tulip_softc_t *sc = TULIP_IFP_TO_SOFTC(ifp);
                   2868:
                   2869:     if (sc->tulip_media == TULIP_MEDIA_UNKNOWN)
                   2870:        return;
                   2871:
                   2872:     req->ifm_status = IFM_AVALID;
                   2873:     if (sc->tulip_flags & TULIP_LINKUP)
                   2874:        req->ifm_status |= IFM_ACTIVE;
                   2875:
                   2876:     req->ifm_active = tulip_media_to_ifmedia[sc->tulip_media];
                   2877: }
                   2878:
                   2879: void
                   2880: tulip_addr_filter(tulip_softc_t * const sc)
                   2881: {
                   2882:     struct ether_multistep step;
                   2883:     struct ether_multi *enm;
                   2884:
                   2885:     sc->tulip_flags &= ~(TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY|TULIP_ALLMULTI);
                   2886:     sc->tulip_flags |= TULIP_WANTSETUP|TULIP_WANTTXSTART;
                   2887:     sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
                   2888:     sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
                   2889:     sc->tulip_if.if_flags &= ~IFF_ALLMULTI;
                   2890:     sc->tulip_if.if_start = tulip_ifstart;     /* so the setup packet gets queued */
                   2891:     if (sc->tulip_multicnt > 14) {
                   2892:        u_int32_t *sp = sc->tulip_setupdata;
                   2893:        unsigned hash;
                   2894:        /*
                   2895:         * Some early passes of the 21140 have broken implementations of
                   2896:         * hash-perfect mode.  When we get too many multicasts for perfect
                   2897:         * filtering with these chips, we need to switch into hash-only
                   2898:         * mode (this is better than all-multicast on network with lots
                   2899:         * of multicast traffic).
                   2900:         */
                   2901:        if (sc->tulip_features & TULIP_HAVE_BROKEN_HASH)
                   2902:            sc->tulip_flags |= TULIP_WANTHASHONLY;
                   2903:        else
                   2904:            sc->tulip_flags |= TULIP_WANTHASHPERFECT;
                   2905:        /*
                   2906:         * If we have more than 14 multicasts, we have
                   2907:         * go into hash perfect mode (512 bit multicast
                   2908:         * hash and one perfect hardware).
                   2909:         */
                   2910:        bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata));
                   2911:        ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
                   2912:        while (enm != NULL) {
                   2913:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) == 0) {
                   2914:                    hash = tulip_mchash(enm->enm_addrlo);
                   2915: #if BYTE_ORDER == BIG_ENDIAN
                   2916:                    sp[hash >> 4] |= swap32(1 << (hash & 0xF));
                   2917: #else
                   2918:                    sp[hash >> 4] |= 1 << (hash & 0xF);
                   2919: #endif
                   2920:                } else {
                   2921:                    sc->tulip_flags |= TULIP_ALLMULTI;
                   2922:                    sc->tulip_flags &= ~(TULIP_WANTHASHONLY|TULIP_WANTHASHPERFECT);
                   2923:                    break;
                   2924:                }
                   2925:                ETHER_NEXT_MULTI(step, enm);
                   2926:        }
                   2927:        /*
                   2928:         * No reason to use a hash if we are going to be
                   2929:         * receiving every multicast.
                   2930:         */
                   2931:        if ((sc->tulip_flags & TULIP_ALLMULTI) == 0) {
                   2932:            hash = tulip_mchash(etherbroadcastaddr);
                   2933: #if BYTE_ORDER == BIG_ENDIAN
                   2934:            sp[hash >> 4] |= swap32(1 << (hash & 0xF));
                   2935: #else
                   2936:            sp[hash >> 4] |= 1 << (hash & 0xF);
                   2937: #endif
                   2938:            if (sc->tulip_flags & TULIP_WANTHASHONLY) {
                   2939:                hash = tulip_mchash(sc->tulip_enaddr);
                   2940: #if BYTE_ORDER == BIG_ENDIAN
                   2941:                sp[hash >> 4] |= swap32(1 << (hash & 0xF));
                   2942: #else
                   2943:                sp[hash >> 4] |= 1 << (hash & 0xF);
                   2944: #endif
                   2945:            } else {
                   2946: #if BYTE_ORDER == BIG_ENDIAN
                   2947:                sp[39] = ((u_int16_t *) sc->tulip_enaddr)[0] << 16;
                   2948:                sp[40] = ((u_int16_t *) sc->tulip_enaddr)[1] << 16;
                   2949:                sp[41] = ((u_int16_t *) sc->tulip_enaddr)[2] << 16;
                   2950: #else
                   2951:                sp[39] = ((u_int16_t *) sc->tulip_enaddr)[0];
                   2952:                sp[40] = ((u_int16_t *) sc->tulip_enaddr)[1];
                   2953:                sp[41] = ((u_int16_t *) sc->tulip_enaddr)[2];
                   2954: #endif
                   2955:            }
                   2956:        }
                   2957:     }
                   2958:     if ((sc->tulip_flags & (TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY)) == 0) {
                   2959:        u_int32_t *sp = sc->tulip_setupdata;
                   2960:        int idx = 0;
                   2961:        if ((sc->tulip_flags & TULIP_ALLMULTI) == 0) {
                   2962:            /*
                   2963:             * Else can get perfect filtering for 16 addresses.
                   2964:             */
                   2965:            ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm);
                   2966:            for (; enm != NULL; idx++) {
                   2967:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) == 0) {
                   2968: #if BYTE_ORDER == BIG_ENDIAN
                   2969:                    *sp++ = ((u_int16_t *) enm->enm_addrlo)[0] << 16;
                   2970:                    *sp++ = ((u_int16_t *) enm->enm_addrlo)[1] << 16;
                   2971:                    *sp++ = ((u_int16_t *) enm->enm_addrlo)[2] << 16;
                   2972: #else
                   2973:                    *sp++ = ((u_int16_t *) enm->enm_addrlo)[0];
                   2974:                    *sp++ = ((u_int16_t *) enm->enm_addrlo)[1];
                   2975:                    *sp++ = ((u_int16_t *) enm->enm_addrlo)[2];
                   2976: #endif
                   2977:                } else {
                   2978:                    sc->tulip_flags |= TULIP_ALLMULTI;
                   2979:                    break;
                   2980:                }
                   2981:                ETHER_NEXT_MULTI(step, enm);
                   2982:            }
                   2983:            /*
                   2984:             * Add the broadcast address.
                   2985:             */
                   2986:            idx++;
                   2987: #if BYTE_ORDER == BIG_ENDIAN
                   2988:            *sp++ = 0xFFFF << 16;
                   2989:            *sp++ = 0xFFFF << 16;
                   2990:            *sp++ = 0xFFFF << 16;
                   2991: #else
                   2992:            *sp++ = 0xFFFF;
                   2993:            *sp++ = 0xFFFF;
                   2994:            *sp++ = 0xFFFF;
                   2995: #endif
                   2996:        }
                   2997:        /*
                   2998:         * Pad the rest with our hardware address
                   2999:         */
                   3000:        for (; idx < 16; idx++) {
                   3001: #if BYTE_ORDER == BIG_ENDIAN
                   3002:            *sp++ = ((u_int16_t *) sc->tulip_enaddr)[0] << 16;
                   3003:            *sp++ = ((u_int16_t *) sc->tulip_enaddr)[1] << 16;
                   3004:            *sp++ = ((u_int16_t *) sc->tulip_enaddr)[2] << 16;
                   3005: #else
                   3006:            *sp++ = ((u_int16_t *) sc->tulip_enaddr)[0];
                   3007:            *sp++ = ((u_int16_t *) sc->tulip_enaddr)[1];
                   3008:            *sp++ = ((u_int16_t *) sc->tulip_enaddr)[2];
                   3009: #endif
                   3010:        }
                   3011:     }
                   3012:     if (sc->tulip_flags & TULIP_ALLMULTI)
                   3013:        sc->tulip_if.if_flags |= IFF_ALLMULTI;
                   3014: }
                   3015:
                   3016: void
                   3017: tulip_reset(tulip_softc_t * const sc)
                   3018: {
                   3019:     tulip_ringinfo_t *ri;
                   3020:     tulip_desc_t *di;
                   3021:     u_int32_t inreset = (sc->tulip_flags & TULIP_INRESET);
                   3022:
                   3023:     /*
                   3024:      * Brilliant.  Simply brilliant.  When switching modes/speeds
                   3025:      * on a 2114*, you need to set the appriopriate MII/PCS/SCL/PS
                   3026:      * bits in CSR6 and then do a software reset to get the 21140
                   3027:      * to properly reset its internal pathways to the right places.
                   3028:      *   Grrrr.
                   3029:      */
                   3030:     if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0
                   3031:            && sc->tulip_boardsw->bd_media_preset != NULL)
                   3032:        (*sc->tulip_boardsw->bd_media_preset)(sc);
                   3033:
                   3034:     TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
                   3035:     DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
                   3036:                   33MHz that comes to two microseconds but wait a
                   3037:                   bit longer anyways) */
                   3038:
                   3039:     if (!inreset) {
                   3040:        sc->tulip_flags |= TULIP_INRESET;
                   3041:        sc->tulip_flags &= ~(TULIP_NEEDRESET|TULIP_RXBUFSLOW);
                   3042:        sc->tulip_if.if_flags &= ~IFF_OACTIVE;
                   3043:        sc->tulip_if.if_start = tulip_ifstart;
                   3044:     }
                   3045:
                   3046:     TULIP_CSR_WRITE(sc, csr_txlist, sc->tulip_txdescmap->dm_segs[0].ds_addr);
                   3047:     TULIP_CSR_WRITE(sc, csr_rxlist, sc->tulip_rxdescmap->dm_segs[0].ds_addr);
                   3048:     TULIP_CSR_WRITE(sc, csr_busmode,
                   3049:                    (1 << (TULIP_BURSTSIZE(sc->tulip_unit) + 8))
                   3050:                    |TULIP_BUSMODE_CACHE_ALIGN8
                   3051:                    |TULIP_BUSMODE_READMULTIPLE
                   3052:                    |(BYTE_ORDER != LITTLE_ENDIAN ?
                   3053:                      TULIP_BUSMODE_DESC_BIGENDIAN : 0));
                   3054:
                   3055:     sc->tulip_txtimer = 0;
                   3056:     sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS;
                   3057:     /*
                   3058:      * Free all the mbufs that were on the transmit ring.
                   3059:      */
                   3060:     for (;;) {
                   3061:        bus_dmamap_t map;
                   3062:        struct mbuf *m;
                   3063:        IF_DEQUEUE(&sc->tulip_txq, m);
                   3064:        if (m == NULL)
                   3065:            break;
                   3066:        map = TULIP_GETCTX(m, bus_dmamap_t);
                   3067:        bus_dmamap_unload(sc->tulip_dmatag, map);
                   3068:        sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
                   3069:        m_freem(m);
                   3070:     }
                   3071:
                   3072:     ri = &sc->tulip_txinfo;
                   3073:     ri->ri_nextin = ri->ri_nextout = ri->ri_first;
                   3074:     ri->ri_free = ri->ri_max;
                   3075:     for (di = ri->ri_first; di < ri->ri_last; di++)
                   3076:        di->d_status = 0;
                   3077:     bus_dmamap_sync(sc->tulip_dmatag, sc->tulip_txdescmap,
                   3078:                    0, sc->tulip_txdescmap->dm_mapsize,
                   3079:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                   3080:
                   3081:     /*
                   3082:      * We need to collect all the mbufs were on the
                   3083:      * receive ring before we reinit it either to put
                   3084:      * them back on or to know if we have to allocate
                   3085:      * more.
                   3086:      */
                   3087:     ri = &sc->tulip_rxinfo;
                   3088:     ri->ri_nextin = ri->ri_nextout = ri->ri_first;
                   3089:     ri->ri_free = ri->ri_max;
                   3090:     for (di = ri->ri_first; di < ri->ri_last; di++) {
                   3091:        di->d_status = 0;
                   3092:        di->d_length1 = 0; di->d_addr1 = 0;
                   3093:        di->d_length2 = 0; di->d_addr2 = 0;
                   3094:     }
                   3095:     bus_dmamap_sync(sc->tulip_dmatag, sc->tulip_rxdescmap,
                   3096:                    0, sc->tulip_rxdescmap->dm_mapsize,
                   3097:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                   3098:     for (;;) {
                   3099:        bus_dmamap_t map;
                   3100:        struct mbuf *m;
                   3101:        IF_DEQUEUE(&sc->tulip_rxq, m);
                   3102:        if (m == NULL)
                   3103:            break;
                   3104:        map = TULIP_GETCTX(m, bus_dmamap_t);
                   3105:        bus_dmamap_unload(sc->tulip_dmatag, map);
                   3106:        sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
                   3107:        m_freem(m);
                   3108:     }
                   3109:
                   3110:     /*
                   3111:      * If tulip_reset is being called recurisvely, exit quickly knowing
                   3112:      * that when the outer tulip_reset returns all the right stuff will
                   3113:      * have happened.
                   3114:      */
                   3115:     if (inreset)
                   3116:        return;
                   3117:
                   3118:     sc->tulip_intrmask |= TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR
                   3119:        |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED
                   3120:        |TULIP_STS_TXUNDERFLOW|TULIP_STS_TXBABBLE
                   3121:        |TULIP_STS_RXSTOPPED;
                   3122:
                   3123:     if ((sc->tulip_flags & TULIP_DEVICEPROBE) == 0)
                   3124:        (*sc->tulip_boardsw->bd_media_select)(sc);
                   3125: #if defined(TULIP_DEBUG)
                   3126:     if ((sc->tulip_flags & TULIP_NEEDRESET) == TULIP_NEEDRESET)
                   3127:        printf(TULIP_PRINTF_FMT ": tulip_reset: additional reset needed?!?\n",
                   3128:               TULIP_PRINTF_ARGS);
                   3129: #endif
                   3130:     tulip_media_print(sc);
                   3131:     if (sc->tulip_features & TULIP_HAVE_DUALSENSE)
                   3132:        TULIP_CSR_WRITE(sc, csr_sia_status, TULIP_CSR_READ(sc, csr_sia_status));
                   3133:
                   3134:     sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP|TULIP_INRESET
                   3135:                         |TULIP_RXACT);
                   3136:     tulip_addr_filter(sc);
                   3137: }
                   3138:
                   3139: void
                   3140: tulip_init(tulip_softc_t * const sc)
                   3141: {
                   3142:     if (sc->tulip_if.if_flags & IFF_UP) {
                   3143:        if ((sc->tulip_if.if_flags & IFF_RUNNING) == 0) {
                   3144:            /* initialize the media */
                   3145:            tulip_reset(sc);
                   3146:        }
                   3147:        sc->tulip_if.if_flags |= IFF_RUNNING;
                   3148:        if (sc->tulip_if.if_flags & IFF_PROMISC) {
                   3149:            sc->tulip_flags |= TULIP_PROMISC;
                   3150:            sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS;
                   3151:            sc->tulip_intrmask |= TULIP_STS_TXINTR;
                   3152:        } else {
                   3153:            sc->tulip_flags &= ~TULIP_PROMISC;
                   3154:            sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS;
                   3155:            if (sc->tulip_flags & TULIP_ALLMULTI)
                   3156:                sc->tulip_cmdmode |= TULIP_CMD_ALLMULTI;
                   3157:            else
                   3158:                sc->tulip_cmdmode &= ~TULIP_CMD_ALLMULTI;
                   3159:        }
                   3160:        sc->tulip_cmdmode |= TULIP_CMD_TXRUN;
                   3161:        if ((sc->tulip_flags & (TULIP_TXPROBE_ACTIVE|TULIP_WANTSETUP)) == 0) {
                   3162:            tulip_rx_intr(sc);
                   3163:            sc->tulip_cmdmode |= TULIP_CMD_RXRUN;
                   3164:            sc->tulip_intrmask |= TULIP_STS_RXSTOPPED;
                   3165:        } else {
                   3166:            sc->tulip_if.if_flags |= IFF_OACTIVE;
                   3167:            sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN;
                   3168:            sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED;
                   3169:        }
                   3170:        TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                   3171:        TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                   3172:        if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
                   3173:            tulip_txput_setup(sc);
                   3174:     } else {
                   3175:        sc->tulip_if.if_flags &= ~IFF_RUNNING;
                   3176:        tulip_reset(sc);
                   3177:     }
                   3178: }
                   3179:
                   3180: void
                   3181: tulip_rx_intr(tulip_softc_t * const sc)
                   3182: {
                   3183:     TULIP_PERFSTART(rxintr)
                   3184:     tulip_ringinfo_t * const ri = &sc->tulip_rxinfo;
                   3185:     struct ifnet * const ifp = &sc->tulip_if;
                   3186:     int fillok = 1;
                   3187: #if defined(TULIP_DEBUG)
                   3188:     int cnt = 0;
                   3189: #endif
                   3190:
                   3191:     for (;;) {
                   3192:        TULIP_PERFSTART(rxget)
                   3193:        tulip_desc_t *eop = ri->ri_nextin;
                   3194:        int total_len = 0, last_offset = 0;
                   3195:        struct mbuf *ms = NULL, *me = NULL;
                   3196:        int accept = 0;
                   3197:        bus_dmamap_t map;
                   3198:        int error;
                   3199:
                   3200:        if (fillok && sc->tulip_rxq.ifq_len < TULIP_RXQ_TARGET)
                   3201:            goto queue_mbuf;
                   3202:
                   3203: #if defined(TULIP_DEBUG)
                   3204:        if (cnt == ri->ri_max)
                   3205:            break;
                   3206: #endif
                   3207:        /*
                   3208:         * If the TULIP has no descriptors, there can't be any receive
                   3209:         * descriptors to process.
                   3210:         */
                   3211:        if (eop == ri->ri_nextout)
                   3212:            break;
                   3213:
                   3214:        /*
                   3215:         * 90% of the packets will fit in one descriptor.  So we optimize
                   3216:         * for that case.
                   3217:         */
                   3218:        TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
                   3219:        if ((((volatile tulip_desc_t *) eop)->d_status & (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) {
                   3220:            IF_DEQUEUE(&sc->tulip_rxq, ms);
                   3221:            me = ms;
                   3222:        } else {
                   3223:            /*
                   3224:             * If still owned by the TULIP, don't touch it.
                   3225:             */
                   3226:            if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER)
                   3227:                break;
                   3228:
                   3229:            /*
                   3230:             * It is possible (though improbable unless MCLBYTES < 1518) for
                   3231:             * a received packet to cross more than one receive descriptor.
                   3232:             */
                   3233:            while ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_RxLASTDESC) == 0) {
                   3234:                if (++eop == ri->ri_last)
                   3235:                    eop = ri->ri_first;
                   3236:                TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
                   3237:                if (eop == ri->ri_nextout || ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER))) {
                   3238: #if defined(TULIP_DEBUG)
                   3239:                    sc->tulip_dbg.dbg_rxintrs++;
                   3240:                    sc->tulip_dbg.dbg_rxpktsperintr[cnt]++;
                   3241: #endif
                   3242:                    TULIP_PERFEND(rxget);
                   3243:                    TULIP_PERFEND(rxintr);
                   3244:                    return;
                   3245:                }
                   3246:                total_len++;
                   3247:            }
                   3248:
                   3249:            /*
                   3250:             * Dequeue the first buffer for the start of the packet.  Hopefully
                   3251:             * this will be the only one we need to dequeue.  However, if the
                   3252:             * packet consumed multiple descriptors, then we need to dequeue
                   3253:             * those buffers and chain to the starting mbuf.  All buffers but
                   3254:             * the last buffer have the same length so we can set that now.
                   3255:             * (we add to last_offset instead of multiplying since we normally
                   3256:             * won't go into the loop and thereby saving a ourselves from
                   3257:             * doing a multiplication by 0 in the normal case).
                   3258:             */
                   3259:            IF_DEQUEUE(&sc->tulip_rxq, ms);
                   3260:            for (me = ms; total_len > 0; total_len--) {
                   3261:                map = TULIP_GETCTX(me, bus_dmamap_t);
                   3262:                TULIP_RXMAP_POSTSYNC(sc, map);
                   3263:                bus_dmamap_unload(sc->tulip_dmatag, map);
                   3264:                sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
                   3265: #if defined(DIAGNOSTIC)
                   3266:                TULIP_SETCTX(me, NULL);
                   3267: #endif
                   3268:                me->m_len = TULIP_RX_BUFLEN;
                   3269:                last_offset += TULIP_RX_BUFLEN;
                   3270:                IF_DEQUEUE(&sc->tulip_rxq, me->m_next);
                   3271:                me = me->m_next;
                   3272:            }
                   3273:        }
                   3274:
                   3275:        /*
                   3276:         *  Now get the size of received packet (minus the CRC).
                   3277:         */
                   3278:        total_len = ((eop->d_status >> 16) & 0x7FFF) - 4;
                   3279:        if ((sc->tulip_flags & TULIP_RXIGNORE) == 0
                   3280:                && ((eop->d_status & TULIP_DSTS_ERRSUM) == 0)) {
                   3281:            me->m_len = total_len - last_offset;
                   3282:
                   3283:            map = TULIP_GETCTX(me, bus_dmamap_t);
                   3284:            bus_dmamap_sync(sc->tulip_dmatag, map, 0, me->m_len,
                   3285:                            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                   3286:            bus_dmamap_unload(sc->tulip_dmatag, map);
                   3287:            sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
                   3288: #if defined(DIAGNOSTIC)
                   3289:            TULIP_SETCTX(me, NULL);
                   3290: #endif
                   3291:
                   3292: #if NBPFILTER > 0
                   3293:            if (sc->tulip_bpf != NULL) {
                   3294:                if (me == ms) {
                   3295:                    bpf_tap(sc->tulip_if.if_bpf, mtod(ms, caddr_t),
                   3296:                        total_len, BPF_DIRECTION_IN);
                   3297:                } else
                   3298:                    bpf_mtap(sc->tulip_if.if_bpf, ms, BPF_DIRECTION_IN);
                   3299:            }
                   3300: #endif
                   3301:            sc->tulip_flags |= TULIP_RXACT;
                   3302:            accept = 1;
                   3303:        } else {
                   3304:            ifp->if_ierrors++;
                   3305:            if (eop->d_status & (TULIP_DSTS_RxBADLENGTH|TULIP_DSTS_RxOVERFLOW|TULIP_DSTS_RxWATCHDOG))
                   3306:                sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
                   3307:            else {
                   3308: #ifdef TULIP_DEBUG
                   3309:                const char *error = NULL;
                   3310:                if (eop->d_status & TULIP_DSTS_RxTOOLONG) {
                   3311:                    sc->tulip_dot3stats.dot3StatsFrameTooLongs++;
                   3312:                    error = "frame too long";
                   3313:                }
                   3314:                if (eop->d_status & TULIP_DSTS_RxBADCRC) {
                   3315:                    if (eop->d_status & TULIP_DSTS_RxDRBBLBIT) {
                   3316:                        sc->tulip_dot3stats.dot3StatsAlignmentErrors++;
                   3317:                        error = "alignment error";
                   3318:                    } else {
                   3319:                        sc->tulip_dot3stats.dot3StatsFCSErrors++;
                   3320:                        error = "bad crc";
                   3321:                    }
                   3322:                }
                   3323:                if (error != NULL && (sc->tulip_flags & TULIP_NOMESSAGES) == 0) {
                   3324:                    printf(TULIP_PRINTF_FMT ": receive: %s: %s\n",
                   3325:                           TULIP_PRINTF_ARGS,
                   3326:                           ether_sprintf(mtod(ms, u_char *) + 6),
                   3327:                           error);
                   3328:                    sc->tulip_flags |= TULIP_NOMESSAGES;
                   3329:                }
                   3330: #endif
                   3331:            }
                   3332:
                   3333:            map = TULIP_GETCTX(me, bus_dmamap_t);
                   3334:            bus_dmamap_unload(sc->tulip_dmatag, map);
                   3335:            sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
                   3336: #if defined(DIAGNOSTIC)
                   3337:            TULIP_SETCTX(me, NULL);
                   3338: #endif
                   3339:        }
                   3340: #if defined(TULIP_DEBUG)
                   3341:        cnt++;
                   3342: #endif
                   3343:        ifp->if_ipackets++;
                   3344:        if (++eop == ri->ri_last)
                   3345:            eop = ri->ri_first;
                   3346:        ri->ri_nextin = eop;
                   3347:       queue_mbuf:
                   3348:        /*
                   3349:         * Either we are priming the TULIP with mbufs (m == NULL)
                   3350:         * or we are about to accept an mbuf for the upper layers
                   3351:         * so we need to allocate an mbuf to replace it.  If we
                   3352:         * can't replace it, send up it anyways.  This may cause
                   3353:         * us to drop packets in the future but that's better than
                   3354:         * being caught in livelock.
                   3355:         *
                   3356:         * Note that if this packet crossed multiple descriptors
                   3357:         * we don't even try to reallocate all the mbufs here.
                   3358:         * Instead we rely on the test of the beginning of
                   3359:         * the loop to refill for the extra consumed mbufs.
                   3360:         */
                   3361:        if (accept || ms == NULL) {
                   3362:            struct mbuf *m0;
                   3363:            MGETHDR(m0, M_DONTWAIT, MT_DATA);
                   3364:            if (m0 != NULL) {
                   3365: #if defined(TULIP_COPY_RXDATA)
                   3366:                if (!accept || total_len >= (MHLEN - 2)) {
                   3367: #endif
                   3368:                    MCLGET(m0, M_DONTWAIT);
                   3369:                    if ((m0->m_flags & M_EXT) == 0) {
                   3370:                        m_freem(m0);
                   3371:                        m0 = NULL;
                   3372:                    }
                   3373: #if defined(TULIP_COPY_RXDATA)
                   3374:                }
                   3375: #endif
                   3376:            }
                   3377:            if (accept
                   3378: #if defined(TULIP_COPY_RXDATA)
                   3379:                && m0 != NULL
                   3380: #endif
                   3381:                ) {
                   3382: #if !defined(TULIP_COPY_RXDATA)
                   3383:                ms->m_pkthdr.len = total_len;
                   3384:                ms->m_pkthdr.rcvif = ifp;
                   3385:                ether_input_mbuf(ifp, ms);
                   3386: #else
                   3387:                m0->m_data += 2;        /* align data after header */
                   3388:                m_copydata(ms, 0, total_len, mtod(m0, caddr_t));
                   3389:                m0->m_len = m0->m_pkthdr.len = total_len;
                   3390:                m0->m_pkthdr.rcvif = ifp;
                   3391:                ether_input_mbuf(ifp, m0);
                   3392:                m0 = ms;
                   3393: #endif
                   3394:            }
                   3395:            ms = m0;
                   3396:        }
                   3397:        if (ms == NULL) {
                   3398:            /*
                   3399:             * Couldn't allocate a new buffer.  Don't bother
                   3400:             * trying to replenish the receive queue.
                   3401:             */
                   3402:            fillok = 0;
                   3403:            sc->tulip_flags |= TULIP_RXBUFSLOW;
                   3404: #if defined(TULIP_DEBUG)
                   3405:            sc->tulip_dbg.dbg_rxlowbufs++;
                   3406: #endif
                   3407:            TULIP_PERFEND(rxget);
                   3408:            continue;
                   3409:        }
                   3410:        /*
                   3411:         * Now give the buffer(s) to the TULIP and save in our
                   3412:         * receive queue.
                   3413:         */
                   3414:        do {
                   3415:            tulip_desc_t * const nextout = ri->ri_nextout;
                   3416:            if (sc->tulip_rxmaps_free > 0)
                   3417:                map = sc->tulip_rxmaps[--sc->tulip_rxmaps_free];
                   3418:            else {
                   3419:                m_freem(ms);
                   3420:                sc->tulip_flags |= TULIP_RXBUFSLOW;
                   3421: #if defined(TULIP_DEBUG)
                   3422:                sc->tulip_dbg.dbg_rxlowbufs++;
                   3423: #endif
                   3424:                break;
                   3425:            }
                   3426:            TULIP_SETCTX(ms, map);
                   3427:            error = bus_dmamap_load(sc->tulip_dmatag, map, mtod(ms, void *),
                   3428:                                    TULIP_RX_BUFLEN, NULL, BUS_DMA_NOWAIT);
                   3429:            if (error) {
                   3430:                printf(TULIP_PRINTF_FMT ": unable to load rx map, "
                   3431:                       "error = %d\n", TULIP_PRINTF_ARGS, error);
                   3432:                panic("tulip_rx_intr");         /* XXX */
                   3433:            }
                   3434:            nextout->d_addr1 = map->dm_segs[0].ds_addr;
                   3435:            nextout->d_length1 = map->dm_segs[0].ds_len;
                   3436:            if (map->dm_nsegs == 2) {
                   3437:                nextout->d_addr2 = map->dm_segs[1].ds_addr;
                   3438:                nextout->d_length2 = map->dm_segs[1].ds_len;
                   3439:            } else {
                   3440:                nextout->d_addr2 = 0;
                   3441:                nextout->d_length2 = 0;
                   3442:            }
                   3443:            TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(*nextout));
                   3444:            nextout->d_status = TULIP_DSTS_OWNER;
                   3445:            TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(u_int32_t));
                   3446:            if (++ri->ri_nextout == ri->ri_last)
                   3447:                ri->ri_nextout = ri->ri_first;
                   3448:            me = ms->m_next;
                   3449:            ms->m_next = NULL;
                   3450:            IF_ENQUEUE(&sc->tulip_rxq, ms);
                   3451:        } while ((ms = me) != NULL);
                   3452:
                   3453:        if (sc->tulip_rxq.ifq_len >= TULIP_RXQ_TARGET)
                   3454:            sc->tulip_flags &= ~TULIP_RXBUFSLOW;
                   3455:        TULIP_PERFEND(rxget);
                   3456:     }
                   3457:
                   3458: #if defined(TULIP_DEBUG)
                   3459:     sc->tulip_dbg.dbg_rxintrs++;
                   3460:     sc->tulip_dbg.dbg_rxpktsperintr[cnt]++;
                   3461: #endif
                   3462:     TULIP_PERFEND(rxintr);
                   3463: }
                   3464:
                   3465: int
                   3466: tulip_tx_intr(tulip_softc_t * const sc)
                   3467: {
                   3468:     TULIP_PERFSTART(txintr)
                   3469:     tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
                   3470:     struct mbuf *m;
                   3471:     int xmits = 0;
                   3472:     int descs = 0;
                   3473:
                   3474:     while (ri->ri_free < ri->ri_max) {
                   3475:        u_int32_t d_flag;
                   3476:
                   3477:        TULIP_TXDESC_POSTSYNC(sc, ri->ri_nextin, sizeof(*ri->ri_nextin));
                   3478:        if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER)
                   3479:            break;
                   3480:
                   3481:        ri->ri_free++;
                   3482:        descs++;
                   3483:        d_flag = ri->ri_nextin->d_flag;
                   3484:        if (d_flag & TULIP_DFLAG_TxLASTSEG) {
                   3485:            if (d_flag & TULIP_DFLAG_TxSETUPPKT) {
                   3486:                /*
                   3487:                 * We've just finished processing a setup packet.
                   3488:                 * Mark that we finished it.  If there's not
                   3489:                 * another pending, startup the TULIP receiver.
                   3490:                 * Make sure we ack the RXSTOPPED so we won't get
                   3491:                 * an abormal interrupt indication.
                   3492:                 */
                   3493:                TULIP_TXMAP_POSTSYNC(sc, sc->tulip_setupmap);
                   3494:                sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_HASHONLY);
                   3495:                if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxINVRSFILT)
                   3496:                    sc->tulip_flags |= TULIP_HASHONLY;
                   3497:                if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == 0) {
                   3498:                    tulip_rx_intr(sc);
                   3499:                    sc->tulip_cmdmode |= TULIP_CMD_RXRUN;
                   3500:                    sc->tulip_intrmask |= TULIP_STS_RXSTOPPED;
                   3501:                    TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
                   3502:                    TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                   3503:                    TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                   3504:                }
                   3505:            } else {
                   3506:                const u_int32_t d_status = ri->ri_nextin->d_status;
                   3507:                IF_DEQUEUE(&sc->tulip_txq, m);
                   3508:                if (m != NULL) {
                   3509:                    bus_dmamap_t map = TULIP_GETCTX(m, bus_dmamap_t);
                   3510:                    TULIP_TXMAP_POSTSYNC(sc, map);
                   3511:                    sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
                   3512: #if NBPFILTER > 0
                   3513:                    if (sc->tulip_bpf != NULL)
                   3514:                        bpf_mtap(sc->tulip_if.if_bpf, m, BPF_DIRECTION_OUT);
                   3515: #endif
                   3516:                    m_freem(m);
                   3517:                }
                   3518:                if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) {
                   3519:                    tulip_mediapoll_event_t event = TULIP_MEDIAPOLL_TXPROBE_OK;
                   3520:                    if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxEXCCOLL)) {
                   3521: #if defined(TULIP_DEBUG)
                   3522:                        if (d_status & TULIP_DSTS_TxNOCARR)
                   3523:                            sc->tulip_dbg.dbg_txprobe_nocarr++;
                   3524:                        if (d_status & TULIP_DSTS_TxEXCCOLL)
                   3525:                            sc->tulip_dbg.dbg_txprobe_exccoll++;
                   3526: #endif
                   3527:                        event = TULIP_MEDIAPOLL_TXPROBE_FAILED;
                   3528:                    }
                   3529:                    (*sc->tulip_boardsw->bd_media_poll)(sc, event);
                   3530:                    /*
                   3531:                     * Escape from the loop before media poll has reset the TULIP!
                   3532:                     */
                   3533:                    break;
                   3534:                } else {
                   3535:                    xmits++;
                   3536:                    if (d_status & TULIP_DSTS_ERRSUM) {
                   3537:                        sc->tulip_if.if_oerrors++;
                   3538:                        if (d_status & TULIP_DSTS_TxEXCCOLL)
                   3539:                            sc->tulip_dot3stats.dot3StatsExcessiveCollisions++;
                   3540:                        if (d_status & TULIP_DSTS_TxLATECOLL)
                   3541:                            sc->tulip_dot3stats.dot3StatsLateCollisions++;
                   3542:                        if (d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxCARRLOSS))
                   3543:                            sc->tulip_dot3stats.dot3StatsCarrierSenseErrors++;
                   3544:                        if (d_status & (TULIP_DSTS_TxUNDERFLOW|TULIP_DSTS_TxBABBLE))
                   3545:                            sc->tulip_dot3stats.dot3StatsInternalMacTransmitErrors++;
                   3546:                        if (d_status & TULIP_DSTS_TxUNDERFLOW)
                   3547:                            sc->tulip_dot3stats.dot3StatsInternalTransmitUnderflows++;
                   3548:                        if (d_status & TULIP_DSTS_TxBABBLE)
                   3549:                            sc->tulip_dot3stats.dot3StatsInternalTransmitBabbles++;
                   3550:                    } else {
                   3551:                        u_int32_t collisions =
                   3552:                            (d_status & TULIP_DSTS_TxCOLLMASK)
                   3553:                                >> TULIP_DSTS_V_TxCOLLCNT;
                   3554:                        sc->tulip_if.if_collisions += collisions;
                   3555:                        if (collisions == 1)
                   3556:                            sc->tulip_dot3stats.dot3StatsSingleCollisionFrames++;
                   3557:                        else if (collisions > 1)
                   3558:                            sc->tulip_dot3stats.dot3StatsMultipleCollisionFrames++;
                   3559:                        else if (d_status & TULIP_DSTS_TxDEFERRED)
                   3560:                            sc->tulip_dot3stats.dot3StatsDeferredTransmissions++;
                   3561:                        /*
                   3562:                         * SQE is only valid for 10baseT/BNC/AUI when not
                   3563:                         * running in full-duplex.  In order to speed up the
                   3564:                         * test, the corresponding bit in tulip_flags needs to
                   3565:                         * set as well to get us to count SQE Test Errors.
                   3566:                         */
                   3567:                        if (d_status & TULIP_DSTS_TxNOHRTBT & sc->tulip_flags)
                   3568:                            sc->tulip_dot3stats.dot3StatsSQETestErrors++;
                   3569:                    }
                   3570:                }
                   3571:            }
                   3572:        }
                   3573:
                   3574:        if (++ri->ri_nextin == ri->ri_last)
                   3575:            ri->ri_nextin = ri->ri_first;
                   3576:
                   3577:        if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
                   3578:            sc->tulip_if.if_flags &= ~IFF_OACTIVE;
                   3579:     }
                   3580:     /*
                   3581:      * If nothing left to transmit, disable the timer.
                   3582:      * Else if progress, reset the timer back to 2 ticks.
                   3583:      */
                   3584:     if (ri->ri_free == ri->ri_max || (sc->tulip_flags & TULIP_TXPROBE_ACTIVE))
                   3585:        sc->tulip_txtimer = 0;
                   3586:     else if (xmits > 0)
                   3587:        sc->tulip_txtimer = TULIP_TXTIMER;
                   3588:     sc->tulip_if.if_opackets += xmits;
                   3589:     TULIP_PERFEND(txintr);
                   3590:     return (descs);
                   3591: }
                   3592:
                   3593: void
                   3594: tulip_print_abnormal_interrupt(tulip_softc_t * const sc, u_int32_t csr)
                   3595: {
                   3596: #ifdef TULIP_DEBUG
                   3597:     const char * const *msgp = tulip_status_bits;
                   3598:     const char *sep;
                   3599:     u_int32_t mask;
                   3600:     const char thrsh[] = "72|128\0\0\0" "96|256\0\0\0" "128|512\0\0" "160|1024\0";
                   3601:
                   3602:     csr &= (1 << (sizeof(tulip_status_bits)/sizeof(tulip_status_bits[0]))) - 1;
                   3603:     printf(TULIP_PRINTF_FMT ": abnormal interrupt:", TULIP_PRINTF_ARGS);
                   3604:     for (sep = " ", mask = 1; mask <= csr; mask <<= 1, msgp++) {
                   3605:        if ((csr & mask) && *msgp != NULL) {
                   3606:            printf("%s%s", sep, *msgp);
                   3607:            if (mask == TULIP_STS_TXUNDERFLOW && (sc->tulip_flags & TULIP_NEWTXTHRESH)) {
                   3608:                sc->tulip_flags &= ~TULIP_NEWTXTHRESH;
                   3609:                if (sc->tulip_cmdmode & TULIP_CMD_STOREFWD)
                   3610:                    printf(" (switching to store-and-forward mode)");
                   3611:                else {
                   3612:                    printf(" (raising TX threshold to %s)",
                   3613:                           &thrsh[9 * ((sc->tulip_cmdmode & TULIP_CMD_THRESHOLDCTL) >> 14)]);
                   3614:                }
                   3615:            }
                   3616:            sep = ", ";
                   3617:        }
                   3618:     }
                   3619:     printf("\n");
                   3620: #endif
                   3621: }
                   3622:
                   3623: void
                   3624: tulip_intr_handler(tulip_softc_t * const sc, int *progress_p)
                   3625: {
                   3626:     TULIP_PERFSTART(intr)
                   3627:     u_int32_t csr;
                   3628:
                   3629:     while ((csr = TULIP_CSR_READ(sc, csr_status)) & sc->tulip_intrmask) {
                   3630:        *progress_p = 1;
                   3631:        TULIP_CSR_WRITE(sc, csr_status, csr);
                   3632:
                   3633:        if (csr & TULIP_STS_SYSERROR) {
                   3634:            sc->tulip_last_system_error = (csr & TULIP_STS_ERRORMASK) >> TULIP_STS_ERR_SHIFT;
                   3635:            if (sc->tulip_flags & TULIP_NOMESSAGES)
                   3636:                sc->tulip_flags |= TULIP_SYSTEMERROR;
                   3637:            else {
                   3638: #if defined(TULIP_DEBUG)
                   3639:                printf(TULIP_PRINTF_FMT ": system error: %s\n",
                   3640:                       TULIP_PRINTF_ARGS,
                   3641:                       tulip_system_errors[sc->tulip_last_system_error]);
                   3642: #endif
                   3643:            }
                   3644:            sc->tulip_flags |= TULIP_NEEDRESET;
                   3645:            sc->tulip_system_errors++;
                   3646:            break;
                   3647:        }
                   3648:        if (csr & (TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL) & sc->tulip_intrmask) {
                   3649: #if defined(TULIP_DEBUG)
                   3650:            sc->tulip_dbg.dbg_link_intrs++;
                   3651: #endif
                   3652:            if (sc->tulip_boardsw->bd_media_poll != NULL) {
                   3653:                (*sc->tulip_boardsw->bd_media_poll)(sc, csr & TULIP_STS_LINKFAIL
                   3654:                                                    ? TULIP_MEDIAPOLL_LINKFAIL
                   3655:                                                    : TULIP_MEDIAPOLL_LINKPASS);
                   3656:                csr &= ~TULIP_STS_ABNRMLINTR;
                   3657:            }
                   3658:            tulip_media_print(sc);
                   3659:        }
                   3660:        if (csr & (TULIP_STS_RXINTR|TULIP_STS_RXNOBUF)) {
                   3661:            u_int32_t misses = TULIP_CSR_READ(sc, csr_missed_frames);
                   3662:            if (csr & TULIP_STS_RXNOBUF)
                   3663:                sc->tulip_dot3stats.dot3StatsMissedFrames += misses & 0xFFFF;
                   3664:            /*
                   3665:             * Pass 2.[012] of the 21140A-A[CDE] may hang and/or corrupt data
                   3666:             * on receive overflows.
                   3667:             */
                   3668:           if ((misses & 0x0FFE0000) && (sc->tulip_features & TULIP_HAVE_RXBADOVRFLW)) {
                   3669:                sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
                   3670:                /*
                   3671:                 * Stop the receiver process and spin until it's stopped.
                   3672:                 * Tell rx_intr to drop the packets it dequeues.
                   3673:                 */
                   3674:                TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode & ~TULIP_CMD_RXRUN);
                   3675:                while ((TULIP_CSR_READ(sc, csr_status) & TULIP_STS_RXSTOPPED) == 0)
                   3676:                    ;
                   3677:                TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
                   3678:                sc->tulip_flags |= TULIP_RXIGNORE;
                   3679:            }
                   3680:            tulip_rx_intr(sc);
                   3681:            if (sc->tulip_flags & TULIP_RXIGNORE) {
                   3682:                /*
                   3683:                 * Restart the receiver.
                   3684:                 */
                   3685:                sc->tulip_flags &= ~TULIP_RXIGNORE;
                   3686:                TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                   3687:            }
                   3688:        }
                   3689:        if (csr & TULIP_STS_ABNRMLINTR) {
                   3690:            u_int32_t tmp = csr & sc->tulip_intrmask
                   3691:                & ~(TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR);
                   3692:            if (csr & TULIP_STS_TXUNDERFLOW) {
                   3693: #if defined(TULIP_DEBUG)
                   3694:                printf ("Underflow interrupt\n");
                   3695: #endif
                   3696:                if ((sc->tulip_cmdmode & TULIP_CMD_THRESHOLDCTL) != TULIP_CMD_THRSHLD160) {
                   3697:                    sc->tulip_cmdmode += TULIP_CMD_THRSHLD96;
                   3698:                    sc->tulip_flags |= TULIP_NEWTXTHRESH;
                   3699:                } else if (sc->tulip_features & TULIP_HAVE_STOREFWD) {
                   3700:                    sc->tulip_cmdmode |= TULIP_CMD_STOREFWD;
                   3701:                    sc->tulip_flags |= TULIP_NEWTXTHRESH;
                   3702:                }
                   3703:            }
                   3704:            if (sc->tulip_flags & TULIP_NOMESSAGES)
                   3705:                sc->tulip_statusbits |= tmp;
                   3706:            else {
                   3707:                tulip_print_abnormal_interrupt(sc, tmp);
                   3708:                sc->tulip_flags |= TULIP_NOMESSAGES;
                   3709:            }
                   3710:            TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode);
                   3711:        }
                   3712:        if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_TXPROBE_ACTIVE|TULIP_DOINGSETUP|TULIP_PROMISC)) {
                   3713:            tulip_tx_intr(sc);
                   3714:            if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0)
                   3715:                tulip_ifstart(&sc->tulip_if);
                   3716:        }
                   3717:     }
                   3718:     if (sc->tulip_flags & TULIP_NEEDRESET) {
                   3719:        tulip_reset(sc);
                   3720:        tulip_init(sc);
                   3721:     }
                   3722:     TULIP_PERFEND(intr);
                   3723: }
                   3724:
                   3725: int
                   3726: tulip_intr_shared(void *arg)
                   3727: {
                   3728:     tulip_softc_t * sc = arg;
                   3729:     int progress = 0;
                   3730:
                   3731:     for (; sc != NULL; sc = sc->tulip_slaves) {
                   3732: #if defined(TULIP_DEBUG)
                   3733:        sc->tulip_dbg.dbg_intrs++;
                   3734: #endif
                   3735:        tulip_intr_handler(sc, &progress);
                   3736:     }
                   3737:     return (progress);
                   3738: }
                   3739:
                   3740: int
                   3741: tulip_intr_normal(void *arg)
                   3742: {
                   3743:     tulip_softc_t * sc = (tulip_softc_t *) arg;
                   3744:     int progress = 0;
                   3745:
                   3746: #if defined(TULIP_DEBUG)
                   3747:     sc->tulip_dbg.dbg_intrs++;
                   3748: #endif
                   3749:     tulip_intr_handler(sc, &progress);
                   3750:
                   3751:     return (progress);
                   3752: }
                   3753:
                   3754: struct mbuf *
                   3755: tulip_mbuf_compress(struct mbuf *m)
                   3756: {
                   3757:     struct mbuf *m0;
                   3758: #if MCLBYTES >= ETHERMTU + 18
                   3759:     MGETHDR(m0, M_DONTWAIT, MT_DATA);
                   3760:     if (m0 != NULL) {
                   3761:        if (m->m_pkthdr.len > MHLEN) {
                   3762:            MCLGET(m0, M_DONTWAIT);
                   3763:            if ((m0->m_flags & M_EXT) == 0) {
                   3764:                m_freem(m);
                   3765:                m_freem(m0);
                   3766:                return (NULL);
                   3767:            }
                   3768:        }
                   3769:        m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
                   3770:        m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
                   3771:     }
                   3772: #else
                   3773:     int mlen = MHLEN;
                   3774:     int len = m->m_pkthdr.len;
                   3775:     struct mbuf **mp = &m0;
                   3776:
                   3777:     while (len > 0) {
                   3778:        if (mlen == MHLEN)
                   3779:            MGETHDR(*mp, M_DONTWAIT, MT_DATA);
                   3780:        else
                   3781:            MGET(*mp, M_DONTWAIT, MT_DATA);
                   3782:        if (*mp == NULL) {
                   3783:            m_freem(m0);
                   3784:            m0 = NULL;
                   3785:            break;
                   3786:        }
                   3787:        if (len > MLEN) {
                   3788:            MCLGET(*mp, M_DONTWAIT);
                   3789:            if (((*mp)->m_flags & M_EXT) == 0) {
                   3790:                m_freem(m0);
                   3791:                m0 = NULL;
                   3792:                break;
                   3793:            }
                   3794:            (*mp)->m_len = len <= MCLBYTES ? len : MCLBYTES;
                   3795:        else
                   3796:            (*mp)->m_len = len <= mlen ? len : mlen;
                   3797:        m_copydata(m, m->m_pkthdr.len - len,
                   3798:                   (*mp)->m_len, mtod((*mp), caddr_t));
                   3799:        len -= (*mp)->m_len;
                   3800:        mp = &(*mp)->m_next;
                   3801:        mlen = MLEN;
                   3802:     }
                   3803: #endif
                   3804:     m_freem(m);
                   3805:     return (m0);
                   3806: }
                   3807:
                   3808: struct mbuf *
                   3809: tulip_txput(tulip_softc_t * const sc, struct mbuf *m)
                   3810: {
                   3811:     TULIP_PERFSTART(txput)
                   3812:     tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
                   3813:     tulip_desc_t *eop, *nextout;
                   3814:     int segcnt, freedescs;
                   3815:     u_int32_t d_status;
                   3816:     bus_dmamap_t map;
                   3817:     int error;
                   3818:     struct ifnet *ifp = &sc->tulip_if;
                   3819:     struct mbuf *ombuf = m;
                   3820:     int compressed = 0;
                   3821:
                   3822: #if defined(TULIP_DEBUG)
                   3823:     if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
                   3824:        printf(TULIP_PRINTF_FMT ": txput%s: tx not running\n",
                   3825:               TULIP_PRINTF_ARGS,
                   3826:               (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) ? "(probe)" : "");
                   3827:        sc->tulip_flags |= TULIP_WANTTXSTART;
                   3828:        sc->tulip_dbg.dbg_txput_finishes[0]++;
                   3829:        goto finish;
                   3830:     }
                   3831: #endif
                   3832:
                   3833:     /*
                   3834:      * Now we try to fill in our transmit descriptors.  This is
                   3835:      * a bit reminiscent of going on the Ark two by two
                   3836:      * since each descriptor for the TULIP can describe
                   3837:      * two buffers.  So we advance through packet filling
                   3838:      * each of the two entries at a time to to fill each
                   3839:      * descriptor.  Clear the first and last segment bits
                   3840:      * in each descriptor (actually just clear everything
                   3841:      * but the end-of-ring or chain bits) to make sure
                   3842:      * we don't get messed up by previously sent packets.
                   3843:      *
                   3844:      * We may fail to put the entire packet on the ring if
                   3845:      * there is either not enough ring entries free or if the
                   3846:      * packet has more than MAX_TXSEG segments.  In the former
                   3847:      * case we will just wait for the ring to empty.  In the
                   3848:      * latter case we have to recopy.
                   3849:      */
                   3850:     d_status = 0;
                   3851:     eop = nextout = ri->ri_nextout;
                   3852:     segcnt = 0;
                   3853:     freedescs = ri->ri_free;
                   3854:
                   3855:     /*
                   3856:      * Reclaim some DMA maps from if we are out.
                   3857:      */
                   3858:     if (sc->tulip_txmaps_free == 0) {
                   3859: #if defined(TULIP_DEBUG)
                   3860:        sc->tulip_dbg.dbg_no_txmaps++;
                   3861: #endif
                   3862:        freedescs += tulip_tx_intr(sc);
                   3863:     }
                   3864:     if (sc->tulip_txmaps_free > 0)
                   3865:        map = sc->tulip_txmaps[sc->tulip_txmaps_free-1];
                   3866:     else {
                   3867:        sc->tulip_flags |= TULIP_WANTTXSTART;
                   3868: #if defined(TULIP_DEBUG)
                   3869:        sc->tulip_dbg.dbg_txput_finishes[1]++;
                   3870: #endif
                   3871:        goto finish;
                   3872:     }
                   3873:     error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
                   3874:     if (error != 0) {
                   3875:        if (error == EFBIG) {
                   3876:            /*
                   3877:             * The packet exceeds the number of transmit buffer
                   3878:             * entries that we can use for one packet, so we have
                   3879:             * to recopy it into one mbuf and then try again.
                   3880:             */
                   3881:            struct mbuf *tmp;
                   3882:            /*
                   3883:             * tulip_mbuf_compress() frees the original mbuf.
                   3884:             * thus, we have to remove the mbuf from the queue
                   3885:             * before calling it.
                   3886:             * we don't have to worry about space shortage
                   3887:             * after compressing the mbuf since the compressed
                   3888:             * mbuf will take only two segs.
                   3889:             */
                   3890:             if (compressed) {
                   3891:                 /* should not happen */
                   3892: #ifdef TULIP_DEBUG
                   3893:                 printf("tulip_txput: compress called twice!\n");
                   3894: #endif
                   3895:                 goto finish;
                   3896:            }
                   3897:            IFQ_DEQUEUE(&ifp->if_snd, tmp);
                   3898:            if (tmp != ombuf)
                   3899:                 panic("tulip_txput: different mbuf dequeued!");
                   3900:            compressed = 1;
                   3901:            m = tulip_mbuf_compress(m);
                   3902:            if (m == NULL) {
                   3903: #if defined(TULIP_DEBUG)
                   3904:                sc->tulip_dbg.dbg_txput_finishes[2]++;
                   3905: #endif
                   3906:                goto finish;
                   3907:            }
                   3908:            error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
                   3909:        }
                   3910:        if (error != 0) {
                   3911:            printf(TULIP_PRINTF_FMT ": unable to load tx map, "
                   3912:                   "error = %d\n", TULIP_PRINTF_ARGS, error);
                   3913: #if defined(TULIP_DEBUG)
                   3914:            sc->tulip_dbg.dbg_txput_finishes[3]++;
                   3915: #endif
                   3916:            goto finish;
                   3917:        }
                   3918:     }
                   3919:     if ((freedescs -= (map->dm_nsegs + 1) / 2) <= 0
                   3920:            /*
                   3921:             * See if there's any unclaimed space in the transmit ring.
                   3922:             */
                   3923:            && (freedescs += tulip_tx_intr(sc)) <= 0) {
                   3924:        /*
                   3925:         * There's no more room but since nothing
                   3926:         * has been committed at this point, just
                   3927:         * show output is active, put back the
                   3928:         * mbuf and return.
                   3929:         */
                   3930:        sc->tulip_flags |= TULIP_WANTTXSTART;
                   3931: #if defined(TULIP_DEBUG)
                   3932:        sc->tulip_dbg.dbg_txput_finishes[4]++;
                   3933: #endif
                   3934:        bus_dmamap_unload(sc->tulip_dmatag, map);
                   3935:        goto finish;
                   3936:     }
                   3937:     for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
                   3938:        eop = nextout;
                   3939:        eop->d_flag   &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
                   3940:        eop->d_status  = d_status;
                   3941:        eop->d_addr1   = map->dm_segs[segcnt].ds_addr;
                   3942:        eop->d_length1 = map->dm_segs[segcnt].ds_len;
                   3943:        eop->d_addr2   = map->dm_segs[segcnt+1].ds_addr;
                   3944:        eop->d_length2 = map->dm_segs[segcnt+1].ds_len;
                   3945:        d_status = TULIP_DSTS_OWNER;
                   3946:        if (++nextout == ri->ri_last)
                   3947:            nextout = ri->ri_first;
                   3948:     }
                   3949:     if (segcnt < map->dm_nsegs) {
                   3950:        eop = nextout;
                   3951:        eop->d_flag   &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
                   3952:        eop->d_status  = d_status;
                   3953:        eop->d_addr1   = map->dm_segs[segcnt].ds_addr;
                   3954:        eop->d_length1 = map->dm_segs[segcnt].ds_len;
                   3955:        eop->d_addr2   = 0;
                   3956:        eop->d_length2 = 0;
                   3957:        if (++nextout == ri->ri_last)
                   3958:            nextout = ri->ri_first;
                   3959:     }
                   3960:     TULIP_TXMAP_PRESYNC(sc, map);
                   3961:     TULIP_SETCTX(m, map);
                   3962:     map = NULL;
                   3963:     --sc->tulip_txmaps_free;           /* commit to using the dmamap */
                   3964:
                   3965:     /*
                   3966:      * The descriptors have been filled in.  Now get ready
                   3967:      * to transmit.
                   3968:      */
                   3969:     if (!compressed && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) {
                   3970:        /* remove the mbuf from the queue */
                   3971:        struct mbuf *tmp;
                   3972:        IFQ_DEQUEUE(&ifp->if_snd, tmp);
                   3973:        if (tmp != ombuf)
                   3974:            panic("tulip_txput: different mbuf dequeued!");
                   3975:     }
                   3976:
                   3977:     IF_ENQUEUE(&sc->tulip_txq, m);
                   3978:     m = NULL;
                   3979:
                   3980:     /*
                   3981:      * Make sure the next descriptor after this packet is owned
                   3982:      * by us since it may have been set up above if we ran out
                   3983:      * of room in the ring.
                   3984:      */
                   3985:     nextout->d_status = 0;
                   3986:     TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
                   3987:
                   3988:     /*
                   3989:      * Mark the last and first segments, indicate we want a transmit
                   3990:      * complete interrupt, and tell it to transmit!
                   3991:      */
                   3992:     eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR;
                   3993:
                   3994:     /*
                   3995:      * Note that ri->ri_nextout is still the start of the packet
                   3996:      * and until we set the OWNER bit, we can still back out of
                   3997:      * everything we have done.
                   3998:      */
                   3999:     ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG;
                   4000:     if (eop < ri->ri_nextout) {
                   4001:        TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout,
                   4002:                             (caddr_t) ri->ri_last - (caddr_t) ri->ri_nextout);
                   4003:        TULIP_TXDESC_PRESYNC(sc, ri->ri_first,
                   4004:                             (caddr_t) (eop + 1) - (caddr_t) ri->ri_first);
                   4005:     } else {
                   4006:        TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout,
                   4007:                             (caddr_t) (eop + 1) - (caddr_t) ri->ri_nextout);
                   4008:     }
                   4009:     ri->ri_nextout->d_status = TULIP_DSTS_OWNER;
                   4010:     TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
                   4011:
                   4012:     /*
                   4013:      * This advances the ring for us.
                   4014:      */
                   4015:     ri->ri_nextout = nextout;
                   4016:     ri->ri_free = freedescs;
                   4017:
                   4018:     TULIP_PERFEND(txput);
                   4019:
                   4020:     if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) {
                   4021:        TULIP_CSR_WRITE(sc, csr_txpoll, 1);
                   4022:        sc->tulip_if.if_flags |= IFF_OACTIVE;
                   4023:        sc->tulip_if.if_start = tulip_ifstart;
                   4024:        TULIP_PERFEND(txput);
                   4025:        return (NULL);
                   4026:     }
                   4027:
                   4028:     /*
                   4029:      * switch back to the single queueing ifstart.
                   4030:      */
                   4031:     sc->tulip_flags &= ~TULIP_WANTTXSTART;
                   4032:     if (sc->tulip_txtimer == 0)
                   4033:        sc->tulip_txtimer = TULIP_TXTIMER;
                   4034: #if defined(TULIP_DEBUG)
                   4035:     sc->tulip_dbg.dbg_txput_finishes[5]++;
                   4036: #endif
                   4037:
                   4038:     /*
                   4039:      * If we want a txstart, there must be not enough space in the
                   4040:      * transmit ring.  So we want to enable transmit done interrupts
                   4041:      * so we can immediately reclaim some space.  When the transmit
                   4042:      * interrupt is posted, the interrupt handler will call tx_intr
                   4043:      * to reclaim space and then txstart (since WANTTXSTART is set).
                   4044:      * txstart will move the packet into the transmit ring and clear
                   4045:      * WANTTXSTART thereby causing TXINTR to be cleared.
                   4046:      */
                   4047:   finish:
                   4048: #if defined(TULIP_DEBUG)
                   4049:     sc->tulip_dbg.dbg_txput_finishes[6]++;
                   4050: #endif
                   4051:     if (sc->tulip_flags & (TULIP_WANTTXSTART|TULIP_DOINGSETUP)) {
                   4052:        sc->tulip_if.if_flags |= IFF_OACTIVE;
                   4053:        sc->tulip_if.if_start = tulip_ifstart;
                   4054:        if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
                   4055:            sc->tulip_intrmask |= TULIP_STS_TXINTR;
                   4056:            TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                   4057:        }
                   4058:     } else if ((sc->tulip_flags & TULIP_PROMISC) == 0) {
                   4059:        if (sc->tulip_intrmask & TULIP_STS_TXINTR) {
                   4060:            sc->tulip_intrmask &= ~TULIP_STS_TXINTR;
                   4061:            TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                   4062:        }
                   4063:     }
                   4064:     TULIP_CSR_WRITE(sc, csr_txpoll, 1);
                   4065:     TULIP_PERFEND(txput);
                   4066:     return (m);
                   4067: }
                   4068:
                   4069: void
                   4070: tulip_txput_setup(tulip_softc_t * const sc)
                   4071: {
                   4072:     tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
                   4073:     tulip_desc_t *nextout;
                   4074:
                   4075:     /*
                   4076:      * We will transmit, at most, one setup packet per call to ifstart.
                   4077:      */
                   4078:
                   4079: #if defined(TULIP_DEBUG)
                   4080:     if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
                   4081:        printf(TULIP_PRINTF_FMT ": txput_setup: tx not running\n",
                   4082:               TULIP_PRINTF_ARGS);
                   4083:        sc->tulip_flags |= TULIP_WANTTXSTART;
                   4084:        sc->tulip_if.if_start = tulip_ifstart;
                   4085:        return;
                   4086:     }
                   4087: #endif
                   4088:     /*
                   4089:      * Try to reclaim some free descriptors..
                   4090:      */
                   4091:     if (ri->ri_free < 2)
                   4092:        tulip_tx_intr(sc);
                   4093:     if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) {
                   4094:        sc->tulip_flags |= TULIP_WANTTXSTART;
                   4095:        sc->tulip_if.if_start = tulip_ifstart;
                   4096:        return;
                   4097:     }
                   4098:     bcopy(sc->tulip_setupdata, sc->tulip_setupbuf,
                   4099:          sizeof(sc->tulip_setupbuf));
                   4100:     /*
                   4101:      * Clear WANTSETUP and set DOINGSETUP.  Set know that WANTSETUP is
                   4102:      * set and DOINGSETUP is clear doing an XOR of the two will DTRT.
                   4103:      */
                   4104:     sc->tulip_flags ^= TULIP_WANTSETUP|TULIP_DOINGSETUP;
                   4105:     ri->ri_free--;
                   4106:     nextout = ri->ri_nextout;
                   4107:     nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
                   4108:     nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG
                   4109:        |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR;
                   4110:     if (sc->tulip_flags & TULIP_WANTHASHPERFECT)
                   4111:        nextout->d_flag |= TULIP_DFLAG_TxHASHFILT;
                   4112:     else if (sc->tulip_flags & TULIP_WANTHASHONLY)
                   4113:        nextout->d_flag |= TULIP_DFLAG_TxHASHFILT|TULIP_DFLAG_TxINVRSFILT;
                   4114:
                   4115:     nextout->d_length2 = 0;
                   4116:     nextout->d_addr2 = 0;
                   4117:     nextout->d_length1 = sc->tulip_setupmap->dm_segs[0].ds_len;
                   4118:     nextout->d_addr1 = sc->tulip_setupmap->dm_segs[0].ds_addr;
                   4119:     if (sc->tulip_setupmap->dm_nsegs == 2) {
                   4120:        nextout->d_length2 = sc->tulip_setupmap->dm_segs[1].ds_len;
                   4121:        nextout->d_addr2 = sc->tulip_setupmap->dm_segs[1].ds_addr;
                   4122:     }
                   4123:     TULIP_TXMAP_PRESYNC(sc, sc->tulip_setupmap);
                   4124:     TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(*nextout));
                   4125:
                   4126:     /*
                   4127:      * Advance the ring for the next transmit packet.
                   4128:      */
                   4129:     if (++ri->ri_nextout == ri->ri_last)
                   4130:        ri->ri_nextout = ri->ri_first;
                   4131:
                   4132:     /*
                   4133:      * Make sure the next descriptor is owned by us since it
                   4134:      * may have been set up above if we ran out of room in the
                   4135:      * ring.
                   4136:      */
                   4137:     ri->ri_nextout->d_status = 0;
                   4138:     TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
                   4139:     nextout->d_status = TULIP_DSTS_OWNER;
                   4140:     /*
                   4141:      * Flush the ownwership of the current descriptor
                   4142:      */
                   4143:     TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
                   4144:     TULIP_CSR_WRITE(sc, csr_txpoll, 1);
                   4145:     if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
                   4146:        sc->tulip_intrmask |= TULIP_STS_TXINTR;
                   4147:        TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask);
                   4148:     }
                   4149: }
                   4150:
                   4151: /*
                   4152:  * This routine is entered at splnet().
                   4153:  */
                   4154: int
                   4155: tulip_ifioctl(struct ifnet * ifp, u_long cmd, caddr_t data)
                   4156: {
                   4157:     TULIP_PERFSTART(ifioctl)
                   4158:     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
                   4159:     struct ifaddr *ifa = (struct ifaddr *)data;
                   4160:     struct ifreq *ifr = (struct ifreq *) data;
                   4161:     int s;
                   4162:     int error = 0;
                   4163:
                   4164:     s = splnet();
                   4165:
                   4166:     if ((error = ether_ioctl(ifp, &sc->tulip_ac, cmd, data)) > 0) {
                   4167:            splx(s);
                   4168:            return (error);
                   4169:     }
                   4170:
                   4171:     switch (cmd) {
                   4172:     case SIOCSIFADDR: {
                   4173:        ifp->if_flags |= IFF_UP;
                   4174:        tulip_init(sc);
                   4175:        switch(ifa->ifa_addr->sa_family) {
                   4176: #ifdef INET
                   4177:        case AF_INET: {
                   4178:            arp_ifinit(&sc->tulip_ac, ifa);
                   4179:            break;
                   4180:        }
                   4181: #endif /* INET */
                   4182:
                   4183:        default: {
                   4184:            break;
                   4185:        }
                   4186:        }
                   4187:        break;
                   4188:     }
                   4189:
                   4190:     case SIOCSIFFLAGS: {
                   4191:        tulip_init(sc);
                   4192:        break;
                   4193:     }
                   4194:
                   4195:     case SIOCSIFMEDIA:
                   4196:     case SIOCGIFMEDIA: {
                   4197:        error = ifmedia_ioctl(ifp, ifr, &sc->tulip_ifmedia, cmd);
                   4198:        break;
                   4199:     }
                   4200:
                   4201:     case SIOCADDMULTI:
                   4202:     case SIOCDELMULTI: {
                   4203:        /*
                   4204:         * Update multicast listeners
                   4205:         */
                   4206:        if (cmd == SIOCADDMULTI)
                   4207:            error = ether_addmulti(ifr, &sc->tulip_ac);
                   4208:        else
                   4209:            error = ether_delmulti(ifr, &sc->tulip_ac);
                   4210:
                   4211:        if (error == ENETRESET) {
                   4212:            if (ifp->if_flags & IFF_RUNNING) {
                   4213:                tulip_addr_filter(sc); /* reset multicast filtering */
                   4214:                tulip_init(sc);
                   4215:            }
                   4216:            error = 0;
                   4217:        }
                   4218:        break;
                   4219:     }
                   4220:
                   4221:     case SIOCSIFMTU:
                   4222:        /*
                   4223:         * Set the interface MTU.
                   4224:         */
                   4225:        if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
                   4226:            error = EINVAL;
                   4227:        else if (ifp->if_mtu != ifr->ifr_mtu)
                   4228:            ifp->if_mtu = ifr->ifr_mtu;
                   4229:        break;
                   4230:
                   4231:     default:
                   4232:        error = ENOTTY;
                   4233:        break;
                   4234:     }
                   4235:
                   4236:     splx(s);
                   4237:     TULIP_PERFEND(ifioctl);
                   4238:     return (error);
                   4239: }
                   4240:
                   4241: /*
                   4242:  * the original dequeueing policy is dequeue-and-prepend if something
                   4243:  * goes wrong.  when altq is used, it is changed to peek-and-dequeue.
                   4244:  * the modification becomes a bit complicated since tulip_txput() might
                   4245:  * copy and modify the mbuf passed.
                   4246:  */
                   4247: /*
                   4248:  * These routines gets called at device spl (from ether_output).
                   4249:  */
                   4250:
                   4251: void
                   4252: tulip_ifstart(struct ifnet * const ifp)
                   4253: {
                   4254:     TULIP_PERFSTART(ifstart)
                   4255:     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
                   4256:
                   4257:     if (sc->tulip_if.if_flags & IFF_RUNNING) {
                   4258:
                   4259:        if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
                   4260:            tulip_txput_setup(sc);
                   4261:
                   4262:        while (!IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
                   4263:            struct mbuf *m, *m0;
                   4264:            IFQ_POLL(&sc->tulip_if.if_snd, m);
                   4265:            if (m == NULL)
                   4266:                break;
                   4267:            if ((m0 = tulip_txput(sc, m)) != NULL) {
                   4268:                if (m0 != m)
                   4269:                    /* should not happen */
                   4270:                    printf("tulip_if_start: txput failed!\n");
                   4271:                break;
                   4272:            }
                   4273:        }
                   4274: #ifdef ALTQ
                   4275:        if (0) /* don't switch to the one packet mode */
                   4276: #else
                   4277:        if (IFQ_IS_EMPTY(&sc->tulip_if.if_snd))
                   4278: #endif
                   4279:            sc->tulip_if.if_start = tulip_ifstart_one;
                   4280:     }
                   4281:
                   4282:     TULIP_PERFEND(ifstart);
                   4283: }
                   4284:
                   4285: void
                   4286: tulip_ifstart_one(struct ifnet * const ifp)
                   4287: {
                   4288:     TULIP_PERFSTART(ifstart_one)
                   4289:     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
                   4290:
                   4291:     if ((sc->tulip_if.if_flags & IFF_RUNNING)
                   4292:            && !IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) {
                   4293:        struct mbuf *m, *m0;
                   4294:        IFQ_POLL(&sc->tulip_if.if_snd, m);
                   4295:        if (m != NULL && (m0 = tulip_txput(sc, m)) != NULL)
                   4296:            if (m0 != m)
                   4297:                /* should not happen */
                   4298:                printf("tulip_if_start_one: txput failed!\n");
                   4299:     }
                   4300:     TULIP_PERFEND(ifstart_one);
                   4301: }
                   4302:
                   4303: void
                   4304: tulip_ifwatchdog(struct ifnet *ifp)
                   4305: {
                   4306:     TULIP_PERFSTART(ifwatchdog)
                   4307:     tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
                   4308:
                   4309: #if defined(TULIP_DEBUG)
                   4310:     u_int32_t rxintrs = sc->tulip_dbg.dbg_rxintrs - sc->tulip_dbg.dbg_last_rxintrs;
                   4311:     if (rxintrs > sc->tulip_dbg.dbg_high_rxintrs_hz)
                   4312:        sc->tulip_dbg.dbg_high_rxintrs_hz = rxintrs;
                   4313:     sc->tulip_dbg.dbg_last_rxintrs = sc->tulip_dbg.dbg_rxintrs;
                   4314: #endif /* TULIP_DEBUG */
                   4315:
                   4316:     sc->tulip_if.if_timer = 1;
                   4317:     /*
                   4318:      * These should be rare so do a bulk test up front so we can just skip
                   4319:      * them if needed.
                   4320:      */
                   4321:     if (sc->tulip_flags & (TULIP_SYSTEMERROR|TULIP_RXBUFSLOW|TULIP_NOMESSAGES)) {
                   4322:        /*
                   4323:         * If the number of receive buffer is low, try to refill
                   4324:         */
                   4325:        if (sc->tulip_flags & TULIP_RXBUFSLOW)
                   4326:            tulip_rx_intr(sc);
                   4327:
                   4328: #if defined(TULIP_DEBUG)
                   4329:        if (sc->tulip_flags & TULIP_SYSTEMERROR) {
                   4330:            printf(TULIP_PRINTF_FMT ": %d system errors: last was %s\n",
                   4331:                   TULIP_PRINTF_ARGS, sc->tulip_system_errors,
                   4332:                   tulip_system_errors[sc->tulip_last_system_error]);
                   4333:        }
                   4334: #endif
                   4335:        if (sc->tulip_statusbits) {
                   4336:            tulip_print_abnormal_interrupt(sc, sc->tulip_statusbits);
                   4337:            sc->tulip_statusbits = 0;
                   4338:        }
                   4339:
                   4340:        sc->tulip_flags &= ~(TULIP_NOMESSAGES|TULIP_SYSTEMERROR);
                   4341:     }
                   4342:
                   4343:     if (sc->tulip_txtimer)
                   4344:        tulip_tx_intr(sc);
                   4345:     if (sc->tulip_txtimer && --sc->tulip_txtimer == 0) {
                   4346:        printf(TULIP_PRINTF_FMT ": transmission timeout\n", TULIP_PRINTF_ARGS);
                   4347:        if (TULIP_DO_AUTOSENSE(sc)) {
                   4348:            sc->tulip_media = TULIP_MEDIA_UNKNOWN;
                   4349:            sc->tulip_probe_state = TULIP_PROBE_INACTIVE;
                   4350:            sc->tulip_flags &= ~(TULIP_WANTRXACT|TULIP_LINKUP);
                   4351:        }
                   4352:        tulip_reset(sc);
                   4353:        tulip_init(sc);
                   4354:     }
                   4355:
                   4356:     TULIP_PERFEND(ifwatchdog);
                   4357:     TULIP_PERFMERGE(sc, perf_intr_cycles);
                   4358:     TULIP_PERFMERGE(sc, perf_ifstart_cycles);
                   4359:     TULIP_PERFMERGE(sc, perf_ifioctl_cycles);
                   4360:     TULIP_PERFMERGE(sc, perf_ifwatchdog_cycles);
                   4361:     TULIP_PERFMERGE(sc, perf_timeout_cycles);
                   4362:     TULIP_PERFMERGE(sc, perf_ifstart_one_cycles);
                   4363:     TULIP_PERFMERGE(sc, perf_txput_cycles);
                   4364:     TULIP_PERFMERGE(sc, perf_txintr_cycles);
                   4365:     TULIP_PERFMERGE(sc, perf_rxintr_cycles);
                   4366:     TULIP_PERFMERGE(sc, perf_rxget_cycles);
                   4367:     TULIP_PERFMERGE(sc, perf_intr);
                   4368:     TULIP_PERFMERGE(sc, perf_ifstart);
                   4369:     TULIP_PERFMERGE(sc, perf_ifioctl);
                   4370:     TULIP_PERFMERGE(sc, perf_ifwatchdog);
                   4371:     TULIP_PERFMERGE(sc, perf_timeout);
                   4372:     TULIP_PERFMERGE(sc, perf_ifstart_one);
                   4373:     TULIP_PERFMERGE(sc, perf_txput);
                   4374:     TULIP_PERFMERGE(sc, perf_txintr);
                   4375:     TULIP_PERFMERGE(sc, perf_rxintr);
                   4376:     TULIP_PERFMERGE(sc, perf_rxget);
                   4377: }
                   4378:
                   4379: /*
                   4380:  * All printf's are real as of now!
                   4381:  */
                   4382: #ifdef printf
                   4383: #undef printf
                   4384: #endif
                   4385:
                   4386: int
                   4387: tulip_busdma_allocmem(tulip_softc_t * const sc, size_t size,
                   4388:     bus_dmamap_t *map_p, tulip_desc_t **desc_p)
                   4389: {
                   4390:     bus_dma_segment_t segs[1];
                   4391:     int nsegs, error;
                   4392:     error = bus_dmamem_alloc(sc->tulip_dmatag, size, 1, PAGE_SIZE,
                   4393:                             segs, sizeof(segs)/sizeof(segs[0]),
                   4394:                             &nsegs, BUS_DMA_NOWAIT);
                   4395:     if (error == 0) {
                   4396:        void *desc;
                   4397:        error = bus_dmamem_map(sc->tulip_dmatag, segs, nsegs, size,
                   4398:                               (void *) &desc, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
                   4399:        if (error == 0) {
                   4400:            bus_dmamap_t map;
                   4401:            error = bus_dmamap_create(sc->tulip_dmatag, size, 1, size, 0,
                   4402:                                      BUS_DMA_NOWAIT, &map);
                   4403:            if (error == 0) {
                   4404:                error = bus_dmamap_load(sc->tulip_dmatag, map, desc,
                   4405:                                        size, NULL, BUS_DMA_NOWAIT);
                   4406:                if (error)
                   4407:                    bus_dmamap_destroy(sc->tulip_dmatag, map);
                   4408:                else
                   4409:                    *map_p = map;
                   4410:            }
                   4411:            if (error)
                   4412:                bus_dmamem_unmap(sc->tulip_dmatag, desc, size);
                   4413:        }
                   4414:        if (error)
                   4415:            bus_dmamem_free(sc->tulip_dmatag, segs, nsegs);
                   4416:        else
                   4417:            *desc_p = desc;
                   4418:     }
                   4419:     return (error);
                   4420: }
                   4421:
                   4422: int
                   4423: tulip_busdma_init(tulip_softc_t * const sc)
                   4424: {
                   4425:     int error = 0;
                   4426:
                   4427:     /*
                   4428:      * Allocate dmamap for setup descriptor
                   4429:      */
                   4430:     error = bus_dmamap_create(sc->tulip_dmatag, sizeof(sc->tulip_setupbuf), 2,
                   4431:                              sizeof(sc->tulip_setupbuf), 0, BUS_DMA_NOWAIT,
                   4432:                              &sc->tulip_setupmap);
                   4433:     if (error == 0) {
                   4434:        error = bus_dmamap_load(sc->tulip_dmatag, sc->tulip_setupmap,
                   4435:                                sc->tulip_setupbuf, sizeof(sc->tulip_setupbuf),
                   4436:                                NULL, BUS_DMA_NOWAIT);
                   4437:        if (error)
                   4438:            bus_dmamap_destroy(sc->tulip_dmatag, sc->tulip_setupmap);
                   4439:     }
                   4440:     /*
                   4441:      * Allocate space and dmamap for transmit ring
                   4442:      */
                   4443:     if (error == 0) {
                   4444:        error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_TXDESCS,
                   4445:                                      &sc->tulip_txdescmap,
                   4446:                                      &sc->tulip_txdescs);
                   4447:     }
                   4448:
                   4449:     /*
                   4450:      * Allocate dmamaps for each transmit descriptors
                   4451:      */
                   4452:     if (error == 0) {
                   4453:        while (error == 0 && sc->tulip_txmaps_free < TULIP_TXDESCS) {
                   4454:            bus_dmamap_t map;
                   4455:            if ((error = TULIP_TXMAP_CREATE(sc, &map)) == 0)
                   4456:                sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
                   4457:        }
                   4458:        if (error) {
                   4459:            while (sc->tulip_txmaps_free > 0)
                   4460:                bus_dmamap_destroy(sc->tulip_dmatag,
                   4461:                                   sc->tulip_txmaps[--sc->tulip_txmaps_free]);
                   4462:        }
                   4463:     }
                   4464:
                   4465:     /*
                   4466:      * Allocate space and dmamap for receive ring
                   4467:      */
                   4468:     if (error == 0) {
                   4469:        error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_RXDESCS,
                   4470:                                      &sc->tulip_rxdescmap,
                   4471:                                      &sc->tulip_rxdescs);
                   4472:     }
                   4473:
                   4474:     /*
                   4475:      * Allocate dmamaps for each receive descriptors
                   4476:      */
                   4477:     if (error == 0) {
                   4478:        while (error == 0 && sc->tulip_rxmaps_free < TULIP_RXDESCS) {
                   4479:            bus_dmamap_t map;
                   4480:            if ((error = TULIP_RXMAP_CREATE(sc, &map)) == 0)
                   4481:                sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
                   4482:        }
                   4483:        if (error) {
                   4484:            while (sc->tulip_rxmaps_free > 0)
                   4485:                bus_dmamap_destroy(sc->tulip_dmatag,
                   4486:                                   sc->tulip_rxmaps[--sc->tulip_rxmaps_free]);
                   4487:        }
                   4488:     }
                   4489:     return (error);
                   4490: }
                   4491:
                   4492: void
                   4493: tulip_initcsrs(tulip_softc_t * const sc, bus_addr_t csr_base, size_t csr_size)
                   4494: {
                   4495:     sc->tulip_csrs.csr_busmode         = csr_base +  0 * csr_size;
                   4496:     sc->tulip_csrs.csr_txpoll          = csr_base +  1 * csr_size;
                   4497:     sc->tulip_csrs.csr_rxpoll          = csr_base +  2 * csr_size;
                   4498:     sc->tulip_csrs.csr_rxlist          = csr_base +  3 * csr_size;
                   4499:     sc->tulip_csrs.csr_txlist          = csr_base +  4 * csr_size;
                   4500:     sc->tulip_csrs.csr_status          = csr_base +  5 * csr_size;
                   4501:     sc->tulip_csrs.csr_command         = csr_base +  6 * csr_size;
                   4502:     sc->tulip_csrs.csr_intr            = csr_base +  7 * csr_size;
                   4503:     sc->tulip_csrs.csr_missed_frames   = csr_base +  8 * csr_size;
                   4504:     sc->tulip_csrs.csr_9               = csr_base +  9 * csr_size;
                   4505:     sc->tulip_csrs.csr_10              = csr_base + 10 * csr_size;
                   4506:     sc->tulip_csrs.csr_11              = csr_base + 11 * csr_size;
                   4507:     sc->tulip_csrs.csr_12              = csr_base + 12 * csr_size;
                   4508:     sc->tulip_csrs.csr_13              = csr_base + 13 * csr_size;
                   4509:     sc->tulip_csrs.csr_14              = csr_base + 14 * csr_size;
                   4510:     sc->tulip_csrs.csr_15              = csr_base + 15 * csr_size;
                   4511: }
                   4512:
                   4513: void
                   4514: tulip_initring(tulip_softc_t * const sc, tulip_ringinfo_t * const ri,
                   4515:     tulip_desc_t *descs, int ndescs)
                   4516: {
                   4517:     ri->ri_max = ndescs;
                   4518:     ri->ri_first = descs;
                   4519:     ri->ri_last = ri->ri_first + ri->ri_max;
                   4520:     bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max);
                   4521:     ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING;
                   4522: }
                   4523:
                   4524: int
                   4525: tulip_probe(struct device *parent, void *match, void *aux)
                   4526: {
                   4527:     struct pci_attach_args *pa = (struct pci_attach_args *) aux;
                   4528:
                   4529:     if (PCI_VENDORID(pa->pa_id) != DEC_VENDORID)
                   4530:        return (0);
                   4531:     if (PCI_CHIPID(pa->pa_id) == CHIPID_21040
                   4532:            || PCI_CHIPID(pa->pa_id) == CHIPID_21041
                   4533:            || PCI_CHIPID(pa->pa_id) == CHIPID_21140
                   4534:            || PCI_CHIPID(pa->pa_id) == CHIPID_21142)
                   4535:        return (2);
                   4536:
                   4537:     return (0);
                   4538: }
                   4539:
                   4540: void
                   4541: tulip_shutdown(void *arg)
                   4542: {
                   4543:     tulip_softc_t * const sc = arg;
                   4544:     TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
                   4545:     DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at
                   4546:                   33MHz that comes to two microseconds but wait a
                   4547:                   bit longer anyways) */
                   4548: }
                   4549:
                   4550: void
                   4551: tulip_attach(struct device * const parent, struct device * const self, void * const aux)
                   4552: {
                   4553:     tulip_softc_t * const sc = (tulip_softc_t *) self;
                   4554:     struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
                   4555:     struct ifnet * const ifp = &sc->tulip_if;
                   4556:     const int unit = sc->tulip_dev.dv_unit;
                   4557:     int retval, idx;
                   4558:     u_int32_t revinfo, cfdainfo, id;
                   4559:     unsigned csroffset = TULIP_PCI_CSROFFSET;
                   4560:     unsigned csrsize = TULIP_PCI_CSRSIZE;
                   4561:     bus_addr_t csr_base;
                   4562:     tulip_chipid_t chipid = TULIP_CHIPID_UNKNOWN;
                   4563:
                   4564:     if (unit >= TULIP_MAX_DEVICES) {
                   4565:        printf(": not configured; limit of %d reached or exceeded\n",
                   4566:               TULIP_MAX_DEVICES);
                   4567:        return;
                   4568:     }
                   4569:
                   4570:     revinfo  = PCI_CONF_READ(PCI_CFRV) & 0xFF;
                   4571:     id       = PCI_CONF_READ(PCI_CFID);
                   4572:     cfdainfo = PCI_CONF_READ(PCI_CFDA);
                   4573:
                   4574:     if (PCI_VENDORID(id) == DEC_VENDORID) {
                   4575:        if (PCI_CHIPID(id) == CHIPID_21040)
                   4576:                chipid = TULIP_21040;
                   4577:        else if (PCI_CHIPID(id) == CHIPID_21041)
                   4578:                chipid = TULIP_21041;
                   4579:        else if (PCI_CHIPID(id) == CHIPID_21140)
                   4580:                chipid = (revinfo >= 0x20) ? TULIP_21140A : TULIP_21140;
                   4581:        else if (PCI_CHIPID(id) == CHIPID_21142)
                   4582:                chipid = (revinfo >= 0x20) ? TULIP_21143 : TULIP_21142;
                   4583:     }
                   4584:
                   4585:     if (chipid == TULIP_CHIPID_UNKNOWN)
                   4586:        return;
                   4587:
                   4588:     if ((chipid == TULIP_21040 || chipid == TULIP_DE425) && revinfo < 0x20) {
                   4589:        printf(": not configured; 21040 pass 2.0 required (%d.%d found)\n",
                   4590:               revinfo >> 4, revinfo & 0x0f);
                   4591:        return;
                   4592:     } else if (chipid == TULIP_21140 && revinfo < 0x11) {
                   4593:        printf(": not configured; 21140 pass 1.1 required (%d.%d found)\n",
                   4594:               revinfo >> 4, revinfo & 0x0f);
                   4595:        return;
                   4596:     }
                   4597:
                   4598:     PCI_GETBUSDEVINFO(sc);
                   4599:     sc->tulip_chipid = chipid;
                   4600:     sc->tulip_flags |= TULIP_DEVICEPROBE;
                   4601:     if (chipid == TULIP_21140 || chipid == TULIP_21140A)
                   4602:        sc->tulip_features |= TULIP_HAVE_GPR|TULIP_HAVE_STOREFWD;
                   4603:     if (chipid == TULIP_21140A && revinfo <= 0x22)
                   4604:        sc->tulip_features |= TULIP_HAVE_RXBADOVRFLW;
                   4605:     if (chipid == TULIP_21140)
                   4606:        sc->tulip_features |= TULIP_HAVE_BROKEN_HASH;
                   4607:     if (chipid != TULIP_21040 && chipid != TULIP_DE425 && chipid != TULIP_21140)
                   4608:        sc->tulip_features |= TULIP_HAVE_POWERMGMT;
                   4609:     if (chipid == TULIP_21041 || chipid == TULIP_21142 || chipid == TULIP_21143) {
                   4610:        sc->tulip_features |= TULIP_HAVE_DUALSENSE;
                   4611:        if (chipid != TULIP_21041 || revinfo >= 0x20)
                   4612:            sc->tulip_features |= TULIP_HAVE_SIANWAY;
                   4613:        if (chipid != TULIP_21041)
                   4614:            sc->tulip_features |= TULIP_HAVE_SIAGP|TULIP_HAVE_RXBADOVRFLW|TULIP_HAVE_STOREFWD;
                   4615:        if (chipid != TULIP_21041 && revinfo >= 0x20)
                   4616:            sc->tulip_features |= TULIP_HAVE_SIA100;
                   4617:     }
                   4618:
                   4619:     if (sc->tulip_features & TULIP_HAVE_POWERMGMT
                   4620:            && (cfdainfo & (TULIP_CFDA_SLEEP|TULIP_CFDA_SNOOZE))) {
                   4621:        cfdainfo &= ~(TULIP_CFDA_SLEEP|TULIP_CFDA_SNOOZE);
                   4622:        PCI_CONF_WRITE(PCI_CFDA, cfdainfo);
                   4623:        DELAY(11*1000);
                   4624:     }
                   4625:
                   4626:     if (sc->tulip_features & TULIP_HAVE_STOREFWD)
                   4627:            sc->tulip_cmdmode |= TULIP_CMD_STOREFWD;
                   4628:
                   4629:     bcopy(self->dv_xname, sc->tulip_if.if_xname, IFNAMSIZ);
                   4630:     sc->tulip_if.if_softc = sc;
                   4631:     sc->tulip_pc = pa->pa_pc;
                   4632:     sc->tulip_dmatag = pa->pa_dmat;
                   4633:     sc->tulip_revinfo = revinfo;
                   4634:
                   4635:     timeout_set(&sc->tulip_stmo, tulip_timeout_callback, sc);
                   4636:
                   4637:     csr_base = 0;
                   4638:     {
                   4639:        bus_space_tag_t iot, memt;
                   4640:        bus_space_handle_t ioh, memh;
                   4641:        int ioh_valid, memh_valid;
                   4642:
                   4643:        ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
                   4644:                 &iot, &ioh, NULL, NULL, 0) == 0);
                   4645:        memh_valid = (pci_mapreg_map(pa, PCI_CBMA,
                   4646:                  PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
                   4647:                  &memt, &memh, NULL, NULL, 0) == 0);
                   4648:
                   4649:        if (memh_valid) {
                   4650:            sc->tulip_bustag = memt;
                   4651:            sc->tulip_bushandle = memh;
                   4652:        } else if (ioh_valid) {
                   4653:            sc->tulip_bustag = iot;
                   4654:            sc->tulip_bushandle = ioh;
                   4655:        } else {
                   4656:           printf(": unable to map device registers\n");
                   4657:            return;
                   4658:        }
                   4659:     }
                   4660:
                   4661:     tulip_initcsrs(sc, csr_base + csroffset, csrsize);
                   4662:
                   4663:     if ((retval = tulip_busdma_init(sc)) != 0) {
                   4664:        printf(": error initing bus_dma: %d\n", retval);
                   4665:        return;
                   4666:     }
                   4667:
                   4668:     tulip_initring(sc, &sc->tulip_rxinfo, sc->tulip_rxdescs, TULIP_RXDESCS);
                   4669:     tulip_initring(sc, &sc->tulip_txinfo, sc->tulip_txdescs, TULIP_TXDESCS);
                   4670:
                   4671:     /*
                   4672:      * Make sure there won't be any interrupts or such...
                   4673:      */
                   4674:     TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
                   4675:     DELAY(100);        /* Wait 10 microseconds (actually 50 PCI cycles but at
                   4676:                   33MHz that comes to two microseconds but wait a
                   4677:                   bit longer anyways) */
                   4678:
                   4679:     if ((retval = tulip_read_macaddr(sc)) < 0) {
                   4680:        printf(", %s%s pass %d.%d", sc->tulip_boardid,
                   4681:             tulip_chipdescs[sc->tulip_chipid],
                   4682:              (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F);
                   4683:        printf(": can't read ENET ROM (why=%d) (", retval);
                   4684:        for (idx = 0; idx < 32; idx++)
                   4685:            printf("%02x", sc->tulip_rombuf[idx]);
                   4686:        printf(", address unknown\n");
                   4687:     } else {
                   4688:        int (*intr_rtn)(void *) = tulip_intr_normal;
                   4689:
                   4690:        if (sc->tulip_features & TULIP_HAVE_SHAREDINTR)
                   4691:            intr_rtn = tulip_intr_shared;
                   4692:
                   4693:        if ((sc->tulip_features & TULIP_HAVE_SLAVEDINTR) == 0) {
                   4694:            pci_intr_handle_t intrhandle;
                   4695:            const char *intrstr;
                   4696:
                   4697:            if (pci_intr_map(pa, &intrhandle)) {
                   4698:                printf(": couldn't map interrupt\n");
                   4699:                return;
                   4700:            }
                   4701:
                   4702:            intrstr = pci_intr_string(pa->pa_pc, intrhandle);
                   4703:            sc->tulip_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET,
                   4704:                                              intr_rtn, sc, self->dv_xname);
                   4705:            if (sc->tulip_ih == NULL) {
                   4706:                printf(": couldn't establish interrupt");
                   4707:                if (intrstr != NULL)
                   4708:                    printf(" at %s", intrstr);
                   4709:                printf("\n");
                   4710:                return;
                   4711:            }
                   4712:
                   4713:            printf(", %s%s pass %d.%d%s: %s, address %s\n",
                   4714:                   sc->tulip_boardid,
                   4715:                   tulip_chipdescs[sc->tulip_chipid],
                   4716:                   (sc->tulip_revinfo & 0xF0) >> 4,
                   4717:                        sc->tulip_revinfo & 0x0F,
                   4718:                        (sc->tulip_features & (TULIP_HAVE_ISVSROM|TULIP_HAVE_OKSROM))
                   4719:                        == TULIP_HAVE_ISVSROM ? " (invalid EESPROM checksum)" : "",
                   4720:                   intrstr, ether_sprintf(sc->tulip_enaddr));
                   4721:        }
                   4722:
                   4723:        sc->tulip_ats = shutdownhook_establish(tulip_shutdown, sc);
                   4724:        if (sc->tulip_ats == NULL)
                   4725:            printf("%s: warning: couldn't establish shutdown hook\n",
                   4726:                   sc->tulip_xname);
                   4727:
                   4728:        ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
                   4729:        ifp->if_ioctl = tulip_ifioctl;
                   4730:        ifp->if_start = tulip_ifstart;
                   4731:        ifp->if_watchdog = tulip_ifwatchdog;
                   4732:        ifp->if_timer = 1;
                   4733:
                   4734:        (*sc->tulip_boardsw->bd_media_probe)(sc);
                   4735:        ifmedia_init(&sc->tulip_ifmedia, 0,
                   4736:            tulip_ifmedia_change, tulip_ifmedia_status);
                   4737:        sc->tulip_flags &= ~TULIP_DEVICEPROBE;
                   4738:        tulip_ifmedia_add(sc);
                   4739:
                   4740:        tulip_reset(sc);
                   4741:
                   4742:        IFQ_SET_READY(&ifp->if_snd);
                   4743:        if_attach(ifp);
                   4744:        ether_ifattach(ifp);
                   4745:     }
                   4746: }

CVSweb