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