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