|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)if_en.c 7.7 (Berkeley) 12/16/90 ! 34: */ ! 35: ! 36: #include "en.h" ! 37: #if NEN > 0 ! 38: ! 39: /* ! 40: * Xerox prototype (3 Mb) Ethernet interface driver. ! 41: */ ! 42: #include "../include/pte.h" ! 43: ! 44: #include "sys/param.h" ! 45: #include "sys/systm.h" ! 46: #include "sys/mbuf.h" ! 47: #include "sys/buf.h" ! 48: #include "sys/protosw.h" ! 49: #include "sys/socket.h" ! 50: #include "sys/vmmac.h" ! 51: #include "sys/errno.h" ! 52: #include "sys/ioctl.h" ! 53: ! 54: #include "net/if.h" ! 55: #include "net/netisr.h" ! 56: #include "net/route.h" ! 57: ! 58: #ifdef INET ! 59: #include "netinet/in.h" ! 60: #include "netinet/in_systm.h" ! 61: #include "netinet/in_var.h" ! 62: #include "netinet/ip.h" ! 63: #endif ! 64: ! 65: #ifdef PUP ! 66: #include "netpup/pup.h" ! 67: #include "netpup/ether.h" ! 68: #endif ! 69: ! 70: #ifdef NS ! 71: #include "netns/ns.h" ! 72: #include "netns/ns_if.h" ! 73: #endif ! 74: ! 75: #include "../include/cpu.h" ! 76: #include "../include/mtpr.h" ! 77: #include "if_en.h" ! 78: #include "if_enreg.h" ! 79: #include "if_uba.h" ! 80: #include "../uba/ubareg.h" ! 81: #include "../uba/ubavar.h" ! 82: ! 83: #define ENMTU (1024+512) ! 84: #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */ ! 85: ! 86: int enprobe(), enattach(), enrint(), enxint(), encollide(); ! 87: struct uba_device *eninfo[NEN]; ! 88: u_short enstd[] = { 0 }; ! 89: struct uba_driver endriver = ! 90: { enprobe, 0, enattach, 0, enstd, "en", eninfo }; ! 91: #define ENUNIT(x) minor(x) ! 92: ! 93: int eninit(),oldenoutput(),enreset(),enioctl(), enstart(); ! 94: ! 95: #ifdef notdef ! 96: /* ! 97: * If you need to byte swap IP's in the system, define ! 98: * this and do a SIOCSIFFLAGS at boot time. ! 99: */ ! 100: #define ENF_SWABIPS 0x1000 ! 101: #endif ! 102: ! 103: /* ! 104: * Ethernet software status per interface. ! 105: * ! 106: * Each interface is referenced by a network interface structure, ! 107: * es_if, which the routing code uses to locate the interface. ! 108: * This structure contains the output queue for the interface, its address, ... ! 109: * We also have, for each interface, a UBA interface structure, which ! 110: * contains information about the UNIBUS resources held by the interface: ! 111: * map registers, buffered data paths, etc. Information is cached in this ! 112: * structure for use by the if_uba.c routines in running the interface ! 113: * efficiently. ! 114: */ ! 115: struct en_softc { ! 116: struct ifnet es_if; /* network-visible interface */ ! 117: struct ifuba es_ifuba; /* UNIBUS resources */ ! 118: short es_host; /* hardware host number */ ! 119: short es_delay; /* current output delay */ ! 120: short es_mask; /* mask for current output delay */ ! 121: short es_lastx; /* host last transmitted to */ ! 122: short es_oactive; /* is output active? */ ! 123: short es_olen; /* length of last output */ ! 124: short es_nsactive; /* is interface enabled for ns? */ ! 125: } en_softc[NEN]; ! 126: ! 127: /* ! 128: * Do output DMA to determine interface presence and ! 129: * interrupt vector. DMA is too short to disturb other hosts. ! 130: */ ! 131: enprobe(reg) ! 132: caddr_t reg; ! 133: { ! 134: register int br, cvec; /* r11, r10 value-result */ ! 135: register struct endevice *addr = (struct endevice *)reg; ! 136: ! 137: #ifdef lint ! 138: br = 0; cvec = br; br = cvec; ! 139: enrint(0); enxint(0); encollide(0); ! 140: #endif ! 141: addr->en_istat = 0; ! 142: addr->en_owc = -1; ! 143: addr->en_oba = 0; ! 144: addr->en_ostat = EN_IEN|EN_GO; ! 145: DELAY(100000); ! 146: addr->en_ostat = 0; ! 147: return (1); ! 148: } ! 149: ! 150: /* ! 151: * Interface exists: make available by filling in network interface ! 152: * record. System will initialize the interface when it is ready ! 153: * to accept packets. ! 154: */ ! 155: enattach(ui) ! 156: struct uba_device *ui; ! 157: { ! 158: register struct en_softc *es = &en_softc[ui->ui_unit]; ! 159: ! 160: es->es_if.if_unit = ui->ui_unit; ! 161: es->es_if.if_name = "en"; ! 162: es->es_if.if_mtu = ENMTU; ! 163: es->es_if.if_flags = IFF_BROADCAST; ! 164: es->es_if.if_init = eninit; ! 165: es->es_if.if_output = oldenoutput; ! 166: es->es_if.if_start = enstart; ! 167: es->es_if.if_ioctl = enioctl; ! 168: es->es_if.if_reset = enreset; ! 169: es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT; ! 170: #if defined(VAX750) ! 171: /* don't chew up 750 bdp's */ ! 172: if (cpu == VAX_750 && ui->ui_unit > 0) ! 173: es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP; ! 174: #endif ! 175: if_attach(&es->es_if); ! 176: } ! 177: ! 178: /* ! 179: * Reset of interface after UNIBUS reset. ! 180: * If interface is on specified uba, reset its state. ! 181: */ ! 182: enreset(unit, uban) ! 183: int unit, uban; ! 184: { ! 185: register struct uba_device *ui; ! 186: ! 187: if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || ! 188: ui->ui_ubanum != uban) ! 189: return; ! 190: printf(" en%d", unit); ! 191: eninit(unit); ! 192: } ! 193: ! 194: /* ! 195: * Initialization of interface; clear recorded pending ! 196: * operations, and reinitialize UNIBUS usage. ! 197: */ ! 198: eninit(unit) ! 199: int unit; ! 200: { ! 201: register struct en_softc *es = &en_softc[unit]; ! 202: register struct uba_device *ui = eninfo[unit]; ! 203: register struct endevice *addr; ! 204: int s; ! 205: ! 206: if (es->es_if.if_addrlist == (struct ifaddr *)0) ! 207: return; ! 208: if (if_ubainit(&es->es_ifuba, ui->ui_ubanum, ! 209: sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { ! 210: printf("en%d: can't initialize\n", unit); ! 211: es->es_if.if_flags &= ~IFF_UP; ! 212: return; ! 213: } ! 214: addr = (struct endevice *)ui->ui_addr; ! 215: addr->en_istat = addr->en_ostat = 0; ! 216: ! 217: /* ! 218: * Hang a receive and start any ! 219: * pending writes by faking a transmit complete. ! 220: */ ! 221: s = splimp(); ! 222: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; ! 223: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; ! 224: addr->en_istat = EN_IEN|EN_GO; ! 225: es->es_oactive = 1; ! 226: es->es_if.if_flags |= IFF_RUNNING; ! 227: enxint(unit); ! 228: splx(s); ! 229: } ! 230: ! 231: int enalldelay = 0; ! 232: int enlastdel = 50; ! 233: int enlastmask = (~0) << 5; ! 234: ! 235: /* ! 236: * Start or restart output on interface. ! 237: * If interface is already active, then this is a retransmit ! 238: * after a collision, and just restuff registers and delay. ! 239: * If interface is not already active, get another datagram ! 240: * to send off of the interface queue, and map it to the interface ! 241: * before starting the output. ! 242: */ ! 243: enstart(dev) ! 244: dev_t dev; ! 245: { ! 246: int unit = ENUNIT(dev); ! 247: struct uba_device *ui = eninfo[unit]; ! 248: register struct en_softc *es = &en_softc[unit]; ! 249: register struct endevice *addr; ! 250: register struct en_header *en; ! 251: struct mbuf *m; ! 252: int dest; ! 253: ! 254: if (es->es_oactive) ! 255: goto restart; ! 256: ! 257: /* ! 258: * Not already active: dequeue another request ! 259: * and map it to the UNIBUS. If no more requests, ! 260: * just return. ! 261: */ ! 262: IF_DEQUEUE(&es->es_if.if_snd, m); ! 263: if (m == 0) { ! 264: es->es_oactive = 0; ! 265: return; ! 266: } ! 267: en = mtod(m, struct en_header *); ! 268: dest = en->en_dhost; ! 269: en->en_shost = es->es_host; ! 270: es->es_olen = if_wubaput(&es->es_ifuba, m); ! 271: #ifdef ENF_SWABIPS ! 272: /* ! 273: * The Xerox interface does word at a time DMA, so ! 274: * someone must do byte swapping of user data if high ! 275: * and low ender machines are to communicate. It doesn't ! 276: * belong here, but certain people depend on it, so... ! 277: * ! 278: * Should swab everybody, but this is a kludge anyway. ! 279: */ ! 280: if (es->es_if.if_flags & ENF_SWABIPS) { ! 281: en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr; ! 282: if (en->en_type == ENTYPE_IP) ! 283: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), ! 284: es->es_olen - sizeof (struct en_header) + 1); ! 285: } ! 286: #endif ! 287: ! 288: /* ! 289: * Ethernet cannot take back-to-back packets (no ! 290: * buffering in interface. To help avoid overrunning ! 291: * receivers, enforce a small delay (about 1ms) in interface: ! 292: * * between all packets when enalldelay ! 293: * * whenever last packet was broadcast ! 294: * * whenever this packet is to same host as last packet ! 295: */ ! 296: if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) { ! 297: es->es_delay = enlastdel; ! 298: es->es_mask = enlastmask; ! 299: } ! 300: es->es_lastx = dest; ! 301: ! 302: restart: ! 303: /* ! 304: * Have request mapped to UNIBUS for transmission. ! 305: * Purge any stale data from this BDP, and start the otput. ! 306: */ ! 307: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) ! 308: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp); ! 309: addr = (struct endevice *)ui->ui_addr; ! 310: addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info; ! 311: addr->en_odelay = es->es_delay; ! 312: addr->en_owc = -((es->es_olen + 1) >> 1); ! 313: addr->en_ostat = EN_IEN|EN_GO; ! 314: es->es_oactive = 1; ! 315: } ! 316: ! 317: /* ! 318: * Ethernet interface transmitter interrupt. ! 319: * Start another output if more data to send. ! 320: */ ! 321: enxint(unit) ! 322: int unit; ! 323: { ! 324: register struct uba_device *ui = eninfo[unit]; ! 325: register struct en_softc *es = &en_softc[unit]; ! 326: register struct endevice *addr = (struct endevice *)ui->ui_addr; ! 327: ! 328: if (es->es_oactive == 0) ! 329: return; ! 330: if (es->es_mask && (addr->en_ostat&EN_OERROR)) { ! 331: es->es_if.if_oerrors++; ! 332: endocoll(unit); ! 333: return; ! 334: } ! 335: es->es_if.if_opackets++; ! 336: es->es_oactive = 0; ! 337: es->es_delay = 0; ! 338: es->es_mask = ~0; ! 339: if (es->es_ifuba.ifu_xtofree) { ! 340: m_freem(es->es_ifuba.ifu_xtofree); ! 341: es->es_ifuba.ifu_xtofree = 0; ! 342: } ! 343: if (es->es_if.if_snd.ifq_head == 0) { ! 344: es->es_lastx = 256; /* putatively illegal */ ! 345: return; ! 346: } ! 347: enstart(unit); ! 348: } ! 349: ! 350: /* ! 351: * Collision on ethernet interface. Do exponential ! 352: * backoff, and retransmit. If have backed off all ! 353: * the way print warning diagnostic, and drop packet. ! 354: */ ! 355: encollide(unit) ! 356: int unit; ! 357: { ! 358: struct en_softc *es = &en_softc[unit]; ! 359: ! 360: es->es_if.if_collisions++; ! 361: if (es->es_oactive == 0) ! 362: return; ! 363: endocoll(unit); ! 364: } ! 365: ! 366: endocoll(unit) ! 367: int unit; ! 368: { ! 369: register struct en_softc *es = &en_softc[unit]; ! 370: ! 371: /* ! 372: * Es_mask is a 16 bit number with n low zero bits, with ! 373: * n the number of backoffs. When es_mask is 0 we have ! 374: * backed off 16 times, and give up. ! 375: */ ! 376: if (es->es_mask == 0) { ! 377: printf("en%d: send error\n", unit); ! 378: enxint(unit); ! 379: return; ! 380: } ! 381: /* ! 382: * Another backoff. Restart with delay based on n low bits ! 383: * of the interval timer. ! 384: */ ! 385: es->es_mask <<= 1; ! 386: es->es_delay = mfpr(ICR) &~ es->es_mask; ! 387: enstart(unit); ! 388: } ! 389: ! 390: #ifdef notdef ! 391: struct sockproto enproto = { AF_ETHERLINK }; ! 392: struct sockaddr_en endst = { sizeof(endst), AF_ETHERLINK }; ! 393: struct sockaddr_en ensrc = { sizeof(ensrc), AF_ETHERLINK }; ! 394: #endif ! 395: /* ! 396: * Ethernet interface receiver interrupt. ! 397: * If input error just drop packet. ! 398: * Otherwise purge input buffered data path and examine ! 399: * packet to determine type. If can't determine length ! 400: * from type, then have to drop packet. Othewise decapsulate ! 401: * packet based on type and pass to type specific higher-level ! 402: * input routine. ! 403: */ ! 404: enrint(unit) ! 405: int unit; ! 406: { ! 407: register struct en_softc *es = &en_softc[unit]; ! 408: struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr; ! 409: register struct en_header *en; ! 410: struct mbuf *m; ! 411: int len; short resid; ! 412: register struct ifqueue *inq; ! 413: int off, s; ! 414: ! 415: es->es_if.if_ipackets++; ! 416: ! 417: /* ! 418: * Purge BDP; drop if input error indicated. ! 419: */ ! 420: if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) ! 421: UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp); ! 422: if (addr->en_istat&EN_IERROR) { ! 423: es->es_if.if_ierrors++; ! 424: goto setup; ! 425: } ! 426: ! 427: /* ! 428: * Calculate input data length. ! 429: * Get pointer to ethernet header (in input buffer). ! 430: * Deal with trailer protocol: if type is PUP trailer ! 431: * get true type from first 16-bit word past data. ! 432: * Remember that type was trailer by setting off. ! 433: */ ! 434: resid = addr->en_iwc; ! 435: if (resid) ! 436: resid |= 0176000; ! 437: len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1; ! 438: len -= sizeof (struct en_header); ! 439: if (len > ENMRU) ! 440: goto setup; /* sanity */ ! 441: en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr); ! 442: en->en_type = ntohs(en->en_type); ! 443: #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) ! 444: if (en->en_type >= ENTYPE_TRAIL && ! 445: en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) { ! 446: off = (en->en_type - ENTYPE_TRAIL) * 512; ! 447: if (off > ENMTU) ! 448: goto setup; /* sanity */ ! 449: en->en_type = ntohs(*endataaddr(en, off, u_short *)); ! 450: resid = ntohs(*(endataaddr(en, off+2, u_short *))); ! 451: if (off + resid > len) ! 452: goto setup; /* sanity */ ! 453: len = off + resid; ! 454: } else ! 455: off = 0; ! 456: if (len == 0) ! 457: goto setup; ! 458: #ifdef ENF_SWABIPS ! 459: if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP) ! 460: enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len); ! 461: #endif ! 462: /* ! 463: * Pull packet off interface. Off is nonzero if packet ! 464: * has trailing header; if_rubaget will then force this header ! 465: * information to be at the front, but we still have to drop ! 466: * the type and length which are at the front of any trailer data. ! 467: */ ! 468: m = if_rubaget(&es->es_ifuba, len, off, &es->es_if); ! 469: if (m == 0) ! 470: goto setup; ! 471: switch (en->en_type) { ! 472: ! 473: #ifdef INET ! 474: case ENTYPE_IP: ! 475: schednetisr(NETISR_IP); ! 476: inq = &ipintrq; ! 477: break; ! 478: #endif ! 479: #ifdef PUP ! 480: case ENTYPE_PUP: ! 481: rpup_input(m); ! 482: goto setup; ! 483: #endif ! 484: #ifdef NS ! 485: case ETHERTYPE_NS: ! 486: if (es->es_nsactive) { ! 487: schednetisr(NETISR_NS); ! 488: inq = &nsintrq; ! 489: } else { ! 490: m_freem(m); ! 491: goto setup; ! 492: } ! 493: break; ! 494: #endif ! 495: ! 496: default: ! 497: #ifdef notdef ! 498: enproto.sp_protocol = en->en_type; ! 499: endst.sen_host = en->en_dhost; ! 500: endst.sen_net = ensrc.sen_net = es->es_if.if_net; ! 501: ensrc.sen_host = en->en_shost; ! 502: raw_input(m, &enproto, ! 503: (struct sockaddr *)&ensrc, (struct sockaddr *)&endst); ! 504: #else ! 505: m_freem(m); ! 506: #endif ! 507: goto setup; ! 508: } ! 509: ! 510: s = splimp(); ! 511: if (IF_QFULL(inq)) { ! 512: IF_DROP(inq); ! 513: m_freem(m); ! 514: } else ! 515: IF_ENQUEUE(inq, m); ! 516: splx(s); ! 517: ! 518: setup: ! 519: /* ! 520: * Reset for next packet. ! 521: */ ! 522: addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; ! 523: addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; ! 524: addr->en_istat = EN_IEN|EN_GO; ! 525: } ! 526: ! 527: /* ! 528: * Ethernet output routine. ! 529: * Encapsulate a packet of type family for the local net. ! 530: * Use trailer local net encapsulation if enough data in first ! 531: * packet leaves a multiple of 512 bytes of data in remainder. ! 532: */ ! 533: oldenoutput(ifp, m0, dst) ! 534: struct ifnet *ifp; ! 535: struct mbuf *m0; ! 536: struct sockaddr *dst; ! 537: { ! 538: int type, dest, s, error; ! 539: register struct mbuf *m = m0; ! 540: register struct en_header *en; ! 541: register int off; ! 542: ! 543: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ! 544: error = ENETDOWN; ! 545: goto bad; ! 546: } ! 547: switch (dst->sa_family) { ! 548: ! 549: #ifdef INET ! 550: case AF_INET: ! 551: { ! 552: struct in_addr in; ! 553: ! 554: in = ((struct sockaddr_in *)dst)->sin_addr; ! 555: if (in_broadcast(in)) ! 556: dest = EN_BROADCAST; ! 557: else ! 558: dest = in_lnaof(in); ! 559: } ! 560: if (dest >= 0x100) { ! 561: error = EPERM; /* ??? */ ! 562: goto bad; ! 563: } ! 564: off = m->m_pkthdr.len - m->m_len; ! 565: /* need per host negotiation */ ! 566: if ((ifp->if_flags & IFF_NOTRAILERS) == 0) ! 567: if (off > 0 && (off & 0x1ff) == 0 && ! 568: (m->m_flags & M_EXT) == 0 && ! 569: m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) { ! 570: type = ENTYPE_TRAIL + (off>>9); ! 571: m->m_data -= 2 * sizeof (u_short); ! 572: m->m_len += 2 * sizeof (u_short); ! 573: *mtod(m, u_short *) = htons((u_short)ENTYPE_IP); ! 574: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); ! 575: goto gottrailertype; ! 576: } ! 577: type = ENTYPE_IP; ! 578: off = 0; ! 579: goto gottype; ! 580: #endif ! 581: #ifdef NS ! 582: case AF_NS: ! 583: { ! 584: u_char *up; ! 585: ! 586: type = ETHERTYPE_NS; ! 587: up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host; ! 588: if (*up & 1) ! 589: dest = EN_BROADCAST; ! 590: else ! 591: dest = up[5]; ! 592: ! 593: off = 0; ! 594: goto gottype; ! 595: } ! 596: #endif ! 597: #ifdef PUP ! 598: case AF_PUP: ! 599: dest = ((struct sockaddr_pup *)dst)->spup_host; ! 600: type = ENTYPE_PUP; ! 601: off = 0; ! 602: goto gottype; ! 603: #endif ! 604: ! 605: #ifdef notdef ! 606: case AF_ETHERLINK: ! 607: goto gotheader; ! 608: #endif ! 609: ! 610: default: ! 611: printf("en%d: can't handle af%d\n", ifp->if_unit, ! 612: dst->sa_family); ! 613: error = EAFNOSUPPORT; ! 614: goto bad; ! 615: } ! 616: ! 617: gottrailertype: ! 618: /* ! 619: * Packet to be sent as trailer: move first packet ! 620: * (control information) to end of chain. ! 621: */ ! 622: while (m->m_next) ! 623: m = m->m_next; ! 624: m->m_next = m0; ! 625: m = m0->m_next; ! 626: m0->m_next = 0; ! 627: m0 = m; ! 628: ! 629: gottype: ! 630: /* ! 631: * Add local net header. If no space in first mbuf, ! 632: * allocate another. ! 633: */ ! 634: M_PREPEND(m, sizeof (struct en_header), M_DONTWAIT); ! 635: if (m == NULL) ! 636: return (ENOBUFS); ! 637: en = mtod(m, struct en_header *); ! 638: /* add en_shost later */ ! 639: en->en_dhost = dest; ! 640: en->en_type = htons((u_short)type); ! 641: ! 642: #ifdef notdef ! 643: gotheader: ! 644: #endif ! 645: /* ! 646: * Queue message on interface, and start output if interface ! 647: * not yet active. ! 648: */ ! 649: s = splimp(); ! 650: if (IF_QFULL(&ifp->if_snd)) { ! 651: IF_DROP(&ifp->if_snd); ! 652: error = ENOBUFS; ! 653: goto qfull; ! 654: } ! 655: IF_ENQUEUE(&ifp->if_snd, m); ! 656: if (en_softc[ifp->if_unit].es_oactive == 0) ! 657: enstart(ifp->if_unit); ! 658: splx(s); ! 659: return (0); ! 660: qfull: ! 661: m0 = m; ! 662: splx(s); ! 663: bad: ! 664: m_freem(m0); ! 665: return (error); ! 666: } ! 667: ! 668: /* ! 669: * Process an ioctl request. ! 670: */ ! 671: enioctl(ifp, cmd, data) ! 672: register struct ifnet *ifp; ! 673: int cmd; ! 674: caddr_t data; ! 675: { ! 676: register struct en_softc *es = ((struct en_softc *)ifp); ! 677: struct ifaddr *ifa = (struct ifaddr *) data; ! 678: int s = splimp(), error = 0; ! 679: struct endevice *enaddr; ! 680: ! 681: switch (cmd) { ! 682: ! 683: case SIOCSIFADDR: ! 684: enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr; ! 685: es->es_host = (~enaddr->en_addr) & 0xff; ! 686: /* ! 687: * Attempt to check agreement of protocol address ! 688: * and board address. ! 689: */ ! 690: switch (ifa->ifa_addr->sa_family) { ! 691: case AF_INET: ! 692: if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host) ! 693: return (EADDRNOTAVAIL); ! 694: break; ! 695: #ifdef NS ! 696: case AF_NS: ! 697: if (IA_SNS(ifa)->sns_addr.x_host.c_host[5] ! 698: != es->es_host) ! 699: return (EADDRNOTAVAIL); ! 700: es->es_nsactive = 1; ! 701: break; ! 702: #endif ! 703: } ! 704: ifp->if_flags |= IFF_UP; ! 705: if ((ifp->if_flags & IFF_RUNNING) == 0) ! 706: eninit(ifp->if_unit); ! 707: break; ! 708: ! 709: default: ! 710: error = EINVAL; ! 711: break; ! 712: } ! 713: splx(s); ! 714: return (error); ! 715: } ! 716: ! 717: #ifdef ENF_SWABIPS ! 718: /* ! 719: * Swab bytes ! 720: * Jeffrey Mogul, Stanford ! 721: */ ! 722: enswab(from, to, n) ! 723: register unsigned char *from, *to; ! 724: register int n; ! 725: { ! 726: register unsigned long temp; ! 727: ! 728: if ((n <= 0) || (n > 0xFFFF)) { ! 729: printf("enswab: bad len %d\n", n); ! 730: return; ! 731: } ! 732: ! 733: n >>= 1; n++; ! 734: #define STEP {temp = *from++;*to++ = *from++;*to++ = temp;} ! 735: /* round to multiple of 8 */ ! 736: while ((--n) & 07) ! 737: STEP; ! 738: n >>= 3; ! 739: while (--n >= 0) { ! 740: STEP; STEP; STEP; STEP; ! 741: STEP; STEP; STEP; STEP; ! 742: } ! 743: } ! 744: #endif ! 745: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.