1 /* 2 * Copyright (c) 1982, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)if_le.c 7.6 (Berkeley) 5/8/91 34 * if_le.c,v 1.2 1993/05/22 07:56:23 cgd Exp 35 */ 36 37 #include "bpfilter.h" 38 39 /* 40 * AMD 7990 LANCE 41 * 42 * This driver will generate and accept tailer encapsulated packets even 43 * though it buys us nothing. The motivation was to avoid incompatibilities 44 * with VAXen, SUNs, and others that handle and benefit from them. 45 * This reasoning is dubious. 46 */ 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/mbuf.h> 50 #include <sys/buf.h> 51 #include <sys/protosw.h> 52 #include <sys/socket.h> 53 #include <sys/syslog.h> 54 #include <sys/ioctl.h> 55 #include <sys/errno.h> 56 #include <sys/device.h> 57 58 #include <net/if.h> 59 #include <net/netisr.h> 60 #include <net/route.h> 61 62 #ifdef INET 63 #include <netinet/in.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/in_var.h> 66 #include <netinet/ip.h> 67 #include <netinet/if_ether.h> 68 #endif 69 70 #ifdef NS 71 #include <netns/ns.h> 72 #include <netns/ns_if.h> 73 #endif 74 75 #ifdef RMP 76 #include <netrmp/rmp.h> 77 #include <netrmp/rmp_var.h> 78 #endif 79 80 #include <machine/autoconf.h> 81 82 #include "if_lereg.h" 83 84 #if NBPFILTER > 0 85 #include <net/bpf.h> 86 #include <net/bpfdesc.h> 87 #endif 88 89 #include "if_le.h" 90 #include "if_le_subr.h" 91 92 int ledebug = 0; /* console error messages */ 93 94 int leintr(), leioctl(), ether_output(), lestart(); 95 void leinit(); 96 struct mbuf *leget(); 97 extern struct ifnet loif; 98 99 /* access LANCE registers */ 100 101 void leattach __P((struct device *, struct device *, void *)); 102 int lematch __P((struct device *, struct cfdata *, void *args)); 103 104 struct cfdriver lecd = 105 { NULL, "le", lematch, leattach, DV_DULL, sizeof(struct le_softc), 0}; 106 107 #define ISQUADALIGN(a) ((a & 0x3) == 0) 108 109 int lematch(parent, cf, args) 110 struct device *parent; 111 struct cfdata *cf; 112 void *args; 113 { 114 return le_machdep_match(parent, cf, args); 115 } 116 /* 117 * Interface exists: make available by filling in network interface 118 * record. System will initialize the interface when it is ready 119 * to accept packets. 120 */ 121 void leattach(parent, self, args) 122 struct device *parent; 123 struct device *self; 124 void *args; 125 { 126 register struct lereg2 *ler2; 127 unsigned int a; 128 struct le_softc *le = (struct le_softc *) self; 129 struct ifnet *ifp = &le->sc_if; 130 char *cp; 131 int i, unit; 132 133 unit = le->sc_dev.dv_unit; 134 if (le_machdep_attach(parent, self, args)) { 135 printf(": bad attach??\n"); 136 return; 137 } 138 ler2 = le->sc_r2; 139 printf(": ether address %s\n", ether_sprintf(le->sc_addr)); 140 141 /* 142 * Setup for transmit/receive 143 */ 144 ler2->ler2_mode = LE_MODE; 145 ler2->ler2_padr[0] = le->sc_addr[1]; 146 ler2->ler2_padr[1] = le->sc_addr[0]; 147 ler2->ler2_padr[2] = le->sc_addr[3]; 148 ler2->ler2_padr[3] = le->sc_addr[2]; 149 ler2->ler2_padr[4] = le->sc_addr[5]; 150 ler2->ler2_padr[5] = le->sc_addr[4]; 151 #ifdef RMP 152 /* 153 * Set up logical addr filter to accept multicast 9:0:9:0:0:4 154 * This should be an ioctl() to the driver. (XXX) 155 */ 156 ler2->ler2_ladrf0 = 0x00100000; 157 ler2->ler2_ladrf1 = 0x0; 158 #else 159 ler2->ler2_ladrf0 = 0; 160 ler2->ler2_ladrf1 = 0; 161 #endif 162 a = LANCE_ADDR(ler2->ler2_rmd); 163 if (!ISQUADALIGN(a)) 164 panic("rdra not quad aligned"); 165 ler2->ler2_rlen = LE_RLEN | (a >> 16); 166 ler2->ler2_rdra = a & LE_ADDR_LOW_MASK; 167 a = LANCE_ADDR(ler2->ler2_tmd); 168 if (!ISQUADALIGN(a)) 169 panic("tdra not quad aligned"); 170 ler2->ler2_tlen = LE_TLEN | (a >> 16); 171 ler2->ler2_tdra = a & LE_ADDR_LOW_MASK; 172 173 ifp->if_unit = unit; 174 ifp->if_name = "le"; 175 ifp->if_ioctl = leioctl; 176 ifp->if_output = ether_output; 177 ifp->if_start = lestart; 178 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 179 #if NBPFILTER > 0 180 bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 181 #endif 182 if_attach(ifp); 183 ether_ifattach(ifp); 184 } 185 186 ledrinit(ler2) 187 register struct lereg2 *ler2; 188 { 189 unsigned int a; 190 register int i; 191 192 for (i = 0; i < LERBUF; i++) { 193 a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]); 194 #if 0 195 if (!ISQUADALIGN(a)) 196 panic("rbuf not quad aligned"); 197 #endif 198 ler2->ler2_rmd[i].rmd0 = a & LE_ADDR_LOW_MASK; 199 ler2->ler2_rmd[i].rmd1_bits = LE_OWN; 200 ler2->ler2_rmd[i].rmd1_hadr = a >> 16; 201 ler2->ler2_rmd[i].rmd2 = -LEMTU; 202 ler2->ler2_rmd[i].rmd3 = 0; 203 } 204 for (i = 0; i < LETBUF; i++) { 205 a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]); 206 #if 0 207 if (!ISQUADALIGN(a)) 208 panic("rbuf not quad aligned"); 209 #endif 210 ler2->ler2_tmd[i].tmd0 = a & LE_ADDR_LOW_MASK; 211 ler2->ler2_tmd[i].tmd1_bits = 0; 212 ler2->ler2_tmd[i].tmd1_hadr = a >> 16; 213 ler2->ler2_tmd[i].tmd2 = 0; 214 ler2->ler2_tmd[i].tmd3 = 0; 215 } 216 } 217 218 lereset(unit) 219 register int unit; 220 { 221 register struct le_softc *le = (struct le_softc *) lecd.cd_devs[unit]; 222 register struct lereg1 *ler1 = le->sc_r1; 223 register struct lereg2 *ler2 = le->sc_r2; 224 unsigned int a; 225 register int timo = 100000; 226 register int stat; 227 228 #ifdef lint 229 stat = unit; 230 #endif 231 #if NBPFILTER > 0 232 if (le->sc_if.if_flags & IFF_PROMISC) 233 /* set the promiscuous bit */ 234 le->sc_r2->ler2_mode = LE_MODE|0x8000; 235 else 236 le->sc_r2->ler2_mode = LE_MODE; 237 #endif 238 if (ledebug) 239 printf("le: resetting unit %d, reg %x, ram %x\n", 240 unit, le->sc_r1, le->sc_r2); 241 LERDWR(le, LE_CSR0, ler1->ler1_rap); 242 LERDWR(le, LE_STOP, ler1->ler1_rdp); 243 ledrinit(le->sc_r2); 244 le->sc_rmd = 0; 245 LERDWR(le, LE_CSR1, ler1->ler1_rap); 246 a = LANCE_ADDR(ler2); 247 LERDWR(le, a & LE_ADDR_LOW_MASK, ler1->ler1_rdp); 248 LERDWR(le, LE_CSR2, ler1->ler1_rap); 249 LERDWR(le, a >> 16, ler1->ler1_rdp); 250 LERDWR(le, LE_CSR0, ler1->ler1_rap); 251 LERDWR(le, LE_INIT, ler1->ler1_rdp); 252 do { 253 if (--timo == 0) { 254 printf("le%d: init timeout, stat = 0x%x\n", 255 unit, stat); 256 break; 257 } 258 LERDWR(le, ler1->ler1_rdp, stat); 259 } while ((stat & LE_IDON) == 0); 260 LERDWR(le, LE_STOP, ler1->ler1_rdp); 261 LERDWR(le, LE_CSR3, ler1->ler1_rap); 262 LERDWR(le, LE_BSWP, ler1->ler1_rdp); 263 LERDWR(le, LE_CSR0, ler1->ler1_rap); 264 LERDWR(le, LE_STRT | LE_INEA, ler1->ler1_rdp); 265 le->sc_if.if_flags &= ~IFF_OACTIVE; 266 } 267 268 /* 269 * Initialization of interface 270 */ 271 void leinit(unit) 272 int unit; 273 { 274 struct le_softc *le = lecd.cd_devs[unit]; 275 register struct ifnet *ifp = &le->sc_if; 276 int s; 277 278 /* not yet, if address still unknown */ 279 if (ifp->if_addrlist == (struct ifaddr *)0) 280 return; 281 if ((ifp->if_flags & IFF_RUNNING) == 0) { 282 s = splimp(); 283 if (ledebug) 284 printf("le: initializing unit %d, reg %x, ram %x\n", 285 unit, le->sc_r1, le->sc_r2); 286 ifp->if_flags |= IFF_RUNNING; 287 lereset(unit); 288 (void) lestart(ifp); 289 splx(s); 290 } 291 } 292 293 /* 294 * Start output on interface. Get another datagram to send 295 * off of the interface queue, and copy it to the interface 296 * before starting the output. 297 */ 298 int lestart(ifp) 299 struct ifnet *ifp; 300 { 301 register struct le_softc *le = lecd.cd_devs[ifp->if_unit]; 302 register struct letmd *tmd; 303 register struct mbuf *m; 304 int len; 305 306 if ((le->sc_if.if_flags & IFF_RUNNING) == 0) 307 return 0; 308 IF_DEQUEUE(&le->sc_if.if_snd, m); 309 if (m == 0) 310 return 0; 311 len = leput(le->sc_r2->ler2_tbuf[0], m); 312 #if NBPFILTER > 0 313 /* 314 * If bpf is listening on this interface, let it 315 * see the packet before we commit it to the wire. 316 */ 317 if (le->sc_bpf) 318 bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len); 319 #endif 320 tmd = le->sc_r2->ler2_tmd; 321 tmd->tmd3 = 0; 322 tmd->tmd2 = -len; 323 tmd->tmd1_bits = LE_OWN | LE_STP | LE_ENP; 324 le->sc_if.if_flags |= IFF_OACTIVE; 325 return 0; 326 } 327 328 leintr(unit) 329 register int unit; 330 { 331 register struct le_softc *le = lecd.cd_devs[unit]; 332 register struct lereg1 *ler1; 333 register int stat; 334 335 le_machdep_intrcheck(le, unit); 336 ler1 = le->sc_r1; 337 LERDWR(le, ler1->ler1_rdp, stat); 338 if (ledebug) 339 printf("[le%d: stat %b]\n", unit, stat, LE_STATUS_BITS); 340 if (stat & LE_SERR) { 341 leerror(unit, stat); 342 if (stat & LE_MERR) { 343 le->sc_merr++; 344 lereset(unit); 345 return(1); 346 } 347 if (stat & LE_BABL) 348 le->sc_babl++; 349 if (stat & LE_CERR) 350 le->sc_cerr++; 351 if (stat & LE_MISS) 352 le->sc_miss++; 353 LERDWR(le, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); 354 } 355 if ((stat & LE_RXON) == 0) { 356 le->sc_rxoff++; 357 lereset(unit); 358 return(1); 359 } 360 if ((stat & LE_TXON) == 0) { 361 le->sc_txoff++; 362 lereset(unit); 363 return(1); 364 } 365 if (stat & LE_RINT) { 366 /* interrupt is cleared in lerint */ 367 lerint(unit); 368 } 369 if (stat & LE_TINT) { 370 LERDWR(le, LE_TINT|LE_INEA, ler1->ler1_rdp); 371 lexint(unit); 372 } 373 return(1); 374 } 375 376 /* 377 * Ethernet interface transmitter interrupt. 378 * Start another output if more data to send. 379 */ 380 lexint(unit) 381 register int unit; 382 { 383 register struct le_softc *le = lecd.cd_devs[unit]; 384 register struct letmd *tmd = le->sc_r2->ler2_tmd; 385 386 if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) { 387 le->sc_xint++; 388 return; 389 } 390 if (tmd->tmd1_bits & LE_OWN) { 391 le->sc_xown++; 392 return; 393 } 394 if (tmd->tmd1_bits & LE_ERR) { 395 err: 396 lexerror(unit); 397 le->sc_if.if_oerrors++; 398 if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { 399 le->sc_uflo++; 400 lereset(unit); 401 } 402 else if (tmd->tmd3 & LE_LCOL) 403 le->sc_if.if_collisions++; 404 else if (tmd->tmd3 & LE_RTRY) 405 le->sc_if.if_collisions += 16; 406 } 407 else if (tmd->tmd3 & LE_TBUFF) 408 /* XXX documentation says BUFF not included in ERR */ 409 goto err; 410 else if (tmd->tmd1_bits & LE_ONE) 411 le->sc_if.if_collisions++; 412 else if (tmd->tmd1_bits & LE_MORE) 413 /* what is the real number? */ 414 le->sc_if.if_collisions += 2; 415 else 416 le->sc_if.if_opackets++; 417 le->sc_if.if_flags &= ~IFF_OACTIVE; 418 (void) lestart(&le->sc_if); 419 } 420 421 #define LENEXTRMP \ 422 if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd 423 424 /* 425 * Ethernet interface receiver interrupt. 426 * If input error just drop packet. 427 * Decapsulate packet based on type and pass to type specific 428 * higher-level input routine. 429 */ 430 lerint(unit) 431 int unit; 432 { 433 register struct le_softc *le = lecd.cd_devs[unit]; 434 register int bix = le->sc_rmd; 435 register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; 436 437 /* 438 * Out of sync with hardware, should never happen? 439 */ 440 if (rmd->rmd1_bits & LE_OWN) { 441 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 442 return; 443 } 444 445 /* 446 * Process all buffers with valid data 447 */ 448 while ((rmd->rmd1_bits & LE_OWN) == 0) { 449 int len = rmd->rmd3; 450 451 /* Clear interrupt to avoid race condition */ 452 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 453 454 if (rmd->rmd1_bits & LE_ERR) { 455 le->sc_rmd = bix; 456 lererror(unit, "bad packet"); 457 le->sc_if.if_ierrors++; 458 } else if ((rmd->rmd1_bits & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { 459 /* 460 * Find the end of the packet so we can see how long 461 * it was. We still throw it away. 462 */ 463 do { 464 LERDWR(le->sc_r0, LE_RINT|LE_INEA, 465 le->sc_r1->ler1_rdp); 466 rmd->rmd3 = 0; 467 rmd->rmd1_bits = LE_OWN; 468 LENEXTRMP; 469 } while (!(rmd->rmd1_bits & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); 470 le->sc_rmd = bix; 471 lererror(unit, "chained buffer"); 472 le->sc_rxlen++; 473 /* 474 * If search terminated without successful completion 475 * we reset the hardware (conservative). 476 */ 477 if ((rmd->rmd1_bits & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != 478 LE_ENP) { 479 lereset(unit); 480 return; 481 } 482 } else 483 leread(unit, le->sc_r2->ler2_rbuf[bix], len); 484 rmd->rmd3 = 0; 485 rmd->rmd1_bits = LE_OWN; 486 LENEXTRMP; 487 } 488 le->sc_rmd = bix; 489 } 490 491 leread(unit, buf, len) 492 int unit; 493 char *buf; 494 int len; 495 { 496 register struct le_softc *le = lecd.cd_devs[unit]; 497 register struct ether_header *et; 498 struct mbuf *m; 499 int off, resid; 500 501 le->sc_if.if_ipackets++; 502 et = (struct ether_header *)buf; 503 et->ether_type = ntohs((u_short)et->ether_type); 504 /* adjust input length to account for header and CRC */ 505 len = len - sizeof(struct ether_header) - 4; 506 507 #ifdef RMP 508 /* (XXX) 509 * 510 * If Ethernet Type field is < MaxPacketSize, we probably have 511 * a IEEE802 packet here. Make sure that the size is at least 512 * that of the HP LLC. Also do sanity checks on length of LLC 513 * (old Ethernet Type field) and packet length. 514 * 515 * Provided the above checks succeed, change `len' to reflect 516 * the length of the LLC (i.e. et->ether_type) and change the 517 * type field to ETHERTYPE_IEEE so we can switch() on it later. 518 * Yes, this is a hack and will eventually be done "right". 519 */ 520 if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) && 521 len >= et->ether_type && len >= IEEE802LEN_MIN) { 522 len = et->ether_type; 523 et->ether_type = ETHERTYPE_IEEE; /* hack! */ 524 } 525 #endif 526 527 #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) 528 if (et->ether_type >= ETHERTYPE_TRAIL && 529 et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 530 off = (et->ether_type - ETHERTYPE_TRAIL) * 512; 531 if (off >= ETHERMTU) 532 return; /* sanity */ 533 et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); 534 resid = ntohs(*(ledataaddr(et, off+2, u_short *))); 535 if (off + resid > len) 536 return; /* sanity */ 537 len = off + resid; 538 } else 539 off = 0; 540 541 if (len <= 0) { 542 if (ledebug) 543 log(LOG_WARNING, 544 "le%d: ierror(runt packet): from %s: len=%d\n", 545 unit, ether_sprintf(et->ether_shost), len); 546 le->sc_runt++; 547 le->sc_if.if_ierrors++; 548 return; 549 } 550 #if NBPFILTER > 0 551 /* 552 * Check if there's a bpf filter listening on this interface. 553 * If so, hand off the raw packet to bpf, which must deal with 554 * trailers in its own way. 555 */ 556 if (le->sc_bpf) { 557 bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header)); 558 559 /* 560 * Note that the interface cannot be in promiscuous mode if 561 * there are no bpf listeners. And if we are in promiscuous 562 * mode, we have to check if this packet is really ours. 563 * 564 * XXX This test does not support multicasts. 565 */ 566 if ((le->sc_if.if_flags & IFF_PROMISC) 567 && bcmp(et->ether_dhost, le->sc_addr, 568 sizeof(et->ether_dhost)) != 0 569 && bcmp(et->ether_dhost, etherbroadcastaddr, 570 sizeof(et->ether_dhost)) != 0) 571 return; 572 } 573 #endif 574 /* 575 * Pull packet off interface. Off is nonzero if packet 576 * has trailing header; leget will then force this header 577 * information to be at the front, but we still have to drop 578 * the type and length which are at the front of any trailer data. 579 */ 580 m = leget(buf, len, off, &le->sc_if); 581 if (m == 0) 582 return; 583 #ifdef RMP 584 /* 585 * (XXX) 586 * This needs to be integrated with the ISO stuff in ether_input() 587 */ 588 if (et->ether_type == ETHERTYPE_IEEE) { 589 /* 590 * Snag the Logical Link Control header (IEEE 802.2). 591 */ 592 struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc); 593 594 /* 595 * If the DSAP (and HP's extended DXSAP) indicate this 596 * is an RMP packet, hand it to the raw input routine. 597 */ 598 if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) { 599 static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT}; 600 static struct sockaddr rmp_src = {AF_RMP}; 601 static struct sockaddr rmp_dst = {AF_RMP}; 602 603 bcopy(et->ether_shost, rmp_src.sa_data, 604 sizeof(et->ether_shost)); 605 bcopy(et->ether_dhost, rmp_dst.sa_data, 606 sizeof(et->ether_dhost)); 607 608 raw_input(m, &rmp_sp, &rmp_src, &rmp_dst); 609 return; 610 } 611 } 612 #endif 613 ether_input(&le->sc_if, et, m); 614 } 615 616 /* 617 * Routine to copy from mbuf chain to transmit 618 * buffer in board local memory. 619 */ 620 leput(lebuf, m) 621 register char *lebuf; 622 register struct mbuf *m; 623 { 624 register struct mbuf *mp; 625 register int len, tlen = 0; 626 627 for (mp = m; mp; mp = mp->m_next) { 628 len = mp->m_len; 629 if (len == 0) 630 continue; 631 tlen += len; 632 bcopy(mtod(mp, char *), lebuf, len); 633 lebuf += len; 634 } 635 m_freem(m); 636 if (tlen < LEMINSIZE) { 637 bzero(lebuf, LEMINSIZE - tlen); 638 tlen = LEMINSIZE; 639 } 640 return(tlen); 641 } 642 643 /* 644 * Routine to copy from board local memory into mbufs. 645 */ 646 struct mbuf * 647 leget(lebuf, totlen, off0, ifp) 648 char *lebuf; 649 int totlen, off0; 650 struct ifnet *ifp; 651 { 652 register struct mbuf *m; 653 struct mbuf *top = 0, **mp = ⊤ 654 register int off = off0, len; 655 register char *cp; 656 char *epkt; 657 658 lebuf += sizeof (struct ether_header); 659 cp = lebuf; 660 epkt = cp + totlen; 661 if (off) { 662 cp += off + 2 * sizeof(u_short); 663 totlen -= 2 * sizeof(u_short); 664 } 665 666 MGETHDR(m, M_DONTWAIT, MT_DATA); 667 if (m == 0) 668 return (0); 669 m->m_pkthdr.rcvif = ifp; 670 m->m_pkthdr.len = totlen; 671 m->m_len = MHLEN; 672 673 while (totlen > 0) { 674 if (top) { 675 MGET(m, M_DONTWAIT, MT_DATA); 676 if (m == 0) { 677 m_freem(top); 678 return (0); 679 } 680 m->m_len = MLEN; 681 } 682 len = min(totlen, epkt - cp); 683 if (len >= MINCLSIZE) { 684 MCLGET(m, M_DONTWAIT); 685 if (m->m_flags & M_EXT) 686 m->m_len = len = min(len, MCLBYTES); 687 else 688 len = m->m_len; 689 } else { 690 /* 691 * Place initial small packet/header at end of mbuf. 692 */ 693 if (len < m->m_len) { 694 if (top == 0 && len + max_linkhdr <= m->m_len) 695 m->m_data += max_linkhdr; 696 m->m_len = len; 697 } else 698 len = m->m_len; 699 } 700 bcopy(cp, mtod(m, caddr_t), (unsigned)len); 701 cp += len; 702 *mp = m; 703 mp = &m->m_next; 704 totlen -= len; 705 if (cp == epkt) 706 cp = lebuf; 707 } 708 return (top); 709 } 710 711 /* 712 * Process an ioctl request. 713 */ 714 leioctl(ifp, cmd, data) 715 register struct ifnet *ifp; 716 int cmd; 717 caddr_t data; 718 { 719 register struct ifaddr *ifa = (struct ifaddr *)data; 720 struct le_softc *le = (struct le_softc *) lecd.cd_devs[ifp->if_unit]; 721 struct lereg1 *ler1 = le->sc_r1; 722 int s = splimp(), error = 0; 723 724 switch (cmd) { 725 726 case SIOCSIFADDR: 727 ifp->if_flags |= IFF_UP; 728 switch (ifa->ifa_addr->sa_family) { 729 #ifdef INET 730 case AF_INET: 731 leinit(ifp->if_unit); /* before arpwhohas */ 732 ((struct arpcom *)ifp)->ac_ipaddr = 733 IA_SIN(ifa)->sin_addr; 734 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 735 break; 736 #endif 737 #ifdef NS 738 case AF_NS: 739 { 740 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 741 742 if (ns_nullhost(*ina)) 743 ina->x_host = *(union ns_host *)(le->sc_addr); 744 else { 745 /* 746 * The manual says we can't change the address 747 * while the receiver is armed, 748 * so reset everything 749 */ 750 ifp->if_flags &= ~IFF_RUNNING; 751 bcopy((caddr_t)ina->x_host.c_host, 752 (caddr_t)le->sc_addr, sizeof(le->sc_addr)); 753 } 754 leinit(ifp->if_unit); /* does le_setaddr() */ 755 break; 756 } 757 #endif 758 default: 759 leinit(ifp->if_unit); 760 break; 761 } 762 break; 763 764 case SIOCSIFFLAGS: 765 if ((ifp->if_flags & IFF_UP) == 0 && 766 ifp->if_flags & IFF_RUNNING) { 767 LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 768 ifp->if_flags &= ~IFF_RUNNING; 769 } else if (ifp->if_flags & IFF_UP && 770 (ifp->if_flags & IFF_RUNNING) == 0) 771 leinit(ifp->if_unit); 772 /* 773 * If the state of the promiscuous bit changes, the interface 774 * must be reset to effect the change. 775 */ 776 if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && 777 (ifp->if_flags & IFF_RUNNING)) { 778 le->sc_iflags = ifp->if_flags; 779 lereset(ifp->if_unit); 780 (void) lestart(ifp); 781 } 782 break; 783 784 default: 785 error = EINVAL; 786 } 787 splx(s); 788 return (error); 789 } 790 791 leerror(unit, stat) 792 int unit; 793 int stat; 794 { 795 struct le_softc *le = NULL; 796 797 798 if (!ledebug) 799 return; 800 801 le = (struct le_softc *) lecd.cd_devs[unit]; 802 /* 803 * Not all transceivers implement heartbeat 804 * so we only log CERR once. 805 */ 806 if ((stat & LE_CERR) && le->sc_cerr) 807 return; 808 log(LOG_WARNING, 809 "le%d: error: stat=%b\n", unit, 810 stat, 811 LE_STATUS_BITS); 812 } 813 814 lererror(unit, msg) 815 int unit; 816 char *msg; 817 { 818 register struct le_softc *le = lecd.cd_devs[unit]; 819 register struct lermd *rmd; 820 int len; 821 822 if (!ledebug) 823 return; 824 825 rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; 826 len = rmd->rmd3; 827 log(LOG_WARNING, 828 "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1_bits=%b\n", 829 unit, msg, 830 len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown", 831 le->sc_rmd, len, 832 rmd->rmd1_bits, 833 "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3RBUF\2STP\1ENP"); 834 } 835 836 lexerror(unit) 837 int unit; 838 { 839 register struct le_softc *le = lecd.cd_devs[unit]; 840 register struct letmd *tmd; 841 int len; 842 843 if (!ledebug) 844 return; 845 846 tmd = le->sc_r2->ler2_tmd; 847 len = -tmd->tmd2; 848 log(LOG_WARNING, 849 "le%d: oerror: to %s: buf=%d, len=%d, tmd1_bits=%b, tmd3=%b\n", 850 unit, 851 len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown", 852 0, len, 853 tmd->tmd1_bits, 854 "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP", 855 tmd->tmd3, 856 "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); 857 } 858