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