1 /* $OpenBSD: am7990.c,v 1.27 2001/07/27 15:30:42 tholo Exp $ */ 2 /* $NetBSD: am7990.c,v 1.22 1996/10/13 01:37:19 christos Exp $ */ 3 4 /*- 5 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Ralph Campbell and Rick Macklem. 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 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 41 */ 42 43 #include "bpfilter.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/mbuf.h> 48 #include <sys/syslog.h> 49 #include <sys/socket.h> 50 #include <sys/device.h> 51 #include <sys/malloc.h> 52 #include <sys/ioctl.h> 53 #include <sys/errno.h> 54 55 #include <net/if.h> 56 #include <net/if_media.h> 57 58 #ifdef INET 59 #include <netinet/in.h> 60 #include <netinet/if_ether.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/in_var.h> 63 #include <netinet/ip.h> 64 #endif 65 66 #if NBPFILTER > 0 67 #include <net/bpf.h> 68 #include <net/bpfdesc.h> 69 #endif 70 71 #include <dev/ic/am7990reg.h> 72 #include <dev/ic/am7990var.h> 73 74 #ifdef LEDEBUG 75 void am7990_recv_print __P((struct am7990_softc *, int)); 76 void am7990_xmit_print __P((struct am7990_softc *, int)); 77 #endif 78 79 integrate void am7990_rint __P((struct am7990_softc *)); 80 integrate void am7990_tint __P((struct am7990_softc *)); 81 82 integrate int am7990_put __P((struct am7990_softc *, int, struct mbuf *)); 83 integrate struct mbuf *am7990_get __P((struct am7990_softc *, int, int)); 84 integrate void am7990_read __P((struct am7990_softc *, int, int)); 85 86 hide void am7990_shutdown __P((void *)); 87 88 #define ifp (&sc->sc_arpcom.ac_if) 89 90 #if 0 /* XXX what do we do about this?! --thorpej */ 91 static inline u_int16_t ether_cmp __P((void *, void *)); 92 93 /* 94 * Compare two Ether/802 addresses for equality, inlined and 95 * unrolled for speed. I'd love to have an inline assembler 96 * version of this... XXX: Who wanted that? mycroft? 97 * I wrote one, but the following is just as efficient. 98 * This expands to 10 short m68k instructions! -gwr 99 * Note: use this like bcmp() 100 */ 101 static inline u_short 102 ether_cmp(one, two) 103 void *one, *two; 104 { 105 register u_int16_t *a = (u_short *) one; 106 register u_int16_t *b = (u_short *) two; 107 register u_int16_t diff; 108 109 diff = *a++ - *b++; 110 diff |= *a++ - *b++; 111 diff |= *a++ - *b++; 112 113 return (diff); 114 } 115 116 #define ETHER_CMP ether_cmp 117 #endif /* XXX */ 118 119 #ifndef ETHER_CMP 120 #define ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN) 121 #endif 122 123 /* 124 * am7990 configuration driver. Attachments are provided by 125 * machine-dependent driver front-ends. 126 */ 127 struct cfdriver le_cd = { 128 NULL, "le", DV_IFNET 129 }; 130 131 void 132 am7990_config(sc) 133 struct am7990_softc *sc; 134 { 135 int mem; 136 137 /* Make sure the chip is stopped. */ 138 am7990_stop(sc); 139 140 /* Initialize ifnet structure. */ 141 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 142 ifp->if_softc = sc; 143 ifp->if_start = am7990_start; 144 ifp->if_ioctl = am7990_ioctl; 145 ifp->if_watchdog = am7990_watchdog; 146 ifp->if_flags = 147 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 148 #ifdef LANCE_REVC_BUG 149 ifp->if_flags &= ~IFF_MULTICAST; 150 #endif 151 IFQ_SET_READY(&ifp->if_snd); 152 153 /* Attach the interface. */ 154 if_attach(ifp); 155 ether_ifattach(ifp); 156 157 if (sc->sc_memsize > 262144) 158 sc->sc_memsize = 262144; 159 160 switch (sc->sc_memsize) { 161 case 8192: 162 sc->sc_nrbuf = 4; 163 sc->sc_ntbuf = 1; 164 break; 165 case 16384: 166 sc->sc_nrbuf = 8; 167 sc->sc_ntbuf = 2; 168 break; 169 case 32768: 170 sc->sc_nrbuf = 16; 171 sc->sc_ntbuf = 4; 172 break; 173 case 65536: 174 sc->sc_nrbuf = 32; 175 sc->sc_ntbuf = 8; 176 break; 177 case 131072: 178 sc->sc_nrbuf = 64; 179 sc->sc_ntbuf = 16; 180 break; 181 case 262144: 182 sc->sc_nrbuf = 128; 183 sc->sc_ntbuf = 32; 184 break; 185 default: 186 panic("am7990_config: weird memory size %d", sc->sc_memsize); 187 } 188 189 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); 190 printf("%s: %d receive buffers, %d transmit buffers\n", 191 sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf); 192 193 sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc); 194 if (sc->sc_sh == NULL) 195 panic("am7990_config: can't establish shutdownhook"); 196 197 mem = 0; 198 sc->sc_initaddr = mem; 199 mem += sizeof(struct leinit); 200 sc->sc_rmdaddr = mem; 201 mem += sizeof(struct lermd) * sc->sc_nrbuf; 202 sc->sc_tmdaddr = mem; 203 mem += sizeof(struct letmd) * sc->sc_ntbuf; 204 sc->sc_rbufaddr = mem; 205 mem += LEBLEN * sc->sc_nrbuf; 206 sc->sc_tbufaddr = mem; 207 mem += LEBLEN * sc->sc_ntbuf; 208 #ifdef notyet 209 if (mem > ...) 210 panic(...); 211 #endif 212 } 213 214 void 215 am7990_reset(sc) 216 struct am7990_softc *sc; 217 { 218 int s; 219 220 s = splimp(); 221 am7990_init(sc); 222 splx(s); 223 } 224 225 /* 226 * Set up the initialization block and the descriptor rings. 227 */ 228 void 229 am7990_meminit(sc) 230 register struct am7990_softc *sc; 231 { 232 u_long a; 233 int bix; 234 struct leinit init; 235 struct lermd rmd; 236 struct letmd tmd; 237 238 #if NBPFILTER > 0 239 if (ifp->if_flags & IFF_PROMISC) 240 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; 241 else 242 #endif 243 init.init_mode = LE_MODE_NORMAL; 244 init.init_padr[0] = 245 (sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0]; 246 init.init_padr[1] = 247 (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2]; 248 init.init_padr[2] = 249 (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4]; 250 am7990_setladrf(&sc->sc_arpcom, init.init_ladrf); 251 252 sc->sc_last_rd = 0; 253 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 254 255 a = sc->sc_addr + LE_RMDADDR(sc, 0); 256 init.init_rdra = a; 257 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); 258 259 a = sc->sc_addr + LE_TMDADDR(sc, 0); 260 init.init_tdra = a; 261 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); 262 263 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 264 265 /* 266 * Set up receive ring descriptors. 267 */ 268 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 269 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 270 rmd.rmd0 = a; 271 rmd.rmd1_hadr = a >> 16; 272 rmd.rmd1_bits = LE_R1_OWN; 273 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 274 rmd.rmd3 = 0; 275 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 276 sizeof(rmd)); 277 } 278 279 /* 280 * Set up transmit ring descriptors. 281 */ 282 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 283 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 284 tmd.tmd0 = a; 285 tmd.tmd1_hadr = a >> 16; 286 tmd.tmd1_bits = 0; 287 tmd.tmd2 = 0 | LE_XMD2_ONES; 288 tmd.tmd3 = 0; 289 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 290 sizeof(tmd)); 291 } 292 } 293 294 void 295 am7990_stop(sc) 296 struct am7990_softc *sc; 297 { 298 299 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); 300 } 301 302 /* 303 * Initialization of interface; set up initialization block 304 * and transmit/receive descriptor rings. 305 */ 306 void 307 am7990_init(sc) 308 register struct am7990_softc *sc; 309 { 310 register int timo; 311 u_long a; 312 313 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); 314 DELAY(100); 315 316 /* Newer LANCE chips have a reset register */ 317 if (sc->sc_hwreset) 318 (*sc->sc_hwreset)(sc); 319 320 /* Set the correct byte swapping mode, etc. */ 321 (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3); 322 323 /* Set up LANCE init block. */ 324 am7990_meminit(sc); 325 326 /* Give LANCE the physical address of its init block. */ 327 a = sc->sc_addr + LE_INITADDR(sc); 328 (*sc->sc_wrcsr)(sc, LE_CSR1, a); 329 (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16); 330 331 /* Try to initialize the LANCE. */ 332 DELAY(100); 333 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT); 334 335 /* Wait for initialization to finish. */ 336 for (timo = 100000; timo; timo--) 337 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) 338 break; 339 340 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) { 341 /* Start the LANCE. */ 342 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | 343 LE_C0_IDON); 344 ifp->if_flags |= IFF_RUNNING; 345 ifp->if_flags &= ~IFF_OACTIVE; 346 ifp->if_timer = 0; 347 am7990_start(ifp); 348 } else 349 printf("%s: controller failed to initialize\n", sc->sc_dev.dv_xname); 350 if (sc->sc_hwinit) 351 (*sc->sc_hwinit)(sc); 352 } 353 354 /* 355 * Routine to copy from mbuf chain to transmit buffer in 356 * network buffer memory. 357 */ 358 integrate int 359 am7990_put(sc, boff, m) 360 struct am7990_softc *sc; 361 int boff; 362 register struct mbuf *m; 363 { 364 register struct mbuf *n; 365 register int len, tlen = 0; 366 367 for (; m; m = n) { 368 len = m->m_len; 369 if (len == 0) { 370 MFREE(m, n); 371 continue; 372 } 373 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len); 374 boff += len; 375 tlen += len; 376 MFREE(m, n); 377 } 378 if (tlen < LEMINSIZE) { 379 (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen); 380 tlen = LEMINSIZE; 381 } 382 return (tlen); 383 } 384 385 /* 386 * Pull data off an interface. 387 * Len is length of data, with local net header stripped. 388 * We copy the data into mbufs. When full cluster sized units are present 389 * we copy into clusters. 390 */ 391 integrate struct mbuf * 392 am7990_get(sc, boff, totlen) 393 struct am7990_softc *sc; 394 int boff, totlen; 395 { 396 register struct mbuf *m; 397 struct mbuf *top, **mp; 398 int len, pad; 399 400 MGETHDR(m, M_DONTWAIT, MT_DATA); 401 if (m == 0) 402 return (0); 403 m->m_pkthdr.rcvif = ifp; 404 m->m_pkthdr.len = totlen; 405 pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header); 406 m->m_data += pad; 407 len = MHLEN - pad; 408 top = 0; 409 mp = ⊤ 410 411 while (totlen > 0) { 412 if (top) { 413 MGET(m, M_DONTWAIT, MT_DATA); 414 if (m == 0) { 415 m_freem(top); 416 return 0; 417 } 418 len = MLEN; 419 } 420 if (totlen >= MINCLSIZE) { 421 MCLGET(m, M_DONTWAIT); 422 if (m->m_flags & M_EXT) { 423 len = MCLBYTES; 424 if (!top) { 425 m->m_data += pad; 426 len -= pad; 427 } 428 } 429 } 430 m->m_len = len = min(totlen, len); 431 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len); 432 boff += len; 433 totlen -= len; 434 *mp = m; 435 mp = &m->m_next; 436 } 437 438 return (top); 439 } 440 441 /* 442 * Pass a packet to the higher levels. 443 */ 444 integrate void 445 am7990_read(sc, boff, len) 446 register struct am7990_softc *sc; 447 int boff, len; 448 { 449 struct mbuf *m; 450 #ifdef LANCE_REVC_BUG 451 struct ether_header *eh; 452 #endif 453 454 if (len <= sizeof(struct ether_header) || 455 len > ETHERMTU + sizeof(struct ether_header)) { 456 #ifdef LEDEBUG 457 printf("%s: invalid packet size %d; dropping\n", 458 sc->sc_dev.dv_xname, len); 459 #endif 460 ifp->if_ierrors++; 461 return; 462 } 463 464 /* Pull packet off interface. */ 465 m = am7990_get(sc, boff, len); 466 if (m == 0) { 467 ifp->if_ierrors++; 468 return; 469 } 470 471 ifp->if_ipackets++; 472 473 #if NBPFILTER > 0 474 /* 475 * Check if there's a BPF listener on this interface. 476 * If so, hand off the raw packet to BPF. 477 */ 478 if (ifp->if_bpf) 479 bpf_mtap(ifp->if_bpf, m); 480 #endif 481 482 #ifdef LANCE_REVC_BUG 483 /* 484 * The old LANCE (Rev. C) chips have a bug which causes 485 * garbage to be inserted in front of the received packet. 486 * The work-around is to ignore packets with an invalid 487 * destination address (garbage will usually not match). 488 * Of course, this precludes multicast support... 489 */ 490 eh = mtod(m, struct ether_header *); 491 if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) && 492 ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) { 493 m_freem(m); 494 return; 495 } 496 #endif 497 498 /* Pass the packet up. */ 499 ether_input_mbuf(ifp, m); 500 } 501 502 integrate void 503 am7990_rint(sc) 504 struct am7990_softc *sc; 505 { 506 register int bix; 507 int rp; 508 struct lermd rmd; 509 510 bix = sc->sc_last_rd; 511 512 /* Process all buffers with valid data. */ 513 for (;;) { 514 rp = LE_RMDADDR(sc, bix); 515 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 516 517 if (rmd.rmd1_bits & LE_R1_OWN) 518 break; 519 520 if (rmd.rmd1_bits & LE_R1_ERR) { 521 if (rmd.rmd1_bits & LE_R1_ENP) { 522 #ifdef LEDEBUG 523 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { 524 if (rmd.rmd1_bits & LE_R1_FRAM) 525 printf("%s: framing error\n", 526 sc->sc_dev.dv_xname); 527 if (rmd.rmd1_bits & LE_R1_CRC) 528 printf("%s: crc mismatch\n", 529 sc->sc_dev.dv_xname); 530 } 531 #endif 532 } else { 533 if (rmd.rmd1_bits & LE_R1_OFLO) 534 printf("%s: overflow\n", 535 sc->sc_dev.dv_xname); 536 } 537 if (rmd.rmd1_bits & LE_R1_BUFF) 538 printf("%s: receive buffer error\n", 539 sc->sc_dev.dv_xname); 540 ifp->if_ierrors++; 541 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != 542 (LE_R1_STP | LE_R1_ENP)) { 543 printf("%s: dropping chained buffer\n", 544 sc->sc_dev.dv_xname); 545 ifp->if_ierrors++; 546 } else { 547 #ifdef LEDEBUG1 548 if (sc->sc_debug) 549 am7990_recv_print(sc, sc->sc_last_rd); 550 #endif 551 am7990_read(sc, LE_RBUFADDR(sc, bix), 552 (int)rmd.rmd3 - 4); 553 } 554 555 rmd.rmd1_bits = LE_R1_OWN; 556 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 557 rmd.rmd3 = 0; 558 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 559 560 #ifdef LEDEBUG1 561 if (sc->sc_debug) 562 printf("sc->sc_last_rd = %x, rmd: " 563 "ladr %04x, hadr %02x, flags %02x, " 564 "bcnt %04x, mcnt %04x\n", 565 sc->sc_last_rd, 566 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, 567 rmd.rmd2, rmd.rmd3); 568 #endif 569 570 if (++bix == sc->sc_nrbuf) 571 bix = 0; 572 } 573 574 sc->sc_last_rd = bix; 575 } 576 577 integrate void 578 am7990_tint(sc) 579 register struct am7990_softc *sc; 580 { 581 register int bix; 582 struct letmd tmd; 583 584 bix = sc->sc_first_td; 585 586 for (;;) { 587 if (sc->sc_no_td <= 0) 588 break; 589 590 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 591 sizeof(tmd)); 592 593 #ifdef LEDEBUG 594 if (sc->sc_debug) 595 printf("trans tmd: " 596 "ladr %04x, hadr %02x, flags %02x, " 597 "bcnt %04x, mcnt %04x\n", 598 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, 599 tmd.tmd2, tmd.tmd3); 600 #endif 601 602 if (tmd.tmd1_bits & LE_T1_OWN) 603 break; 604 605 ifp->if_flags &= ~IFF_OACTIVE; 606 607 if (tmd.tmd1_bits & LE_T1_ERR) { 608 if (tmd.tmd3 & LE_T3_BUFF) 609 printf("%s: transmit buffer error\n", 610 sc->sc_dev.dv_xname); 611 else if (tmd.tmd3 & LE_T3_UFLO) 612 printf("%s: underflow\n", sc->sc_dev.dv_xname); 613 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { 614 am7990_reset(sc); 615 return; 616 } 617 if (tmd.tmd3 & LE_T3_LCAR) { 618 if (sc->sc_nocarrier) 619 (*sc->sc_nocarrier)(sc); 620 else 621 printf("%s: lost carrier\n", 622 sc->sc_dev.dv_xname); 623 } 624 if (tmd.tmd3 & LE_T3_LCOL) 625 ifp->if_collisions++; 626 if (tmd.tmd3 & LE_T3_RTRY) { 627 printf("%s: excessive collisions, tdr %d\n", 628 sc->sc_dev.dv_xname, 629 tmd.tmd3 & LE_T3_TDR_MASK); 630 ifp->if_collisions += 16; 631 } 632 ifp->if_oerrors++; 633 } else { 634 if (tmd.tmd1_bits & LE_T1_ONE) 635 ifp->if_collisions++; 636 else if (tmd.tmd1_bits & LE_T1_MORE) 637 /* Real number is unknown. */ 638 ifp->if_collisions += 2; 639 ifp->if_opackets++; 640 } 641 642 if (++bix == sc->sc_ntbuf) 643 bix = 0; 644 645 --sc->sc_no_td; 646 } 647 648 sc->sc_first_td = bix; 649 650 am7990_start(ifp); 651 652 if (sc->sc_no_td == 0) 653 ifp->if_timer = 0; 654 } 655 656 /* 657 * Controller interrupt. 658 */ 659 int 660 am7990_intr(arg) 661 register void *arg; 662 { 663 register struct am7990_softc *sc = arg; 664 register u_int16_t isr; 665 666 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 667 #ifdef LEDEBUG 668 if (sc->sc_debug){ 669 printf("%s: am7990_intr entering with isr=%04x\n", 670 sc->sc_dev.dv_xname, isr); 671 printf(" isr: 0x%b\n", isr, LE_C0_BITS); 672 } 673 #endif 674 if ((isr & LE_C0_INTR) == 0) 675 return (0); 676 677 /* 678 * After receiving an interrupt, we need to toggle the interrupt 679 * enable bit in order to keep receiving them (some chips works 680 * without this, some do not) 681 */ 682 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~LE_C0_INEA); 683 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 684 685 if (isr & LE_C0_ERR) { 686 if (isr & LE_C0_BABL) { 687 #ifdef LEDEBUG 688 printf("%s: babble\n", sc->sc_dev.dv_xname); 689 #endif 690 ifp->if_oerrors++; 691 } 692 #if 0 693 if (isr & LE_C0_CERR) { 694 printf("%s: collision error\n", sc->sc_dev.dv_xname); 695 ifp->if_collisions++; 696 } 697 #endif 698 if (isr & LE_C0_MISS) { 699 #ifdef LEDEBUG 700 printf("%s: missed packet\n", sc->sc_dev.dv_xname); 701 #endif 702 ifp->if_ierrors++; 703 } 704 if (isr & LE_C0_MERR) { 705 printf("%s: memory error\n", sc->sc_dev.dv_xname); 706 am7990_reset(sc); 707 return (1); 708 } 709 } 710 711 if ((isr & LE_C0_RXON) == 0) { 712 printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); 713 ifp->if_ierrors++; 714 am7990_reset(sc); 715 return (1); 716 } 717 if ((isr & LE_C0_TXON) == 0) { 718 printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); 719 ifp->if_oerrors++; 720 am7990_reset(sc); 721 return (1); 722 } 723 724 if (isr & LE_C0_RINT) 725 am7990_rint(sc); 726 if (isr & LE_C0_TINT) 727 am7990_tint(sc); 728 729 return (1); 730 } 731 732 #undef ifp 733 734 void 735 am7990_watchdog(ifp) 736 struct ifnet *ifp; 737 { 738 struct am7990_softc *sc = ifp->if_softc; 739 740 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 741 ++ifp->if_oerrors; 742 743 am7990_reset(sc); 744 } 745 746 /* 747 * Setup output on interface. 748 * Get another datagram to send off of the interface queue, and map it to the 749 * interface before starting the output. 750 * Called only at splimp or interrupt level. 751 */ 752 void 753 am7990_start(ifp) 754 register struct ifnet *ifp; 755 { 756 register struct am7990_softc *sc = ifp->if_softc; 757 register int bix; 758 register struct mbuf *m; 759 struct letmd tmd; 760 int rp; 761 int len; 762 763 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 764 return; 765 766 bix = sc->sc_last_td; 767 768 for (;;) { 769 rp = LE_TMDADDR(sc, bix); 770 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 771 772 if (tmd.tmd1_bits & LE_T1_OWN) { 773 ifp->if_flags |= IFF_OACTIVE; 774 printf("missing buffer, no_td = %d, last_td = %d\n", 775 sc->sc_no_td, sc->sc_last_td); 776 } 777 778 IFQ_DEQUEUE(&ifp->if_snd, m); 779 if (m == 0) 780 break; 781 782 #if NBPFILTER > 0 783 /* 784 * If BPF is listening on this interface, let it see the packet 785 * before we commit it to the wire. 786 */ 787 if (ifp->if_bpf) 788 bpf_mtap(ifp->if_bpf, m); 789 #endif 790 791 /* 792 * Copy the mbuf chain into the transmit buffer. 793 */ 794 len = am7990_put(sc, LE_TBUFADDR(sc, bix), m); 795 796 #ifdef LEDEBUG 797 if (len > ETHERMTU + sizeof(struct ether_header)) 798 printf("packet length %d\n", len); 799 #endif 800 801 ifp->if_timer = 5; 802 803 /* 804 * Init transmit registers, and set transmit start flag. 805 */ 806 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; 807 tmd.tmd2 = -len | LE_XMD2_ONES; 808 tmd.tmd3 = 0; 809 810 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 811 812 #ifdef LEDEBUG 813 if (sc->sc_debug) 814 am7990_xmit_print(sc, sc->sc_last_td); 815 #endif 816 817 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 818 819 if (++bix == sc->sc_ntbuf) 820 bix = 0; 821 822 if (++sc->sc_no_td == sc->sc_ntbuf) { 823 #ifdef LEDEBUG 824 printf("\nequal!\n"); 825 #endif 826 ifp->if_flags |= IFF_OACTIVE; 827 break; 828 } 829 830 } 831 832 sc->sc_last_td = bix; 833 } 834 835 /* 836 * Process an ioctl request. 837 */ 838 int 839 am7990_ioctl(ifp, cmd, data) 840 register struct ifnet *ifp; 841 u_long cmd; 842 caddr_t data; 843 { 844 register struct am7990_softc *sc = ifp->if_softc; 845 struct ifaddr *ifa = (struct ifaddr *)data; 846 struct ifreq *ifr = (struct ifreq *)data; 847 int s, error = 0; 848 849 s = splimp(); 850 851 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) { 852 splx(s); 853 return error; 854 } 855 856 switch (cmd) { 857 858 case SIOCSIFADDR: 859 ifp->if_flags |= IFF_UP; 860 861 switch (ifa->ifa_addr->sa_family) { 862 #ifdef INET 863 case AF_INET: 864 am7990_init(sc); 865 arp_ifinit(&sc->sc_arpcom, ifa); 866 break; 867 #endif 868 default: 869 am7990_init(sc); 870 break; 871 } 872 break; 873 874 case SIOCSIFFLAGS: 875 if ((ifp->if_flags & IFF_UP) == 0 && 876 (ifp->if_flags & IFF_RUNNING) != 0) { 877 /* 878 * If interface is marked down and it is running, then 879 * stop it. 880 */ 881 am7990_stop(sc); 882 ifp->if_flags &= ~IFF_RUNNING; 883 } else if ((ifp->if_flags & IFF_UP) != 0 && 884 (ifp->if_flags & IFF_RUNNING) == 0) { 885 /* 886 * If interface is marked up and it is stopped, then 887 * start it. 888 */ 889 am7990_init(sc); 890 } else { 891 /* 892 * Reset the interface to pick up changes in any other 893 * flags that affect hardware registers. 894 */ 895 /*am7990_stop(sc);*/ 896 am7990_init(sc); 897 } 898 #ifdef LEDEBUG 899 if (ifp->if_flags & IFF_DEBUG) 900 sc->sc_debug = 1; 901 else 902 sc->sc_debug = 0; 903 #endif 904 break; 905 906 case SIOCADDMULTI: 907 case SIOCDELMULTI: 908 error = (cmd == SIOCADDMULTI) ? 909 ether_addmulti(ifr, &sc->sc_arpcom) : 910 ether_delmulti(ifr, &sc->sc_arpcom); 911 912 if (error == ENETRESET) { 913 /* 914 * Multicast list has changed; set the hardware filter 915 * accordingly. 916 */ 917 am7990_reset(sc); 918 error = 0; 919 } 920 break; 921 922 case SIOCGIFMEDIA: 923 case SIOCSIFMEDIA: 924 if (sc->sc_hasifmedia) 925 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd); 926 else 927 error = EINVAL; 928 break; 929 930 default: 931 error = EINVAL; 932 break; 933 } 934 935 splx(s); 936 return (error); 937 } 938 939 hide void 940 am7990_shutdown(arg) 941 void *arg; 942 { 943 944 am7990_stop((struct am7990_softc *)arg); 945 } 946 947 #ifdef LEDEBUG 948 void 949 am7990_recv_print(sc, no) 950 struct am7990_softc *sc; 951 int no; 952 { 953 struct lermd rmd; 954 u_int16_t len; 955 struct ether_header eh; 956 957 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 958 len = rmd.rmd3; 959 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, 960 len); 961 printf("%s: status %04x\n", sc->sc_dev.dv_xname, 962 (*sc->sc_rdcsr)(sc, LE_CSR0)); 963 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 964 sc->sc_dev.dv_xname, 965 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); 966 if (len >= sizeof(eh)) { 967 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 968 printf("%s: dst %s", sc->sc_dev.dv_xname, 969 ether_sprintf(eh.ether_dhost)); 970 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 971 ntohs(eh.ether_type)); 972 } 973 } 974 975 void 976 am7990_xmit_print(sc, no) 977 struct am7990_softc *sc; 978 int no; 979 { 980 struct letmd tmd; 981 u_int16_t len; 982 struct ether_header eh; 983 984 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 985 len = -tmd.tmd2; 986 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, 987 len); 988 printf("%s: status %04x\n", sc->sc_dev.dv_xname, 989 (*sc->sc_rdcsr)(sc, LE_CSR0)); 990 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 991 sc->sc_dev.dv_xname, 992 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); 993 if (len >= sizeof(eh)) { 994 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 995 printf("%s: dst %s", sc->sc_dev.dv_xname, 996 ether_sprintf(eh.ether_dhost)); 997 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 998 ntohs(eh.ether_type)); 999 } 1000 } 1001 #endif /* LEDEBUG */ 1002 1003 /* 1004 * Set up the logical address filter. 1005 */ 1006 void 1007 am7990_setladrf(ac, af) 1008 struct arpcom *ac; 1009 u_int16_t *af; 1010 { 1011 struct ifnet *ifp = &ac->ac_if; 1012 struct ether_multi *enm; 1013 register u_char *cp, c; 1014 register u_int32_t crc; 1015 register int i, len; 1016 struct ether_multistep step; 1017 1018 /* 1019 * Set up multicast address filter by passing all multicast addresses 1020 * through a crc generator, and then using the high order 6 bits as an 1021 * index into the 64 bit logical address filter. The high order bit 1022 * selects the word, while the rest of the bits select the bit within 1023 * the word. 1024 */ 1025 1026 if (ifp->if_flags & IFF_PROMISC) 1027 goto allmulti; 1028 1029 af[0] = af[1] = af[2] = af[3] = 0x0000; 1030 ETHER_FIRST_MULTI(step, ac, enm); 1031 while (enm != NULL) { 1032 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) { 1033 /* 1034 * We must listen to a range of multicast addresses. 1035 * For now, just accept all multicasts, rather than 1036 * trying to set only those filter bits needed to match 1037 * the range. (At this time, the only use of address 1038 * ranges is for IP multicast routing, for which the 1039 * range is big enough to require all bits set.) 1040 */ 1041 goto allmulti; 1042 } 1043 1044 cp = enm->enm_addrlo; 1045 crc = 0xffffffff; 1046 for (len = sizeof(enm->enm_addrlo); --len >= 0;) { 1047 c = *cp++; 1048 for (i = 8; --i >= 0;) { 1049 if ((crc & 0x01) ^ (c & 0x01)) { 1050 crc >>= 1; 1051 crc ^= 0xedb88320; 1052 } else 1053 crc >>= 1; 1054 c >>= 1; 1055 } 1056 } 1057 /* Just want the 6 most significant bits. */ 1058 crc >>= 26; 1059 1060 /* Set the corresponding bit in the filter. */ 1061 af[crc >> 4] |= 1 << (crc & 0xf); 1062 1063 ETHER_NEXT_MULTI(step, enm); 1064 } 1065 ifp->if_flags &= ~IFF_ALLMULTI; 1066 return; 1067 1068 allmulti: 1069 ifp->if_flags |= IFF_ALLMULTI; 1070 af[0] = af[1] = af[2] = af[3] = 0xffff; 1071 } 1072 1073 1074 /* 1075 * Routines for accessing the transmit and receive buffers. 1076 * The various CPU and adapter configurations supported by this 1077 * driver require three different access methods for buffers 1078 * and descriptors: 1079 * (1) contig (contiguous data; no padding), 1080 * (2) gap2 (two bytes of data followed by two bytes of padding), 1081 * (3) gap16 (16 bytes of data followed by 16 bytes of padding). 1082 */ 1083 1084 /* 1085 * contig: contiguous data with no padding. 1086 * 1087 * Buffers may have any alignment. 1088 */ 1089 1090 void 1091 am7990_copytobuf_contig(sc, from, boff, len) 1092 struct am7990_softc *sc; 1093 void *from; 1094 int boff, len; 1095 { 1096 volatile caddr_t buf = sc->sc_mem; 1097 1098 /* 1099 * Just call bcopy() to do the work. 1100 */ 1101 bcopy(from, buf + boff, len); 1102 } 1103 1104 void 1105 am7990_copyfrombuf_contig(sc, to, boff, len) 1106 struct am7990_softc *sc; 1107 void *to; 1108 int boff, len; 1109 { 1110 volatile caddr_t buf = sc->sc_mem; 1111 1112 /* 1113 * Just call bcopy() to do the work. 1114 */ 1115 bcopy(buf + boff, to, len); 1116 } 1117 1118 void 1119 am7990_zerobuf_contig(sc, boff, len) 1120 struct am7990_softc *sc; 1121 int boff, len; 1122 { 1123 volatile caddr_t buf = sc->sc_mem; 1124 1125 /* 1126 * Just let bzero() do the work 1127 */ 1128 bzero(buf + boff, len); 1129 } 1130 1131 #if 0 1132 /* 1133 * Examples only; duplicate these and tweak (if necessary) in 1134 * machine-specific front-ends. 1135 */ 1136 1137 /* 1138 * gap2: two bytes of data followed by two bytes of pad. 1139 * 1140 * Buffers must be 4-byte aligned. The code doesn't worry about 1141 * doing an extra byte. 1142 */ 1143 1144 void 1145 am7990_copytobuf_gap2(sc, fromv, boff, len) 1146 struct am7990_softc *sc; 1147 void *fromv; 1148 int boff; 1149 register int len; 1150 { 1151 volatile caddr_t buf = sc->sc_mem; 1152 register caddr_t from = fromv; 1153 register volatile u_int16_t *bptr; 1154 1155 if (boff & 0x1) { 1156 /* handle unaligned first byte */ 1157 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 1158 *bptr = (*from++ << 8) | (*bptr & 0xff); 1159 bptr += 2; 1160 len--; 1161 } else 1162 bptr = ((volatile u_int16_t *)buf) + boff; 1163 while (len > 1) { 1164 *bptr = (from[1] << 8) | (from[0] & 0xff); 1165 bptr += 2; 1166 from += 2; 1167 len -= 2; 1168 } 1169 if (len == 1) 1170 *bptr = (u_int16_t)*from; 1171 } 1172 1173 void 1174 am7990_copyfrombuf_gap2(sc, tov, boff, len) 1175 struct am7990_softc *sc; 1176 void *tov; 1177 int boff, len; 1178 { 1179 volatile caddr_t buf = sc->sc_mem; 1180 register caddr_t to = tov; 1181 register volatile u_int16_t *bptr; 1182 register u_int16_t tmp; 1183 1184 if (boff & 0x1) { 1185 /* handle unaligned first byte */ 1186 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 1187 *to++ = (*bptr >> 8) & 0xff; 1188 bptr += 2; 1189 len--; 1190 } else 1191 bptr = ((volatile u_int16_t *)buf) + boff; 1192 while (len > 1) { 1193 tmp = *bptr; 1194 *to++ = tmp & 0xff; 1195 *to++ = (tmp >> 8) & 0xff; 1196 bptr += 2; 1197 len -= 2; 1198 } 1199 if (len == 1) 1200 *to = *bptr & 0xff; 1201 } 1202 1203 void 1204 am7990_zerobuf_gap2(sc, boff, len) 1205 struct am7990_softc *sc; 1206 int boff, len; 1207 { 1208 volatile caddr_t buf = sc->sc_mem; 1209 register volatile u_int16_t *bptr; 1210 1211 if ((unsigned)boff & 0x1) { 1212 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 1213 *bptr &= 0xff; 1214 bptr += 2; 1215 len--; 1216 } else 1217 bptr = ((volatile u_int16_t *)buf) + boff; 1218 while (len > 0) { 1219 *bptr = 0; 1220 bptr += 2; 1221 len -= 2; 1222 } 1223 } 1224 1225 /* 1226 * gap16: 16 bytes of data followed by 16 bytes of pad. 1227 * 1228 * Buffers must be 32-byte aligned. 1229 */ 1230 1231 void 1232 am7990_copytobuf_gap16(sc, fromv, boff, len) 1233 struct am7990_softc *sc; 1234 void *fromv; 1235 int boff; 1236 register int len; 1237 { 1238 volatile caddr_t buf = sc->sc_mem; 1239 register caddr_t from = fromv; 1240 register caddr_t bptr; 1241 register int xfer; 1242 1243 bptr = buf + ((boff << 1) & ~0x1f); 1244 boff &= 0xf; 1245 xfer = min(len, 16 - boff); 1246 while (len > 0) { 1247 bcopy(from, bptr + boff, xfer); 1248 from += xfer; 1249 bptr += 32; 1250 boff = 0; 1251 len -= xfer; 1252 xfer = min(len, 16); 1253 } 1254 } 1255 1256 void 1257 am7990_copyfrombuf_gap16(sc, tov, boff, len) 1258 struct am7990_softc *sc; 1259 void *tov; 1260 int boff, len; 1261 { 1262 volatile caddr_t buf = sc->sc_mem; 1263 register caddr_t to = tov; 1264 register caddr_t bptr; 1265 register int xfer; 1266 1267 bptr = buf + ((boff << 1) & ~0x1f); 1268 boff &= 0xf; 1269 xfer = min(len, 16 - boff); 1270 while (len > 0) { 1271 bcopy(bptr + boff, to, xfer); 1272 to += xfer; 1273 bptr += 32; 1274 boff = 0; 1275 len -= xfer; 1276 xfer = min(len, 16); 1277 } 1278 } 1279 1280 void 1281 am7990_zerobuf_gap16(sc, boff, len) 1282 struct am7990_softc *sc; 1283 int boff, len; 1284 { 1285 volatile caddr_t buf = sc->sc_mem; 1286 register caddr_t bptr; 1287 register int xfer; 1288 1289 bptr = buf + ((boff << 1) & ~0x1f); 1290 boff &= 0xf; 1291 xfer = min(len, 16 - boff); 1292 while (len > 0) { 1293 bzero(bptr + boff, xfer); 1294 bptr += 32; 1295 boff = 0; 1296 len -= xfer; 1297 xfer = min(len, 16); 1298 } 1299 } 1300 #endif /* Example only */ 1301