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