|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.