1 /* $NetBSD: if_le.c,v 1.20 1994/10/26 07:24:21 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)if_le.c 7.6 (Berkeley) 5/8/91 36 */ 37 38 #include "le.h" 39 #if NLE > 0 40 41 #include "bpfilter.h" 42 43 /* 44 * AMD 7990 LANCE 45 */ 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/mbuf.h> 50 #include <sys/buf.h> 51 #include <sys/socket.h> 52 #include <sys/syslog.h> 53 #include <sys/ioctl.h> 54 #include <sys/malloc.h> 55 #include <sys/errno.h> 56 57 #include <net/if.h> 58 #include <net/netisr.h> 59 #include <net/route.h> 60 #if NBPFILTER > 0 61 #include <net/bpf.h> 62 #include <net/bpfdesc.h> 63 #endif 64 65 #ifdef INET 66 #include <netinet/in.h> 67 #include <netinet/in_systm.h> 68 #include <netinet/in_var.h> 69 #include <netinet/ip.h> 70 #include <netinet/if_ether.h> 71 #endif 72 73 #ifdef NS 74 #include <netns/ns.h> 75 #include <netns/ns_if.h> 76 #endif 77 78 #include <machine/cpu.h> 79 #include <machine/mtpr.h> 80 #include <hp300/hp300/isr.h> 81 #ifdef USELEDS 82 #include <hp300/hp300/led.h> 83 #endif 84 85 #include <hp300/dev/device.h> 86 #include <hp300/dev/if_lereg.h> 87 88 89 #define ETHER_MIN_LEN 64 90 #define ETHER_MAX_LEN 1518 91 #define ETHER_ADDR_LEN 6 92 93 94 /* offsets for: ID, REGS, MEM, NVRAM */ 95 int lestd[] = { 0, 0x4000, 0x8000, 0xC008 }; 96 97 struct isr le_isr[NLE]; 98 99 /* 100 * Ethernet software status per interface. 101 * 102 * Each interface is referenced by a network interface structure, 103 * arpcom.ac_if, which the routing code uses to locate the interface. 104 * This structure contains the output queue for the interface, its address, ... 105 */ 106 struct le_softc { 107 struct arpcom sc_arpcom; /* common Ethernet structures */ 108 struct lereg0 *sc_r0; /* DIO registers */ 109 struct lereg1 *sc_r1; /* LANCE registers */ 110 void *sc_mem; 111 struct init_block *sc_init; 112 struct mds *sc_rd, *sc_td; 113 u_char *sc_rbuf, *sc_tbuf; 114 int sc_last_rd, sc_last_td; 115 int sc_no_td; 116 #ifdef LEDEBUG 117 int sc_debug; 118 #endif 119 } le_softc[NLE]; 120 121 int leintr __P((int)); 122 int leioctl __P((struct ifnet *, int, caddr_t)); 123 int lestart __P((struct ifnet *)); 124 int lewatchdog __P((/* short */)); 125 static inline void lewrcsr __P((/* struct le_softc *, u_short, u_short */)); 126 static inline u_short lerdcsr __P((/* struct le_softc *, u_short */)); 127 void leinit __P((struct le_softc *)); 128 void lememinit __P((struct le_softc *)); 129 void lereset __P((struct le_softc *)); 130 void lestop __P((struct le_softc *)); 131 void letint __P((int)); 132 void lerint __P((int)); 133 void leread __P((struct le_softc *, u_char *, int)); 134 struct mbuf *leget __P((u_char *, int, struct ifnet *)); 135 #ifdef LEDEBUG 136 void recv_print __P((struct le_softc *, int)); 137 void xmit_print __P((struct le_softc *, int)); 138 #endif 139 void lesetladrf __P((struct arpcom *, u_long *)); 140 141 int leattach __P((struct hp_device *)); 142 143 struct driver ledriver = { 144 leattach, "le", 145 }; 146 147 static inline void 148 lewrcsr(sc, port, val) 149 struct le_softc *sc; 150 register u_short port; 151 register u_short val; 152 { 153 register struct lereg0 *ler0 = sc->sc_r0; 154 register struct lereg1 *ler1 = sc->sc_r1; 155 156 do { 157 ler1->ler1_rap = port; 158 } while ((ler0->ler0_status & LE_ACK) == 0); 159 do { 160 ler1->ler1_rdp = val; 161 } while ((ler0->ler0_status & LE_ACK) == 0); 162 } 163 164 static inline u_short 165 lerdcsr(sc, port) 166 struct le_softc *sc; 167 register u_short port; 168 { 169 register struct lereg0 *ler0 = sc->sc_r0; 170 register struct lereg1 *ler1 = sc->sc_r1; 171 register u_short val; 172 173 do { 174 ler1->ler1_rap = port; 175 } while ((ler0->ler0_status & LE_ACK) == 0); 176 do { 177 val = ler1->ler1_rdp; 178 } while ((ler0->ler0_status & LE_ACK) == 0); 179 return (val); 180 } 181 182 /* 183 * Interface exists: make available by filling in network interface 184 * record. System will initialize the interface when it is ready 185 * to accept packets. 186 */ 187 int 188 leattach(hd) 189 struct hp_device *hd; 190 { 191 register struct lereg0 *ler0; 192 struct le_softc *sc = &le_softc[hd->hp_unit]; 193 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 194 char *cp; 195 int i; 196 197 ler0 = sc->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr); 198 if (ler0->ler0_id != LEID) 199 return(0); 200 sc->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr); 201 sc->sc_mem = (void *)(lestd[2] + (int)hd->hp_addr); 202 le_isr[hd->hp_unit].isr_intr = leintr; 203 hd->hp_ipl = le_isr[hd->hp_unit].isr_ipl = LE_IPL(ler0->ler0_status); 204 le_isr[hd->hp_unit].isr_arg = hd->hp_unit; 205 ler0->ler0_id = 0xFF; 206 DELAY(100); 207 208 /* 209 * Read the ethernet address off the board, one nibble at a time. 210 */ 211 cp = (char *)(lestd[3] + (int)hd->hp_addr); 212 for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) { 213 sc->sc_arpcom.ac_enaddr[i] = (*++cp & 0xF) << 4; 214 cp++; 215 sc->sc_arpcom.ac_enaddr[i] |= *++cp & 0xF; 216 cp++; 217 } 218 printf("le%d: hardware address %s\n", hd->hp_unit, 219 ether_sprintf(sc->sc_arpcom.ac_enaddr)); 220 221 isrlink(&le_isr[hd->hp_unit]); 222 ler0->ler0_status = LE_IE; 223 224 ifp->if_unit = hd->hp_unit; 225 ifp->if_name = "le"; 226 ifp->if_output = ether_output; 227 ifp->if_start = lestart; 228 ifp->if_ioctl = leioctl; 229 ifp->if_watchdog = lewatchdog; 230 ifp->if_flags = 231 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 232 233 if_attach(ifp); 234 ether_ifattach(ifp); 235 236 #if NBPFILTER > 0 237 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 238 #endif 239 return (1); 240 } 241 242 void 243 lereset(sc) 244 struct le_softc *sc; 245 { 246 247 leinit(sc); 248 } 249 250 int 251 lewatchdog(unit) 252 short unit; 253 { 254 struct le_softc *sc = &le_softc[unit]; 255 256 log(LOG_ERR, "le%d: device timeout\n", unit); 257 ++sc->sc_arpcom.ac_if.if_oerrors; 258 lereset(sc); 259 } 260 261 #define LANCE_ADDR(sc, a) \ 262 ((u_long)(a) - (u_long)sc->sc_mem) 263 264 /* LANCE initialization block set up. */ 265 void 266 lememinit(sc) 267 register struct le_softc *sc; 268 { 269 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 270 int i; 271 void *mem; 272 u_long a; 273 274 /* 275 * At this point we assume that the memory allocated to the Lance is 276 * quadword aligned. If it isn't then the initialisation is going 277 * fail later on. 278 */ 279 mem = sc->sc_mem; 280 281 sc->sc_init = mem; 282 #if NBPFILTER > 0 283 if (ifp->if_flags & IFF_PROMISC) 284 sc->sc_init->mode = LE_NORMAL | LE_PROM; 285 else 286 #endif 287 sc->sc_init->mode = LE_NORMAL; 288 for (i = 0; i < ETHER_ADDR_LEN; i++) 289 sc->sc_init->padr[i] = sc->sc_arpcom.ac_enaddr[i^1]; 290 lesetladrf(&sc->sc_arpcom, sc->sc_init->ladrf); 291 mem += sizeof(struct init_block); 292 293 sc->sc_rd = mem; 294 a = LANCE_ADDR(sc, mem); 295 sc->sc_init->rdra = a; 296 sc->sc_init->rlen = ((a >> 16) & 0xff) | (RLEN << 13); 297 mem += NRBUF * sizeof(struct mds); 298 299 sc->sc_td = mem; 300 a = LANCE_ADDR(sc, mem); 301 sc->sc_init->tdra = a; 302 sc->sc_init->tlen = ((a >> 16) & 0xff) | (TLEN << 13); 303 mem += NTBUF * sizeof(struct mds); 304 305 /* 306 * Set up receive ring descriptors. 307 */ 308 sc->sc_rbuf = mem; 309 for (i = 0; i < NRBUF; i++) { 310 a = LANCE_ADDR(sc, mem); 311 sc->sc_rd[i].addr = a; 312 sc->sc_rd[i].flags = ((a >> 16) & 0xff) | LE_OWN; 313 sc->sc_rd[i].bcnt = -BUFSIZE; 314 sc->sc_rd[i].mcnt = 0; 315 mem += BUFSIZE; 316 } 317 318 /* 319 * Set up transmit ring descriptors. 320 */ 321 sc->sc_tbuf = mem; 322 for (i = 0; i < NTBUF; i++) { 323 a = LANCE_ADDR(sc, mem); 324 sc->sc_td[i].addr = a; 325 sc->sc_td[i].flags= ((a >> 16) & 0xff); 326 sc->sc_td[i].bcnt = 0xf000; 327 sc->sc_td[i].mcnt = 0; 328 mem += BUFSIZE; 329 } 330 } 331 332 void 333 lestop(sc) 334 struct le_softc *sc; 335 { 336 337 lewrcsr(sc, 0, LE_STOP); 338 } 339 340 /* 341 * Initialization of interface; set up initialization block 342 * and transmit/receive descriptor rings. 343 */ 344 void 345 leinit(sc) 346 register struct le_softc *sc; 347 { 348 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 349 int s; 350 register int timo; 351 u_long a; 352 353 /* Address not known. */ 354 if (!ifp->if_addrlist) 355 return; 356 357 s = splimp(); 358 359 /* Don't want to get in a weird state. */ 360 lewrcsr(sc, 0, LE_STOP); 361 DELAY(100); 362 363 sc->sc_last_rd = sc->sc_last_td = sc->sc_no_td = 0; 364 365 /* Set up LANCE init block. */ 366 lememinit(sc); 367 368 /* Turn on byte swapping. */ 369 lewrcsr(sc, 3, LE_BSWP); 370 371 /* Give LANCE the physical address of its init block. */ 372 a = LANCE_ADDR(sc, sc->sc_init); 373 lewrcsr(sc, 1, a); 374 lewrcsr(sc, 2, (a >> 16) & 0xff); 375 376 /* Try to initialize the LANCE. */ 377 DELAY(100); 378 lewrcsr(sc, 0, LE_INIT); 379 380 /* Wait for initialization to finish. */ 381 for (timo = 100000; timo; timo--) 382 if (lerdcsr(sc, 0) & LE_IDON) 383 break; 384 385 if (lerdcsr(sc, 0) & LE_IDON) { 386 /* Start the LANCE. */ 387 lewrcsr(sc, 0, LE_INEA | LE_STRT | LE_IDON); 388 ifp->if_flags |= IFF_RUNNING; 389 ifp->if_flags &= ~IFF_OACTIVE; 390 lestart(ifp); 391 } else 392 printf("le%d: card failed to initialize\n", ifp->if_unit); 393 394 (void) splx(s); 395 } 396 397 /* 398 * Controller interrupt. 399 */ 400 int 401 leintr(unit) 402 int unit; 403 { 404 register struct le_softc *sc = &le_softc[unit]; 405 register u_short isr; 406 407 isr = lerdcsr(sc, 0); 408 #ifdef LEDEBUG 409 if (sc->sc_debug) 410 printf("le%d: leintr entering with isr=%04x\n", 411 unit, isr); 412 #endif 413 if ((isr & LE_INTR) == 0) 414 return 0; 415 416 do { 417 lewrcsr(sc, 0, 418 isr & (LE_INEA | LE_BABL | LE_MISS | LE_MERR | 419 LE_RINT | LE_TINT | LE_IDON)); 420 if (isr & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) { 421 if (isr & LE_BABL) { 422 printf("le%d: BABL\n", unit); 423 sc->sc_arpcom.ac_if.if_oerrors++; 424 } 425 #if 0 426 if (isr & LE_CERR) { 427 printf("le%d: CERR\n", unit); 428 sc->sc_arpcom.ac_if.if_collisions++; 429 } 430 #endif 431 if (isr & LE_MISS) { 432 #if 0 433 printf("le%d: MISS\n", unit); 434 #endif 435 sc->sc_arpcom.ac_if.if_ierrors++; 436 } 437 if (isr & LE_MERR) { 438 printf("le%d: MERR\n", unit); 439 lereset(sc); 440 goto out; 441 } 442 } 443 444 if ((isr & LE_RXON) == 0) { 445 printf("le%d: receiver disabled\n", unit); 446 sc->sc_arpcom.ac_if.if_ierrors++; 447 lereset(sc); 448 goto out; 449 } 450 if ((isr & LE_TXON) == 0) { 451 printf("le%d: transmitter disabled\n", unit); 452 sc->sc_arpcom.ac_if.if_oerrors++; 453 lereset(sc); 454 goto out; 455 } 456 457 if (isr & LE_RINT) { 458 /* Reset watchdog timer. */ 459 sc->sc_arpcom.ac_if.if_timer = 0; 460 lerint(unit); 461 } 462 if (isr & LE_TINT) { 463 /* Reset watchdog timer. */ 464 sc->sc_arpcom.ac_if.if_timer = 0; 465 letint(unit); 466 } 467 468 isr = lerdcsr(sc, 0); 469 } while ((isr & LE_INTR) != 0); 470 471 #ifdef LEDEBUG 472 if (sc->sc_debug) 473 printf("le%d: leintr returning with isr=%04x\n", 474 unit, isr); 475 #endif 476 477 out: 478 return 1; 479 } 480 481 #define NEXTTDS \ 482 if (++tmd == NTBUF) tmd=0, cdm=sc->sc_td; else ++cdm 483 484 /* 485 * Setup output on interface. 486 * Get another datagram to send off of the interface queue, and map it to the 487 * interface before starting the output. 488 * Called only at splimp or interrupt level. 489 */ 490 int 491 lestart(ifp) 492 struct ifnet *ifp; 493 { 494 register struct le_softc *sc = &le_softc[ifp->if_unit]; 495 register int tmd; 496 struct mds *cdm; 497 struct mbuf *m0, *m; 498 u_char *buffer; 499 int len; 500 501 if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) != 502 IFF_RUNNING) 503 return; 504 505 tmd = sc->sc_last_td; 506 cdm = &sc->sc_td[tmd]; 507 508 for (;;) { 509 if (sc->sc_no_td >= NTBUF) { 510 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE; 511 #ifdef LEDEBUG 512 if (sc->sc_debug) 513 printf("no_td = %d, last_td = %d\n", sc->sc_no_td, 514 sc->sc_last_td); 515 #endif 516 break; 517 } 518 519 #ifdef LEDEBUG 520 if (cdm->flags & LE_OWN) { 521 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE; 522 printf("missing buffer, no_td = %d, last_td = %d\n", 523 sc->sc_no_td, sc->sc_last_td); 524 } 525 #endif 526 527 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m); 528 if (!m) 529 break; 530 531 ++sc->sc_no_td; 532 533 /* 534 * Copy the mbuf chain into the transmit buffer. 535 */ 536 buffer = sc->sc_tbuf + (BUFSIZE * sc->sc_last_td); 537 len = 0; 538 for (m0 = m; m; m = m->m_next) { 539 bcopy(mtod(m, caddr_t), buffer, m->m_len); 540 buffer += m->m_len; 541 len += m->m_len; 542 } 543 544 #ifdef LEDEBUG 545 if (len > ETHER_MAX_LEN) 546 printf("packet length %d\n", len); 547 #endif 548 549 #if NBPFILTER > 0 550 if (sc->sc_arpcom.ac_if.if_bpf) 551 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0); 552 #endif 553 554 m_freem(m0); 555 len = max(len, ETHER_MIN_LEN); 556 557 /* 558 * Init transmit registers, and set transmit start flag. 559 */ 560 cdm->bcnt = -len; 561 cdm->mcnt = 0; 562 cdm->flags |= LE_OWN | LE_STP | LE_ENP; 563 564 #ifdef LEDEBUG 565 if (sc->sc_debug) 566 xmit_print(sc, sc->sc_last_td); 567 #endif 568 569 lewrcsr(sc, 0, LE_INEA | LE_TDMD); 570 571 NEXTTDS; 572 } 573 574 sc->sc_last_td = tmd; 575 } 576 577 void 578 letint(unit) 579 int unit; 580 { 581 register struct le_softc *sc = &le_softc[unit]; 582 register int tmd = (sc->sc_last_td - sc->sc_no_td + NTBUF) % NTBUF; 583 struct mds *cdm = &sc->sc_td[tmd]; 584 585 #ifdef USELEDS 586 if (inledcontrol == 0) 587 ledcontrol(0, 0, LED_LANXMT); 588 #endif 589 590 if (cdm->flags & LE_OWN) { 591 /* Race condition with loop below. */ 592 #ifdef LEDEBUG 593 if (sc->sc_debug) 594 printf("le%d: extra tint\n", unit); 595 #endif 596 return; 597 } 598 599 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; 600 601 do { 602 if (sc->sc_no_td <= 0) 603 break; 604 #ifdef LEDEBUG 605 if (sc->sc_debug) 606 printf("trans cdm = %x\n", cdm); 607 #endif 608 sc->sc_arpcom.ac_if.if_opackets++; 609 --sc->sc_no_td; 610 if (cdm->mcnt & (LE_TBUFF | LE_UFLO | LE_LCOL | LE_LCAR | LE_RTRY)) { 611 if (cdm->mcnt & LE_TBUFF) 612 printf("le%d: TBUFF\n", unit); 613 if ((cdm->mcnt & (LE_TBUFF | LE_UFLO)) == LE_UFLO) 614 printf("le%d: UFLO\n", unit); 615 if (cdm->mcnt & LE_UFLO) { 616 lereset(sc); 617 return; 618 } 619 #if 0 620 if (cdm->mcnt & LE_LCOL) { 621 printf("le%d: late collision\n", unit); 622 sc->sc_arpcom.ac_if.if_collisions++; 623 } 624 if (cdm->mcnt & LE_LCAR) 625 printf("le%d: lost carrier\n", unit); 626 if (cdm->mcnt & LE_RTRY) { 627 printf("le%d: excessive collisions, tdr %d\n", 628 unit, cdm->mcnt & 0x1ff); 629 sc->sc_arpcom.ac_if.if_collisions += 16; 630 } 631 #endif 632 } else if (cdm->flags & LE_ONE) 633 sc->sc_arpcom.ac_if.if_collisions++; 634 else if (cdm->flags & LE_MORE) 635 /* Real number is unknown. */ 636 sc->sc_arpcom.ac_if.if_collisions += 2; 637 NEXTTDS; 638 } while ((cdm->flags & LE_OWN) == 0); 639 640 lestart(&sc->sc_arpcom.ac_if); 641 } 642 643 #define NEXTRDS \ 644 if (++rmd == NRBUF) rmd=0, cdm=sc->sc_rd; else ++cdm 645 646 /* only called from one place, so may as well integrate */ 647 void 648 lerint(unit) 649 int unit; 650 { 651 register struct le_softc *sc = &le_softc[unit]; 652 register int rmd = sc->sc_last_rd; 653 struct mds *cdm = &sc->sc_rd[rmd]; 654 655 #ifdef USELEDS 656 if (inledcontrol == 0) 657 ledcontrol(0, 0, LED_LANRCV); 658 #endif 659 660 if (cdm->flags & LE_OWN) { 661 /* Race condition with loop below. */ 662 #ifdef LEDEBUG 663 if (sc->sc_debug) 664 printf("le%d: extra rint\n", unit); 665 #endif 666 return; 667 } 668 669 /* Process all buffers with valid data. */ 670 do { 671 if (cdm->flags & (LE_FRAM | LE_OFLO | LE_CRC | LE_RBUFF)) { 672 if ((cdm->flags & (LE_FRAM | LE_OFLO | LE_ENP)) == (LE_FRAM | LE_ENP)) 673 printf("le%d: FRAM\n", unit); 674 if ((cdm->flags & (LE_OFLO | LE_ENP)) == LE_OFLO) 675 printf("le%d: OFLO\n", unit); 676 if ((cdm->flags & (LE_CRC | LE_OFLO | LE_ENP)) == (LE_CRC | LE_ENP)) 677 printf("le%d: CRC\n", unit); 678 if (cdm->flags & LE_RBUFF) 679 printf("le%d: RBUFF\n", unit); 680 } else if (cdm->flags & (LE_STP | LE_ENP) != (LE_STP | LE_ENP)) { 681 do { 682 cdm->mcnt = 0; 683 cdm->flags |= LE_OWN; 684 NEXTRDS; 685 } while ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) == 0); 686 sc->sc_last_rd = rmd; 687 printf("le%d: chained buffer\n", unit); 688 if ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) != LE_ENP) { 689 lereset(sc); 690 return; 691 } 692 } else { 693 #ifdef LEDEBUG 694 if (sc->sc_debug) 695 recv_print(sc, sc->sc_last_rd); 696 #endif 697 leread(sc, sc->sc_rbuf + (BUFSIZE * rmd), 698 (int)cdm->mcnt); 699 sc->sc_arpcom.ac_if.if_ipackets++; 700 } 701 702 cdm->mcnt = 0; 703 cdm->flags |= LE_OWN; 704 NEXTRDS; 705 #ifdef LEDEBUG 706 if (sc->sc_debug) 707 printf("sc->sc_last_rd = %x, cdm = %x\n", 708 sc->sc_last_rd, cdm); 709 #endif 710 } while ((cdm->flags & LE_OWN) == 0); 711 712 sc->sc_last_rd = rmd; 713 } 714 715 /* 716 * Pass a packet to the higher levels. 717 */ 718 void 719 leread(sc, buf, len) 720 register struct le_softc *sc; 721 u_char *buf; 722 int len; 723 { 724 struct ifnet *ifp; 725 struct mbuf *m; 726 struct ether_header *eh; 727 728 len -= 4; 729 if (len <= 0) 730 return; 731 732 /* Pull packet off interface. */ 733 ifp = &sc->sc_arpcom.ac_if; 734 m = leget(buf, len, ifp); 735 if (m == 0) 736 return; 737 738 /* We assume that the header fit entirely in one mbuf. */ 739 eh = mtod(m, struct ether_header *); 740 741 #if NBPFILTER > 0 742 /* 743 * Check if there's a BPF listener on this interface. 744 * If so, hand off the raw packet to BPF. 745 */ 746 if (ifp->if_bpf) { 747 bpf_mtap(ifp->if_bpf, m); 748 749 /* 750 * Note that the interface cannot be in promiscuous mode if 751 * there are no BPF listeners. And if we are in promiscuous 752 * mode, we have to check if this packet is really ours. 753 */ 754 if ((ifp->if_flags & IFF_PROMISC) && 755 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ 756 bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, 757 sizeof(eh->ether_dhost)) != 0) { 758 m_freem(m); 759 return; 760 } 761 } 762 #endif 763 764 /* We assume that the header fit entirely in one mbuf. */ 765 m->m_pkthdr.len -= sizeof(*eh); 766 m->m_len -= sizeof(*eh); 767 m->m_data += sizeof(*eh); 768 769 ether_input(ifp, eh, m); 770 } 771 772 /* 773 * Supporting routines 774 */ 775 776 /* 777 * Pull data off an interface. 778 * Len is length of data, with local net header stripped. 779 * We copy the data into mbufs. When full cluster sized units are present 780 * we copy into clusters. 781 */ 782 struct mbuf * 783 leget(buf, totlen, ifp) 784 u_char *buf; 785 int totlen; 786 struct ifnet *ifp; 787 { 788 struct mbuf *top, **mp, *m; 789 int len; 790 791 MGETHDR(m, M_DONTWAIT, MT_DATA); 792 if (m == 0) 793 return 0; 794 m->m_pkthdr.rcvif = ifp; 795 m->m_pkthdr.len = totlen; 796 len = MHLEN; 797 top = 0; 798 mp = ⊤ 799 800 while (totlen > 0) { 801 if (top) { 802 MGET(m, M_DONTWAIT, MT_DATA); 803 if (m == 0) { 804 m_freem(top); 805 return 0; 806 } 807 len = MLEN; 808 } 809 if (totlen >= MINCLSIZE) { 810 MCLGET(m, M_DONTWAIT); 811 if (m->m_flags & M_EXT) 812 len = MCLBYTES; 813 } 814 m->m_len = len = min(totlen, len); 815 bcopy((caddr_t)buf, mtod(m, caddr_t), len); 816 buf += len; 817 totlen -= len; 818 *mp = m; 819 mp = &m->m_next; 820 } 821 822 return top; 823 } 824 825 /* 826 * Process an ioctl request. 827 */ 828 int 829 leioctl(ifp, cmd, data) 830 register struct ifnet *ifp; 831 int cmd; 832 caddr_t data; 833 { 834 struct le_softc *sc = &le_softc[ifp->if_unit]; 835 struct ifaddr *ifa = (struct ifaddr *)data; 836 struct ifreq *ifr = (struct ifreq *)data; 837 int s, error = 0; 838 839 s = splimp(); 840 841 switch (cmd) { 842 843 case SIOCSIFADDR: 844 ifp->if_flags |= IFF_UP; 845 846 switch (ifa->ifa_addr->sa_family) { 847 #ifdef INET 848 case AF_INET: 849 leinit(sc); /* before arpwhohas */ 850 /* 851 * See if another station has *our* IP address. 852 * i.e.: There is an address conflict! If a 853 * conflict exists, a message is sent to the 854 * console. 855 */ 856 sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr; 857 arpwhohas(&sc->sc_arpcom, &IA_SIN(ifa)->sin_addr); 858 break; 859 #endif 860 #ifdef NS 861 /* XXX - This code is probably wrong. */ 862 case AF_NS: 863 { 864 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 865 866 if (ns_nullhost(*ina)) 867 ina->x_host = 868 *(union ns_host *)(sc->sc_arpcom.ac_enaddr); 869 else 870 bcopy(ina->x_host.c_host, 871 sc->sc_arpcom.ac_enaddr, 872 sizeof(sc->sc_arpcom.ac_enaddr)); 873 /* Set new address. */ 874 leinit(sc); 875 break; 876 } 877 #endif 878 default: 879 leinit(sc); 880 break; 881 } 882 break; 883 884 case SIOCSIFFLAGS: 885 /* 886 * If interface is marked down and it is running, then stop it 887 */ 888 if ((ifp->if_flags & IFF_UP) == 0 && 889 (ifp->if_flags & IFF_RUNNING) != 0) { 890 /* 891 * If interface is marked down and it is running, then 892 * stop it. 893 */ 894 lestop(sc); 895 ifp->if_flags &= ~IFF_RUNNING; 896 } else if ((ifp->if_flags & IFF_UP) != 0 && 897 (ifp->if_flags & IFF_RUNNING) == 0) { 898 /* 899 * If interface is marked up and it is stopped, then 900 * start it. 901 */ 902 leinit(sc); 903 } else { 904 /* 905 * Reset the interface to pick up changes in any other 906 * flags that affect hardware registers. 907 */ 908 /*lestop(sc);*/ 909 leinit(sc); 910 } 911 #ifdef LEDEBUG 912 if (ifp->if_flags & IFF_DEBUG) 913 sc->sc_debug = 1; 914 else 915 sc->sc_debug = 0; 916 #endif 917 break; 918 919 case SIOCADDMULTI: 920 case SIOCDELMULTI: 921 error = (cmd == SIOCADDMULTI) ? 922 ether_addmulti(ifr, &sc->sc_arpcom): 923 ether_delmulti(ifr, &sc->sc_arpcom); 924 925 if (error == ENETRESET) { 926 /* 927 * Multicast list has changed; set the hardware filter 928 * accordingly. 929 */ 930 leinit(sc); 931 error = 0; 932 } 933 break; 934 935 default: 936 error = EINVAL; 937 } 938 (void) splx(s); 939 return error; 940 } 941 942 #ifdef LEDEBUG 943 void 944 recv_print(sc, no) 945 struct le_softc *sc; 946 int no; 947 { 948 struct mds *rmd; 949 int i, printed = 0; 950 u_short len; 951 952 rmd = &sc->sc_rd[no]; 953 len = rmd->mcnt; 954 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, 955 len); 956 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0)); 957 for (i = 0; i < len; i++) { 958 if (!printed) { 959 printed = 1; 960 printf("%s: data: ", sc->sc_dev.dv_xname); 961 } 962 printf("%x ", *(sc->sc_rbuf + (BUFSIZE*no) + i)); 963 } 964 if (printed) 965 printf("\n"); 966 } 967 968 void 969 xmit_print(sc, no) 970 struct le_softc *sc; 971 int no; 972 { 973 struct mds *rmd; 974 int i, printed=0; 975 u_short len; 976 977 rmd = &sc->sc_td[no]; 978 len = -rmd->bcnt; 979 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, 980 len); 981 printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0)); 982 printf("%s: addr %x, flags %x, bcnt %x, mcnt %x\n", 983 sc->sc_dev.dv_xname, rmd->addr, rmd->flags, rmd->bcnt, rmd->mcnt); 984 for (i = 0; i < len; i++) { 985 if (!printed) { 986 printed = 1; 987 printf("%s: data: ", sc->sc_dev.dv_xname); 988 } 989 printf("%x ", *(sc->sc_tbuf + (BUFSIZE*no) + i)); 990 } 991 if (printed) 992 printf("\n"); 993 } 994 #endif /* LEDEBUG */ 995 996 /* 997 * Set up the logical address filter. 998 */ 999 void 1000 lesetladrf(ac, af) 1001 struct arpcom *ac; 1002 u_long *af; 1003 { 1004 struct ifnet *ifp = &ac->ac_if; 1005 struct ether_multi *enm; 1006 register u_char *cp, c; 1007 register u_long crc; 1008 register int i, len; 1009 struct ether_multistep step; 1010 1011 /* 1012 * Set up multicast address filter by passing all multicast addresses 1013 * through a crc generator, and then using the high order 6 bits as an 1014 * index into the 64 bit logical address filter. The high order bit 1015 * selects the word, while the rest of the bits select the bit within 1016 * the word. 1017 */ 1018 1019 if (ifp->if_flags & IFF_PROMISC) { 1020 ifp->if_flags |= IFF_ALLMULTI; 1021 af[0] = af[1] = 0xffffffff; 1022 return; 1023 } 1024 1025 af[0] = af[1] = 0; 1026 ETHER_FIRST_MULTI(step, ac, enm); 1027 while (enm != NULL) { 1028 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 1029 sizeof(enm->enm_addrlo)) != 0) { 1030 /* 1031 * We must listen to a range of multicast addresses. 1032 * For now, just accept all multicasts, rather than 1033 * trying to set only those filter bits needed to match 1034 * the range. (At this time, the only use of address 1035 * ranges is for IP multicast routing, for which the 1036 * range is big enough to require all bits set.) 1037 */ 1038 ifp->if_flags |= IFF_ALLMULTI; 1039 af[0] = af[1] = 0xffffffff; 1040 return; 1041 } 1042 1043 cp = enm->enm_addrlo; 1044 crc = 0xffffffff; 1045 for (len = sizeof(enm->enm_addrlo); --len >= 0;) { 1046 c = *cp++; 1047 for (i = 8; --i >= 0;) { 1048 if ((crc & 0x01) ^ (c & 0x01)) { 1049 crc >>= 1; 1050 crc ^= 0x6db88320 | 0x80000000; 1051 } else 1052 crc >>= 1; 1053 c >>= 1; 1054 } 1055 } 1056 /* Just want the 6 most significant bits. */ 1057 crc >>= 26; 1058 1059 /* Turn on the corresponding bit in the filter. */ 1060 af[crc >> 5] |= 1 << ((crc & 0x1f) ^ 16); 1061 1062 ETHER_NEXT_MULTI(step, enm); 1063 } 1064 ifp->if_flags &= ~IFF_ALLMULTI; 1065 } 1066 1067 #endif /* NLE > 0 */ 1068