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