1 /* $NetBSD: if_le.c,v 1.8 1997/04/21 22:04:23 ragge Exp $ */ 2 3 /* #define LE_CHIP_IS_POKEY /* does VS2000 need this ??? */ 4 5 /*- 6 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 7 * Copyright (c) 1992, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Ralph Campbell and Rick Macklem. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 42 */ 43 44 #include "bpfilter.h" 45 46 #include <sys/param.h> 47 #include <sys/syslog.h> 48 #include <sys/socket.h> 49 #include <sys/device.h> 50 #include <sys/reboot.h> 51 52 #include <net/if.h> 53 #include <net/if_ether.h> 54 #include <net/if_media.h> 55 56 #if INET 57 #include <netinet/in.h> 58 #include <netinet/if_inarp.h> 59 #endif 60 61 /* 62 * This would be nice, but it's not yet there... 63 * 64 * #include <machine/autoconf.h> 65 */ 66 67 #include <machine/pte.h> 68 #include <machine/cpu.h> 69 #include <machine/mtpr.h> 70 #include <machine/uvax.h> 71 #include <machine/ka410.h> 72 #include <machine/vsbus.h> 73 #include <machine/rpb.h> 74 75 #include <dev/ic/am7990reg.h> 76 #define LE_NEED_BUF_CONTIG 77 #include <dev/ic/am7990var.h> 78 79 #include <dev/tc/if_levar.h> 80 81 #define xdebug(x) 82 83 #ifdef LE_CHIP_IS_POKEY 84 /* 85 * access LANCE registers and double-check their contents 86 */ 87 #define wbflush() /* do nothing */ 88 void lewritereg(); 89 #define LERDWR(cntl, src, dst) { (dst) = (src); wbflush(); } 90 #define LEWREG(src, dst) lewritereg(&(dst), (src)) 91 #endif 92 93 #define LE_IOSIZE 64*1024 /* 64K of real-mem are reserved and already */ 94 extern void *le_iomem; /* mapped into virt-mem by cpu_steal_pages */ 95 extern u_long le_ioaddr; /* le_iomem is virt, le_ioaddr is phys */ 96 97 #define LE_SOFTC(unit) le_cd.cd_devs[unit] 98 #define LE_DELAY(x) DELAY(x) 99 100 int lematch __P((struct device *, void *, void *)); 101 void leattach __P((struct device *, struct device *, void *)); 102 103 int leintr __P((void *sc)); 104 105 struct cfattach le_ca = { 106 sizeof(struct le_softc), lematch, leattach 107 }; 108 109 hide void lewrcsr __P ((struct am7990_softc *, u_int16_t, u_int16_t)); 110 hide u_int16_t lerdcsr __P ((struct am7990_softc *, u_int16_t)); 111 112 hide void 113 lewrcsr(sc, port, val) 114 struct am7990_softc *sc; 115 u_int16_t port, val; 116 { 117 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 118 119 #ifdef LE_CHIP_IS_POKEY 120 LEWREG(port, ler1->ler1_rap); 121 LERDWR(port, val, ler1->ler1_rdp); 122 #else 123 ler1->ler1_rap = port; 124 ler1->ler1_rdp = val; 125 #endif 126 } 127 128 hide u_int16_t 129 lerdcsr(sc, port) 130 struct am7990_softc *sc; 131 u_int16_t port; 132 { 133 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 134 u_int16_t val; 135 136 #ifdef LE_CHIP_IS_POKEY 137 LEWREG(port, ler1->ler1_rap); 138 LERDWR(0, ler1->ler1_rdp, val); 139 #else 140 ler1->ler1_rap = port; 141 val = ler1->ler1_rdp; 142 #endif 143 return (val); 144 } 145 146 integrate void 147 lehwinit(sc) 148 struct am7990_softc *sc; 149 { 150 } 151 152 int 153 lematch(parent, match, aux) 154 struct device *parent; 155 void *match, *aux; 156 { 157 struct cfdata *cf = match; 158 struct confargs *ca = aux; 159 160 /* 161 * There could/should be more checks, but for now... 162 */ 163 if (strcmp(ca->ca_name, "le") && 164 strcmp(ca->ca_name, "am7990") && 165 strcmp(ca->ca_name, "AM7990")) 166 return (0); 167 168 return (1); 169 } 170 171 /* 172 * 173 */ 174 void 175 leattach(parent, self, aux) 176 struct device *parent, *self; 177 void *aux; 178 { 179 register struct le_softc *sc = (void *)self; 180 struct confargs *ca = aux; 181 u_char *cp; /* pointer to MAC address */ 182 int i; 183 184 sc->sc_r1 = (void*)uvax_phys2virt(ca->ca_ioaddr); 185 186 sc->sc_am7990.sc_conf3 = 0; 187 sc->sc_am7990.sc_mem = le_iomem; 188 sc->sc_am7990.sc_addr = le_ioaddr; 189 sc->sc_am7990.sc_memsize = LE_IOSIZE; 190 sc->sc_am7990.sc_wrcsr = lewrcsr; 191 sc->sc_am7990.sc_rdcsr = lerdcsr; 192 sc->sc_am7990.sc_hwinit = lehwinit; 193 sc->sc_am7990.sc_nocarrier = NULL; 194 195 xdebug(("leattach: mem=%x, addr=%x, size=%x (%d)\n", 196 sc->sc_am7990.sc_mem, sc->sc_am7990.sc_addr, 197 sc->sc_am7990.sc_memsize, sc->sc_am7990.sc_memsize)); 198 199 sc->sc_am7990.sc_copytodesc = am7990_copytobuf_contig; 200 sc->sc_am7990.sc_copyfromdesc = am7990_copyfrombuf_contig; 201 sc->sc_am7990.sc_copytobuf = am7990_copytobuf_contig; 202 sc->sc_am7990.sc_copyfrombuf = am7990_copyfrombuf_contig; 203 sc->sc_am7990.sc_zerobuf = am7990_zerobuf_contig; 204 205 /* 206 * Get the ethernet address out of rom 207 */ 208 for (i = 0; i < sizeof(sc->sc_am7990.sc_enaddr); i++) { 209 int *eaddr = (void*)uvax_phys2virt(ca->ca_enaddr); 210 sc->sc_am7990.sc_enaddr[i] = (u_char)eaddr[i]; 211 } 212 213 bcopy(self->dv_xname, sc->sc_am7990.sc_ethercom.ec_if.if_xname, 214 IFNAMSIZ); 215 am7990_config(&sc->sc_am7990); 216 217 #ifdef LEDEBUG 218 sc->sc_am7990.sc_debug = LEDEBUG; 219 #endif 220 221 vsbus_intr_register(ca, am7990_intr, &sc->sc_am7990); 222 vsbus_intr_enable(ca); 223 224 /* 225 * Register this device as boot device if we booted from it. 226 * This will fail if there are more than one le in a machine, 227 * fortunately there may be only one. 228 */ 229 if (B_TYPE(bootdev) == BDEV_LE) 230 booted_from = self; 231 } 232 233 #ifdef LE_CHIP_IS_POKEY 234 /* 235 * Write a lance register port, reading it back to ensure success. This seems 236 * to be necessary during initialization, since the chip appears to be a bit 237 * pokey sometimes. 238 */ 239 void 240 lewritereg(regptr, val) 241 register volatile u_short *regptr; 242 register u_short val; 243 { 244 register int i = 0; 245 246 while (*regptr != val) { 247 *regptr = val; 248 wbflush(); 249 if (++i > 10000) { 250 printf("le: Reg did not settle (to x%x): x%x\n", val, 251 *regptr); 252 return; 253 } 254 DELAY(100); 255 } 256 } 257 #endif 258