1 /* $NetBSD: if_le.c,v 1.27 1997/10/04 09:43:10 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * 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) 1997 Bernd Ernesti. All rights reserved. 42 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 43 * Copyright (c) 1992, 1993 44 * The Regents of the University of California. All rights reserved. 45 * 46 * This code is derived from software contributed to Berkeley by 47 * Ralph Campbell and Rick Macklem. 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 3. All advertising materials mentioning features or use of this software 58 * must display the following acknowledgement: 59 * This product includes software developed for the NetBSD Project 60 * by Bernd Ernesti. 61 * This product includes software developed by the University of 62 * California, Berkeley and its contributors. 63 * 4. Neither the name of the University nor the names of its contributors 64 * may be used to endorse or promote products derived from this software 65 * without specific prior written permission. 66 * 67 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 68 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 69 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 70 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 71 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 72 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 73 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 74 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 75 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 76 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 77 * SUCH DAMAGE. 78 * 79 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 80 */ 81 82 #include "bpfilter.h" 83 84 #include <sys/param.h> 85 #include <sys/systm.h> 86 #include <sys/mbuf.h> 87 #include <sys/syslog.h> 88 #include <sys/socket.h> 89 #include <sys/device.h> 90 91 #include <net/if.h> 92 #include <net/if_ether.h> 93 #include <net/if_media.h> 94 95 #ifdef INET 96 #include <netinet/in.h> 97 #include <netinet/if_inarp.h> 98 #endif 99 100 #include <machine/cpu.h> 101 #include <machine/mtpr.h> 102 103 #include <amiga/amiga/device.h> 104 #include <amiga/amiga/isr.h> 105 106 #include <dev/ic/am7990reg.h> 107 #include <dev/ic/am7990var.h> 108 109 #include <amiga/dev/zbusvar.h> 110 #include <amiga/dev/if_levar.h> 111 112 int le_zbus_match __P((struct device *, struct cfdata *, void *)); 113 void le_zbus_attach __P((struct device *, struct device *, void *)); 114 115 struct cfattach le_zbus_ca = { 116 sizeof(struct le_softc), le_zbus_match, le_zbus_attach 117 }; 118 119 hide void lepcnet_reset __P((struct am7990_softc *)); 120 hide void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); 121 hide u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t)); 122 123 hide u_int16_t ariadne_swapreg __P((u_int16_t)); 124 hide void ariadne_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t)); 125 hide u_int16_t ariadne_rdcsr __P((struct am7990_softc *, u_int16_t)); 126 hide void ariadne_wribcr __P((struct am7990_softc *, u_int16_t, u_int16_t)); 127 integrate void ariadne_copytodesc_word __P((struct am7990_softc *, void *, int, int)); 128 integrate void ariadne_copyfromdesc_word __P((struct am7990_softc *, void *, int, int)); 129 integrate void ariadne_copytobuf_word __P((struct am7990_softc *, void *, int, int)); 130 integrate void ariadne_copyfrombuf_word __P((struct am7990_softc *, void *, int, int)); 131 integrate void ariadne_zerobuf_word __P((struct am7990_softc *, int, int)); 132 void ariadne_autoselect __P((struct am7990_softc *, int)); 133 int ariadne_mediachange __P((struct am7990_softc *)); 134 void ariadne_hwinit __P((struct am7990_softc *)); 135 136 /* 137 * Media types supported by the Ariadne. 138 */ 139 int lemedia_ariadne[] = { 140 IFM_ETHER | IFM_10_T, 141 IFM_ETHER | IFM_10_2, 142 IFM_ETHER | IFM_AUTO, 143 }; 144 #define NLEMEDIA_ARIADNE (sizeof(lemedia_ariadne) / sizeof(lemedia_ariadne[0])) 145 146 147 hide u_int16_t 148 ariadne_swapreg(val) 149 u_int16_t val; 150 { 151 152 return (((val & 0xff) << 8 ) | (( val >> 8) & 0xff)); 153 } 154 155 hide void 156 ariadne_wrcsr(sc, port, val) 157 struct am7990_softc *sc; 158 u_int16_t port, val; 159 { 160 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 161 162 ler1->ler1_rap = ariadne_swapreg(port); 163 ler1->ler1_rdp = ariadne_swapreg(val); 164 } 165 166 hide u_int16_t 167 ariadne_rdcsr(sc, port) 168 struct am7990_softc *sc; 169 u_int16_t port; 170 { 171 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 172 u_int16_t val; 173 174 ler1->ler1_rap = ariadne_swapreg(port); 175 val = ariadne_swapreg(ler1->ler1_rdp); 176 return (val); 177 } 178 179 hide void 180 ariadne_wribcr(sc, port, val) 181 struct am7990_softc *sc; 182 u_int16_t port, val; 183 { 184 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 185 186 ler1->ler1_rap = ariadne_swapreg(port); 187 ler1->ler1_idp = ariadne_swapreg(val); 188 } 189 190 hide void 191 lewrcsr(sc, port, val) 192 struct am7990_softc *sc; 193 u_int16_t port, val; 194 { 195 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 196 197 ler1->ler1_rap = port; 198 ler1->ler1_rdp = val; 199 } 200 201 hide u_int16_t 202 lerdcsr(sc, port) 203 struct am7990_softc *sc; 204 u_int16_t port; 205 { 206 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 207 u_int16_t val; 208 209 ler1->ler1_rap = port; 210 val = ler1->ler1_rdp; 211 return (val); 212 } 213 214 hide void 215 lepcnet_reset(sc) 216 struct am7990_softc *sc; 217 { 218 struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; 219 volatile int dummy; 220 221 dummy = ler1->ler1_reset; /* Reset PCNet-ISA */ 222 } 223 224 void 225 ariadne_autoselect(sc, on) 226 struct am7990_softc *sc; 227 int on; 228 { 229 230 /* 231 * on = 0: autoselect disabled 232 * on = 1: autoselect enabled 233 */ 234 if (on == 0) 235 ariadne_wribcr(sc, LE_BCR_MC, 0x0000); 236 else 237 ariadne_wribcr(sc, LE_BCR_MC, LE_MC_ASEL); 238 } 239 240 int 241 ariadne_mediachange(sc) 242 struct am7990_softc *sc; 243 { 244 struct ifmedia *ifm = &sc->sc_media; 245 246 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 247 return (EINVAL); 248 249 /* 250 * Switch to the selected media. If autoselect is 251 * set, switch it on otherwise disable it. We'll 252 * switch to the other media when we detect loss of 253 * carrier. 254 */ 255 switch (IFM_SUBTYPE(ifm->ifm_media)) { 256 case IFM_10_T: 257 sc->sc_initmodemedia = 1; 258 am7990_init(sc); 259 break; 260 261 case IFM_10_2: 262 sc->sc_initmodemedia = 0; 263 am7990_init(sc); 264 break; 265 266 case IFM_AUTO: 267 sc->sc_initmodemedia = 2; 268 ariadne_hwinit(sc); 269 break; 270 271 default: 272 return (EINVAL); 273 } 274 275 return (0); 276 } 277 278 void 279 ariadne_hwinit(sc) 280 struct am7990_softc *sc; 281 { 282 283 /* 284 * Re-program LEDs to match meaning used on the Ariadne board. 285 */ 286 ariadne_wribcr(sc, LE_BCR_LED1, 0x0090); 287 ariadne_wribcr(sc, LE_BCR_LED2, 0x0081); 288 ariadne_wribcr(sc, LE_BCR_LED3, 0x0084); 289 290 /* 291 * Enabel/Disable auto selection 292 */ 293 if (sc->sc_initmodemedia == 2) 294 ariadne_autoselect(sc, 1); 295 else 296 ariadne_autoselect(sc, 0); 297 } 298 299 int 300 le_zbus_match(parent, cfp, aux) 301 struct device *parent; 302 struct cfdata *cfp; 303 void *aux; 304 { 305 struct zbus_args *zap = aux; 306 307 /* Commodore ethernet card */ 308 if (zap->manid == 514 && zap->prodid == 112) 309 return (1); 310 311 /* Ameristar ethernet card */ 312 if (zap->manid == 1053 && zap->prodid == 1) 313 return (1); 314 315 /* Ariadne ethernet card */ 316 if (zap->manid == 2167 && zap->prodid == 201) 317 return (1); 318 319 return (0); 320 } 321 322 void 323 le_zbus_attach(parent, self, aux) 324 struct device *parent, *self; 325 void *aux; 326 { 327 struct le_softc *lesc = (struct le_softc *)self; 328 struct am7990_softc *sc = &lesc->sc_am7990; 329 struct zbus_args *zap = aux; 330 u_long ser; 331 332 /* This has no effect on PCnet-ISA LANCE chips */ 333 sc->sc_conf3 = LE_C3_BSWP; 334 335 /* 336 * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID. 337 */ 338 switch (zap->manid) { 339 case 514: 340 /* Commodore */ 341 sc->sc_memsize = 32768; 342 sc->sc_enaddr[0] = 0x00; 343 sc->sc_enaddr[1] = 0x80; 344 sc->sc_enaddr[2] = 0x10; 345 lesc->sc_r1 = (struct lereg1 *)(0x4000 + (int)zap->va); 346 sc->sc_mem = (void *)(0x8000 + (int)zap->va); 347 sc->sc_addr = 0x8000; 348 sc->sc_copytodesc = am7990_copytobuf_contig; 349 sc->sc_copyfromdesc = am7990_copyfrombuf_contig; 350 sc->sc_copytobuf = am7990_copytobuf_contig; 351 sc->sc_copyfrombuf = am7990_copyfrombuf_contig; 352 sc->sc_zerobuf = am7990_zerobuf_contig; 353 sc->sc_rdcsr = lerdcsr; 354 sc->sc_wrcsr = lewrcsr; 355 sc->sc_hwreset = NULL; 356 sc->sc_hwinit = NULL; 357 break; 358 359 case 1053: 360 /* Ameristar */ 361 sc->sc_memsize = 32768; 362 sc->sc_enaddr[0] = 0x00; 363 sc->sc_enaddr[1] = 0x00; 364 sc->sc_enaddr[2] = 0x9f; 365 lesc->sc_r1 = (struct lereg1 *)(0x4000 + (int)zap->va); 366 sc->sc_mem = (void *)(0x8000 + (int)zap->va); 367 sc->sc_addr = 0x8000; 368 sc->sc_copytodesc = am7990_copytobuf_contig; 369 sc->sc_copyfromdesc = am7990_copyfrombuf_contig; 370 sc->sc_copytobuf = am7990_copytobuf_contig; 371 sc->sc_copyfrombuf = am7990_copyfrombuf_contig; 372 sc->sc_zerobuf = am7990_zerobuf_contig; 373 sc->sc_rdcsr = lerdcsr; 374 sc->sc_wrcsr = lewrcsr; 375 sc->sc_hwreset = NULL; 376 sc->sc_hwinit = NULL; 377 break; 378 379 case 2167: 380 /* Village Tronic */ 381 sc->sc_memsize = 32768; 382 sc->sc_enaddr[0] = 0x00; 383 sc->sc_enaddr[1] = 0x60; 384 sc->sc_enaddr[2] = 0x30; 385 lesc->sc_r1 = (struct lereg1 *)(0x0370 + (int)zap->va); 386 sc->sc_mem = (void *)(0x8000 + (int)zap->va); 387 sc->sc_addr = 0x8000; 388 sc->sc_copytodesc = ariadne_copytodesc_word; 389 sc->sc_copyfromdesc = ariadne_copyfromdesc_word; 390 sc->sc_copytobuf = ariadne_copytobuf_word; 391 sc->sc_copyfrombuf = ariadne_copyfrombuf_word; 392 sc->sc_zerobuf = ariadne_zerobuf_word; 393 sc->sc_rdcsr = ariadne_rdcsr; 394 sc->sc_wrcsr = ariadne_wrcsr; 395 sc->sc_hwreset = lepcnet_reset; 396 sc->sc_hwinit = ariadne_hwinit; 397 sc->sc_mediachange = ariadne_mediachange; 398 sc->sc_supmedia = lemedia_ariadne; 399 sc->sc_nsupmedia = NLEMEDIA_ARIADNE; 400 sc->sc_defaultmedia = IFM_ETHER | IFM_AUTO; 401 sc->sc_initmodemedia = 2; 402 break; 403 404 default: 405 panic("le_zbus_attach: bad manid"); 406 } 407 408 /* 409 * Serial number for board is used as host ID. 410 */ 411 ser = (u_long)zap->serno; 412 sc->sc_enaddr[3] = (ser >> 16) & 0xff; 413 sc->sc_enaddr[4] = (ser >> 8) & 0xff; 414 sc->sc_enaddr[5] = (ser ) & 0xff; 415 416 am7990_config(sc); 417 418 lesc->sc_isr.isr_intr = am7990_intr; 419 lesc->sc_isr.isr_arg = sc; 420 lesc->sc_isr.isr_ipl = 2; 421 add_isr(&lesc->sc_isr); 422 } 423 424 425 integrate void 426 ariadne_copytodesc_word(sc, from, boff, len) 427 struct am7990_softc *sc; 428 void *from; 429 int boff, len; 430 { 431 u_short *b1 = from; 432 volatile u_short *b2 = sc->sc_mem + boff; 433 434 for (len >>= 1; len > 0; len--) 435 *b2++ = ariadne_swapreg(*b1++); 436 } 437 438 integrate void 439 ariadne_copyfromdesc_word(sc, to, boff, len) 440 struct am7990_softc *sc; 441 void *to; 442 int boff, len; 443 { 444 volatile u_short *b1 = sc->sc_mem + boff; 445 u_short *b2 = to; 446 447 for (len >>= 1; len > 0; len--) 448 *b2++ = ariadne_swapreg(*b1++); 449 } 450 451 #define isodd(n) ((n) & 1) 452 453 integrate void 454 ariadne_copytobuf_word(sc, from, boff, len) 455 struct am7990_softc *sc; 456 void *from; 457 int boff, len; 458 { 459 u_char *a1 = from; 460 volatile u_char *a2 = sc->sc_mem + boff; 461 u_short *b1; 462 volatile u_short *b2; 463 int i; 464 465 if (len > 0 && isodd(boff)) { 466 b1 = (u_short *)(a1 + 1); 467 b2 = (u_short *)(a2 + 1); 468 b2[-1] = (b2[-1] & 0xff00) | (b1[-1] & 0x00ff); 469 --len; 470 } else { 471 b1 = (u_short *)a1; 472 b2 = (u_short *)a2; 473 } 474 475 for (i = len >> 1; i > 0; i--) 476 *b2++ = *b1++; 477 478 if (isodd(len)) 479 *b2 = (*b2 & 0x00ff) | (*b1 & 0xff00); 480 } 481 482 integrate void 483 ariadne_copyfrombuf_word(sc, to, boff, len) 484 struct am7990_softc *sc; 485 void *to; 486 int boff, len; 487 { 488 volatile u_char *a1 = sc->sc_mem + boff; 489 u_char *a2 = to; 490 volatile u_short *b1; 491 u_short *b2; 492 int i; 493 494 if (len > 0 && isodd(boff)) { 495 b1 = (u_short *)(a1 + 1); 496 b2 = (u_short *)(a2 + 1); 497 b2[-1] = (b2[-1] & 0xff00) | (b1[-1] & 0x00ff); 498 --len; 499 } else { 500 b1 = (u_short *)a1; 501 b2 = (u_short *)a2; 502 } 503 504 for (i = len >> 1; i > 0; i--) 505 *b2++ = *b1++; 506 507 if (isodd(len)) 508 *b2 = (*b2 & 0x00ff) | (*b1 & 0xff00); 509 } 510 511 integrate void 512 ariadne_zerobuf_word(sc, boff, len) 513 struct am7990_softc *sc; 514 int boff, len; 515 { 516 volatile u_char *a1 = sc->sc_mem + boff; 517 volatile u_short *b1; 518 int i; 519 520 if (len > 0 && isodd(boff)) { 521 b1 = (u_short *)(a1 + 1); 522 b1[-1] &= 0xff00; 523 --len; 524 } else { 525 b1 = (u_short *)a1; 526 } 527 528 for (i = len >> 1; i > 0; i--) 529 *b1++ = 0; 530 531 if (isodd(len)) 532 *b1 &= 0x00ff; 533 } 534