1 /* $NetBSD: am7990.c,v 1.71 2008/04/28 20:23:49 martin 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: am7990.c,v 1.71 2008/04/28 20:23:49 martin Exp $"); 69 70 #include "bpfilter.h" 71 #include "rnd.h" 72 73 #include <sys/param.h> 74 #include <sys/systm.h> 75 #include <sys/mbuf.h> 76 #include <sys/syslog.h> 77 #include <sys/socket.h> 78 #include <sys/device.h> 79 #include <sys/malloc.h> 80 #include <sys/ioctl.h> 81 #include <sys/errno.h> 82 #if NRND > 0 83 #include <sys/rnd.h> 84 #endif 85 86 #include <net/if.h> 87 #include <net/if_dl.h> 88 #include <net/if_ether.h> 89 #include <net/if_media.h> 90 91 #if NBPFILTER > 0 92 #include <net/bpf.h> 93 #include <net/bpfdesc.h> 94 #endif 95 96 #include <dev/ic/lancereg.h> 97 #include <dev/ic/lancevar.h> 98 #include <dev/ic/am7990reg.h> 99 #include <dev/ic/am7990var.h> 100 101 static void am7990_meminit(struct lance_softc *); 102 static void am7990_start(struct ifnet *); 103 104 #if defined(_KERNEL_OPT) 105 #include "opt_ddb.h" 106 #endif 107 108 #ifdef LEDEBUG 109 static void am7990_recv_print(struct lance_softc *, int); 110 static void am7990_xmit_print(struct lance_softc *, int); 111 #endif 112 113 #define ifp (&sc->sc_ethercom.ec_if) 114 115 void 116 am7990_config(struct am7990_softc *sc) 117 { 118 int mem, i; 119 120 sc->lsc.sc_meminit = am7990_meminit; 121 sc->lsc.sc_start = am7990_start; 122 123 lance_config(&sc->lsc); 124 125 mem = 0; 126 sc->lsc.sc_initaddr = mem; 127 mem += sizeof(struct leinit); 128 sc->lsc.sc_rmdaddr = mem; 129 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 130 sc->lsc.sc_tmdaddr = mem; 131 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 132 for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN) 133 sc->lsc.sc_rbufaddr[i] = mem; 134 for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN) 135 sc->lsc.sc_tbufaddr[i] = mem; 136 #ifdef notyet 137 if (mem > ...) 138 panic(...); 139 #endif 140 } 141 142 /* 143 * Set up the initialization block and the descriptor rings. 144 */ 145 static void 146 am7990_meminit(struct lance_softc *sc) 147 { 148 u_long a; 149 int bix; 150 struct leinit init; 151 struct lermd rmd; 152 struct letmd tmd; 153 uint8_t *myaddr; 154 155 #if NBPFILTER > 0 156 if (ifp->if_flags & IFF_PROMISC) 157 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; 158 else 159 #endif 160 init.init_mode = LE_MODE_NORMAL; 161 if (sc->sc_initmodemedia == 1) 162 init.init_mode |= LE_MODE_PSEL0; 163 164 /* 165 * Update our private copy of the Ethernet address. 166 * We NEED the copy so we can ensure its alignment! 167 */ 168 memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN); 169 myaddr = sc->sc_enaddr; 170 171 init.init_padr[0] = (myaddr[1] << 8) | myaddr[0]; 172 init.init_padr[1] = (myaddr[3] << 8) | myaddr[2]; 173 init.init_padr[2] = (myaddr[5] << 8) | myaddr[4]; 174 lance_setladrf(&sc->sc_ethercom, init.init_ladrf); 175 176 sc->sc_last_rd = 0; 177 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 178 179 a = sc->sc_addr + LE_RMDADDR(sc, 0); 180 init.init_rdra = a; 181 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); 182 183 a = sc->sc_addr + LE_TMDADDR(sc, 0); 184 init.init_tdra = a; 185 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); 186 187 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 188 189 /* 190 * Set up receive ring descriptors. 191 */ 192 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 193 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 194 rmd.rmd0 = a; 195 rmd.rmd1_hadr = a >> 16; 196 rmd.rmd1_bits = LE_R1_OWN; 197 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 198 rmd.rmd3 = 0; 199 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 200 sizeof(rmd)); 201 } 202 203 /* 204 * Set up transmit ring descriptors. 205 */ 206 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 207 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 208 tmd.tmd0 = a; 209 tmd.tmd1_hadr = a >> 16; 210 tmd.tmd1_bits = 0; 211 tmd.tmd2 = 0 | LE_XMD2_ONES; 212 tmd.tmd3 = 0; 213 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 214 sizeof(tmd)); 215 } 216 } 217 218 static void 219 am7990_rint(struct lance_softc *sc) 220 { 221 int bix; 222 int rp; 223 struct lermd rmd; 224 225 bix = sc->sc_last_rd; 226 227 /* Process all buffers with valid data. */ 228 for (;;) { 229 rp = LE_RMDADDR(sc, bix); 230 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 231 232 if (rmd.rmd1_bits & LE_R1_OWN) 233 break; 234 235 if (rmd.rmd1_bits & LE_R1_ERR) { 236 if (rmd.rmd1_bits & LE_R1_ENP) { 237 #ifdef LEDEBUG 238 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { 239 if (rmd.rmd1_bits & LE_R1_FRAM) 240 printf("%s: framing error\n", 241 device_xname(sc->sc_dev)); 242 if (rmd.rmd1_bits & LE_R1_CRC) 243 printf("%s: crc mismatch\n", 244 device_xname(sc->sc_dev)); 245 } 246 #endif 247 } else { 248 if (rmd.rmd1_bits & LE_R1_OFLO) 249 printf("%s: overflow\n", 250 device_xname(sc->sc_dev)); 251 } 252 if (rmd.rmd1_bits & LE_R1_BUFF) 253 printf("%s: receive buffer error\n", 254 device_xname(sc->sc_dev)); 255 ifp->if_ierrors++; 256 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != 257 (LE_R1_STP | LE_R1_ENP)) { 258 printf("%s: dropping chained buffer\n", 259 device_xname(sc->sc_dev)); 260 ifp->if_ierrors++; 261 } else { 262 #ifdef LEDEBUG 263 if (sc->sc_debug > 1) 264 am7990_recv_print(sc, sc->sc_last_rd); 265 #endif 266 lance_read(sc, LE_RBUFADDR(sc, bix), 267 (int)rmd.rmd3 - 4); 268 } 269 270 rmd.rmd1_bits = LE_R1_OWN; 271 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 272 rmd.rmd3 = 0; 273 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 274 275 #ifdef LEDEBUG 276 if (sc->sc_debug) 277 printf("sc->sc_last_rd = %x, rmd: " 278 "ladr %04x, hadr %02x, flags %02x, " 279 "bcnt %04x, mcnt %04x\n", 280 sc->sc_last_rd, 281 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, 282 rmd.rmd2, rmd.rmd3); 283 #endif 284 285 if (++bix == sc->sc_nrbuf) 286 bix = 0; 287 } 288 289 sc->sc_last_rd = bix; 290 } 291 292 static void 293 am7990_tint(struct lance_softc *sc) 294 { 295 int bix; 296 struct letmd tmd; 297 298 bix = sc->sc_first_td; 299 300 for (;;) { 301 if (sc->sc_no_td <= 0) 302 break; 303 304 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 305 sizeof(tmd)); 306 307 #ifdef LEDEBUG 308 if (sc->sc_debug) 309 printf("trans tmd: " 310 "ladr %04x, hadr %02x, flags %02x, " 311 "bcnt %04x, mcnt %04x\n", 312 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, 313 tmd.tmd2, tmd.tmd3); 314 #endif 315 316 if (tmd.tmd1_bits & LE_T1_OWN) 317 break; 318 319 ifp->if_flags &= ~IFF_OACTIVE; 320 321 if (tmd.tmd1_bits & LE_T1_ERR) { 322 if (tmd.tmd3 & LE_T3_BUFF) 323 printf("%s: transmit buffer error\n", 324 device_xname(sc->sc_dev)); 325 else if (tmd.tmd3 & LE_T3_UFLO) 326 printf("%s: underflow\n", 327 device_xname(sc->sc_dev)); 328 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { 329 lance_reset(sc); 330 return; 331 } 332 if (tmd.tmd3 & LE_T3_LCAR) { 333 sc->sc_havecarrier = 0; 334 if (sc->sc_nocarrier) 335 (*sc->sc_nocarrier)(sc); 336 else 337 printf("%s: lost carrier\n", 338 device_xname(sc->sc_dev)); 339 } 340 if (tmd.tmd3 & LE_T3_LCOL) 341 ifp->if_collisions++; 342 if (tmd.tmd3 & LE_T3_RTRY) { 343 #ifdef LEDEBUG 344 printf("%s: excessive collisions, tdr %d\n", 345 device_xname(sc->sc_dev), 346 tmd.tmd3 & LE_T3_TDR_MASK); 347 #endif 348 ifp->if_collisions += 16; 349 } 350 ifp->if_oerrors++; 351 } else { 352 if (tmd.tmd1_bits & LE_T1_ONE) 353 ifp->if_collisions++; 354 else if (tmd.tmd1_bits & LE_T1_MORE) 355 /* Real number is unknown. */ 356 ifp->if_collisions += 2; 357 ifp->if_opackets++; 358 } 359 360 if (++bix == sc->sc_ntbuf) 361 bix = 0; 362 363 --sc->sc_no_td; 364 } 365 366 sc->sc_first_td = bix; 367 368 am7990_start(ifp); 369 370 if (sc->sc_no_td == 0) 371 ifp->if_timer = 0; 372 } 373 374 /* 375 * Controller interrupt. 376 */ 377 int 378 am7990_intr(void *arg) 379 { 380 struct lance_softc *sc = arg; 381 uint16_t isr; 382 383 isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0; 384 sc->sc_saved_csr0 = 0; 385 #if defined(LEDEBUG) && LEDEBUG > 1 386 if (sc->sc_debug) 387 printf("%s: am7990_intr entering with isr=%04x\n", 388 device_xname(sc->sc_dev), isr); 389 #endif 390 if ((isr & LE_C0_INTR) == 0) 391 return (0); 392 393 #ifdef __vax__ 394 /* 395 * DEC needs this write order to the registers, don't know 396 * the results on other arch's. Ragge 991029 397 */ 398 isr &= ~LE_C0_INEA; 399 (*sc->sc_wrcsr)(sc, LE_CSR0, isr); 400 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 401 #else 402 (*sc->sc_wrcsr)(sc, LE_CSR0, 403 isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR | 404 LE_C0_RINT | LE_C0_TINT | LE_C0_IDON)); 405 #endif 406 if (isr & LE_C0_ERR) { 407 if (isr & LE_C0_BABL) { 408 #ifdef LEDEBUG 409 printf("%s: babble\n", device_xname(sc->sc_dev)); 410 #endif 411 ifp->if_oerrors++; 412 } 413 #if 0 414 if (isr & LE_C0_CERR) { 415 printf("%s: collision error\n", 416 device_xname(sc->sc_dev)); 417 ifp->if_collisions++; 418 } 419 #endif 420 if (isr & LE_C0_MISS) { 421 #ifdef LEDEBUG 422 printf("%s: missed packet\n", device_xname(sc->sc_dev)); 423 #endif 424 ifp->if_ierrors++; 425 } 426 if (isr & LE_C0_MERR) { 427 printf("%s: memory error\n", device_xname(sc->sc_dev)); 428 lance_reset(sc); 429 return (1); 430 } 431 } 432 433 if ((isr & LE_C0_RXON) == 0) { 434 printf("%s: receiver disabled\n", device_xname(sc->sc_dev)); 435 ifp->if_ierrors++; 436 lance_reset(sc); 437 return (1); 438 } 439 if ((isr & LE_C0_TXON) == 0) { 440 printf("%s: transmitter disabled\n", device_xname(sc->sc_dev)); 441 ifp->if_oerrors++; 442 lance_reset(sc); 443 return (1); 444 } 445 446 /* 447 * Pretend we have carrier; if we don't this will be cleared 448 * shortly. 449 */ 450 sc->sc_havecarrier = 1; 451 452 if (isr & LE_C0_RINT) 453 am7990_rint(sc); 454 if (isr & LE_C0_TINT) 455 am7990_tint(sc); 456 457 #if NRND > 0 458 rnd_add_uint32(&sc->rnd_source, isr); 459 #endif 460 461 return (1); 462 } 463 464 #undef ifp 465 466 /* 467 * Setup output on interface. 468 * Get another datagram to send off of the interface queue, and map it to the 469 * interface before starting the output. 470 * Called only at splnet or interrupt level. 471 */ 472 static void 473 am7990_start(struct ifnet *ifp) 474 { 475 struct lance_softc *sc = ifp->if_softc; 476 int bix; 477 struct mbuf *m; 478 struct letmd tmd; 479 int rp; 480 int len; 481 482 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 483 return; 484 485 bix = sc->sc_last_td; 486 487 for (;;) { 488 rp = LE_TMDADDR(sc, bix); 489 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 490 491 if (tmd.tmd1_bits & LE_T1_OWN) { 492 ifp->if_flags |= IFF_OACTIVE; 493 printf("missing buffer, no_td = %d, last_td = %d\n", 494 sc->sc_no_td, sc->sc_last_td); 495 } 496 497 IFQ_DEQUEUE(&ifp->if_snd, m); 498 if (m == 0) 499 break; 500 501 #if NBPFILTER > 0 502 /* 503 * If BPF is listening on this interface, let it see the packet 504 * before we commit it to the wire. 505 */ 506 if (ifp->if_bpf) 507 bpf_mtap(ifp->if_bpf, m); 508 #endif 509 510 /* 511 * Copy the mbuf chain into the transmit buffer. 512 */ 513 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 514 515 #ifdef LEDEBUG 516 if (len > ETHERMTU + sizeof(struct ether_header)) 517 printf("packet length %d\n", len); 518 #endif 519 520 ifp->if_timer = 5; 521 522 /* 523 * Init transmit registers, and set transmit start flag. 524 */ 525 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; 526 tmd.tmd2 = -len | LE_XMD2_ONES; 527 tmd.tmd3 = 0; 528 529 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 530 531 #ifdef LEDEBUG 532 if (sc->sc_debug > 1) 533 am7990_xmit_print(sc, sc->sc_last_td); 534 #endif 535 536 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 537 538 if (++bix == sc->sc_ntbuf) 539 bix = 0; 540 541 if (++sc->sc_no_td == sc->sc_ntbuf) { 542 ifp->if_flags |= IFF_OACTIVE; 543 break; 544 } 545 546 } 547 548 sc->sc_last_td = bix; 549 } 550 551 #ifdef LEDEBUG 552 static void 553 am7990_recv_print(struct lance_softc *sc, int no) 554 { 555 struct lermd rmd; 556 uint16_t len; 557 struct ether_header eh; 558 559 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 560 len = rmd.rmd3; 561 printf("%s: receive buffer %d, len = %d\n", 562 device_xname(sc->sc_dev), no, len); 563 printf("%s: status %04x\n", device_xname(sc->sc_dev), 564 (*sc->sc_rdcsr)(sc, LE_CSR0)); 565 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 566 device_xname(sc->sc_dev), 567 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); 568 if (len >= sizeof(eh)) { 569 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 570 printf("%s: dst %s", device_xname(sc->sc_dev), 571 ether_sprintf(eh.ether_dhost)); 572 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 573 ntohs(eh.ether_type)); 574 } 575 } 576 577 static void 578 am7990_xmit_print(struct lance_softc *sc, int no) 579 { 580 struct letmd tmd; 581 uint16_t len; 582 struct ether_header eh; 583 584 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 585 len = -tmd.tmd2; 586 printf("%s: transmit buffer %d, len = %d\n", 587 device_xname(sc->sc_dev), no, len); 588 printf("%s: status %04x\n", device_xname(sc->sc_dev), 589 (*sc->sc_rdcsr)(sc, LE_CSR0)); 590 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 591 device_xname(sc->sc_dev), 592 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); 593 if (len >= sizeof(eh)) { 594 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 595 printf("%s: dst %s", device_xname(sc->sc_dev), 596 ether_sprintf(eh.ether_dhost)); 597 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 598 ntohs(eh.ether_type)); 599 } 600 } 601 #endif /* LEDEBUG */ 602