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