1 /* $NetBSD: if_le_isa.c,v 1.49 2010/11/13 13:52:03 uebayasi Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 9 * Simulation Facility, NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /*- 34 * Copyright (c) 1992, 1993 35 * The Regents of the University of California. All rights reserved. 36 * 37 * This code is derived from software contributed to Berkeley by 38 * Ralph Campbell and Rick Macklem. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 65 */ 66 67 #include <sys/cdefs.h> 68 __KERNEL_RCSID(0, "$NetBSD: if_le_isa.c,v 1.49 2010/11/13 13:52:03 uebayasi Exp $"); 69 70 #include <sys/param.h> 71 #include <sys/systm.h> 72 #include <sys/mbuf.h> 73 #include <sys/syslog.h> 74 #include <sys/socket.h> 75 #include <sys/device.h> 76 77 #include <net/if.h> 78 #include <net/if_ether.h> 79 #include <net/if_media.h> 80 81 #include <sys/cpu.h> 82 #include <sys/intr.h> 83 #include <sys/bus.h> 84 85 #include <dev/isa/isareg.h> 86 #include <dev/isa/isavar.h> 87 #include <dev/isa/isadmavar.h> 88 89 #include <dev/ic/lancereg.h> 90 #include <dev/ic/lancevar.h> 91 #include <dev/ic/am7990reg.h> 92 #include <dev/ic/am7990var.h> 93 94 #include <dev/isa/if_levar.h> 95 96 int ne2100_isa_probe(device_t, cfdata_t, void *); 97 int bicc_isa_probe(device_t, cfdata_t, void *); 98 void le_dummyattach(device_t, device_t, void *); 99 int le_dummyprobe(device_t, cfdata_t, void *); 100 void le_ne2100_attach(device_t, device_t, void *); 101 void le_bicc_attach(device_t, device_t, void *); 102 103 CFATTACH_DECL_NEW(nele, 0, 104 ne2100_isa_probe, le_dummyattach, NULL, NULL); 105 106 CFATTACH_DECL_NEW(le_nele, sizeof(struct le_softc), 107 le_dummyprobe, le_ne2100_attach, NULL, NULL); 108 109 CFATTACH_DECL_NEW(bicc, 0, 110 bicc_isa_probe, le_dummyattach, NULL, NULL); 111 112 CFATTACH_DECL_NEW(le_bicc, sizeof(struct le_softc), 113 le_dummyprobe, le_bicc_attach, NULL, NULL); 114 115 struct le_isa_params { 116 const char *name; 117 int iosize, rap, rdp; 118 int macstart, macstride; 119 } ne2100_params = { 120 "NE2100", 121 24, NE2100_RAP, NE2100_RDP, 122 0, 1 123 }, bicc_params = { 124 "BICC Isolan", 125 16, BICC_RAP, BICC_RDP, 126 0, 2 127 }; 128 129 int lance_isa_probe(struct isa_attach_args *, struct le_isa_params *, int); 130 void le_isa_attach(device_t, struct le_softc *, 131 struct isa_attach_args *, struct le_isa_params *); 132 133 int le_isa_intredge(void *); 134 135 #if defined(_KERNEL_OPT) 136 #include "opt_ddb.h" 137 #endif 138 139 #ifdef DDB 140 #define integrate 141 #define hide 142 #else 143 #define integrate static inline 144 #define hide static 145 #endif 146 147 hide void le_isa_wrcsr(struct lance_softc *, uint16_t, uint16_t); 148 hide uint16_t le_isa_rdcsr(struct lance_softc *, uint16_t); 149 150 #define LE_ISA_MEMSIZE 16384 151 152 hide void 153 le_isa_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 154 { 155 struct le_softc *lesc = (struct le_softc *)sc; 156 bus_space_tag_t iot = lesc->sc_iot; 157 bus_space_handle_t ioh = lesc->sc_ioh; 158 159 bus_space_write_2(iot, ioh, lesc->sc_rap, port); 160 bus_space_write_2(iot, ioh, lesc->sc_rdp, val); 161 } 162 163 hide uint16_t 164 le_isa_rdcsr(struct lance_softc *sc, uint16_t port) 165 { 166 struct le_softc *lesc = (struct le_softc *)sc; 167 bus_space_tag_t iot = lesc->sc_iot; 168 bus_space_handle_t ioh = lesc->sc_ioh; 169 uint16_t val; 170 171 bus_space_write_2(iot, ioh, lesc->sc_rap, port); 172 val = bus_space_read_2(iot, ioh, lesc->sc_rdp); 173 return (val); 174 } 175 176 int 177 ne2100_isa_probe(device_t parent, cfdata_t cf, void *aux) 178 { 179 180 return (lance_isa_probe(aux, &ne2100_params, cf->cf_flags)); 181 } 182 183 int 184 bicc_isa_probe(device_t parent, cfdata_t cf, void *aux) 185 { 186 187 return (lance_isa_probe(aux, &bicc_params, cf->cf_flags)); 188 } 189 190 /* 191 * Determine which chip is present on the card. 192 */ 193 int 194 lance_isa_probe(struct isa_attach_args *ia, struct le_isa_params *p, int flags) 195 { 196 bus_space_tag_t iot = ia->ia_iot; 197 bus_space_handle_t ioh; 198 int rap, rdp; 199 int rv = 0; 200 201 if (ia->ia_nio < 1) 202 return (0); 203 if (ia->ia_nirq < 1) 204 return (0); 205 if (ia->ia_ndrq < 1) 206 return (0); 207 208 if (ISA_DIRECT_CONFIG(ia)) 209 return (0); 210 211 /* Disallow wildcarded i/o address. */ 212 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 213 return (0); 214 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 215 return (0); 216 if ((flags & LANCEISA_FLAG_LOCALBUS) == 0 && 217 ia->ia_drq[0].ir_drq == ISA_UNKNOWN_DRQ) 218 return (0); 219 220 /* Map i/o space. */ 221 if (bus_space_map(iot, ia->ia_io[0].ir_addr, p->iosize, 0, &ioh)) 222 return (0); 223 224 rap = p->rap; 225 rdp = p->rdp; 226 227 /* Stop the LANCE chip and put it in a known state. */ 228 bus_space_write_2(iot, ioh, rap, LE_CSR0); 229 bus_space_write_2(iot, ioh, rdp, LE_C0_STOP); 230 delay(100); 231 232 bus_space_write_2(iot, ioh, rap, LE_CSR0); 233 if (bus_space_read_2(iot, ioh, rdp) != LE_C0_STOP) 234 goto bad; 235 236 bus_space_write_2(iot, ioh, rap, LE_CSR3); 237 bus_space_write_2(iot, ioh, rdp, 0); 238 239 ia->ia_nio = 1; 240 ia->ia_io[0].ir_size = p->iosize; 241 242 ia->ia_nirq = 1; 243 244 if ((flags & LANCEISA_FLAG_LOCALBUS) != 0 && 245 ia->ia_drq[0].ir_drq == ISA_UNKNOWN_DRQ) 246 ia->ia_ndrq = 0; 247 else 248 ia->ia_ndrq = 1; 249 250 ia->ia_niomem = 0; 251 252 rv = 1; 253 254 bad: 255 bus_space_unmap(iot, ioh, p->iosize); 256 return (rv); 257 } 258 259 void 260 le_dummyattach(device_t parent, device_t self, void *aux) 261 { 262 263 aprint_normal("\n"); 264 265 config_found(self, aux, 0); 266 } 267 268 int 269 le_dummyprobe(device_t parent, cfdata_t cf, void *aux) 270 { 271 272 return (1); 273 } 274 275 void 276 le_ne2100_attach(device_t parent, device_t self, void *aux) 277 { 278 struct le_softc *lesc = device_private(self); 279 struct lance_softc *sc = &lesc->sc_am7990.lsc; 280 281 sc->sc_dev = self; 282 le_isa_attach(parent, lesc, aux, &ne2100_params); 283 } 284 285 void 286 le_bicc_attach(device_t parent, device_t self, void *aux) 287 { 288 struct le_softc *lesc = device_private(self); 289 struct lance_softc *sc = &lesc->sc_am7990.lsc; 290 291 sc->sc_dev = self; 292 le_isa_attach(parent, lesc, aux, &bicc_params); 293 } 294 295 void 296 le_isa_attach(device_t parent, struct le_softc *lesc, 297 struct isa_attach_args *ia, struct le_isa_params *p) 298 { 299 struct lance_softc *sc = &lesc->sc_am7990.lsc; 300 bus_space_tag_t iot = ia->ia_iot; 301 bus_space_handle_t ioh; 302 bus_dma_tag_t dmat = ia->ia_dmat; 303 bus_dma_segment_t seg; 304 int i, rseg, error; 305 306 aprint_normal(": %s Ethernet\n", p->name); 307 308 if (bus_space_map(iot, ia->ia_io[0].ir_addr, p->iosize, 0, &ioh)) 309 panic("%s: can't map io", device_xname(sc->sc_dev)); 310 311 /* 312 * Extract the physical MAC address from the ROM. 313 */ 314 for (i = 0; i < sizeof(sc->sc_enaddr); i++) 315 sc->sc_enaddr[i] = 316 bus_space_read_1(iot, ioh, p->macstart + i * p->macstride); 317 318 lesc->sc_iot = iot; 319 lesc->sc_ioh = ioh; 320 lesc->sc_dmat = dmat; 321 lesc->sc_rap = p->rap; 322 lesc->sc_rdp = p->rdp; 323 324 /* 325 * Allocate a DMA area for the card. 326 */ 327 if (bus_dmamem_alloc(dmat, LE_ISA_MEMSIZE, PAGE_SIZE, 0, &seg, 1, 328 &rseg, BUS_DMA_NOWAIT)) { 329 aprint_error_dev(sc->sc_dev, 330 "couldn't allocate memory for card\n"); 331 return; 332 } 333 if (bus_dmamem_map(dmat, &seg, rseg, LE_ISA_MEMSIZE, 334 (void **)&sc->sc_mem, 335 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 336 aprint_error_dev(sc->sc_dev, "couldn't map memory for card\n"); 337 return; 338 } 339 340 /* 341 * Create and load the DMA map for the DMA area. 342 */ 343 if (bus_dmamap_create(dmat, LE_ISA_MEMSIZE, 1, 344 LE_ISA_MEMSIZE, 0, BUS_DMA_NOWAIT, &lesc->sc_dmam)) { 345 aprint_error_dev(sc->sc_dev, "couldn't create DMA map\n"); 346 bus_dmamem_free(dmat, &seg, rseg); 347 return; 348 } 349 if (bus_dmamap_load(dmat, lesc->sc_dmam, 350 sc->sc_mem, LE_ISA_MEMSIZE, NULL, BUS_DMA_NOWAIT)) { 351 aprint_error_dev(sc->sc_dev, "coundn't load DMA map\n"); 352 bus_dmamem_free(dmat, &seg, rseg); 353 return; 354 } 355 356 sc->sc_conf3 = 0; 357 sc->sc_addr = lesc->sc_dmam->dm_segs[0].ds_addr; 358 sc->sc_memsize = LE_ISA_MEMSIZE; 359 360 sc->sc_copytodesc = lance_copytobuf_contig; 361 sc->sc_copyfromdesc = lance_copyfrombuf_contig; 362 sc->sc_copytobuf = lance_copytobuf_contig; 363 sc->sc_copyfrombuf = lance_copyfrombuf_contig; 364 sc->sc_zerobuf = lance_zerobuf_contig; 365 366 sc->sc_rdcsr = le_isa_rdcsr; 367 sc->sc_wrcsr = le_isa_wrcsr; 368 sc->sc_hwinit = NULL; 369 370 if (ia->ia_ndrq > 0) { 371 if ((error = isa_dmacascade(ia->ia_ic, 372 ia->ia_drq[0].ir_drq)) != 0) { 373 aprint_error_dev(sc->sc_dev, 374 "unable to cascade DRQ, error = %d\n", error); 375 return; 376 } 377 } 378 379 lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 380 IST_EDGE, IPL_NET, le_isa_intredge, sc); 381 382 aprint_normal("%s", device_xname(sc->sc_dev)); 383 am7990_config(&lesc->sc_am7990); 384 } 385 386 /* 387 * Controller interrupt. 388 */ 389 int 390 le_isa_intredge(void *arg) 391 { 392 393 if (am7990_intr(arg) == 0) 394 return (0); 395 for (;;) 396 if (am7990_intr(arg) == 0) 397 return (1); 398 } 399