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