[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     ! 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