1 /* $NetBSD: depca.c,v 1.8 2002/10/02 16:33:32 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 2000 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /*- 41 * Copyright (c) 1992, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * Ralph Campbell and Rick Macklem. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the University of 58 * California, Berkeley and its contributors. 59 * 4. Neither the name of the University nor the names of its contributors 60 * may be used to endorse or promote products derived from this software 61 * without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 76 */ 77 78 #include <sys/cdefs.h> 79 __KERNEL_RCSID(0, "$NetBSD: depca.c,v 1.8 2002/10/02 16:33:32 thorpej Exp $"); 80 81 #include <sys/param.h> 82 #include <sys/systm.h> 83 #include <sys/mbuf.h> 84 #include <sys/syslog.h> 85 #include <sys/socket.h> 86 #include <sys/device.h> 87 88 #include <net/if.h> 89 #include <net/if_ether.h> 90 #include <net/if_media.h> 91 92 #include <machine/cpu.h> 93 #include <machine/intr.h> 94 #include <machine/bus.h> 95 96 #include <dev/isa/isareg.h> 97 #include <dev/isa/isavar.h> 98 99 #include <dev/ic/lancereg.h> 100 #include <dev/ic/lancevar.h> 101 #include <dev/ic/am7990reg.h> 102 #include <dev/ic/am7990var.h> 103 #include <dev/ic/depcareg.h> 104 #include <dev/ic/depcavar.h> 105 106 struct le_depca_softc { 107 struct am7990_softc sc_am7990; /* glue to MI code */ 108 109 void *sc_ih; 110 }; 111 112 int le_depca_match(struct device *, struct cfdata *, void *); 113 void le_depca_attach(struct device *, struct device *, void *); 114 115 CFATTACH_DECL(le_depca, sizeof(struct le_depca_softc), 116 le_depca_match, le_depca_attach, NULL, NULL); 117 118 void depca_copytobuf(struct lance_softc *, void *, int, int); 119 void depca_copyfrombuf(struct lance_softc *, void *, int, int); 120 void depca_zerobuf(struct lance_softc *, int, int); 121 122 struct depca_attach_args { 123 const char *da_name; 124 }; 125 126 int depca_print(void *, const char *); 127 128 void 129 depca_attach(struct depca_softc *sc) 130 { 131 struct depca_attach_args da; 132 133 da.da_name = "le"; 134 135 (void) config_found(&sc->sc_dev, &da, depca_print); 136 } 137 138 int 139 depca_print(void *aux, const char *pnp) 140 { 141 struct depca_attach_args *da = aux; 142 143 if (pnp) 144 printf("%s at %s", da->da_name, pnp); 145 146 return (UNCONF); 147 } 148 149 void 150 depca_wrcsr(struct lance_softc *sc, u_int16_t port, u_int16_t val) 151 { 152 struct depca_softc *dsc = (void *) sc->sc_dev.dv_parent; 153 154 bus_space_write_2(dsc->sc_iot, dsc->sc_ioh, DEPCA_RAP, port); 155 bus_space_write_2(dsc->sc_iot, dsc->sc_ioh, DEPCA_RDP, val); 156 } 157 158 u_int16_t 159 depca_rdcsr(struct lance_softc *sc, u_int16_t port) 160 { 161 struct depca_softc *dsc = (void *) sc->sc_dev.dv_parent; 162 163 bus_space_write_2(dsc->sc_iot, dsc->sc_ioh, DEPCA_RAP, port); 164 return (bus_space_read_2(dsc->sc_iot, dsc->sc_ioh, DEPCA_RDP)); 165 } 166 167 int 168 depca_readprom(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t *laddr) 169 { 170 int port, i; 171 172 /* 173 * Extract the physical MAC address from the ROM. 174 * 175 * The address PROM is 32 bytes wide, and we access it through 176 * a single I/O port. On each read, it rotates to the next 177 * position. We find the ethernet address by looking for a 178 * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff, 179 * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the 180 * ethernet address and a checksum). 181 * 182 * It appears that the PROM can be at one of two locations, so 183 * we just try both. 184 */ 185 port = DEPCA_ADP; 186 for (i = 0; i < 32; i++) 187 if (bus_space_read_1(iot, ioh, port) == 0xff && 188 bus_space_read_1(iot, ioh, port) == 0x00 && 189 bus_space_read_1(iot, ioh, port) == 0x55 && 190 bus_space_read_1(iot, ioh, port) == 0xaa && 191 bus_space_read_1(iot, ioh, port) == 0xff && 192 bus_space_read_1(iot, ioh, port) == 0x00 && 193 bus_space_read_1(iot, ioh, port) == 0x55 && 194 bus_space_read_1(iot, ioh, port) == 0xaa) 195 goto found; 196 port = DEPCA_ADP + 1; 197 for (i = 0; i < 32; i++) 198 if (bus_space_read_1(iot, ioh, port) == 0xff && 199 bus_space_read_1(iot, ioh, port) == 0x00 && 200 bus_space_read_1(iot, ioh, port) == 0x55 && 201 bus_space_read_1(iot, ioh, port) == 0xaa && 202 bus_space_read_1(iot, ioh, port) == 0xff && 203 bus_space_read_1(iot, ioh, port) == 0x00 && 204 bus_space_read_1(iot, ioh, port) == 0x55 && 205 bus_space_read_1(iot, ioh, port) == 0xaa) 206 goto found; 207 printf("depca: address not found\n"); 208 return (-1); 209 210 found: 211 212 if (laddr) { 213 for (i = 0; i < 6; i++) 214 laddr[i] = bus_space_read_1(iot, ioh, port); 215 } 216 217 #if 0 218 sum = 219 (laddr[0] << 2) + 220 (laddr[1] << 10) + 221 (laddr[2] << 1) + 222 (laddr[3] << 9) + 223 (laddr[4] << 0) + 224 (laddr[5] << 8); 225 sum = (sum & 0xffff) + (sum >> 16); 226 sum = (sum & 0xffff) + (sum >> 16); 227 228 rom_sum = bus_space_read_1(iot, ioh, port); 229 rom_sum |= bus_space_read_1(iot, ioh, port) << 8; 230 231 if (sum != rom_sum) { 232 printf("depca: checksum mismatch; calculated %04x != read %04x", 233 sum, rom_sum); 234 return (-1); 235 } 236 #endif 237 238 return (0); 239 } 240 241 int 242 le_depca_match(struct device *parent, struct cfdata *match, void *aux) 243 { 244 struct depca_attach_args *da = aux; 245 246 return (strcmp(da->da_name, match->cf_name) == 0); 247 } 248 249 void 250 le_depca_attach(struct device *parent, struct device *self, void *aux) 251 { 252 struct depca_softc *dsc = (void *) parent; 253 struct le_depca_softc *lesc = (void *) self; 254 struct lance_softc *sc = &lesc->sc_am7990.lsc; 255 u_int8_t val; 256 int i; 257 258 printf("\n"); 259 260 /* I/O and memory spaces already mapped. */ 261 262 if (depca_readprom(dsc->sc_iot, dsc->sc_ioh, sc->sc_enaddr)) { 263 printf("%s: can't read PROM\n", self->dv_xname); 264 return; 265 } 266 267 bus_space_write_2(dsc->sc_iot, dsc->sc_ioh, DEPCA_CSR, 268 DEPCA_CSR_DUM | DEPCA_CSR_IEN | DEPCA_CSR_SHE | 269 (dsc->sc_memsize == 32*1024 ? DEPCA_CSR_LOW32K : 0)); 270 271 val = 0xff; 272 for (;;) { 273 u_int8_t cv; 274 275 bus_space_set_region_1(dsc->sc_memt, dsc->sc_memh, 0, val, 276 dsc->sc_memsize); 277 for (i = 0; i < dsc->sc_memsize; i++) { 278 cv = bus_space_read_1(dsc->sc_memt, dsc->sc_memh, i); 279 if (cv != val) { 280 printf("%s: failed to clear memory at %d " 281 "(0x%02x != 0x%02x)\n", 282 sc->sc_dev.dv_xname, i, cv, val); 283 return; 284 } 285 } 286 if (val == 0x00) 287 break; 288 val -= 0x55; 289 } 290 291 sc->sc_conf3 = LE_C3_ACON; 292 sc->sc_mem = 0; /* Not used. */ 293 sc->sc_addr = 0; 294 sc->sc_memsize = dsc->sc_memsize; 295 296 sc->sc_copytodesc = depca_copytobuf; 297 sc->sc_copyfromdesc = depca_copyfrombuf; 298 sc->sc_copytobuf = depca_copytobuf; 299 sc->sc_copyfrombuf = depca_copyfrombuf; 300 sc->sc_zerobuf = depca_zerobuf; 301 302 sc->sc_rdcsr = depca_rdcsr; 303 sc->sc_wrcsr = depca_wrcsr; 304 sc->sc_hwinit = NULL; 305 306 printf("%s", sc->sc_dev.dv_xname); 307 am7990_config(&lesc->sc_am7990); 308 309 lesc->sc_ih = (*dsc->sc_intr_establish)(dsc, sc); 310 } 311 312 /* 313 * Controller interrupt. 314 */ 315 int 316 depca_intredge(void *arg) 317 { 318 319 if (am7990_intr(arg) == 0) 320 return (0); 321 for (;;) 322 if (am7990_intr(arg) == 0) 323 return (1); 324 } 325 326 /* 327 * DEPCA shared memory access functions. 328 */ 329 330 void 331 depca_copytobuf(struct lance_softc *sc, void *from, int boff, int len) 332 { 333 struct depca_softc *dsc = (void *) sc->sc_dev.dv_parent; 334 335 bus_space_write_region_1(dsc->sc_memt, dsc->sc_memh, boff, 336 from, len); 337 } 338 339 void 340 depca_copyfrombuf(struct lance_softc *sc, void *to, int boff, int len) 341 { 342 struct depca_softc *dsc = (void *) sc->sc_dev.dv_parent; 343 344 bus_space_read_region_1(dsc->sc_memt, dsc->sc_memh, boff, 345 to, len); 346 } 347 348 void 349 depca_zerobuf(struct lance_softc *sc, int boff, int len) 350 { 351 struct depca_softc *dsc = (void *) sc->sc_dev.dv_parent; 352 353 bus_space_set_region_1(dsc->sc_memt, dsc->sc_memh, boff, 354 0x00, len); 355 } 356