1 /* $OpenBSD: if_le_isa.c,v 1.14 1998/09/16 22:41:21 jason Exp $ */ 2 /* $NetBSD: if_le_isa.c,v 1.2 1996/05/12 23:52:56 mycroft Exp $ */ 3 4 /*- 5 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Ralph Campbell and Rick Macklem. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 41 */ 42 43 #include "bpfilter.h" 44 #include "isadma.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/mbuf.h> 49 #include <sys/syslog.h> 50 #include <sys/socket.h> 51 #include <sys/device.h> 52 53 #include <net/if.h> 54 #include <net/if_media.h> 55 56 #ifdef INET 57 #include <netinet/in.h> 58 #include <netinet/if_ether.h> 59 #endif 60 61 #include <vm/vm.h> 62 63 #include <machine/cpu.h> 64 #include <machine/intr.h> 65 66 #include <dev/isa/isareg.h> 67 #include <dev/isa/isavar.h> 68 #include <dev/isa/isadmavar.h> 69 70 #include <dev/ic/am7990reg.h> 71 #include <dev/ic/am7990var.h> 72 73 #include <dev/isa/if_levar.h> 74 75 static char *card_type[] = 76 { "unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA" }; 77 78 int le_isa_probe __P((struct device *, void *, void *)); 79 void le_isa_attach __P((struct device *, struct device *, void *)); 80 81 struct cfattach le_isa_ca = { 82 sizeof(struct le_softc), le_isa_probe, le_isa_attach 83 }; 84 85 int depca_isa_probe __P((struct le_softc *, struct isa_attach_args *)); 86 int ne2100_isa_probe __P((struct le_softc *, struct isa_attach_args *)); 87 int bicc_isa_probe __P((struct le_softc *, struct isa_attach_args *)); 88 int lance_isa_probe __P((struct am7990_softc *)); 89 90 int 91 le_isa_probe(parent, match, aux) 92 struct device *parent; 93 void *match, *aux; 94 { 95 struct le_softc *lesc = match; 96 struct isa_attach_args *ia = aux; 97 u_int8_t bogusether[ETHER_ADDR_LEN] = { 255, 255, 255, 255, 255, 255 }; 98 99 #if NISADMA == 0 100 if (ia->ia_drq != DRQUNK) { 101 printf("cannot support dma lance devices\n"); 102 return 0; 103 } 104 #endif 105 106 if (bicc_isa_probe(lesc, ia) == 0 && ne2100_isa_probe(lesc, ia) == 0 && 107 depca_isa_probe(lesc, ia) == 0) 108 return (0); 109 110 if (bcmp(lesc->sc_am7990.sc_arpcom.ac_enaddr, bogusether, 111 sizeof(bogusether)) == 0) 112 return (0); 113 114 return (1); 115 } 116 117 int 118 depca_isa_probe(lesc, ia) 119 struct le_softc *lesc; 120 struct isa_attach_args *ia; 121 { 122 struct am7990_softc *sc = &lesc->sc_am7990; 123 bus_space_tag_t iot = lesc->sc_iot; 124 bus_space_handle_t ioh = lesc->sc_ioh; 125 int iosize = 16; 126 int port; 127 128 #if 0 129 u_long sum, rom_sum; 130 u_char x; 131 #endif 132 int i; 133 134 if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh)) 135 return (0); 136 lesc->sc_iot = iot; 137 lesc->sc_ioh = ioh; 138 lesc->sc_rap = DEPCA_RAP; 139 lesc->sc_rdp = DEPCA_RDP; 140 lesc->sc_card = DEPCA; 141 142 if (lance_isa_probe(sc) == 0) { 143 bus_space_unmap(iot, ioh, iosize); 144 return 0; 145 } 146 147 bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_DUM); 148 149 /* 150 * Extract the physical MAC address from the ROM. 151 * 152 * The address PROM is 32 bytes wide, and we access it through 153 * a single I/O port. On each read, it rotates to the next 154 * position. We find the ethernet address by looking for a 155 * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff, 156 * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the 157 * ethernet address and a checksum). 158 * 159 * It appears that the PROM can be at one of two locations, so 160 * we just try both. 161 */ 162 port = DEPCA_ADP; 163 for (i = 0; i < 32; i++) 164 if (bus_space_read_1(iot, ioh, port) == 0xff && 165 bus_space_read_1(iot, ioh, port) == 0x00 && 166 bus_space_read_1(iot, ioh, port) == 0x55 && 167 bus_space_read_1(iot, ioh, port) == 0xaa && 168 bus_space_read_1(iot, ioh, port) == 0xff && 169 bus_space_read_1(iot, ioh, port) == 0x00 && 170 bus_space_read_1(iot, ioh, port) == 0x55 && 171 bus_space_read_1(iot, ioh, port) == 0xaa) 172 goto found; 173 port = DEPCA_ADP + 1; 174 for (i = 0; i < 32; i++) 175 if (bus_space_read_1(iot, ioh, port) == 0xff && 176 bus_space_read_1(iot, ioh, port) == 0x00 && 177 bus_space_read_1(iot, ioh, port) == 0x55 && 178 bus_space_read_1(iot, ioh, port) == 0xaa && 179 bus_space_read_1(iot, ioh, port) == 0xff && 180 bus_space_read_1(iot, ioh, port) == 0x00 && 181 bus_space_read_1(iot, ioh, port) == 0x55 && 182 bus_space_read_1(iot, ioh, port) == 0xaa) 183 goto found; 184 printf("%s: address not found\n", sc->sc_dev.dv_xname); 185 return 0; 186 187 found: 188 for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) 189 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, port); 190 191 #if 0 192 sum = 193 (sc->sc_arpcom.ac_enaddr[0] << 2) + 194 (sc->sc_arpcom.ac_enaddr[1] << 10) + 195 (sc->sc_arpcom.ac_enaddr[2] << 1) + 196 (sc->sc_arpcom.ac_enaddr[3] << 9) + 197 (sc->sc_arpcom.ac_enaddr[4] << 0) + 198 (sc->sc_arpcom.ac_enaddr[5] << 8); 199 sum = (sum & 0xffff) + (sum >> 16); 200 sum = (sum & 0xffff) + (sum >> 16); 201 202 rom_sum = bus_space_read_1(iot, ioh, port); 203 rom_sum |= bus_space_read_1(iot, ioh, port << 8); 204 205 if (sum != rom_sum) { 206 printf("%s: checksum mismatch; calculated %04x != read %04x", 207 sc->sc_dev.dv_xname, sum, rom_sum); 208 bus_space_unmap(iot, ioh, iosize); 209 return 0; 210 } 211 #endif 212 213 bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_NORMAL); 214 215 ia->ia_iosize = iosize; 216 ia->ia_drq = DRQUNK; 217 bus_space_unmap(iot, ioh, ia->ia_iosize); 218 return 1; 219 } 220 221 int 222 ne2100_isa_probe(lesc, ia) 223 struct le_softc *lesc; 224 struct isa_attach_args *ia; 225 { 226 struct am7990_softc *sc = &lesc->sc_am7990; 227 bus_space_tag_t iot = lesc->sc_iot; 228 bus_space_handle_t ioh = lesc->sc_ioh; 229 int iosize = 24; 230 int i; 231 232 if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh)) 233 return (0); 234 lesc->sc_iot = iot; 235 lesc->sc_ioh = ioh; 236 lesc->sc_rap = NE2100_RAP; 237 lesc->sc_rdp = NE2100_RDP; 238 lesc->sc_card = NE2100; 239 240 if (lance_isa_probe(sc) == 0) { 241 bus_space_unmap(iot, ioh, iosize); 242 return 0; 243 } 244 245 /* 246 * Extract the physical MAC address from the ROM. 247 */ 248 for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) 249 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, i); 250 251 ia->ia_iosize = iosize; 252 bus_space_unmap(iot, ioh, ia->ia_iosize); 253 return 1; 254 } 255 256 int 257 bicc_isa_probe(lesc, ia) 258 struct le_softc *lesc; 259 struct isa_attach_args *ia; 260 { 261 struct am7990_softc *sc = &lesc->sc_am7990; 262 bus_space_handle_t ioh; 263 bus_space_tag_t iot = ia->ia_iot; 264 int iosize = 16; 265 int i; 266 267 if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh)) 268 return (0); 269 lesc->sc_iot = iot; 270 lesc->sc_ioh = ioh; 271 lesc->sc_rap = BICC_RAP; 272 lesc->sc_rdp = BICC_RDP; 273 lesc->sc_card = BICC; 274 275 if (lance_isa_probe(sc) == 0) { 276 bus_space_unmap(iot, ioh, iosize); 277 return 0; 278 } 279 280 /* 281 * Extract the physical MAC address from the ROM. 282 */ 283 for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) 284 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, i * 2); 285 286 ia->ia_iosize = iosize; 287 bus_space_unmap(iot, ioh, ia->ia_iosize); 288 return 1; 289 } 290 291 /* 292 * Determine which chip is present on the card. 293 */ 294 int 295 lance_isa_probe(sc) 296 struct am7990_softc *sc; 297 { 298 299 /* Stop the LANCE chip and put it in a known state. */ 300 le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP); 301 delay(100); 302 303 if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP) 304 return 0; 305 306 le_isa_wrcsr(sc, LE_CSR3, sc->sc_conf3); 307 return 1; 308 } 309 310 void 311 le_isa_attach(parent, self, aux) 312 struct device *parent, *self; 313 void *aux; 314 { 315 struct le_softc *lesc = (void *)self; 316 struct am7990_softc *sc = &lesc->sc_am7990; 317 struct isa_attach_args *ia = aux; 318 bus_space_tag_t iot = ia->ia_iot; 319 bus_space_handle_t ioh; 320 321 if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) 322 panic("%s: could not map I/O-ports", sc->sc_dev.dv_xname); 323 lesc->sc_iot = iot; 324 lesc->sc_ioh = ioh; 325 326 printf(": %s Ethernet\n", card_type[lesc->sc_card]); 327 328 if (lesc->sc_card == DEPCA) { 329 u_char *mem, val; 330 int i; 331 332 mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr); 333 334 val = 0xff; 335 for (;;) { 336 for (i = 0; i < ia->ia_msize; i++) 337 mem[i] = val; 338 for (i = 0; i < ia->ia_msize; i++) 339 if (mem[i] != val) { 340 printf("%s: failed to clear memory\n", 341 sc->sc_dev.dv_xname); 342 return; 343 } 344 if (val == 0x00) 345 break; 346 val -= 0x55; 347 } 348 349 sc->sc_conf3 = LE_C3_ACON; 350 sc->sc_addr = 0; 351 sc->sc_memsize = ia->ia_msize; 352 } else { 353 sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT); 354 if (sc->sc_mem == 0) { 355 printf("%s: couldn't allocate memory for card\n", 356 sc->sc_dev.dv_xname); 357 return; 358 } 359 360 sc->sc_conf3 = 0; 361 sc->sc_addr = kvtop(sc->sc_mem); 362 sc->sc_memsize = 16384; 363 } 364 365 sc->sc_copytodesc = am7990_copytobuf_contig; 366 sc->sc_copyfromdesc = am7990_copyfrombuf_contig; 367 sc->sc_copytobuf = am7990_copytobuf_contig; 368 sc->sc_copyfrombuf = am7990_copyfrombuf_contig; 369 sc->sc_zerobuf = am7990_zerobuf_contig; 370 371 sc->sc_rdcsr = le_isa_rdcsr; 372 sc->sc_wrcsr = le_isa_wrcsr; 373 sc->sc_hwreset = NULL; 374 sc->sc_hwinit = NULL; 375 376 printf("%s", sc->sc_dev.dv_xname); 377 am7990_config(sc); 378 379 #if NISADMA > 0 380 if (ia->ia_drq != DRQUNK) 381 isadma_cascade(ia->ia_drq); 382 #endif 383 384 lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 385 IPL_NET, le_isa_intredge, sc, sc->sc_dev.dv_xname); 386 } 387