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