1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)if_il.c 7.5 (Berkeley) 04/25/89 18 */ 19 20 #include "il.h" 21 #if NIL > 0 22 23 /* 24 * Interlan Ethernet Communications Controller interface 25 */ 26 #include "machine/pte.h" 27 28 #include "param.h" 29 #include "systm.h" 30 #include "mbuf.h" 31 #include "buf.h" 32 #include "protosw.h" 33 #include "socket.h" 34 #include "vmmac.h" 35 #include "ioctl.h" 36 #include "errno.h" 37 #include "syslog.h" 38 39 #include "../net/if.h" 40 #include "../net/netisr.h" 41 #include "../net/route.h" 42 43 #ifdef INET 44 #include "../netinet/in.h" 45 #include "../netinet/in_systm.h" 46 #include "../netinet/in_var.h" 47 #include "../netinet/ip.h" 48 #include "../netinet/if_ether.h" 49 #endif 50 51 #ifdef NS 52 #include "../netns/ns.h" 53 #include "../netns/ns_if.h" 54 #endif 55 56 #include "../vax/cpu.h" 57 #include "../vax/mtpr.h" 58 #include "if_il.h" 59 #include "if_ilreg.h" 60 #include "if_uba.h" 61 #include "../vaxuba/ubareg.h" 62 #include "../vaxuba/ubavar.h" 63 64 int ilprobe(), ilattach(), ilrint(), ilcint(); 65 struct uba_device *ilinfo[NIL]; 66 u_short ilstd[] = { 0 }; 67 struct uba_driver ildriver = 68 { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo }; 69 #define ILUNIT(x) minor(x) 70 int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(),ilstart(); 71 int ildebug = 0; 72 73 /* 74 * Ethernet software status per interface. 75 * 76 * Each interface is referenced by a network interface structure, 77 * is_if, which the routing code uses to locate the interface. 78 * This structure contains the output queue for the interface, its address, ... 79 * We also have, for each interface, a UBA interface structure, which 80 * contains information about the UNIBUS resources held by the interface: 81 * map registers, buffered data paths, etc. Information is cached in this 82 * structure for use by the if_uba.c routines in running the interface 83 * efficiently. 84 */ 85 86 struct ether_addr { 87 u_char addr[6]; 88 }; 89 struct il_softc { 90 struct arpcom is_ac; /* Ethernet common part */ 91 #define is_if is_ac.ac_if /* network-visible interface */ 92 #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ 93 struct ifuba is_ifuba; /* UNIBUS resources */ 94 int is_flags; 95 #define ILF_RCVPENDING 0x2 /* start rcv in ilcint */ 96 #define ILF_STATPENDING 0x4 /* stat cmd pending */ 97 #define ILF_RUNNING 0x8 /* board is running */ 98 #define ILF_SETADDR 0x10 /* physical address is changed */ 99 short is_lastcmd; /* can't read csr, so must save it */ 100 short is_scaninterval; /* interval of stat collection */ 101 #define ILWATCHINTERVAL 60 /* once every 60 seconds */ 102 union { 103 struct il_stats isu_stats; /* holds on-board statistics */ 104 struct ether_addr isu_maddrs[63]; /* multicast addrs */ 105 } is_isu; 106 #define is_stats is_isu.isu_stats 107 #define is_maddrs is_isu.isu_maddrs 108 struct il_stats is_sum; /* summation over time */ 109 int is_ubaddr; /* mapping registers of is_stats */ 110 } il_softc[NIL]; 111 112 ilprobe(reg) 113 caddr_t reg; 114 { 115 register int br, cvec; /* r11, r10 value-result */ 116 register struct ildevice *addr = (struct ildevice *)reg; 117 register i; 118 119 #ifdef lint 120 br = 0; cvec = br; br = cvec; 121 i = 0; ilrint(i); ilcint(i); ilwatch(i); 122 #endif 123 124 addr->il_csr = ILC_OFFLINE|IL_CIE; 125 DELAY(100000); 126 i = addr->il_csr; /* clear CDONE */ 127 if (cvec > 0 && cvec != 0x200) 128 cvec -= 4; 129 return (1); 130 } 131 132 /* 133 * Interface exists: make available by filling in network interface 134 * record. System will initialize the interface when it is ready 135 * to accept packets. A STATUS command is done to get the ethernet 136 * address and other interesting data. 137 */ 138 ilattach(ui) 139 struct uba_device *ui; 140 { 141 register struct il_softc *is = &il_softc[ui->ui_unit]; 142 register struct ifnet *ifp = &is->is_if; 143 register struct ildevice *addr = (struct ildevice *)ui->ui_addr; 144 145 ifp->if_unit = ui->ui_unit; 146 ifp->if_name = "il"; 147 ifp->if_mtu = ETHERMTU; 148 ifp->if_flags = IFF_BROADCAST; 149 150 /* 151 * Reset the board and map the statistics 152 * buffer onto the Unibus. 153 */ 154 addr->il_csr = ILC_RESET; 155 (void)ilwait(ui, "reset"); 156 157 is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, 158 sizeof (struct il_stats), 0); 159 addr->il_bar = is->is_ubaddr & 0xffff; 160 addr->il_bcr = sizeof (struct il_stats); 161 addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; 162 (void)ilwait(ui, "status"); 163 ubarelse(ui->ui_ubanum, &is->is_ubaddr); 164 if (ildebug) 165 printf("il%d: module=%s firmware=%s\n", ui->ui_unit, 166 is->is_stats.ils_module, is->is_stats.ils_firmware); 167 bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, 168 sizeof (is->is_addr)); 169 printf("il%d: hardware address %s\n", ui->ui_unit, 170 ether_sprintf(is->is_addr)); 171 ifp->if_init = ilinit; 172 ifp->if_output = ether_output; 173 ifp->if_ioctl = ilioctl; 174 ifp->if_reset = ilreset; 175 ifp->if_start = ilstart; 176 is->is_ifuba.ifu_flags = UBA_CANTWAIT; 177 if_attach(ifp); 178 } 179 180 ilwait(ui, op) 181 struct uba_device *ui; 182 char *op; 183 { 184 register struct ildevice *addr = (struct ildevice *)ui->ui_addr; 185 186 while ((addr->il_csr&IL_CDONE) == 0) 187 ; 188 if (addr->il_csr&IL_STATUS) { 189 printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op, 190 addr->il_csr, IL_BITS); 191 return (-1); 192 } 193 return (0); 194 } 195 196 /* 197 * Reset of interface after UNIBUS reset. 198 * If interface is on specified uba, reset its state. 199 */ 200 ilreset(unit, uban) 201 int unit, uban; 202 { 203 register struct uba_device *ui; 204 205 if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 || 206 ui->ui_ubanum != uban) 207 return; 208 printf(" il%d", unit); 209 il_softc[unit].is_if.if_flags &= ~IFF_RUNNING; 210 il_softc[unit].is_flags &= ~ILF_RUNNING; 211 ilinit(unit); 212 } 213 214 /* 215 * Initialization of interface; clear recorded pending 216 * operations, and reinitialize UNIBUS usage. 217 */ 218 ilinit(unit) 219 int unit; 220 { 221 register struct il_softc *is = &il_softc[unit]; 222 register struct uba_device *ui = ilinfo[unit]; 223 register struct ildevice *addr; 224 register struct ifnet *ifp = &is->is_if; 225 int s; 226 227 /* not yet, if address still unknown */ 228 if (ifp->if_addrlist == (struct ifaddr *)0) 229 return; 230 if (is->is_flags & ILF_RUNNING) 231 return; 232 233 if ((ifp->if_flags & IFF_RUNNING) == 0) { 234 if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, 235 sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { 236 printf("il%d: can't initialize\n", unit); 237 is->is_if.if_flags &= ~IFF_UP; 238 return; 239 } 240 is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_isu, 241 sizeof (is->is_isu), 0); 242 } 243 ifp->if_watchdog = ilwatch; 244 is->is_scaninterval = ILWATCHINTERVAL; 245 ifp->if_timer = is->is_scaninterval; 246 addr = (struct ildevice *)ui->ui_addr; 247 248 /* 249 * Turn off source address insertion (it's faster this way), 250 * and set board online. Former doesn't work if board is 251 * already online (happens on ubareset), so we put it offline 252 * first. 253 */ 254 s = splimp(); 255 addr->il_csr = ILC_RESET; 256 if (ilwait(ui, "hardware diag")) { 257 is->is_if.if_flags &= ~IFF_UP; 258 splx(s); 259 return; 260 } 261 addr->il_csr = ILC_CISA; 262 while ((addr->il_csr & IL_CDONE) == 0) 263 ; 264 /* 265 * If we must reprogram this board's physical ethernet 266 * address (as for secondary XNS interfaces), we do so 267 * before putting it on line, and starting receive requests. 268 * If you try this on an older 1010 board, it will total 269 * wedge the board. 270 */ 271 if (is->is_flags & ILF_SETADDR) { 272 bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_isu, 273 sizeof is->is_addr); 274 addr->il_bar = is->is_ubaddr & 0xffff; 275 addr->il_bcr = sizeof is->is_addr; 276 addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA; 277 if (ilwait(ui, "setaddr")) 278 return; 279 addr->il_bar = is->is_ubaddr & 0xffff; 280 addr->il_bcr = sizeof (struct il_stats); 281 addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; 282 if (ilwait(ui, "verifying setaddr")) 283 return; 284 if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, 285 sizeof (is->is_addr)) != 0) { 286 printf("il%d: setaddr didn't work\n", ui->ui_unit); 287 return; 288 } 289 } 290 #ifdef MULTICAST 291 if (is->is_if.if_flags & IFF_PROMISC) { 292 addr->il_csr = ILC_PRMSC; 293 if (ilwait(ui, "all multi")) 294 return; 295 } else if (is->is_if.if_flags & IFF_ALLMULTI) { 296 too_many_multis: 297 addr->il_csr = ILC_ALLMC; 298 if (ilwait(ui, "all multi")) 299 return; 300 else { 301 int i; 302 register struct ether_addr *ep = is->is_maddrs; 303 struct ether_multi *enm; 304 struct ether_multistep step; 305 /* 306 * Step through our list of multicast addresses. If we have 307 * too many multicast addresses, or if we have to listen to 308 * a range of multicast addresses, turn on reception of all 309 * multicasts. 310 */ 311 i = 0; 312 ETHER_FIRST_MULTI(step, &is->is_ac, enm); 313 while (enm != NULL) { 314 if (++i > 63 && k != 0) { 315 break; 316 } 317 *ep++ = *(struct ether_addr *)enm->enm_addrlo; 318 ETHER_NEXT_MULTI(step, enm); 319 } 320 if (i = 0) { 321 /* no multicasts! */ 322 } else if (i <= 63) { 323 addr->il_bar = is->is_ubaddr & 0xffff; 324 addr->il_bcr = i * sizeof (struct ether_addr); 325 addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)| 326 LC_LDGRPS; 327 if (ilwait(ui, "load multi")) 328 return; 329 } else { 330 is->is_if.if_flags |= IFF_ALLMULTI; 331 goto too_many_multis; 332 } 333 } 334 #endif MULTI 335 /* 336 * Set board online. 337 * Hang receive buffer and start any pending 338 * writes by faking a transmit complete. 339 * Receive bcr is not a multiple of 8 so buffer 340 * chaining can't happen. 341 */ 342 addr->il_csr = ILC_ONLINE; 343 while ((addr->il_csr & IL_CDONE) == 0) 344 ; 345 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 346 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 347 addr->il_csr = 348 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 349 while ((addr->il_csr & IL_CDONE) == 0) 350 ; 351 is->is_if.if_flags = IFF_OACTIVE; 352 is->is_if.if_flags |= IFF_RUNNING; 353 is->is_flags |= ILF_RUNNING; 354 is->is_lastcmd = 0; 355 ilcint(unit); 356 splx(s); 357 } 358 359 /* 360 * Start output on interface. 361 * Get another datagram to send off of the interface queue, 362 * and map it to the interface before starting the output. 363 */ 364 ilstart(ifp) 365 register struct ifnet *ifp; 366 { 367 int unit = ifp->if_unit, len; 368 struct uba_device *ui = ilinfo[unit]; 369 register struct il_softc *is = &il_softc[unit]; 370 register struct ildevice *addr; 371 struct mbuf *m; 372 short csr; 373 374 IF_DEQUEUE(&is->is_if.if_snd, m); 375 addr = (struct ildevice *)ui->ui_addr; 376 if (m == 0) { 377 if ((is->is_flags & ILF_STATPENDING) == 0) 378 return (0); 379 addr->il_bar = is->is_ubaddr & 0xffff; 380 addr->il_bcr = sizeof (struct il_stats); 381 csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE; 382 is->is_flags &= ~ILF_STATPENDING; 383 goto startcmd; 384 } 385 len = if_wubaput(&is->is_ifuba, m); 386 /* 387 * Ensure minimum packet length. 388 * This makes the safe assumtion that there are no virtual holes 389 * after the data. 390 * For security, it might be wise to zero out the added bytes, 391 * but we're mainly interested in speed at the moment. 392 */ 393 if (len - sizeof(struct ether_header) < ETHERMIN) 394 len = ETHERMIN + sizeof(struct ether_header); 395 if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) 396 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); 397 addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; 398 addr->il_bcr = len; 399 csr = 400 ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; 401 402 startcmd: 403 is->is_lastcmd = csr & IL_CMD; 404 addr->il_csr = csr; 405 is->is_if.if_flags |= IFF_OACTIVE; 406 return (0); 407 } 408 409 /* 410 * Command done interrupt. 411 */ 412 ilcint(unit) 413 int unit; 414 { 415 register struct il_softc *is = &il_softc[unit]; 416 struct uba_device *ui = ilinfo[unit]; 417 register struct ildevice *addr = (struct ildevice *)ui->ui_addr; 418 short csr; 419 420 if ((is->is_if.if_flags & IFF_OACTIVE) == 0) { 421 printf("il%d: stray xmit interrupt, csr=%b\n", unit, 422 addr->il_csr, IL_BITS); 423 return; 424 } 425 426 csr = addr->il_csr; 427 /* 428 * Hang receive buffer if it couldn't 429 * be done earlier (in ilrint). 430 */ 431 if (is->is_flags & ILF_RCVPENDING) { 432 int s; 433 434 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 435 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 436 addr->il_csr = 437 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 438 s = splhigh(); 439 while ((addr->il_csr & IL_CDONE) == 0) 440 ; 441 splx(s); 442 is->is_flags &= ~ILF_RCVPENDING; 443 } 444 is->is_if.if_flags &= ~IFF_OACTIVE; 445 csr &= IL_STATUS; 446 switch (is->is_lastcmd) { 447 448 case ILC_XMIT: 449 is->is_if.if_opackets++; 450 if (csr > ILERR_RETRIES) 451 is->is_if.if_oerrors++; 452 break; 453 454 case ILC_STAT: 455 if (csr == ILERR_SUCCESS) 456 iltotal(is); 457 break; 458 } 459 if (is->is_ifuba.ifu_xtofree) { 460 m_freem(is->is_ifuba.ifu_xtofree); 461 is->is_ifuba.ifu_xtofree = 0; 462 } 463 (void) ilstart(&is->is_if); 464 } 465 466 /* 467 * Ethernet interface receiver interrupt. 468 * If input error just drop packet. 469 * Otherwise purge input buffered data path and examine 470 * packet to determine type. If can't determine length 471 * from type, then have to drop packet. Othewise decapsulate 472 * packet based on type and pass to type specific higher-level 473 * input routine. 474 */ 475 ilrint(unit) 476 int unit; 477 { 478 register struct il_softc *is = &il_softc[unit]; 479 struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr; 480 register struct il_rheader *il; 481 struct mbuf *m; 482 int len, off, resid, s; 483 register struct ifqueue *inq; 484 485 is->is_if.if_ipackets++; 486 if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) 487 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp); 488 il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr); 489 len = il->ilr_length - sizeof(struct il_rheader); 490 if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 || 491 len > ETHERMTU) { 492 is->is_if.if_ierrors++; 493 #ifdef notdef 494 if (is->is_if.if_ierrors % 100 == 0) 495 printf("il%d: += 100 input errors\n", unit); 496 #endif 497 goto setup; 498 } 499 500 /* 501 * Deal with trailer protocol: if type is trailer type 502 * get true type from first 16-bit word past data. 503 * Remember that type was trailer by setting off. 504 */ 505 il->ilr_type = ntohs((u_short)il->ilr_type); 506 #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) 507 if (il->ilr_type >= ETHERTYPE_TRAIL && 508 il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 509 off = (il->ilr_type - ETHERTYPE_TRAIL) * 512; 510 if (off >= ETHERMTU) 511 goto setup; /* sanity */ 512 il->ilr_type = ntohs(*ildataaddr(il, off, u_short *)); 513 resid = ntohs(*(ildataaddr(il, off+2, u_short *))); 514 if (off + resid > len) 515 goto setup; /* sanity */ 516 len = off + resid; 517 } else 518 off = 0; 519 if (len == 0) 520 goto setup; 521 522 /* 523 * Pull packet off interface. Off is nonzero if packet 524 * has trailing header; ilget will then force this header 525 * information to be at the front, but we still have to drop 526 * the type and length which are at the front of any trailer data. 527 */ 528 m = if_rubaget(&is->is_ifuba, len, off, &is->is_if); 529 if (m) 530 ether_input(&is->is_if, (struct ether_header *)il->ilr_dhost, m); 531 setup: 532 /* 533 * Reset for next packet if possible. 534 * If waiting for transmit command completion, set flag 535 * and wait until command completes. 536 */ 537 if (is->is_if.if_flags & IFF_OACTIVE) { 538 is->is_flags |= ILF_RCVPENDING; 539 return; 540 } 541 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 542 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 543 addr->il_csr = 544 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 545 s = splhigh(); 546 while ((addr->il_csr & IL_CDONE) == 0) 547 ; 548 splx(s); 549 } 550 /* 551 * Watchdog routine, request statistics from board. 552 */ 553 ilwatch(unit) 554 int unit; 555 { 556 register struct il_softc *is = &il_softc[unit]; 557 register struct ifnet *ifp = &is->is_if; 558 int s; 559 560 if (is->is_flags & ILF_STATPENDING) { 561 ifp->if_timer = is->is_scaninterval; 562 return; 563 } 564 s = splimp(); 565 is->is_flags |= ILF_STATPENDING; 566 if ((is->is_if.if_flags & IFF_OACTIVE) == 0) 567 (void) ilstart(ifp); 568 splx(s); 569 ifp->if_timer = is->is_scaninterval; 570 } 571 572 /* 573 * Total up the on-board statistics. 574 */ 575 iltotal(is) 576 register struct il_softc *is; 577 { 578 register u_short *interval, *sum, *end; 579 580 interval = &is->is_stats.ils_frames; 581 sum = &is->is_sum.ils_frames; 582 end = is->is_sum.ils_fill2; 583 while (sum < end) 584 *sum++ += *interval++; 585 is->is_if.if_collisions = is->is_sum.ils_collis; 586 if ((is->is_flags & ILF_SETADDR) && 587 (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, 588 sizeof (is->is_addr)) != 0)) { 589 log(LOG_ERR, "il%d: physaddr reverted\n", is->is_if.if_unit); 590 is->is_flags &= ~ILF_RUNNING; 591 ilinit(is->is_if.if_unit); 592 } 593 } 594 595 /* 596 * Process an ioctl request. 597 */ 598 ilioctl(ifp, cmd, data) 599 register struct ifnet *ifp; 600 int cmd; 601 caddr_t data; 602 { 603 register struct ifaddr *ifa = (struct ifaddr *)data; 604 register struct il_softc *is = &il_softc[ifp->if_unit]; 605 int s = splimp(), error = 0; 606 607 switch (cmd) { 608 609 case SIOCSIFADDR: 610 ifp->if_flags |= IFF_UP; 611 ilinit(ifp->if_unit); 612 613 switch (ifa->ifa_addr->sa_family) { 614 #ifdef INET 615 case AF_INET: 616 ((struct arpcom *)ifp)->ac_ipaddr = 617 IA_SIN(ifa)->sin_addr; 618 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 619 break; 620 #endif 621 #ifdef NS 622 case AF_NS: 623 { 624 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 625 626 if (ns_nullhost(*ina)) { 627 ina->x_host = * (union ns_host *) 628 (il_softc[ifp->if_unit].is_addr); 629 } else { 630 il_setaddr(ina->x_host.c_host, ifp->if_unit); 631 return (0); 632 } 633 break; 634 } 635 #endif 636 } 637 break; 638 639 case SIOCSIFFLAGS: 640 if ((ifp->if_flags & IFF_UP) == 0 && 641 is->is_flags & ILF_RUNNING) { 642 ((struct ildevice *) 643 (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET; 644 is->is_flags &= ~ILF_RUNNING; 645 } else if (ifp->if_flags & IFF_UP && 646 (is->is_flags & ILF_RUNNING) == 0) 647 ilinit(ifp->if_unit); 648 break; 649 650 default: 651 error = EINVAL; 652 } 653 splx(s); 654 return (error); 655 } 656 657 /* 658 * set ethernet address for unit 659 */ 660 il_setaddr(physaddr, unit) 661 u_char *physaddr; 662 int unit; 663 { 664 register struct il_softc *is = &il_softc[unit]; 665 666 if (! (is->is_flags & ILF_RUNNING)) 667 return; 668 669 bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr); 670 is->is_flags &= ~ILF_RUNNING; 671 is->is_flags |= ILF_SETADDR; 672 ilinit(unit); 673 } 674 #endif 675