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