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