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