11.30Sthorpej/* $NetBSD: if_tlp_eisa.c,v 1.30 2023/12/20 04:32:30 thorpej Exp $ */ 21.1Sthorpej 31.1Sthorpej/*- 41.6Sthorpej * Copyright (c) 1999, 2000 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 * 201.1Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 211.1Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 221.1Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 231.1Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 241.1Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 251.1Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 261.1Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 271.1Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 281.1Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 291.1Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 301.1Sthorpej * POSSIBILITY OF SUCH DAMAGE. 311.1Sthorpej */ 321.1Sthorpej 331.1Sthorpej/* 341.1Sthorpej * EISA bus front-end for the Digital Semiconductor ``Tulip'' (21x4x) 351.1Sthorpej * Ethernet controller family driver. 361.1Sthorpej */ 371.7Slukem 381.7Slukem#include <sys/cdefs.h> 391.30Sthorpej__KERNEL_RCSID(0, "$NetBSD: if_tlp_eisa.c,v 1.30 2023/12/20 04:32:30 thorpej Exp $"); 401.1Sthorpej 411.1Sthorpej#include "opt_inet.h" 421.1Sthorpej 431.1Sthorpej#include <sys/param.h> 441.13Sperry#include <sys/systm.h> 451.13Sperry#include <sys/mbuf.h> 461.30Sthorpej#include <sys/kmem.h> 471.1Sthorpej#include <sys/kernel.h> 481.1Sthorpej#include <sys/socket.h> 491.1Sthorpej#include <sys/ioctl.h> 501.1Sthorpej#include <sys/errno.h> 511.1Sthorpej#include <sys/device.h> 521.4Sthorpej 531.4Sthorpej#include <machine/endian.h> 541.13Sperry 551.1Sthorpej#include <net/if.h> 561.1Sthorpej#include <net/if_dl.h> 571.1Sthorpej#include <net/if_media.h> 581.1Sthorpej#include <net/if_ether.h> 591.1Sthorpej 601.1Sthorpej#ifdef INET 611.13Sperry#include <netinet/in.h> 621.1Sthorpej#include <netinet/if_inarp.h> 631.1Sthorpej#endif 641.1Sthorpej 651.1Sthorpej 661.19Sad#include <sys/bus.h> 671.19Sad#include <sys/intr.h> 681.1Sthorpej 691.1Sthorpej#include <dev/mii/miivar.h> 701.3Sthorpej#include <dev/mii/mii_bitbang.h> 711.1Sthorpej 721.1Sthorpej#include <dev/ic/tulipreg.h> 731.1Sthorpej#include <dev/ic/tulipvar.h> 741.1Sthorpej 751.1Sthorpej#include <dev/eisa/eisareg.h> 761.1Sthorpej#include <dev/eisa/eisavar.h> 771.1Sthorpej#include <dev/eisa/eisadevs.h> 781.1Sthorpej 791.1Sthorpej#include <dev/pci/pcireg.h> 801.1Sthorpej 811.1Sthorpej/* 821.1Sthorpej * DE425 configuration registers; literal offsets from CSR base. 831.1Sthorpej * This is effectively the 21040 PCI configuration space interleaved 841.1Sthorpej * into the CSR space (CSRs are space 16 bytes on the DE425). 851.1Sthorpej * 861.1Sthorpej * What a cool address decoder hack they must have on that board... 871.1Sthorpej */ 881.1Sthorpej#define DE425_CFID 0x08 /* Configuration ID */ 891.1Sthorpej#define DE425_CFCS 0x0c /* Configuration Command-Status */ 901.1Sthorpej#define DE425_CFRV 0x18 /* Configuration Revision */ 911.1Sthorpej#define DE425_CFLT 0x1c /* Configuration Latency Timer */ 921.1Sthorpej#define DE425_CBIO 0x28 /* Configuration Base I/O Address */ 931.1Sthorpej#define DE425_CFDA 0x2c /* Configuration Driver Area */ 941.1Sthorpej#define DE425_ENETROM 0xc90 /* Offset in I/O space for ENETROM */ 951.1Sthorpej#define DE425_CFG0 0xc88 /* IRQ Configuration Register */ 961.1Sthorpej 971.1Sthorpejstruct tulip_eisa_softc { 981.1Sthorpej struct tulip_softc sc_tulip; /* real Tulip softc */ 991.1Sthorpej 1001.1Sthorpej /* EISA-specific goo. */ 1011.1Sthorpej void *sc_ih; /* interrupt handle */ 1021.1Sthorpej}; 1031.1Sthorpej 1041.22Sceggerstatic int tlp_eisa_match(device_t, cfdata_t, void *); 1051.22Sceggerstatic void tlp_eisa_attach(device_t, device_t, void *); 1061.1Sthorpej 1071.22SceggerCFATTACH_DECL_NEW(tlp_eisa, sizeof(struct tulip_eisa_softc), 1081.11Sthorpej tlp_eisa_match, tlp_eisa_attach, NULL, NULL); 1091.1Sthorpej 1101.12Sthorpejstatic const int tlp_eisa_irqs[] = { 5, 9, 10, 11 }; 1111.1Sthorpej 1121.28Sthorpejstruct tulip_eisa_product { 1131.28Sthorpej const char *name; /* device name */ 1141.28Sthorpej tulip_chip_t chip; /* base Tulip chip type */ 1151.28Sthorpej}; 1161.1Sthorpej 1171.28Sthorpejstatic const struct tulip_eisa_product dec4250 = { 1181.28Sthorpej .name = "DEC DE425", 1191.28Sthorpej .chip = TULIP_CHIP_DE425, 1201.1Sthorpej}; 1211.1Sthorpej 1221.28Sthorpejstatic const struct device_compatible_entry compat_data[] = { 1231.28Sthorpej { .compat = "DEC4250", .data = &dec4250 }, 1241.28Sthorpej DEVICE_COMPAT_EOL 1251.28Sthorpej}; 1261.1Sthorpej 1271.12Sthorpejstatic int 1281.22Sceggertlp_eisa_match(device_t parent, cfdata_t match, 1291.17Schristos void *aux) 1301.1Sthorpej{ 1311.1Sthorpej struct eisa_attach_args *ea = aux; 1321.1Sthorpej 1331.28Sthorpej return (eisa_compatible_match(ea, compat_data)); 1341.1Sthorpej} 1351.1Sthorpej 1361.12Sthorpejstatic void 1371.22Sceggertlp_eisa_attach(device_t parent, device_t self, void *aux) 1381.1Sthorpej{ 1391.1Sthorpej static const u_int8_t testpat[] = 1401.1Sthorpej { 0xff, 0, 0x55, 0xaa, 0xff, 0, 0x55, 0xaa }; 1411.15Sthorpej struct tulip_eisa_softc *esc = device_private(self); 1421.1Sthorpej struct tulip_softc *sc = &esc->sc_tulip; 1431.1Sthorpej struct eisa_attach_args *ea = aux; 1441.28Sthorpej const struct device_compatible_entry *dce; 1451.1Sthorpej eisa_chipset_tag_t ec = ea->ea_ec; 1461.1Sthorpej eisa_intr_handle_t ih; 1471.1Sthorpej bus_space_tag_t iot = ea->ea_iot; 1481.1Sthorpej bus_space_handle_t ioh; 1491.1Sthorpej const char *intrstr; 1501.1Sthorpej const struct tulip_eisa_product *tep; 1511.1Sthorpej u_int8_t enaddr[ETHER_ADDR_LEN], tmpbuf[sizeof(testpat)]; 1521.1Sthorpej u_int32_t val; 1531.29Sthorpej int irq, ist, i, cnt; 1541.25Schristos char intrbuf[EISA_INTRSTR_LEN]; 1551.1Sthorpej 1561.1Sthorpej /* 1571.1Sthorpej * Map the device. 1581.1Sthorpej */ 1591.1Sthorpej if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot), 1601.1Sthorpej EISA_SLOT_SIZE, 0, &ioh)) { 1611.27Smsaitoh aprint_error(": unable to map I/O space\n"); 1621.1Sthorpej return; 1631.1Sthorpej } 1641.1Sthorpej 1651.22Scegger sc->sc_dev = self; 1661.1Sthorpej sc->sc_st = iot; 1671.1Sthorpej sc->sc_sh = ioh; 1681.1Sthorpej 1691.28Sthorpej dce = eisa_compatible_lookup(ea, compat_data); 1701.28Sthorpej KASSERT(dce != NULL); 1711.28Sthorpej tep = dce->data; 1721.28Sthorpej 1731.28Sthorpej sc->sc_chip = tep->chip; 1741.1Sthorpej 1751.1Sthorpej /* 1761.1Sthorpej * DE425's registers are 16 bytes long; the PCI configuration 1771.1Sthorpej * space registers are interleaved in the I/O space. 1781.1Sthorpej */ 1791.1Sthorpej sc->sc_regshift = 4; 1801.5Sthorpej 1811.5Sthorpej /* 1821.5Sthorpej * No power management hooks. 1831.5Sthorpej */ 1841.5Sthorpej sc->sc_flags |= TULIPF_ENABLED; 1851.1Sthorpej 1861.1Sthorpej /* 1871.1Sthorpej * CBIO must map the EISA slot, and I/O access and Bus Mastering 1881.1Sthorpej * must be enabled. 1891.1Sthorpej */ 1901.1Sthorpej bus_space_write_4(iot, ioh, DE425_CBIO, EISA_SLOT_ADDR(ea->ea_slot)); 1911.1Sthorpej bus_space_write_4(iot, ioh, DE425_CFCS, 1921.1Sthorpej bus_space_read_4(iot, ioh, DE425_CFCS) | 1931.1Sthorpej PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE); 1941.1Sthorpej 1951.1Sthorpej /* 1961.1Sthorpej * Get revision info. 1971.1Sthorpej */ 1981.1Sthorpej sc->sc_rev = bus_space_read_4(iot, ioh, DE425_CFRV) & 0xff; 1991.1Sthorpej 2001.27Smsaitoh aprint_normal(": %s Ethernet, pass %d.%d\n", 2011.28Sthorpej tep->name, (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf); 2021.1Sthorpej 2031.1Sthorpej sc->sc_dmat = ea->ea_dmat; 2041.1Sthorpej 2051.1Sthorpej /* 2061.1Sthorpej * EISA doesn't have a cache line register. 2071.1Sthorpej */ 2081.1Sthorpej sc->sc_cacheline = 0; 2091.1Sthorpej 2101.1Sthorpej /* 2111.1Sthorpej * Find the beginning of the Ethernet Address ROM. 2121.1Sthorpej */ 2131.1Sthorpej for (i = 0, cnt = 0; i < sizeof(testpat) && cnt < 32; cnt++) { 2141.1Sthorpej tmpbuf[i] = bus_space_read_1(iot, ioh, DE425_ENETROM); 2151.1Sthorpej if (tmpbuf[i] == testpat[i]) 2161.1Sthorpej i++; 2171.1Sthorpej else 2181.1Sthorpej i = 0; 2191.1Sthorpej } 2201.1Sthorpej 2211.1Sthorpej /* 2221.1Sthorpej * ...and now read the contents of the Ethernet Address ROM. 2231.1Sthorpej */ 2241.30Sthorpej sc->sc_srom_addrbits = 4; /* 32 bytes */ 2251.30Sthorpej sc->sc_srom = kmem_alloc(TULIP_ROM_SIZE(4), KM_SLEEP); 2261.30Sthorpej for (i = 0; i < TULIP_ROM_SIZE(4); i++) 2271.1Sthorpej sc->sc_srom[i] = bus_space_read_1(iot, ioh, DE425_ENETROM); 2281.1Sthorpej 2291.1Sthorpej /* 2301.1Sthorpej * None of the DE425 boards have the new-style SROMs. 2311.1Sthorpej */ 2321.1Sthorpej if (tlp_parse_old_srom(sc, enaddr) == 0) { 2331.22Scegger aprint_error_dev(self, "unable to decode old-style SROM\n"); 2341.1Sthorpej return; 2351.1Sthorpej } 2361.1Sthorpej 2371.1Sthorpej /* 2381.1Sthorpej * All DE425 boards use the 21040 media switch. 2391.1Sthorpej */ 2401.1Sthorpej sc->sc_mediasw = &tlp_21040_mediasw; 2411.1Sthorpej 2421.1Sthorpej /* 2431.26Ssnj * Figure out which IRQ we want to use, and determine if it's 2441.1Sthorpej * edge- or level-triggered. 2451.1Sthorpej */ 2461.1Sthorpej val = bus_space_read_4(iot, ioh, DE425_CFG0); 2471.1Sthorpej irq = tlp_eisa_irqs[(val >> 1) & 0x03]; 2481.29Sthorpej ist = (val & 0x01) ? IST_EDGE : IST_LEVEL; 2491.1Sthorpej 2501.1Sthorpej /* 2511.1Sthorpej * Map and establish our interrupt. 2521.1Sthorpej */ 2531.1Sthorpej if (eisa_intr_map(ec, irq, &ih)) { 2541.27Smsaitoh aprint_error_dev(self, "unable to map interrupt (%u)\n", irq); 2551.1Sthorpej return; 2561.1Sthorpej } 2571.25Schristos intrstr = eisa_intr_string(ec, ih, intrbuf, sizeof(intrbuf)); 2581.29Sthorpej esc->sc_ih = eisa_intr_establish(ec, ih, ist, IPL_NET, tlp_intr, sc); 2591.1Sthorpej if (esc->sc_ih == NULL) { 2601.22Scegger aprint_error_dev(self, "unable to establish interrupt"); 2611.1Sthorpej if (intrstr != NULL) 2621.23Snjoly aprint_error(" at %s", intrstr); 2631.23Snjoly aprint_error("\n"); 2641.1Sthorpej return; 2651.1Sthorpej } 2661.29Sthorpej if (intrstr != NULL) { 2671.29Sthorpej aprint_normal_dev(self, "interrupting at %s (%s trigger)\n", 2681.29Sthorpej ist == IST_EDGE ? "edge" : "level", intrstr); 2691.29Sthorpej } 2701.1Sthorpej 2711.1Sthorpej /* 2721.1Sthorpej * Finish off the attach. 2731.1Sthorpej */ 2741.2Sthorpej tlp_attach(sc, enaddr); 2751.1Sthorpej} 276