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.6 (Berkeley) 08/31/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_RUNNING | IFF_OACTIVE; 352 is->is_flags |= ILF_RUNNING; 353 is->is_lastcmd = 0; 354 ilcint(unit); 355 splx(s); 356 } 357 358 /* 359 * Start output on interface. 360 * Get another datagram to send off of the interface queue, 361 * and map it to the interface before starting the output. 362 */ 363 ilstart(ifp) 364 register struct ifnet *ifp; 365 { 366 int unit = ifp->if_unit, len; 367 struct uba_device *ui = ilinfo[unit]; 368 register struct il_softc *is = &il_softc[unit]; 369 register struct ildevice *addr; 370 struct mbuf *m; 371 short csr; 372 373 IF_DEQUEUE(&is->is_if.if_snd, m); 374 addr = (struct ildevice *)ui->ui_addr; 375 if (m == 0) { 376 if ((is->is_flags & ILF_STATPENDING) == 0) 377 return (0); 378 addr->il_bar = is->is_ubaddr & 0xffff; 379 addr->il_bcr = sizeof (struct il_stats); 380 csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE; 381 is->is_flags &= ~ILF_STATPENDING; 382 goto startcmd; 383 } 384 len = if_wubaput(&is->is_ifuba, m); 385 /* 386 * Ensure minimum packet length. 387 * This makes the safe assumtion that there are no virtual holes 388 * after the data. 389 * For security, it might be wise to zero out the added bytes, 390 * but we're mainly interested in speed at the moment. 391 */ 392 if (len - sizeof(struct ether_header) < ETHERMIN) 393 len = ETHERMIN + sizeof(struct ether_header); 394 if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) 395 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); 396 addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; 397 addr->il_bcr = len; 398 csr = 399 ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; 400 401 startcmd: 402 is->is_lastcmd = csr & IL_CMD; 403 addr->il_csr = csr; 404 is->is_if.if_flags |= IFF_OACTIVE; 405 return (0); 406 } 407 408 /* 409 * Command done interrupt. 410 */ 411 ilcint(unit) 412 int unit; 413 { 414 register struct il_softc *is = &il_softc[unit]; 415 struct uba_device *ui = ilinfo[unit]; 416 register struct ildevice *addr = (struct ildevice *)ui->ui_addr; 417 short csr; 418 419 if ((is->is_if.if_flags & IFF_OACTIVE) == 0) { 420 printf("il%d: stray xmit interrupt, csr=%b\n", unit, 421 addr->il_csr, IL_BITS); 422 return; 423 } 424 425 csr = addr->il_csr; 426 /* 427 * Hang receive buffer if it couldn't 428 * be done earlier (in ilrint). 429 */ 430 if (is->is_flags & ILF_RCVPENDING) { 431 int s; 432 433 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 434 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 435 addr->il_csr = 436 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 437 s = splhigh(); 438 while ((addr->il_csr & IL_CDONE) == 0) 439 ; 440 splx(s); 441 is->is_flags &= ~ILF_RCVPENDING; 442 } 443 is->is_if.if_flags &= ~IFF_OACTIVE; 444 csr &= IL_STATUS; 445 switch (is->is_lastcmd) { 446 447 case ILC_XMIT: 448 is->is_if.if_opackets++; 449 if (csr > ILERR_RETRIES) 450 is->is_if.if_oerrors++; 451 break; 452 453 case ILC_STAT: 454 if (csr == ILERR_SUCCESS) 455 iltotal(is); 456 break; 457 } 458 if (is->is_ifuba.ifu_xtofree) { 459 m_freem(is->is_ifuba.ifu_xtofree); 460 is->is_ifuba.ifu_xtofree = 0; 461 } 462 (void) ilstart(&is->is_if); 463 } 464 465 /* 466 * Ethernet interface receiver interrupt. 467 * If input error just drop packet. 468 * Otherwise purge input buffered data path and examine 469 * packet to determine type. If can't determine length 470 * from type, then have to drop packet. Othewise decapsulate 471 * packet based on type and pass to type specific higher-level 472 * input routine. 473 */ 474 ilrint(unit) 475 int unit; 476 { 477 register struct il_softc *is = &il_softc[unit]; 478 struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr; 479 register struct il_rheader *il; 480 struct mbuf *m; 481 int len, off, resid, s; 482 register struct ifqueue *inq; 483 484 is->is_if.if_ipackets++; 485 if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) 486 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp); 487 il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr); 488 len = il->ilr_length - sizeof(struct il_rheader); 489 if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 || 490 len > ETHERMTU) { 491 is->is_if.if_ierrors++; 492 #ifdef notdef 493 if (is->is_if.if_ierrors % 100 == 0) 494 printf("il%d: += 100 input errors\n", unit); 495 #endif 496 goto setup; 497 } 498 499 /* 500 * Deal with trailer protocol: if type is trailer type 501 * get true type from first 16-bit word past data. 502 * Remember that type was trailer by setting off. 503 */ 504 il->ilr_type = ntohs((u_short)il->ilr_type); 505 #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) 506 if (il->ilr_type >= ETHERTYPE_TRAIL && 507 il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 508 off = (il->ilr_type - ETHERTYPE_TRAIL) * 512; 509 if (off >= ETHERMTU) 510 goto setup; /* sanity */ 511 il->ilr_type = ntohs(*ildataaddr(il, off, u_short *)); 512 resid = ntohs(*(ildataaddr(il, off+2, u_short *))); 513 if (off + resid > len) 514 goto setup; /* sanity */ 515 len = off + resid; 516 } else 517 off = 0; 518 if (len == 0) 519 goto setup; 520 521 /* 522 * Pull packet off interface. Off is nonzero if packet 523 * has trailing header; ilget will then force this header 524 * information to be at the front, but we still have to drop 525 * the type and length which are at the front of any trailer data. 526 */ 527 m = if_rubaget(&is->is_ifuba, len, off, &is->is_if); 528 if (m) 529 ether_input(&is->is_if, (struct ether_header *)il->ilr_dhost, m); 530 setup: 531 /* 532 * Reset for next packet if possible. 533 * If waiting for transmit command completion, set flag 534 * and wait until command completes. 535 */ 536 if (is->is_if.if_flags & IFF_OACTIVE) { 537 is->is_flags |= ILF_RCVPENDING; 538 return; 539 } 540 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 541 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 542 addr->il_csr = 543 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 544 s = splhigh(); 545 while ((addr->il_csr & IL_CDONE) == 0) 546 ; 547 splx(s); 548 } 549 /* 550 * Watchdog routine, request statistics from board. 551 */ 552 ilwatch(unit) 553 int unit; 554 { 555 register struct il_softc *is = &il_softc[unit]; 556 register struct ifnet *ifp = &is->is_if; 557 int s; 558 559 if (is->is_flags & ILF_STATPENDING) { 560 ifp->if_timer = is->is_scaninterval; 561 return; 562 } 563 s = splimp(); 564 is->is_flags |= ILF_STATPENDING; 565 if ((is->is_if.if_flags & IFF_OACTIVE) == 0) 566 (void) ilstart(ifp); 567 splx(s); 568 ifp->if_timer = is->is_scaninterval; 569 } 570 571 /* 572 * Total up the on-board statistics. 573 */ 574 iltotal(is) 575 register struct il_softc *is; 576 { 577 register u_short *interval, *sum, *end; 578 579 interval = &is->is_stats.ils_frames; 580 sum = &is->is_sum.ils_frames; 581 end = is->is_sum.ils_fill2; 582 while (sum < end) 583 *sum++ += *interval++; 584 is->is_if.if_collisions = is->is_sum.ils_collis; 585 if ((is->is_flags & ILF_SETADDR) && 586 (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, 587 sizeof (is->is_addr)) != 0)) { 588 log(LOG_ERR, "il%d: physaddr reverted\n", is->is_if.if_unit); 589 is->is_flags &= ~ILF_RUNNING; 590 ilinit(is->is_if.if_unit); 591 } 592 } 593 594 /* 595 * Process an ioctl request. 596 */ 597 ilioctl(ifp, cmd, data) 598 register struct ifnet *ifp; 599 int cmd; 600 caddr_t data; 601 { 602 register struct ifaddr *ifa = (struct ifaddr *)data; 603 register struct il_softc *is = &il_softc[ifp->if_unit]; 604 int s = splimp(), error = 0; 605 606 switch (cmd) { 607 608 case SIOCSIFADDR: 609 ifp->if_flags |= IFF_UP; 610 ilinit(ifp->if_unit); 611 612 switch (ifa->ifa_addr->sa_family) { 613 #ifdef INET 614 case AF_INET: 615 ((struct arpcom *)ifp)->ac_ipaddr = 616 IA_SIN(ifa)->sin_addr; 617 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 618 break; 619 #endif 620 #ifdef NS 621 case AF_NS: 622 { 623 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 624 625 if (ns_nullhost(*ina)) { 626 ina->x_host = * (union ns_host *) 627 (il_softc[ifp->if_unit].is_addr); 628 } else { 629 il_setaddr(ina->x_host.c_host, ifp->if_unit); 630 return (0); 631 } 632 break; 633 } 634 #endif 635 } 636 break; 637 638 case SIOCSIFFLAGS: 639 if ((ifp->if_flags & IFF_UP) == 0 && 640 is->is_flags & ILF_RUNNING) { 641 ((struct ildevice *) 642 (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET; 643 is->is_flags &= ~ILF_RUNNING; 644 } else if (ifp->if_flags & IFF_UP && 645 (is->is_flags & ILF_RUNNING) == 0) 646 ilinit(ifp->if_unit); 647 break; 648 649 default: 650 error = EINVAL; 651 } 652 splx(s); 653 return (error); 654 } 655 656 /* 657 * set ethernet address for unit 658 */ 659 il_setaddr(physaddr, unit) 660 u_char *physaddr; 661 int unit; 662 { 663 register struct il_softc *is = &il_softc[unit]; 664 665 if (! (is->is_flags & ILF_RUNNING)) 666 return; 667 668 bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr); 669 is->is_flags &= ~ILF_RUNNING; 670 is->is_flags |= ILF_SETADDR; 671 ilinit(unit); 672 } 673 #endif 674