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 = 1; /* console error messages */ 93 94 int leintr(), leioctl(), ether_output(); 95 void lestart(), 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_mtu = ETHERMTU; 176 ifp->if_ioctl = leioctl; 177 ifp->if_output = ether_output; 178 ifp->if_start = lestart; 179 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 180 #if NBPFILTER > 0 181 bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 182 #endif 183 if_attach(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 void 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; 308 IF_DEQUEUE(&le->sc_if.if_snd, m); 309 if (m == 0) 310 return; 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 } 326 327 leintr(unit) 328 register int unit; 329 { 330 register struct le_softc *le = lecd.cd_devs[unit]; 331 register struct lereg1 *ler1; 332 register int stat; 333 334 le_machdep_intrcheck(le, unit); 335 ler1 = le->sc_r1; 336 LERDWR(le, ler1->ler1_rdp, stat); 337 if (ledebug) 338 printf("[le%d: stat %b]", unit, stat, LE_STATUS_BITS); 339 if (stat & LE_SERR) { 340 leerror(unit, stat); 341 if (stat & LE_MERR) { 342 le->sc_merr++; 343 lereset(unit); 344 return(1); 345 } 346 if (stat & LE_BABL) 347 le->sc_babl++; 348 if (stat & LE_CERR) 349 le->sc_cerr++; 350 if (stat & LE_MISS) 351 le->sc_miss++; 352 LERDWR(le, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); 353 } 354 if ((stat & LE_RXON) == 0) { 355 le->sc_rxoff++; 356 lereset(unit); 357 return(1); 358 } 359 if ((stat & LE_TXON) == 0) { 360 le->sc_txoff++; 361 lereset(unit); 362 return(1); 363 } 364 if (stat & LE_RINT) { 365 /* interrupt is cleared in lerint */ 366 lerint(unit); 367 } 368 if (stat & LE_TINT) { 369 LERDWR(le, LE_TINT|LE_INEA, ler1->ler1_rdp); 370 lexint(unit); 371 } 372 return(1); 373 } 374 375 /* 376 * Ethernet interface transmitter interrupt. 377 * Start another output if more data to send. 378 */ 379 lexint(unit) 380 register int unit; 381 { 382 register struct le_softc *le = lecd.cd_devs[unit]; 383 register struct letmd *tmd = le->sc_r2->ler2_tmd; 384 385 if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) { 386 le->sc_xint++; 387 return; 388 } 389 if (tmd->tmd1_bits & LE_OWN) { 390 le->sc_xown++; 391 return; 392 } 393 if (tmd->tmd1_bits & LE_ERR) { 394 err: 395 lexerror(unit); 396 le->sc_if.if_oerrors++; 397 if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { 398 le->sc_uflo++; 399 lereset(unit); 400 } 401 else if (tmd->tmd3 & LE_LCOL) 402 le->sc_if.if_collisions++; 403 else if (tmd->tmd3 & LE_RTRY) 404 le->sc_if.if_collisions += 16; 405 } 406 else if (tmd->tmd3 & LE_TBUFF) 407 /* XXX documentation says BUFF not included in ERR */ 408 goto err; 409 else if (tmd->tmd1_bits & LE_ONE) 410 le->sc_if.if_collisions++; 411 else if (tmd->tmd1_bits & LE_MORE) 412 /* what is the real number? */ 413 le->sc_if.if_collisions += 2; 414 else 415 le->sc_if.if_opackets++; 416 le->sc_if.if_flags &= ~IFF_OACTIVE; 417 (void) lestart(&le->sc_if); 418 } 419 420 #define LENEXTRMP \ 421 if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd 422 423 /* 424 * Ethernet interface receiver interrupt. 425 * If input error just drop packet. 426 * Decapsulate packet based on type and pass to type specific 427 * higher-level input routine. 428 */ 429 lerint(unit) 430 int unit; 431 { 432 register struct le_softc *le = lecd.cd_devs[unit]; 433 register int bix = le->sc_rmd; 434 register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; 435 436 /* 437 * Out of sync with hardware, should never happen? 438 */ 439 if (rmd->rmd1_bits & LE_OWN) { 440 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 441 return; 442 } 443 444 /* 445 * Process all buffers with valid data 446 */ 447 while ((rmd->rmd1_bits & LE_OWN) == 0) { 448 int len = rmd->rmd3; 449 450 /* Clear interrupt to avoid race condition */ 451 LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 452 453 if (rmd->rmd1_bits & LE_ERR) { 454 le->sc_rmd = bix; 455 lererror(unit, "bad packet"); 456 le->sc_if.if_ierrors++; 457 } else if ((rmd->rmd1_bits & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { 458 /* 459 * Find the end of the packet so we can see how long 460 * it was. We still throw it away. 461 */ 462 do { 463 LERDWR(le->sc_r0, LE_RINT|LE_INEA, 464 le->sc_r1->ler1_rdp); 465 rmd->rmd3 = 0; 466 rmd->rmd1_bits = LE_OWN; 467 LENEXTRMP; 468 } while (!(rmd->rmd1_bits & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); 469 le->sc_rmd = bix; 470 lererror(unit, "chained buffer"); 471 le->sc_rxlen++; 472 /* 473 * If search terminated without successful completion 474 * we reset the hardware (conservative). 475 */ 476 if ((rmd->rmd1_bits & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != 477 LE_ENP) { 478 lereset(unit); 479 return; 480 } 481 } else 482 leread(unit, le->sc_r2->ler2_rbuf[bix], len); 483 rmd->rmd3 = 0; 484 rmd->rmd1_bits = LE_OWN; 485 LENEXTRMP; 486 } 487 le->sc_rmd = bix; 488 } 489 490 leread(unit, buf, len) 491 int unit; 492 char *buf; 493 int len; 494 { 495 register struct le_softc *le = lecd.cd_devs[unit]; 496 register struct ether_header *et; 497 struct mbuf *m; 498 int off, resid; 499 500 le->sc_if.if_ipackets++; 501 et = (struct ether_header *)buf; 502 et->ether_type = ntohs((u_short)et->ether_type); 503 /* adjust input length to account for header and CRC */ 504 len = len - sizeof(struct ether_header) - 4; 505 506 #ifdef RMP 507 /* (XXX) 508 * 509 * If Ethernet Type field is < MaxPacketSize, we probably have 510 * a IEEE802 packet here. Make sure that the size is at least 511 * that of the HP LLC. Also do sanity checks on length of LLC 512 * (old Ethernet Type field) and packet length. 513 * 514 * Provided the above checks succeed, change `len' to reflect 515 * the length of the LLC (i.e. et->ether_type) and change the 516 * type field to ETHERTYPE_IEEE so we can switch() on it later. 517 * Yes, this is a hack and will eventually be done "right". 518 */ 519 if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) && 520 len >= et->ether_type && len >= IEEE802LEN_MIN) { 521 len = et->ether_type; 522 et->ether_type = ETHERTYPE_IEEE; /* hack! */ 523 } 524 #endif 525 526 #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) 527 if (et->ether_type >= ETHERTYPE_TRAIL && 528 et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 529 off = (et->ether_type - ETHERTYPE_TRAIL) * 512; 530 if (off >= ETHERMTU) 531 return; /* sanity */ 532 et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); 533 resid = ntohs(*(ledataaddr(et, off+2, u_short *))); 534 if (off + resid > len) 535 return; /* sanity */ 536 len = off + resid; 537 } else 538 off = 0; 539 540 if (len <= 0) { 541 if (ledebug) 542 log(LOG_WARNING, 543 "le%d: ierror(runt packet): from %s: len=%d\n", 544 unit, ether_sprintf(et->ether_shost), len); 545 le->sc_runt++; 546 le->sc_if.if_ierrors++; 547 return; 548 } 549 #if NBPFILTER > 0 550 /* 551 * Check if there's a bpf filter listening on this interface. 552 * If so, hand off the raw packet to bpf, which must deal with 553 * trailers in its own way. 554 */ 555 if (le->sc_bpf) { 556 bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header)); 557 558 /* 559 * Note that the interface cannot be in promiscuous mode if 560 * there are no bpf listeners. And if we are in promiscuous 561 * mode, we have to check if this packet is really ours. 562 * 563 * XXX This test does not support multicasts. 564 */ 565 if ((le->sc_if.if_flags & IFF_PROMISC) 566 && bcmp(et->ether_dhost, le->sc_addr, 567 sizeof(et->ether_dhost)) != 0 568 && bcmp(et->ether_dhost, etherbroadcastaddr, 569 sizeof(et->ether_dhost)) != 0) 570 return; 571 } 572 #endif 573 /* 574 * Pull packet off interface. Off is nonzero if packet 575 * has trailing header; leget will then force this header 576 * information to be at the front, but we still have to drop 577 * the type and length which are at the front of any trailer data. 578 */ 579 m = leget(buf, len, off, &le->sc_if); 580 if (m == 0) 581 return; 582 #ifdef RMP 583 /* 584 * (XXX) 585 * This needs to be integrated with the ISO stuff in ether_input() 586 */ 587 if (et->ether_type == ETHERTYPE_IEEE) { 588 /* 589 * Snag the Logical Link Control header (IEEE 802.2). 590 */ 591 struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc); 592 593 /* 594 * If the DSAP (and HP's extended DXSAP) indicate this 595 * is an RMP packet, hand it to the raw input routine. 596 */ 597 if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) { 598 static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT}; 599 static struct sockaddr rmp_src = {AF_RMP}; 600 static struct sockaddr rmp_dst = {AF_RMP}; 601 602 bcopy(et->ether_shost, rmp_src.sa_data, 603 sizeof(et->ether_shost)); 604 bcopy(et->ether_dhost, rmp_dst.sa_data, 605 sizeof(et->ether_dhost)); 606 607 raw_input(m, &rmp_sp, &rmp_src, &rmp_dst); 608 return; 609 } 610 } 611 #endif 612 ether_input(&le->sc_if, et, m); 613 } 614 615 /* 616 * Routine to copy from mbuf chain to transmit 617 * buffer in board local memory. 618 */ 619 leput(lebuf, m) 620 register char *lebuf; 621 register struct mbuf *m; 622 { 623 register struct mbuf *mp; 624 register int len, tlen = 0; 625 626 for (mp = m; mp; mp = mp->m_next) { 627 len = mp->m_len; 628 if (len == 0) 629 continue; 630 tlen += len; 631 bcopy(mtod(mp, char *), lebuf, len); 632 lebuf += len; 633 } 634 m_freem(m); 635 if (tlen < LEMINSIZE) { 636 bzero(lebuf, LEMINSIZE - tlen); 637 tlen = LEMINSIZE; 638 } 639 return(tlen); 640 } 641 642 /* 643 * Routine to copy from board local memory into mbufs. 644 */ 645 struct mbuf * 646 leget(lebuf, totlen, off0, ifp) 647 char *lebuf; 648 int totlen, off0; 649 struct ifnet *ifp; 650 { 651 register struct mbuf *m; 652 struct mbuf *top = 0, **mp = ⊤ 653 register int off = off0, len; 654 register char *cp; 655 char *epkt; 656 657 lebuf += sizeof (struct ether_header); 658 cp = lebuf; 659 epkt = cp + totlen; 660 if (off) { 661 cp += off + 2 * sizeof(u_short); 662 totlen -= 2 * sizeof(u_short); 663 } 664 665 MGETHDR(m, M_DONTWAIT, MT_DATA); 666 if (m == 0) 667 return (0); 668 m->m_pkthdr.rcvif = ifp; 669 m->m_pkthdr.len = totlen; 670 m->m_len = MHLEN; 671 672 while (totlen > 0) { 673 if (top) { 674 MGET(m, M_DONTWAIT, MT_DATA); 675 if (m == 0) { 676 m_freem(top); 677 return (0); 678 } 679 m->m_len = MLEN; 680 } 681 len = min(totlen, epkt - cp); 682 if (len >= MINCLSIZE) { 683 MCLGET(m, M_DONTWAIT); 684 if (m->m_flags & M_EXT) 685 m->m_len = len = min(len, MCLBYTES); 686 else 687 len = m->m_len; 688 } else { 689 /* 690 * Place initial small packet/header at end of mbuf. 691 */ 692 if (len < m->m_len) { 693 if (top == 0 && len + max_linkhdr <= m->m_len) 694 m->m_data += max_linkhdr; 695 m->m_len = len; 696 } else 697 len = m->m_len; 698 } 699 bcopy(cp, mtod(m, caddr_t), (unsigned)len); 700 cp += len; 701 *mp = m; 702 mp = &m->m_next; 703 totlen -= len; 704 if (cp == epkt) 705 cp = lebuf; 706 } 707 return (top); 708 } 709 710 /* 711 * Process an ioctl request. 712 */ 713 leioctl(ifp, cmd, data) 714 register struct ifnet *ifp; 715 int cmd; 716 caddr_t data; 717 { 718 register struct ifaddr *ifa = (struct ifaddr *)data; 719 struct le_softc *le = (struct le_softc *) lecd.cd_devs[ifp->if_unit]; 720 struct lereg1 *ler1 = le->sc_r1; 721 int s = splimp(), error = 0; 722 723 switch (cmd) { 724 725 case SIOCSIFADDR: 726 ifp->if_flags |= IFF_UP; 727 switch (ifa->ifa_addr->sa_family) { 728 #ifdef INET 729 case AF_INET: 730 leinit(ifp->if_unit); /* before arpwhohas */ 731 ((struct arpcom *)ifp)->ac_ipaddr = 732 IA_SIN(ifa)->sin_addr; 733 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 734 break; 735 #endif 736 #ifdef NS 737 case AF_NS: 738 { 739 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 740 741 if (ns_nullhost(*ina)) 742 ina->x_host = *(union ns_host *)(le->sc_addr); 743 else { 744 /* 745 * The manual says we can't change the address 746 * while the receiver is armed, 747 * so reset everything 748 */ 749 ifp->if_flags &= ~IFF_RUNNING; 750 bcopy((caddr_t)ina->x_host.c_host, 751 (caddr_t)le->sc_addr, sizeof(le->sc_addr)); 752 } 753 leinit(ifp->if_unit); /* does le_setaddr() */ 754 break; 755 } 756 #endif 757 default: 758 leinit(ifp->if_unit); 759 break; 760 } 761 break; 762 763 case SIOCSIFFLAGS: 764 if ((ifp->if_flags & IFF_UP) == 0 && 765 ifp->if_flags & IFF_RUNNING) { 766 LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 767 ifp->if_flags &= ~IFF_RUNNING; 768 } else if (ifp->if_flags & IFF_UP && 769 (ifp->if_flags & IFF_RUNNING) == 0) 770 leinit(ifp->if_unit); 771 /* 772 * If the state of the promiscuous bit changes, the interface 773 * must be reset to effect the change. 774 */ 775 if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && 776 (ifp->if_flags & IFF_RUNNING)) { 777 le->sc_iflags = ifp->if_flags; 778 lereset(ifp->if_unit); 779 lestart(ifp); 780 } 781 break; 782 783 default: 784 error = EINVAL; 785 } 786 splx(s); 787 return (error); 788 } 789 790 leerror(unit, stat) 791 int unit; 792 int stat; 793 { 794 struct le_softc *le = NULL; 795 796 797 if (!ledebug) 798 return; 799 800 le = (struct le_softc *) lecd.cd_devs[unit]; 801 /* 802 * Not all transceivers implement heartbeat 803 * so we only log CERR once. 804 */ 805 if ((stat & LE_CERR) && le->sc_cerr) 806 return; 807 log(LOG_WARNING, 808 "le%d: error: stat=%b\n", unit, 809 stat, 810 LE_STATUS_BITS); 811 } 812 813 lererror(unit, msg) 814 int unit; 815 char *msg; 816 { 817 register struct le_softc *le = lecd.cd_devs[unit]; 818 register struct lermd *rmd; 819 int len; 820 821 if (!ledebug) 822 return; 823 824 rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; 825 len = rmd->rmd3; 826 log(LOG_WARNING, 827 "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1_bits=%b\n", 828 unit, msg, 829 len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown", 830 le->sc_rmd, len, 831 rmd->rmd1_bits, 832 "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3RBUF\2STP\1ENP"); 833 } 834 835 lexerror(unit) 836 int unit; 837 { 838 register struct le_softc *le = lecd.cd_devs[unit]; 839 register struct letmd *tmd; 840 int len; 841 842 if (!ledebug) 843 return; 844 845 tmd = le->sc_r2->ler2_tmd; 846 len = -tmd->tmd2; 847 log(LOG_WARNING, 848 "le%d: oerror: to %s: buf=%d, len=%d, tmd1_bits=%b, tmd3=%b\n", 849 unit, 850 len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown", 851 0, len, 852 tmd->tmd1_bits, 853 "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP", 854 tmd->tmd3, 855 "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); 856 } 857