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