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