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