1 /* $OpenBSD: am7990.c,v 1.52 2015/11/25 03:09:58 dlg Exp $ */ 2 /* $NetBSD: am7990.c,v 1.74 2012/02/02 19:43:02 tls Exp $ */ 3 4 /*- 5 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 10 * Simulation Facility, NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /*- 35 * Copyright (c) 1992, 1993 36 * The Regents of the University of California. All rights reserved. 37 * 38 * This code is derived from software contributed to Berkeley by 39 * Ralph Campbell and Rick Macklem. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 66 */ 67 68 #include "bpfilter.h" 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 80 #include <net/if.h> 81 #include <net/if_media.h> 82 83 #include <netinet/in.h> 84 #include <netinet/if_ether.h> 85 86 #if NBPFILTER > 0 87 #include <net/bpf.h> 88 #endif 89 90 #include <dev/ic/lancereg.h> 91 #include <dev/ic/lancevar.h> 92 #include <dev/ic/am7990reg.h> 93 #include <dev/ic/am7990var.h> 94 95 void am7990_meminit(struct lance_softc *); 96 void am7990_start(struct ifnet *); 97 98 void am7990_rint(struct lance_softc *); 99 void am7990_tint(struct lance_softc *); 100 101 #ifdef LEDEBUG 102 void am7990_recv_print(struct lance_softc *, int); 103 void am7990_xmit_print(struct lance_softc *, int); 104 #endif 105 106 /* 107 * am7990 configuration driver. Attachments are provided by 108 * machine-dependent driver front-ends. 109 */ 110 void 111 am7990_config(struct am7990_softc *sc) 112 { 113 int mem, i; 114 115 sc->lsc.sc_meminit = am7990_meminit; 116 sc->lsc.sc_start = am7990_start; 117 118 lance_config(&sc->lsc); 119 120 mem = 0; 121 sc->lsc.sc_initaddr = mem; 122 mem += sizeof(struct leinit); 123 sc->lsc.sc_rmdaddr = mem; 124 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 125 sc->lsc.sc_tmdaddr = mem; 126 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 127 for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN) 128 sc->lsc.sc_rbufaddr[i] = mem; 129 for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN) 130 sc->lsc.sc_tbufaddr[i] = mem; 131 #ifdef notyet 132 if (mem > ...) 133 panic(...); 134 #endif 135 } 136 137 /* 138 * Set up the initialization block and the descriptor rings. 139 */ 140 void 141 am7990_meminit(struct lance_softc *sc) 142 { 143 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 144 u_long a; 145 int bix; 146 struct leinit init; 147 struct lermd rmd; 148 struct letmd tmd; 149 uint8_t *myaddr; 150 151 if (ifp->if_flags & IFF_PROMISC) 152 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; 153 else 154 init.init_mode = LE_MODE_NORMAL; 155 if (sc->sc_initmodemedia == 1) 156 init.init_mode |= LE_MODE_PSEL0; 157 158 /* 159 * Update our private copy of the Ethernet address. 160 * We NEED the copy so we can ensure its alignment! 161 */ 162 memcpy(sc->sc_enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 163 myaddr = sc->sc_enaddr; 164 165 init.init_padr[0] = (myaddr[1] << 8) | myaddr[0]; 166 init.init_padr[1] = (myaddr[3] << 8) | myaddr[2]; 167 init.init_padr[2] = (myaddr[5] << 8) | myaddr[4]; 168 lance_setladrf(&sc->sc_arpcom, init.init_ladrf); 169 170 sc->sc_last_rd = 0; 171 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 172 173 a = sc->sc_addr + LE_RMDADDR(sc, 0); 174 init.init_rdra = a; 175 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); 176 177 a = sc->sc_addr + LE_TMDADDR(sc, 0); 178 init.init_tdra = a; 179 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); 180 181 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 182 183 /* 184 * Set up receive ring descriptors. 185 */ 186 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 187 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 188 rmd.rmd0 = a; 189 rmd.rmd1_hadr = a >> 16; 190 rmd.rmd1_bits = LE_R1_OWN; 191 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 192 rmd.rmd3 = 0; 193 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 194 sizeof(rmd)); 195 } 196 197 /* 198 * Set up transmit ring descriptors. 199 */ 200 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 201 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 202 tmd.tmd0 = a; 203 tmd.tmd1_hadr = a >> 16; 204 tmd.tmd1_bits = 0; 205 tmd.tmd2 = 0 | LE_XMD2_ONES; 206 tmd.tmd3 = 0; 207 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 208 sizeof(tmd)); 209 } 210 } 211 212 void 213 am7990_rint(struct lance_softc *sc) 214 { 215 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 216 struct mbuf *m; 217 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 218 int bix; 219 int rp; 220 struct lermd rmd; 221 222 bix = sc->sc_last_rd; 223 224 /* Process all buffers with valid data. */ 225 for (;;) { 226 rp = LE_RMDADDR(sc, bix); 227 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 228 229 if (rmd.rmd1_bits & LE_R1_OWN) 230 break; 231 232 if (rmd.rmd1_bits & LE_R1_ERR) { 233 if (rmd.rmd1_bits & LE_R1_ENP) { 234 #ifdef LEDEBUG 235 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { 236 if (rmd.rmd1_bits & LE_R1_FRAM) 237 printf("%s: framing error\n", 238 sc->sc_dev.dv_xname); 239 if (rmd.rmd1_bits & LE_R1_CRC) 240 printf("%s: crc mismatch\n", 241 sc->sc_dev.dv_xname); 242 } 243 #endif 244 } else { 245 if (rmd.rmd1_bits & LE_R1_OFLO) 246 printf("%s: overflow\n", 247 sc->sc_dev.dv_xname); 248 } 249 if (rmd.rmd1_bits & LE_R1_BUFF) 250 printf("%s: receive buffer error\n", 251 sc->sc_dev.dv_xname); 252 ifp->if_ierrors++; 253 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != 254 (LE_R1_STP | LE_R1_ENP)) { 255 printf("%s: dropping chained buffer\n", 256 sc->sc_dev.dv_xname); 257 ifp->if_ierrors++; 258 } else { 259 #ifdef LEDEBUG 260 if (sc->sc_debug > 1) 261 am7990_recv_print(sc, sc->sc_last_rd); 262 #endif 263 m = lance_read(sc, LE_RBUFADDR(sc, bix), 264 (int)rmd.rmd3 - 4); 265 if (m != NULL) 266 ml_enqueue(&ml, m); 267 } 268 269 rmd.rmd1_bits = LE_R1_OWN; 270 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 271 rmd.rmd3 = 0; 272 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 273 274 #ifdef LEDEBUG 275 if (sc->sc_debug) 276 printf("sc->sc_last_rd = %x, rmd: " 277 "ladr %04x, hadr %02x, flags %02x, " 278 "bcnt %04x, mcnt %04x\n", 279 sc->sc_last_rd, 280 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, 281 rmd.rmd2, rmd.rmd3); 282 #endif 283 284 if (++bix == sc->sc_nrbuf) 285 bix = 0; 286 } 287 288 sc->sc_last_rd = bix; 289 290 if_input(ifp, &ml); 291 } 292 293 void 294 am7990_tint(struct lance_softc *sc) 295 { 296 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 297 int bix; 298 struct letmd tmd; 299 300 bix = sc->sc_first_td; 301 302 for (;;) { 303 if (sc->sc_no_td <= 0) 304 break; 305 306 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 307 sizeof(tmd)); 308 309 #ifdef LEDEBUG 310 if (sc->sc_debug) 311 printf("trans tmd: " 312 "ladr %04x, hadr %02x, flags %02x, " 313 "bcnt %04x, mcnt %04x\n", 314 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, 315 tmd.tmd2, tmd.tmd3); 316 #endif 317 318 if (tmd.tmd1_bits & LE_T1_OWN) 319 break; 320 321 ifq_clr_oactive(&ifp->if_snd); 322 323 if (tmd.tmd1_bits & LE_T1_ERR) { 324 if (tmd.tmd3 & LE_T3_BUFF) 325 printf("%s: transmit buffer error\n", 326 sc->sc_dev.dv_xname); 327 else if (tmd.tmd3 & LE_T3_UFLO) 328 printf("%s: underflow\n", sc->sc_dev.dv_xname); 329 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { 330 lance_reset(sc); 331 return; 332 } 333 if (tmd.tmd3 & LE_T3_LCAR) { 334 sc->sc_havecarrier = 0; 335 if (sc->sc_nocarrier) 336 (*sc->sc_nocarrier)(sc); 337 else 338 printf("%s: lost carrier\n", 339 sc->sc_dev.dv_xname); 340 } 341 if (tmd.tmd3 & LE_T3_LCOL) 342 ifp->if_collisions++; 343 if (tmd.tmd3 & LE_T3_RTRY) { 344 #ifdef LEDEBUG 345 printf("%s: excessive collisions, tdr %d\n", 346 sc->sc_dev.dv_xname, 347 tmd.tmd3 & LE_T3_TDR_MASK); 348 #endif 349 ifp->if_collisions += 16; 350 } 351 ifp->if_oerrors++; 352 } else { 353 if (tmd.tmd1_bits & LE_T1_ONE) 354 ifp->if_collisions++; 355 else if (tmd.tmd1_bits & LE_T1_MORE) 356 /* Real number is unknown. */ 357 ifp->if_collisions += 2; 358 ifp->if_opackets++; 359 } 360 361 if (++bix == sc->sc_ntbuf) 362 bix = 0; 363 364 --sc->sc_no_td; 365 } 366 367 sc->sc_first_td = bix; 368 369 am7990_start(ifp); 370 371 if (sc->sc_no_td == 0) 372 ifp->if_timer = 0; 373 } 374 375 /* 376 * Controller interrupt. 377 */ 378 int 379 am7990_intr(void *arg) 380 { 381 struct lance_softc *sc = arg; 382 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 383 uint16_t isr; 384 385 isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0; 386 sc->sc_saved_csr0 = 0; 387 #if defined(LEDEBUG) && LEDEBUG > 1 388 if (sc->sc_debug) 389 printf("%s: am7990_intr entering with isr=%04x\n", 390 sc->sc_dev.dv_xname, isr); 391 #endif 392 if ((isr & LE_C0_INTR) == 0) 393 return (0); 394 395 /* 396 * After receiving an interrupt, we need to toggle the interrupt 397 * enable bit in order to keep receiving them (some chips works 398 * without this, some do not) 399 */ 400 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~LE_C0_INEA); 401 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 402 403 if (isr & LE_C0_ERR) { 404 if (isr & LE_C0_BABL) { 405 #ifdef LEDEBUG 406 printf("%s: babble\n", sc->sc_dev.dv_xname); 407 #endif 408 ifp->if_oerrors++; 409 } 410 #if 0 411 if (isr & LE_C0_CERR) { 412 printf("%s: collision error\n", sc->sc_dev.dv_xname); 413 ifp->if_collisions++; 414 } 415 #endif 416 if (isr & LE_C0_MISS) { 417 #ifdef LEDEBUG 418 printf("%s: missed packet\n", sc->sc_dev.dv_xname); 419 #endif 420 ifp->if_ierrors++; 421 } 422 if (isr & LE_C0_MERR) { 423 printf("%s: memory error\n", sc->sc_dev.dv_xname); 424 lance_reset(sc); 425 return (1); 426 } 427 } 428 429 if ((isr & LE_C0_RXON) == 0) { 430 printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); 431 ifp->if_ierrors++; 432 lance_reset(sc); 433 return (1); 434 } 435 if ((isr & LE_C0_TXON) == 0) { 436 printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); 437 ifp->if_oerrors++; 438 lance_reset(sc); 439 return (1); 440 } 441 442 /* 443 * Pretend we have carrier; if we don't this will be cleared 444 * shortly. 445 */ 446 sc->sc_havecarrier = 1; 447 448 if (isr & LE_C0_RINT) 449 am7990_rint(sc); 450 if (isr & LE_C0_TINT) 451 am7990_tint(sc); 452 453 return (1); 454 } 455 456 /* 457 * Setup output on interface. 458 * Get another datagram to send off of the interface queue, and map it to the 459 * interface before starting the output. 460 * Called only at splnet or interrupt level. 461 */ 462 void 463 am7990_start(struct ifnet *ifp) 464 { 465 struct lance_softc *sc = ifp->if_softc; 466 int bix; 467 struct mbuf *m; 468 struct letmd tmd; 469 int rp; 470 int len; 471 472 if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) 473 return; 474 475 bix = sc->sc_last_td; 476 477 for (;;) { 478 rp = LE_TMDADDR(sc, bix); 479 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 480 481 if (tmd.tmd1_bits & LE_T1_OWN) { 482 ifq_set_oactive(&ifp->if_snd); 483 printf("missing buffer, no_td = %d, last_td = %d\n", 484 sc->sc_no_td, sc->sc_last_td); 485 } 486 487 IFQ_DEQUEUE(&ifp->if_snd, m); 488 if (m == NULL) 489 break; 490 491 #if NBPFILTER > 0 492 /* 493 * If BPF is listening on this interface, let it see the packet 494 * before we commit it to the wire. 495 */ 496 if (ifp->if_bpf) 497 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 498 #endif 499 500 /* 501 * Copy the mbuf chain into the transmit buffer. 502 */ 503 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 504 505 #ifdef LEDEBUG 506 if (len > ETHERMTU + sizeof(struct ether_header)) 507 printf("packet length %d\n", len); 508 #endif 509 510 ifp->if_timer = 5; 511 512 /* 513 * Init transmit registers, and set transmit start flag. 514 */ 515 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; 516 tmd.tmd2 = -len | LE_XMD2_ONES; 517 tmd.tmd3 = 0; 518 519 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 520 521 #ifdef LEDEBUG 522 if (sc->sc_debug > 1) 523 am7990_xmit_print(sc, sc->sc_last_td); 524 #endif 525 526 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 527 528 if (++bix == sc->sc_ntbuf) 529 bix = 0; 530 531 if (++sc->sc_no_td == sc->sc_ntbuf) { 532 ifq_set_oactive(&ifp->if_snd); 533 break; 534 } 535 536 } 537 538 sc->sc_last_td = bix; 539 } 540 541 #ifdef LEDEBUG 542 void 543 am7990_recv_print(struct lance_softc *sc, int no) 544 { 545 struct lermd rmd; 546 uint16_t len; 547 struct ether_header eh; 548 549 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 550 len = rmd.rmd3; 551 printf("%s: receive buffer %d, len = %d\n", 552 sc->sc_dev.dv_xname, no, len); 553 printf("%s: status %04x\n", sc->sc_dev.dv_xname, 554 (*sc->sc_rdcsr)(sc, LE_CSR0)); 555 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 556 sc->sc_dev.dv_xname, 557 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); 558 if (len >= sizeof(eh)) { 559 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 560 printf("%s: dst %s", sc->sc_dev.dv_xname, 561 ether_sprintf(eh.ether_dhost)); 562 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 563 ntohs(eh.ether_type)); 564 } 565 } 566 567 void 568 am7990_xmit_print(struct lance_softc *sc, int no) 569 { 570 struct letmd tmd; 571 uint16_t len; 572 struct ether_header eh; 573 574 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 575 len = -tmd.tmd2; 576 printf("%s: transmit buffer %d, len = %d\n", 577 sc->sc_dev.dv_xname, no, len); 578 printf("%s: status %04x\n", sc->sc_dev.dv_xname, 579 (*sc->sc_rdcsr)(sc, LE_CSR0)); 580 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 581 sc->sc_dev.dv_xname, 582 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); 583 if (len >= sizeof(eh)) { 584 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 585 printf("%s: dst %s", sc->sc_dev.dv_xname, 586 ether_sprintf(eh.ether_dhost)); 587 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 588 ntohs(eh.ether_type)); 589 } 590 } 591 #endif /* LEDEBUG */ 592