if_tlp_eisa.c revision 1.2
11.2Sthorpej/* $NetBSD: if_tlp_eisa.c,v 1.2 1999/09/14 22:25:48 thorpej Exp $ */ 21.1Sthorpej 31.1Sthorpej/*- 41.1Sthorpej * Copyright (c) 1999 The NetBSD Foundation, Inc. 51.1Sthorpej * All rights reserved. 61.1Sthorpej * 71.1Sthorpej * This code is derived from software contributed to The NetBSD Foundation 81.1Sthorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 91.1Sthorpej * NASA Ames Research Center. 101.1Sthorpej * 111.1Sthorpej * Redistribution and use in source and binary forms, with or without 121.1Sthorpej * modification, are permitted provided that the following conditions 131.1Sthorpej * are met: 141.1Sthorpej * 1. Redistributions of source code must retain the above copyright 151.1Sthorpej * notice, this list of conditions and the following disclaimer. 161.1Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 171.1Sthorpej * notice, this list of conditions and the following disclaimer in the 181.1Sthorpej * documentation and/or other materials provided with the distribution. 191.1Sthorpej * 3. All advertising materials mentioning features or use of this software 201.1Sthorpej * must display the following acknowledgement: 211.1Sthorpej * This product includes software developed by the NetBSD 221.1Sthorpej * Foundation, Inc. and its contributors. 231.1Sthorpej * 4. Neither the name of The NetBSD Foundation nor the names of its 241.1Sthorpej * contributors may be used to endorse or promote products derived 251.1Sthorpej * from this software without specific prior written permission. 261.1Sthorpej * 271.1Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 281.1Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 291.1Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 301.1Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 311.1Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 321.1Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 331.1Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 341.1Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 351.1Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 361.1Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 371.1Sthorpej * POSSIBILITY OF SUCH DAMAGE. 381.1Sthorpej */ 391.1Sthorpej 401.1Sthorpej/* 411.1Sthorpej * EISA bus front-end for the Digital Semiconductor ``Tulip'' (21x4x) 421.1Sthorpej * Ethernet controller family driver. 431.1Sthorpej */ 441.1Sthorpej 451.1Sthorpej#include "opt_inet.h" 461.1Sthorpej#include "opt_ns.h" 471.1Sthorpej#include "bpfilter.h" 481.1Sthorpej 491.1Sthorpej#include <sys/param.h> 501.1Sthorpej#include <sys/systm.h> 511.1Sthorpej#include <sys/mbuf.h> 521.1Sthorpej#include <sys/malloc.h> 531.1Sthorpej#include <sys/kernel.h> 541.1Sthorpej#include <sys/socket.h> 551.1Sthorpej#include <sys/ioctl.h> 561.1Sthorpej#include <sys/errno.h> 571.1Sthorpej#include <sys/device.h> 581.1Sthorpej 591.1Sthorpej#include <net/if.h> 601.1Sthorpej#include <net/if_dl.h> 611.1Sthorpej#include <net/if_media.h> 621.1Sthorpej#include <net/if_ether.h> 631.1Sthorpej 641.1Sthorpej#if NBPFILTER > 0 651.1Sthorpej#include <net/bpf.h> 661.1Sthorpej#endif 671.1Sthorpej 681.1Sthorpej#ifdef INET 691.1Sthorpej#include <netinet/in.h> 701.1Sthorpej#include <netinet/if_inarp.h> 711.1Sthorpej#endif 721.1Sthorpej 731.1Sthorpej#ifdef NS 741.1Sthorpej#include <netns/ns.h> 751.1Sthorpej#include <netns/ns_if.h> 761.1Sthorpej#endif 771.1Sthorpej 781.1Sthorpej#include <machine/bus.h> 791.1Sthorpej#include <machine/intr.h> 801.1Sthorpej 811.1Sthorpej#include <dev/mii/miivar.h> 821.1Sthorpej 831.1Sthorpej#include <dev/ic/tulipreg.h> 841.1Sthorpej#include <dev/ic/tulipvar.h> 851.1Sthorpej 861.1Sthorpej#include <dev/eisa/eisareg.h> 871.1Sthorpej#include <dev/eisa/eisavar.h> 881.1Sthorpej#include <dev/eisa/eisadevs.h> 891.1Sthorpej 901.1Sthorpej#include <dev/pci/pcireg.h> 911.1Sthorpej 921.1Sthorpej/* 931.1Sthorpej * DE425 configuration registers; literal offsets from CSR base. 941.1Sthorpej * This is effectively the 21040 PCI configuration space interleaved 951.1Sthorpej * into the CSR space (CSRs are space 16 bytes on the DE425). 961.1Sthorpej * 971.1Sthorpej * What a cool address decoder hack they must have on that board... 981.1Sthorpej */ 991.1Sthorpej#define DE425_CFID 0x08 /* Configuration ID */ 1001.1Sthorpej#define DE425_CFCS 0x0c /* Configuration Command-Status */ 1011.1Sthorpej#define DE425_CFRV 0x18 /* Configuration Revision */ 1021.1Sthorpej#define DE425_CFLT 0x1c /* Configuration Latency Timer */ 1031.1Sthorpej#define DE425_CBIO 0x28 /* Configuration Base I/O Address */ 1041.1Sthorpej#define DE425_CFDA 0x2c /* Configuration Driver Area */ 1051.1Sthorpej#define DE425_ENETROM 0xc90 /* Offset in I/O space for ENETROM */ 1061.1Sthorpej#define DE425_CFG0 0xc88 /* IRQ Configuration Register */ 1071.1Sthorpej 1081.1Sthorpejstruct tulip_eisa_softc { 1091.1Sthorpej struct tulip_softc sc_tulip; /* real Tulip softc */ 1101.1Sthorpej 1111.1Sthorpej /* EISA-specific goo. */ 1121.1Sthorpej void *sc_ih; /* interrupt handle */ 1131.1Sthorpej}; 1141.1Sthorpej 1151.1Sthorpejint tlp_eisa_match __P((struct device *, struct cfdata *, void *)); 1161.1Sthorpejvoid tlp_eisa_attach __P((struct device *, struct device *, void *)); 1171.1Sthorpej 1181.1Sthorpejstruct cfattach tlp_eisa_ca = { 1191.1Sthorpej sizeof(struct tulip_eisa_softc), tlp_eisa_match, tlp_eisa_attach, 1201.1Sthorpej}; 1211.1Sthorpej 1221.1Sthorpejconst int tlp_eisa_irqs[] = { 5, 9, 10, 11 }; 1231.1Sthorpej 1241.1Sthorpejconst struct tulip_eisa_product { 1251.1Sthorpej const char *tep_eisaid; /* EISA ID */ 1261.1Sthorpej const char *tep_name; /* device name */ 1271.1Sthorpej tulip_chip_t tep_chip; /* base Tulip chip type */ 1281.1Sthorpej} tlp_eisa_products[] = { 1291.1Sthorpej { "DEC4250", "DEC DE425", 1301.1Sthorpej TULIP_CHIP_DE425 }, 1311.1Sthorpej 1321.1Sthorpej { NULL, NULL, 1331.1Sthorpej TULIP_CHIP_INVALID }, 1341.1Sthorpej}; 1351.1Sthorpej 1361.1Sthorpejconst struct tulip_eisa_product *tlp_eisa_lookup 1371.1Sthorpej __P((const struct eisa_attach_args *)); 1381.1Sthorpej 1391.1Sthorpejconst struct tulip_eisa_product * 1401.1Sthorpejtlp_eisa_lookup(ea) 1411.1Sthorpej const struct eisa_attach_args *ea; 1421.1Sthorpej{ 1431.1Sthorpej const struct tulip_eisa_product *tep; 1441.1Sthorpej 1451.1Sthorpej for (tep = tlp_eisa_products; 1461.1Sthorpej tep->tep_chip != TULIP_CHIP_INVALID; tep++) 1471.1Sthorpej if (strcmp(ea->ea_idstring, tep->tep_eisaid) == 0) 1481.1Sthorpej return (tep); 1491.1Sthorpej return (NULL); 1501.1Sthorpej} 1511.1Sthorpej 1521.1Sthorpejint 1531.1Sthorpejtlp_eisa_match(parent, match, aux) 1541.1Sthorpej struct device *parent; 1551.1Sthorpej struct cfdata *match; 1561.1Sthorpej void *aux; 1571.1Sthorpej{ 1581.1Sthorpej struct eisa_attach_args *ea = aux; 1591.1Sthorpej 1601.1Sthorpej if (tlp_eisa_lookup(ea) != NULL) 1611.1Sthorpej return (1); 1621.1Sthorpej 1631.1Sthorpej return (0); 1641.1Sthorpej} 1651.1Sthorpej 1661.1Sthorpejvoid 1671.1Sthorpejtlp_eisa_attach(parent, self, aux) 1681.1Sthorpej struct device *parent, *self; 1691.1Sthorpej void *aux; 1701.1Sthorpej{ 1711.1Sthorpej static const u_int8_t testpat[] = 1721.1Sthorpej { 0xff, 0, 0x55, 0xaa, 0xff, 0, 0x55, 0xaa }; 1731.1Sthorpej struct tulip_eisa_softc *esc = (void *) self; 1741.1Sthorpej struct tulip_softc *sc = &esc->sc_tulip; 1751.1Sthorpej struct eisa_attach_args *ea = aux; 1761.1Sthorpej eisa_chipset_tag_t ec = ea->ea_ec; 1771.1Sthorpej eisa_intr_handle_t ih; 1781.1Sthorpej bus_space_tag_t iot = ea->ea_iot; 1791.1Sthorpej bus_space_handle_t ioh; 1801.1Sthorpej const char *intrstr; 1811.1Sthorpej const struct tulip_eisa_product *tep; 1821.1Sthorpej u_int8_t enaddr[ETHER_ADDR_LEN], tmpbuf[sizeof(testpat)]; 1831.1Sthorpej u_int32_t val; 1841.1Sthorpej int irq, i, cnt; 1851.1Sthorpej 1861.1Sthorpej /* 1871.1Sthorpej * Map the device. 1881.1Sthorpej */ 1891.1Sthorpej if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot), 1901.1Sthorpej EISA_SLOT_SIZE, 0, &ioh)) { 1911.1Sthorpej printf(": unable to map I/O space\n"); 1921.1Sthorpej return; 1931.1Sthorpej } 1941.1Sthorpej 1951.1Sthorpej sc->sc_st = iot; 1961.1Sthorpej sc->sc_sh = ioh; 1971.1Sthorpej 1981.1Sthorpej tep = tlp_eisa_lookup(ea); 1991.1Sthorpej if (tep == NULL) { 2001.1Sthorpej printf("\n"); 2011.1Sthorpej panic("tlp_eisa_attach: impossible"); 2021.1Sthorpej } 2031.1Sthorpej sc->sc_chip = tep->tep_chip; 2041.1Sthorpej 2051.1Sthorpej /* 2061.1Sthorpej * DE425's registers are 16 bytes long; the PCI configuration 2071.1Sthorpej * space registers are interleaved in the I/O space. 2081.1Sthorpej */ 2091.1Sthorpej sc->sc_regshift = 4; 2101.1Sthorpej 2111.1Sthorpej /* 2121.1Sthorpej * CBIO must map the EISA slot, and I/O access and Bus Mastering 2131.1Sthorpej * must be enabled. 2141.1Sthorpej */ 2151.1Sthorpej bus_space_write_4(iot, ioh, DE425_CBIO, EISA_SLOT_ADDR(ea->ea_slot)); 2161.1Sthorpej bus_space_write_4(iot, ioh, DE425_CFCS, 2171.1Sthorpej bus_space_read_4(iot, ioh, DE425_CFCS) | 2181.1Sthorpej PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE); 2191.1Sthorpej 2201.1Sthorpej /* 2211.1Sthorpej * Get revision info. 2221.1Sthorpej */ 2231.1Sthorpej sc->sc_rev = bus_space_read_4(iot, ioh, DE425_CFRV) & 0xff; 2241.1Sthorpej 2251.1Sthorpej printf(": %s Ethernet, pass %d.%d\n", 2261.1Sthorpej tep->tep_name, (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf); 2271.1Sthorpej 2281.1Sthorpej sc->sc_dmat = ea->ea_dmat; 2291.1Sthorpej 2301.1Sthorpej /* 2311.1Sthorpej * EISA doesn't have a cache line register. 2321.1Sthorpej */ 2331.1Sthorpej sc->sc_cacheline = 0; 2341.1Sthorpej 2351.1Sthorpej /* 2361.1Sthorpej * Find the beginning of the Ethernet Address ROM. 2371.1Sthorpej */ 2381.1Sthorpej for (i = 0, cnt = 0; i < sizeof(testpat) && cnt < 32; cnt++) { 2391.1Sthorpej tmpbuf[i] = bus_space_read_1(iot, ioh, DE425_ENETROM); 2401.1Sthorpej if (tmpbuf[i] == testpat[i]) 2411.1Sthorpej i++; 2421.1Sthorpej else 2431.1Sthorpej i = 0; 2441.1Sthorpej } 2451.1Sthorpej 2461.1Sthorpej /* 2471.1Sthorpej * ...and now read the contents of the Ethernet Address ROM. 2481.1Sthorpej */ 2491.1Sthorpej memset(sc->sc_srom, 0, sizeof(sc->sc_srom)); 2501.1Sthorpej for (i = 0; i < 32; i++) 2511.1Sthorpej sc->sc_srom[i] = bus_space_read_1(iot, ioh, DE425_ENETROM); 2521.1Sthorpej 2531.1Sthorpej /* 2541.1Sthorpej * None of the DE425 boards have the new-style SROMs. 2551.1Sthorpej */ 2561.1Sthorpej if (tlp_parse_old_srom(sc, enaddr) == 0) { 2571.1Sthorpej printf("%s: unable to decode old-style SROM\n", 2581.1Sthorpej sc->sc_dev.dv_xname); 2591.1Sthorpej return; 2601.1Sthorpej } 2611.1Sthorpej 2621.1Sthorpej /* 2631.1Sthorpej * All DE425 boards use the 21040 media switch. 2641.1Sthorpej */ 2651.1Sthorpej sc->sc_mediasw = &tlp_21040_mediasw; 2661.1Sthorpej 2671.1Sthorpej /* 2681.1Sthorpej * Figure out which IRQ we want to use, and determine of it's 2691.1Sthorpej * edge- or level-triggered. 2701.1Sthorpej */ 2711.1Sthorpej val = bus_space_read_4(iot, ioh, DE425_CFG0); 2721.1Sthorpej irq = tlp_eisa_irqs[(val >> 1) & 0x03]; 2731.1Sthorpej 2741.1Sthorpej /* 2751.1Sthorpej * Map and establish our interrupt. 2761.1Sthorpej */ 2771.1Sthorpej if (eisa_intr_map(ec, irq, &ih)) { 2781.1Sthorpej printf("%s: unable to map interrupt (%u)\n", 2791.1Sthorpej sc->sc_dev.dv_xname, irq); 2801.1Sthorpej return; 2811.1Sthorpej } 2821.1Sthorpej intrstr = eisa_intr_string(ec, ih); 2831.1Sthorpej esc->sc_ih = eisa_intr_establish(ec, ih, 2841.1Sthorpej (val & 0x01) ? IST_EDGE : IST_LEVEL, IPL_NET, tlp_intr, sc); 2851.1Sthorpej if (esc->sc_ih == NULL) { 2861.1Sthorpej printf("%s: unable to establish interrupt", 2871.1Sthorpej sc->sc_dev.dv_xname); 2881.1Sthorpej if (intrstr != NULL) 2891.1Sthorpej printf(" at %s", intrstr); 2901.1Sthorpej printf("\n"); 2911.1Sthorpej return; 2921.1Sthorpej } 2931.1Sthorpej if (intrstr != NULL) 2941.1Sthorpej printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, 2951.1Sthorpej intrstr); 2961.1Sthorpej 2971.1Sthorpej /* 2981.1Sthorpej * Finish off the attach. 2991.1Sthorpej */ 3001.2Sthorpej tlp_attach(sc, enaddr); 3011.1Sthorpej} 302