|
|
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.2 (Berkeley) 8/7/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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.