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 * $Id: if_le.c,v 1.5 1994/02/13 21:10:39 chopps Exp $ 35 */ 36 37 #include "le.h" 38 #if NLE > 0 39 40 #include "bpfilter.h" 41 42 /* 43 * AMD 7990 LANCE 44 * 45 * This driver will generate and accept tailer encapsulated packets even 46 * though it buys us nothing. The motivation was to avoid incompatibilities 47 * with VAXen, SUNs, and others that handle and benefit from them. 48 * This reasoning is dubious. 49 */ 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/mbuf.h> 53 #include <sys/buf.h> 54 #include <sys/protosw.h> 55 #include <sys/socket.h> 56 #include <sys/syslog.h> 57 #include <sys/ioctl.h> 58 #include <sys/errno.h> 59 60 #include <net/if.h> 61 #include <net/netisr.h> 62 #include <net/route.h> 63 64 #ifdef INET 65 #include <netinet/in.h> 66 #include <netinet/in_systm.h> 67 #include <netinet/in_var.h> 68 #include <netinet/ip.h> 69 #include <netinet/if_ether.h> 70 #endif 71 72 #ifdef NS 73 #include <netns/ns.h> 74 #include <netns/ns_if.h> 75 #endif 76 77 #ifdef RMP 78 #include <netrmp/rmp.h> 79 #include <netrmp/rmp_var.h> 80 #endif 81 82 #include <machine/cpu.h> 83 #include <machine/mtpr.h> 84 #include <amiga/dev/device.h> 85 #include <amiga/dev/if_lereg.h> 86 87 #if NBPFILTER > 0 88 #include <net/bpf.h> 89 #include <net/bpfdesc.h> 90 #endif 91 92 #if 0 93 /* offsets for: ID, REGS, MEM, NVRAM */ 94 int lestd[] = { 0, 0x4000, 0x8000, 0xC008 }; 95 #else 96 /* offsets for: ID, REGS, MEM */ 97 int lestd[] = { 0, 0x4000, 0x8000 }; 98 #endif 99 100 int leattach(); 101 struct driver ledriver = { 102 leattach, "le", 103 }; 104 105 #if 0 106 struct isr le_isr[NLE]; 107 #endif 108 int ledebug = 0; /* console error messages */ 109 110 int leintr(), leinit(), leioctl(), lestart(), ether_output(); 111 struct mbuf *leget(); 112 extern struct ifnet loif; 113 114 /* 115 * Ethernet software status per interface. 116 * 117 * Each interface is referenced by a network interface structure, 118 * le_if, which the routing code uses to locate the interface. 119 * This structure contains the output queue for the interface, its address, ... 120 */ 121 struct le_softc { 122 struct arpcom sc_ac; /* common Ethernet structures */ 123 #define sc_if sc_ac.ac_if /* network-visible interface */ 124 #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ 125 void *sc_base; /* base address of board */ 126 struct lereg1 *sc_r1; /* LANCE registers */ 127 struct lereg2 *sc_r2; /* dual-port RAM */ 128 int sc_rmd; /* predicted next rmd to process */ 129 int sc_runt; 130 int sc_jab; 131 int sc_merr; 132 int sc_babl; 133 int sc_cerr; 134 int sc_miss; 135 int sc_xint; 136 int sc_xown; 137 int sc_uflo; 138 int sc_rxlen; 139 int sc_rxoff; 140 int sc_txoff; 141 int sc_busy; 142 short sc_iflags; 143 #if NBPFILTER > 0 144 caddr_t sc_bpf; 145 #endif 146 } le_softc[NLE]; 147 148 149 /* 150 * Interface exists: make available by filling in network interface 151 * record. System will initialize the interface when it is ready 152 * to accept packets. 153 */ 154 leattach(ad) 155 struct amiga_device *ad; 156 { 157 register struct lereg0 *ler0; 158 register struct lereg2 *ler2; 159 struct lereg2 *lemem = (struct lereg2 *) 0x8000; 160 struct le_softc *le = &le_softc[ad->amiga_unit]; 161 struct ifnet *ifp = &le->sc_if; 162 char *cp; 163 int i; 164 unsigned long ser; 165 int s = splhigh (); 166 167 ler0 = le->sc_base = ad->amiga_addr; 168 le->sc_r1 = (struct lereg1 *)(lestd[1] + (int)ad->amiga_addr); 169 ler2 = le->sc_r2 = (struct lereg2 *)(lestd[2] + (int)ad->amiga_addr); 170 171 #if 0 172 if (ler0->ler0_id == 0xff) 173 goto noreset; 174 if (ler0->ler0_id != LEID) 175 { 176 le->sc_base = 0; 177 splx (s); 178 printf ("le%d: ler0_id[%d] != LEID[%d], board ignored.\n", 179 ad->amiga_unit, ler0->ler0_id, LEID); 180 return(0); 181 } 182 le_isr[ad->amiga_unit].isr_intr = leintr; 183 ad->amiga_ipl = le_isr[ad->amiga_unit].isr_ipl = LE_IPL(ler0->ler0_status); 184 le_isr[ad->amiga_unit].isr_arg = ad->amiga_unit; 185 ler0->ler0_id = 0xFF; 186 DELAY(100); 187 noreset: 188 189 /* 190 * Read the ethernet address off the board, one nibble at a time. 191 */ 192 cp = (char *)(lestd[3] + (int)ad->amiga_addr); 193 for (i = 0; i < sizeof(le->sc_addr); i++) { 194 le->sc_addr[i] = (*++cp & 0xF) << 4; 195 cp++; 196 le->sc_addr[i] |= *++cp & 0xF; 197 cp++; 198 } 199 #else 200 /* serial number contains this information. Manufacturer decides 201 the 3 first bytes. */ 202 ser = (unsigned long) ad->amiga_serno; 203 if ((ser >> 24) == 1) 204 { 205 /* Commodore */ 206 le->sc_addr[0] = 0x00; 207 le->sc_addr[1] = 0x80; 208 le->sc_addr[2] = 0x10; 209 } 210 else if ((ser >> 24) == 2) 211 { 212 le->sc_addr[0] = 0x00; 213 le->sc_addr[1] = 0x00; 214 le->sc_addr[2] = 0x9f; 215 } 216 le->sc_addr[3] = (ser >> 16) & 0xff; 217 le->sc_addr[4] = (ser >> 8) & 0xff; 218 le->sc_addr[5] = (ser ) & 0xff; 219 #endif 220 printf("le%d: hardware address %s\n", ad->amiga_unit, 221 ether_sprintf(le->sc_addr)); 222 223 /* 224 * Setup for transmit/receive 225 */ 226 ler2->ler2_mode = LE_MODE; 227 ler2->ler2_padr[0] = le->sc_addr[1]; 228 ler2->ler2_padr[1] = le->sc_addr[0]; 229 ler2->ler2_padr[2] = le->sc_addr[3]; 230 ler2->ler2_padr[3] = le->sc_addr[2]; 231 ler2->ler2_padr[4] = le->sc_addr[5]; 232 ler2->ler2_padr[5] = le->sc_addr[4]; 233 #ifdef RMP 234 /* 235 * Set up logical addr filter to accept multicast 9:0:9:0:0:4 236 * This should be an ioctl() to the driver. (XXX) 237 */ 238 ler2->ler2_ladrf0 = 0x00100000; 239 ler2->ler2_ladrf1 = 0x0; 240 #else 241 ler2->ler2_ladrf0 = 0; 242 ler2->ler2_ladrf1 = 0; 243 #endif 244 ler2->ler2_rlen = LE_RLEN; 245 ler2->ler2_rdra = (int)lemem->ler2_rmd; 246 ler2->ler2_tlen = LE_TLEN; 247 ler2->ler2_tdra = (int)lemem->ler2_tmd; 248 #if 0 249 isrlink(&le_isr[ad->amiga_unit]); 250 #endif 251 splx (s); 252 253 ifp->if_unit = ad->amiga_unit; 254 ifp->if_name = "le"; 255 ifp->if_mtu = ETHERMTU; 256 ifp->if_ioctl = leioctl; 257 ifp->if_output = ether_output; 258 ifp->if_start = lestart; 259 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 260 #if NBPFILTER > 0 261 bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 262 #endif 263 if_attach(ifp); 264 return (1); 265 } 266 267 ledrinit(ler2) 268 register struct lereg2 *ler2; 269 { 270 register struct lereg2 *lemem = (struct lereg2 *) 0x8000; 271 register int i; 272 273 for (i = 0; i < LERBUF; i++) { 274 ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i]; 275 ler2->ler2_rmd[i].rmd1 = LE_OWN; 276 ler2->ler2_rmd[i].rmd2 = -LEMTU; 277 ler2->ler2_rmd[i].rmd3 = 0; 278 } 279 for (i = 0; i < LETBUF; i++) { 280 ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i]; 281 ler2->ler2_tmd[i].tmd1 = 0; 282 ler2->ler2_tmd[i].tmd2 = 0; 283 ler2->ler2_tmd[i].tmd3 = 0; 284 } 285 } 286 287 lereset(unit) 288 register int unit; 289 { 290 register struct le_softc *le = &le_softc[unit]; 291 register struct lereg1 *ler1 = le->sc_r1; 292 register struct lereg2 *lemem = (struct lereg2 *) 0x8000; 293 register int timo = 100000; 294 register int stat; 295 296 #ifdef lint 297 stat = unit; 298 #endif 299 #if NBPFILTER > 0 300 if (le->sc_if.if_flags & IFF_PROMISC) 301 /* set the promiscuous bit */ 302 le->sc_r2->ler2_mode = LE_MODE|0x8000; 303 else 304 le->sc_r2->ler2_mode = LE_MODE; 305 #endif 306 ler1->ler1_rap = LE_CSR0; 307 ler1->ler1_rdp = LE_STOP; 308 ledrinit(le->sc_r2); 309 le->sc_rmd = 0; 310 ler1->ler1_rap = LE_CSR1; 311 ler1->ler1_rdp = (int)&lemem->ler2_mode; 312 ler1->ler1_rap = LE_CSR2; 313 ler1->ler1_rdp = 0; 314 ler1->ler1_rap = LE_CSR0; 315 ler1->ler1_rdp = LE_INIT; 316 do { 317 if (--timo == 0) { 318 printf("le%d: init timeout, stat = 0x%x\n", 319 unit, stat); 320 break; 321 } 322 stat = ler1->ler1_rdp; 323 } while ((stat & LE_IDON) == 0); 324 ler1->ler1_rdp = LE_STOP; 325 ler1->ler1_rap = LE_CSR3; 326 ler1->ler1_rdp = LE_BSWP; 327 ler1->ler1_rap = LE_CSR0; 328 ler1->ler1_rdp = LE_STRT | LE_INEA; 329 le->sc_if.if_flags &= ~IFF_OACTIVE; 330 } 331 332 /* 333 * Initialization of interface 334 */ 335 leinit(unit) 336 int unit; 337 { 338 struct le_softc *le = &le_softc[unit]; 339 register struct ifnet *ifp = &le->sc_if; 340 int s; 341 342 /* not yet, if address still unknown */ 343 if (ifp->if_addrlist == (struct ifaddr *)0) 344 return; 345 if ((ifp->if_flags & IFF_RUNNING) == 0) { 346 s = splimp(); 347 ifp->if_flags |= IFF_RUNNING; 348 lereset(unit); 349 (void) lestart(ifp); 350 splx(s); 351 } 352 } 353 354 /* 355 * Start output on interface. Get another datagram to send 356 * off of the interface queue, and copy it to the interface 357 * before starting the output. 358 */ 359 lestart(ifp) 360 struct ifnet *ifp; 361 { 362 register struct le_softc *le = &le_softc[ifp->if_unit]; 363 register struct letmd *tmd; 364 register struct mbuf *m; 365 int len; 366 367 if ((le->sc_if.if_flags & IFF_RUNNING) == 0) 368 return (0); 369 IF_DEQUEUE(&le->sc_if.if_snd, m); 370 if (m == 0) 371 return (0); 372 len = leput(le->sc_r2->ler2_tbuf[0], m); 373 #if NBPFILTER > 0 374 /* 375 * If bpf is listening on this interface, let it 376 * see the packet before we commit it to the wire. 377 */ 378 if (le->sc_bpf) 379 bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len); 380 #endif 381 tmd = le->sc_r2->ler2_tmd; 382 tmd->tmd3 = 0; 383 tmd->tmd2 = -len; 384 tmd->tmd1 = LE_OWN | LE_STP | LE_ENP; 385 le->sc_if.if_flags |= IFF_OACTIVE; 386 return (0); 387 } 388 389 leintr(unit) 390 register int unit; 391 { 392 register struct le_softc *le = &le_softc[unit]; 393 register struct lereg1 *ler1; 394 register int stat; 395 396 /* if not even initialized, don't do anything further.. */ 397 if (! le->sc_base) 398 return 0; 399 400 ler1 = le->sc_r1; 401 stat = ler1->ler1_rdp; 402 403 if (! (stat & LE_INTR)) 404 return 0; 405 406 if (stat & LE_SERR) { 407 leerror(unit, stat); 408 if (stat & LE_MERR) { 409 le->sc_merr++; 410 lereset(unit); 411 return(1); 412 } 413 if (stat & LE_BABL) 414 le->sc_babl++; 415 if (stat & LE_CERR) 416 le->sc_cerr++; 417 if (stat & LE_MISS) 418 le->sc_miss++; 419 ler1->ler1_rdp = LE_BABL|LE_CERR|LE_MISS|LE_INEA; 420 } 421 if ((stat & LE_RXON) == 0) { 422 le->sc_rxoff++; 423 lereset(unit); 424 return(1); 425 } 426 if ((stat & LE_TXON) == 0) { 427 le->sc_txoff++; 428 lereset(unit); 429 return(1); 430 } 431 if (stat & LE_RINT) { 432 /* interrupt is cleared in lerint */ 433 lerint(unit); 434 } 435 if (stat & LE_TINT) { 436 ler1->ler1_rdp = LE_TINT|LE_INEA; 437 lexint(unit); 438 } 439 return(1); 440 } 441 442 /* 443 * Ethernet interface transmitter interrupt. 444 * Start another output if more data to send. 445 */ 446 lexint(unit) 447 register int unit; 448 { 449 register struct le_softc *le = &le_softc[unit]; 450 register struct letmd *tmd = le->sc_r2->ler2_tmd; 451 452 if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) { 453 le->sc_xint++; 454 return; 455 } 456 if (tmd->tmd1 & LE_OWN) { 457 le->sc_xown++; 458 return; 459 } 460 if (tmd->tmd1 & LE_ERR) { 461 err: 462 lexerror(unit); 463 le->sc_if.if_oerrors++; 464 if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { 465 le->sc_uflo++; 466 lereset(unit); 467 } 468 else if (tmd->tmd3 & LE_LCOL) 469 le->sc_if.if_collisions++; 470 else if (tmd->tmd3 & LE_RTRY) 471 le->sc_if.if_collisions += 16; 472 } 473 else if (tmd->tmd3 & LE_TBUFF) 474 /* XXX documentation says BUFF not included in ERR */ 475 goto err; 476 else if (tmd->tmd1 & LE_ONE) 477 le->sc_if.if_collisions++; 478 else if (tmd->tmd1 & LE_MORE) 479 /* what is the real number? */ 480 le->sc_if.if_collisions += 2; 481 else 482 le->sc_if.if_opackets++; 483 le->sc_if.if_flags &= ~IFF_OACTIVE; 484 (void) lestart(&le->sc_if); 485 } 486 487 #define LENEXTRMP \ 488 if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd 489 490 /* 491 * Ethernet interface receiver interrupt. 492 * If input error just drop packet. 493 * Decapsulate packet based on type and pass to type specific 494 * higher-level input routine. 495 */ 496 lerint(unit) 497 int unit; 498 { 499 register struct le_softc *le = &le_softc[unit]; 500 register int bix = le->sc_rmd; 501 register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; 502 503 /* 504 * Out of sync with hardware, should never happen? 505 */ 506 if (rmd->rmd1 & LE_OWN) { 507 le->sc_r1->ler1_rdp = LE_RINT|LE_INEA; 508 return; 509 } 510 511 /* 512 * Process all buffers with valid data 513 */ 514 while ((rmd->rmd1 & LE_OWN) == 0) { 515 int len = rmd->rmd3; 516 517 /* Clear interrupt to avoid race condition */ 518 le->sc_r1->ler1_rdp = LE_RINT|LE_INEA; 519 520 if (rmd->rmd1 & LE_ERR) { 521 le->sc_rmd = bix; 522 lererror(unit, "bad packet"); 523 le->sc_if.if_ierrors++; 524 } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { 525 /* 526 * Find the end of the packet so we can see how long 527 * it was. We still throw it away. 528 */ 529 do { 530 le->sc_r1->ler1_rdp = LE_RINT|LE_INEA; 531 rmd->rmd3 = 0; 532 rmd->rmd1 = LE_OWN; 533 LENEXTRMP; 534 } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); 535 le->sc_rmd = bix; 536 lererror(unit, "chained buffer"); 537 le->sc_rxlen++; 538 /* 539 * If search terminated without successful completion 540 * we reset the hardware (conservative). 541 */ 542 if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != 543 LE_ENP) { 544 lereset(unit); 545 return; 546 } 547 } else 548 leread(unit, le->sc_r2->ler2_rbuf[bix], len); 549 rmd->rmd3 = 0; 550 rmd->rmd1 = LE_OWN; 551 LENEXTRMP; 552 } 553 le->sc_rmd = bix; 554 } 555 556 leread(unit, buf, len) 557 int unit; 558 char *buf; 559 int len; 560 { 561 register struct le_softc *le = &le_softc[unit]; 562 register struct ether_header *et; 563 struct mbuf *m; 564 int off, resid; 565 566 le->sc_if.if_ipackets++; 567 et = (struct ether_header *)buf; 568 et->ether_type = ntohs((u_short)et->ether_type); 569 /* adjust input length to account for header and CRC */ 570 len = len - sizeof(struct ether_header) - 4; 571 572 #ifdef RMP 573 /* (XXX) 574 * 575 * If Ethernet Type field is < MaxPacketSize, we probably have 576 * a IEEE802 packet here. Make sure that the size is at least 577 * that of the HP LLC. Also do sanity checks on length of LLC 578 * (old Ethernet Type field) and packet length. 579 * 580 * Provided the above checks succeed, change `len' to reflect 581 * the length of the LLC (i.e. et->ether_type) and change the 582 * type field to ETHERTYPE_IEEE so we can switch() on it later. 583 * Yes, this is a hack and will eventually be done "right". 584 */ 585 if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct amiga_llc) && 586 len >= et->ether_type && len >= IEEE802LEN_MIN) { 587 len = et->ether_type; 588 et->ether_type = ETHERTYPE_IEEE; /* hack! */ 589 } 590 #endif 591 592 #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) 593 if (et->ether_type >= ETHERTYPE_TRAIL && 594 et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 595 off = (et->ether_type - ETHERTYPE_TRAIL) * 512; 596 if (off >= ETHERMTU) 597 return; /* sanity */ 598 et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); 599 resid = ntohs(*(ledataaddr(et, off+2, u_short *))); 600 if (off + resid > len) 601 return; /* sanity */ 602 len = off + resid; 603 } else 604 off = 0; 605 606 if (len <= 0) { 607 if (ledebug) 608 log(LOG_WARNING, 609 "le%d: ierror(runt packet): from %s: len=%d\n", 610 unit, ether_sprintf(et->ether_shost), len); 611 le->sc_runt++; 612 le->sc_if.if_ierrors++; 613 return; 614 } 615 #if NBPFILTER > 0 616 /* 617 * Check if there's a bpf filter listening on this interface. 618 * If so, hand off the raw packet to bpf, which must deal with 619 * trailers in its own way. 620 */ 621 if (le->sc_bpf) { 622 bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header)); 623 624 /* 625 * Note that the interface cannot be in promiscuous mode if 626 * there are no bpf listeners. And if we are in promiscuous 627 * mode, we have to check if this packet is really ours. 628 * 629 * XXX This test does not support multicasts. 630 */ 631 if ((le->sc_if.if_flags & IFF_PROMISC) 632 && bcmp(et->ether_dhost, le->sc_addr, 633 sizeof(et->ether_dhost)) != 0 634 && bcmp(et->ether_dhost, etherbroadcastaddr, 635 sizeof(et->ether_dhost)) != 0) 636 return; 637 } 638 #endif 639 /* 640 * Pull packet off interface. Off is nonzero if packet 641 * has trailing header; leget will then force this header 642 * information to be at the front, but we still have to drop 643 * the type and length which are at the front of any trailer data. 644 */ 645 m = leget(buf, len, off, &le->sc_if); 646 if (m == 0) 647 return; 648 #ifdef RMP 649 /* 650 * (XXX) 651 * This needs to be integrated with the ISO stuff in ether_input() 652 */ 653 if (et->ether_type == ETHERTYPE_IEEE) { 654 /* 655 * Snag the Logical Link Control header (IEEE 802.2). 656 */ 657 struct amiga_llc *llc = &(mtod(m, struct rmp_packet *)->amiga_llc); 658 659 /* 660 * If the DSAP (and HP's extended DXSAP) indicate this 661 * is an RMP packet, hand it to the raw input routine. 662 */ 663 if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) { 664 static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT}; 665 static struct sockaddr rmp_src = {AF_RMP}; 666 static struct sockaddr rmp_dst = {AF_RMP}; 667 668 bcopy(et->ether_shost, rmp_src.sa_data, 669 sizeof(et->ether_shost)); 670 bcopy(et->ether_dhost, rmp_dst.sa_data, 671 sizeof(et->ether_dhost)); 672 673 raw_input(m, &rmp_sp, &rmp_src, &rmp_dst); 674 return; 675 } 676 } 677 #endif 678 ether_input(&le->sc_if, et, m); 679 } 680 681 /* 682 * Routine to copy from mbuf chain to transmit 683 * buffer in board local memory. 684 */ 685 leput(lebuf, m) 686 register char *lebuf; 687 register struct mbuf *m; 688 { 689 register struct mbuf *mp; 690 register int len, tlen = 0; 691 692 for (mp = m; mp; mp = mp->m_next) { 693 len = mp->m_len; 694 if (len == 0) 695 continue; 696 tlen += len; 697 bcopy(mtod(mp, char *), lebuf, len); 698 lebuf += len; 699 } 700 m_freem(m); 701 if (tlen < LEMINSIZE) { 702 bzero(lebuf, LEMINSIZE - tlen); 703 tlen = LEMINSIZE; 704 } 705 return(tlen); 706 } 707 708 /* 709 * Routine to copy from board local memory into mbufs. 710 */ 711 struct mbuf * 712 leget(lebuf, totlen, off0, ifp) 713 char *lebuf; 714 int totlen, off0; 715 struct ifnet *ifp; 716 { 717 register struct mbuf *m; 718 struct mbuf *top = 0, **mp = ⊤ 719 register int off = off0, len; 720 register char *cp; 721 char *epkt; 722 723 lebuf += sizeof (struct ether_header); 724 cp = lebuf; 725 epkt = cp + totlen; 726 if (off) { 727 cp += off + 2 * sizeof(u_short); 728 totlen -= 2 * sizeof(u_short); 729 } 730 731 MGETHDR(m, M_DONTWAIT, MT_DATA); 732 if (m == 0) 733 return (0); 734 m->m_pkthdr.rcvif = ifp; 735 m->m_pkthdr.len = totlen; 736 m->m_len = MHLEN; 737 738 while (totlen > 0) { 739 if (top) { 740 MGET(m, M_DONTWAIT, MT_DATA); 741 if (m == 0) { 742 m_freem(top); 743 return (0); 744 } 745 m->m_len = MLEN; 746 } 747 len = min(totlen, epkt - cp); 748 if (len >= MINCLSIZE) { 749 MCLGET(m, M_DONTWAIT); 750 if (m->m_flags & M_EXT) 751 m->m_len = len = min(len, MCLBYTES); 752 else 753 len = m->m_len; 754 } else { 755 /* 756 * Place initial small packet/header at end of mbuf. 757 */ 758 if (len < m->m_len) { 759 if (top == 0 && len + max_linkhdr <= m->m_len) 760 m->m_data += max_linkhdr; 761 m->m_len = len; 762 } else 763 len = m->m_len; 764 } 765 bcopy(cp, mtod(m, caddr_t), (unsigned)len); 766 cp += len; 767 *mp = m; 768 mp = &m->m_next; 769 totlen -= len; 770 if (cp == epkt) 771 cp = lebuf; 772 } 773 return (top); 774 } 775 776 /* 777 * Process an ioctl request. 778 */ 779 leioctl(ifp, cmd, data) 780 register struct ifnet *ifp; 781 int cmd; 782 caddr_t data; 783 { 784 register struct ifaddr *ifa = (struct ifaddr *)data; 785 struct le_softc *le = &le_softc[ifp->if_unit]; 786 struct lereg1 *ler1 = le->sc_r1; 787 int s = splimp(), error = 0; 788 789 switch (cmd) { 790 791 case SIOCSIFADDR: 792 ifp->if_flags |= IFF_UP; 793 switch (ifa->ifa_addr->sa_family) { 794 #ifdef INET 795 case AF_INET: 796 leinit(ifp->if_unit); /* before arpwhohas */ 797 ((struct arpcom *)ifp)->ac_ipaddr = 798 IA_SIN(ifa)->sin_addr; 799 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 800 break; 801 #endif 802 #ifdef NS 803 case AF_NS: 804 { 805 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 806 807 if (ns_nullhost(*ina)) 808 ina->x_host = *(union ns_host *)(le->sc_addr); 809 else { 810 /* 811 * The manual says we can't change the address 812 * while the receiver is armed, 813 * so reset everything 814 */ 815 ifp->if_flags &= ~IFF_RUNNING; 816 bcopy((caddr_t)ina->x_host.c_host, 817 (caddr_t)le->sc_addr, sizeof(le->sc_addr)); 818 } 819 leinit(ifp->if_unit); /* does le_setaddr() */ 820 break; 821 } 822 #endif 823 default: 824 leinit(ifp->if_unit); 825 break; 826 } 827 break; 828 829 case SIOCSIFFLAGS: 830 if ((ifp->if_flags & IFF_UP) == 0 && 831 ifp->if_flags & IFF_RUNNING) { 832 ler1->ler1_rdp = LE_STOP; 833 ifp->if_flags &= ~IFF_RUNNING; 834 } else if (ifp->if_flags & IFF_UP && 835 (ifp->if_flags & IFF_RUNNING) == 0) 836 leinit(ifp->if_unit); 837 /* 838 * If the state of the promiscuous bit changes, the interface 839 * must be reset to effect the change. 840 */ 841 if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && 842 (ifp->if_flags & IFF_RUNNING)) { 843 le->sc_iflags = ifp->if_flags; 844 lereset(ifp->if_unit); 845 lestart(ifp); 846 } 847 break; 848 849 default: 850 error = EINVAL; 851 } 852 splx(s); 853 return (error); 854 } 855 856 leerror(unit, stat) 857 int unit; 858 int stat; 859 { 860 if (!ledebug) 861 return; 862 863 /* 864 * Not all transceivers implement heartbeat 865 * so we only log CERR once. 866 */ 867 if ((stat & LE_CERR) && le_softc[unit].sc_cerr) 868 return; 869 log(LOG_WARNING, 870 "le%d: error: stat=%b\n", unit, 871 stat, 872 "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"); 873 } 874 875 lererror(unit, msg) 876 int unit; 877 char *msg; 878 { 879 register struct le_softc *le = &le_softc[unit]; 880 register struct lermd *rmd; 881 int len; 882 883 if (!ledebug) 884 return; 885 886 rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; 887 len = rmd->rmd3; 888 log(LOG_WARNING, 889 "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", 890 unit, msg, 891 len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown", 892 le->sc_rmd, len, 893 rmd->rmd1, 894 "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP"); 895 } 896 897 lexerror(unit) 898 int unit; 899 { 900 register struct le_softc *le = &le_softc[unit]; 901 register struct letmd *tmd; 902 int len; 903 904 if (!ledebug) 905 return; 906 907 tmd = le->sc_r2->ler2_tmd; 908 len = -tmd->tmd2; 909 log(LOG_WARNING, 910 "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", 911 unit, 912 len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown", 913 0, len, 914 tmd->tmd1, 915 "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", 916 tmd->tmd3, 917 "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); 918 } 919 #endif 920