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