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: #include "enetfilter.h"
  11: #if NEN > 0
  12: 
  13: /*
  14:  * Xerox prototype (3 Mb) Ethernet interface driver.
  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 "errno.h"
  26: #include "ioctl.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: #endif
  38: 
  39: #ifdef PUP
  40: #include "../netpup/pup.h"
  41: #include "../netpup/ether.h"
  42: #endif
  43: 
  44: #ifdef NS
  45: #include "../netns/ns.h"
  46: #include "../netns/ns_if.h"
  47: #endif
  48: 
  49: #include "../vax/cpu.h"
  50: #include "../vax/mtpr.h"
  51: #include "if_en.h"
  52: #include "if_enreg.h"
  53: #include "if_uba.h"
  54: #if NENETFILTER > 0
  55: #include "../net/enet.h"
  56: #endif	NENETFILTER > 0
  57: #include "../vaxuba/ubareg.h"
  58: #include "../vaxuba/ubavar.h"
  59: 
  60: #define ENMTU   (1024+512)
  61: #define ENMRU   (1024+512+16)       /* 16 is enough to receive trailer */
  62: 
  63: int enprobe(), enattach(), enrint(), enxint(), encollide();
  64: struct  uba_device *eninfo[NEN];
  65: u_short enstd[] = { 0 };
  66: struct  uba_driver endriver =
  67:     { enprobe, 0, enattach, 0, enstd, "en", eninfo };
  68: #define ENUNIT(x)   minor(x)
  69: 
  70: int eninit(),enoutput(),enreset(),enioctl();
  71: 
  72: #ifdef notdef
  73: /*
  74:  * If you need to byte swap IP's in the system, define
  75:  * this and do a SIOCSIFFLAGS at boot time.
  76:  */
  77: #define ENF_SWABIPS 0x1000
  78: #endif
  79: 
  80: /*
  81:  * Ethernet software status per interface.
  82:  *
  83:  * Each interface is referenced by a network interface structure,
  84:  * es_if, which the routing code uses to locate the interface.
  85:  * This structure contains the output queue for the interface, its address, ...
  86:  * We also have, for each interface, a UBA interface structure, which
  87:  * contains information about the UNIBUS resources held by the interface:
  88:  * map registers, buffered data paths, etc.  Information is cached in this
  89:  * structure for use by the if_uba.c routines in running the interface
  90:  * efficiently.
  91:  */
  92: struct  en_softc {
  93:     struct  ifnet es_if;        /* network-visible interface */
  94:     struct  ifuba es_ifuba;     /* UNIBUS resources */
  95:     short   es_host;        /* hardware host number */
  96:     short   es_delay;       /* current output delay */
  97:     short   es_mask;        /* mask for current output delay */
  98:     short   es_lastx;       /* host last transmitted to */
  99:     short   es_oactive;     /* is output active? */
 100:     short   es_olen;        /* length of last output */
 101:     short   es_nsactive;        /* is interface enabled for ns? */
 102: #if NENETFILTER > 0
 103:     short   es_enetunit;        /* unit number for enet filtering */
 104: #endif	NENETFILTER > 0
 105: } en_softc[NEN];
 106: 
 107: /*
 108:  * Do output DMA to determine interface presence and
 109:  * interrupt vector.  DMA is too short to disturb other hosts.
 110:  */
 111: enprobe(reg)
 112:     caddr_t reg;
 113: {
 114:     register int br, cvec;      /* r11, r10 value-result */
 115:     register struct endevice *addr = (struct endevice *)reg;
 116: 
 117: #ifdef lint
 118:     br = 0; cvec = br; br = cvec;
 119:     enrint(0); enxint(0); encollide(0);
 120: #endif
 121:     addr->en_istat = 0;
 122:     addr->en_owc = -1;
 123:     addr->en_oba = 0;
 124:     addr->en_ostat = EN_IEN|EN_GO;
 125:     DELAY(100000);
 126:     addr->en_ostat = 0;
 127:     return (1);
 128: }
 129: 
 130: /*
 131:  * Interface exists: make available by filling in network interface
 132:  * record.  System will initialize the interface when it is ready
 133:  * to accept packets.
 134:  */
 135: enattach(ui)
 136:     struct uba_device *ui;
 137: {
 138:     register struct en_softc *es = &en_softc[ui->ui_unit];
 139: 
 140:     es->es_if.if_unit = ui->ui_unit;
 141:     es->es_if.if_name = "en";
 142:     es->es_if.if_mtu = ENMTU;
 143:     es->es_if.if_flags = IFF_BROADCAST;
 144:     es->es_if.if_init = eninit;
 145:     es->es_if.if_output = enoutput;
 146:     es->es_if.if_ioctl = enioctl;
 147:     es->es_if.if_reset = enreset;
 148:     es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
 149: #if defined(VAX750)
 150:     /* don't chew up 750 bdp's */
 151:     if (cpu == VAX_750 && ui->ui_unit > 0)
 152:         es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;
 153: #endif
 154: #if NENETFILTER > 0
 155:     {
 156:         struct endevp enp;
 157:         struct en_header dummy;
 158:         struct endevice *enaddr = (struct endevice *)ui->ui_addr;
 159: 
 160: #ifdef  SWABALL
 161:         enp.end_dev_type = ENDT_3MB;
 162: #else
 163:         enp.end_dev_type = ENDT_BS3MB;   /* packets appear byte-swapped */
 164: #endif
 165: 
 166:         enp.end_addr_len = sizeof(dummy.en_shost);
 167:         enp.end_hdr_len = sizeof(struct en_header);
 168:         enp.end_MTU = ENMTU;
 169:         enp.end_addr[0] = (~enaddr->en_addr) & 0xFF;
 170:         enp.end_broadaddr[0] = 0;
 171: 
 172:         es->es_enetunit = enetattach(&es->es_if, &enp);
 173:     }
 174: #endif NENETFILTER > 0
 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.
 276: 	 */
 277:     if (es->es_if.if_flags & ENF_SWABIPS) {
 278:         en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
 279:         enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
 280:             es->es_olen - sizeof (struct en_header) + 1);
 281:     }
 282: #endif
 283: 
 284:     /*
 285: 	 * Ethernet cannot take back-to-back packets (no
 286: 	 * buffering in interface.  To help avoid overrunning
 287: 	 * receivers, enforce a small delay (about 1ms) in interface:
 288: 	 *	* between all packets when enalldelay
 289: 	 *	* whenever last packet was broadcast
 290: 	 *	* whenever this packet is to same host as last packet
 291: 	 */
 292:     if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
 293:         es->es_delay = enlastdel;
 294:         es->es_mask = enlastmask;
 295:     }
 296:     es->es_lastx = dest;
 297: 
 298: restart:
 299:     /*
 300: 	 * Have request mapped to UNIBUS for transmission.
 301: 	 * Purge any stale data from this BDP, and start the otput.
 302: 	 */
 303:     if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
 304:         UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
 305:     addr = (struct endevice *)ui->ui_addr;
 306:     addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
 307:     addr->en_odelay = es->es_delay;
 308:     addr->en_owc = -((es->es_olen + 1) >> 1);
 309:     addr->en_ostat = EN_IEN|EN_GO;
 310:     es->es_oactive = 1;
 311: }
 312: 
 313: /*
 314:  * Ethernet interface transmitter interrupt.
 315:  * Start another output if more data to send.
 316:  */
 317: enxint(unit)
 318:     int unit;
 319: {
 320:     register struct uba_device *ui = eninfo[unit];
 321:     register struct en_softc *es = &en_softc[unit];
 322:     register struct endevice *addr = (struct endevice *)ui->ui_addr;
 323: 
 324:     if (es->es_oactive == 0)
 325:         return;
 326:     if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
 327:         es->es_if.if_oerrors++;
 328:         endocoll(unit);
 329:         return;
 330:     }
 331:     es->es_if.if_opackets++;
 332:     es->es_oactive = 0;
 333:     es->es_delay = 0;
 334:     es->es_mask = ~0;
 335:     if (es->es_ifuba.ifu_xtofree) {
 336:         m_freem(es->es_ifuba.ifu_xtofree);
 337:         es->es_ifuba.ifu_xtofree = 0;
 338:     }
 339:     if (es->es_if.if_snd.ifq_head == 0) {
 340:         es->es_lastx = 256;     /* putatively illegal */
 341:         return;
 342:     }
 343:     enstart(unit);
 344: }
 345: 
 346: /*
 347:  * Collision on ethernet interface.  Do exponential
 348:  * backoff, and retransmit.  If have backed off all
 349:  * the way print warning diagnostic, and drop packet.
 350:  */
 351: encollide(unit)
 352:     int unit;
 353: {
 354:     struct en_softc *es = &en_softc[unit];
 355: 
 356:     es->es_if.if_collisions++;
 357:     if (es->es_oactive == 0)
 358:         return;
 359:     endocoll(unit);
 360: }
 361: 
 362: endocoll(unit)
 363:     int unit;
 364: {
 365:     register struct en_softc *es = &en_softc[unit];
 366: 
 367:     /*
 368: 	 * Es_mask is a 16 bit number with n low zero bits, with
 369: 	 * n the number of backoffs.  When es_mask is 0 we have
 370: 	 * backed off 16 times, and give up.
 371: 	 */
 372:     if (es->es_mask == 0) {
 373:         printf("en%d: send error\n", unit);
 374:         enxint(unit);
 375:         return;
 376:     }
 377:     /*
 378: 	 * Another backoff.  Restart with delay based on n low bits
 379: 	 * of the interval timer.
 380: 	 */
 381:     es->es_mask <<= 1;
 382:     es->es_delay = mfpr(ICR) &~ es->es_mask;
 383:     enstart(unit);
 384: }
 385: 
 386: #ifdef notdef
 387: struct  sockproto enproto = { AF_ETHERLINK };
 388: struct  sockaddr_en endst = { AF_ETHERLINK };
 389: struct  sockaddr_en ensrc = { AF_ETHERLINK };
 390: #endif
 391: /*
 392:  * Ethernet interface receiver interrupt.
 393:  * If input error just drop packet.
 394:  * Otherwise purge input buffered data path and examine
 395:  * packet to determine type.  If can't determine length
 396:  * from type, then have to drop packet.  Othewise decapsulate
 397:  * packet based on type and pass to type specific higher-level
 398:  * input routine.
 399:  */
 400: enrint(unit)
 401:     int unit;
 402: {
 403:     register struct en_softc *es = &en_softc[unit];
 404:     struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
 405:     register struct en_header *en;
 406:         struct mbuf *m;
 407:     int len; short resid;
 408:     register struct ifqueue *inq;
 409:     int off, s;
 410: 
 411:     es->es_if.if_ipackets++;
 412: 
 413:     /*
 414: 	 * Purge BDP; drop if input error indicated.
 415: 	 */
 416:     if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
 417:         UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
 418:     if (addr->en_istat&EN_IERROR) {
 419:         es->es_if.if_ierrors++;
 420:         goto setup;
 421:     }
 422: 
 423:     /*
 424: 	 * Calculate input data length.
 425: 	 * Get pointer to ethernet header (in input buffer).
 426: 	 * Deal with trailer protocol: if type is PUP trailer
 427: 	 * get true type from first 16-bit word past data.
 428: 	 * Remember that type was trailer by setting off.
 429: 	 */
 430:     resid = addr->en_iwc;
 431:     if (resid)
 432:         resid |= 0176000;
 433:     len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
 434:     len -= sizeof (struct en_header);
 435:     if (len > ENMRU || len <= 0)
 436:         goto setup;         /* sanity */
 437:     en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
 438: #ifdef  SWABALL
 439:     enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
 440: #else
 441:     en->en_type = ntohs(en->en_type);
 442: #endif SWABALL
 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: #ifndef SWABALL
 450:         en->en_type = *endataaddr(en, off, u_short *);
 451:         resid = *(endataaddr(en, off+2, u_short *));
 452: #else SWABALL
 453:         en->en_type = ntohs(*endataaddr(en, off, u_short *));
 454:         resid = ntohs(*(endataaddr(en, off+2, u_short *)));
 455: #endif SWABALL
 456:         if (off + resid > len)
 457:             goto setup;     /* sanity */
 458:         len = off + resid;
 459:     } else
 460:         off = 0;
 461:     if (len == 0)
 462:         goto setup;
 463: #ifdef ENF_SWABIPS
 464:     if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
 465:         enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
 466: #endif
 467:     /*
 468: 	 * Pull packet off interface.  Off is nonzero if packet
 469: 	 * has trailing header; if_rubaget will then force this header
 470: 	 * information to be at the front, but we still have to drop
 471: 	 * the type and length which are at the front of any trailer data.
 472: 	 */
 473:     m = if_rubaget(&es->es_ifuba, len, off, &es->es_if);
 474:     if (m == 0)
 475:         goto setup;
 476:     if (off) {
 477:         struct ifnet *ifp;
 478: 
 479:         ifp = *(mtod(m, struct ifnet **));
 480:         m->m_off += 2 * sizeof (u_short);
 481:         m->m_len -= 2 * sizeof (u_short);
 482:         *(mtod(m, struct ifnet **)) = ifp;
 483:     }
 484:     switch (en->en_type) {
 485: 
 486: #ifdef INET
 487:     case ENTYPE_IP:
 488:         schednetisr(NETISR_IP);
 489:         inq = &ipintrq;
 490:         break;
 491: #endif
 492: #ifdef PUP
 493:     case ENTYPE_PUP:
 494:         rpup_input(m);
 495:         goto setup;
 496: #endif
 497: #ifdef NS
 498:     case ETHERTYPE_NS:
 499:         if (es->es_nsactive) {
 500:             schednetisr(NETISR_NS);
 501:             inq = &nsintrq;
 502:         } else {
 503:             m_freem(m);
 504:             goto setup;
 505:         }
 506:         break;
 507: #endif
 508: 
 509: #if NENETFILTER > 0
 510:     default:
 511:     {
 512:         register struct mbuf *mtop;
 513:         /*
 514: 		 * We need the local net header after all.  Oh well,
 515: 		 * this could be improved.
 516: 		 */
 517:         MGET(mtop, M_DONTWAIT, MT_DATA);
 518:         if (mtop == 0) {    /* no more mbufs? */
 519:             m_freem(m);     /* wasted effort */
 520:             goto setup;
 521:         }
 522: #ifdef  SWABALL
 523:         /*
 524: 		 * the interface has put en_type in host order and we
 525: 		 * want it in net order.
 526: 		 */
 527:         en->en_type = htons(en->en_type);
 528: #endif	SWABALL
 529:         bcopy(en, mtod(mtop, struct en_header *),
 530:                         sizeof(struct en_header));
 531:         mtop->m_len = sizeof(struct en_header);
 532:         IF_ADJ(m);
 533:         mtop->m_next = m;
 534:         enetFilter(es->es_enetunit, mtop,
 535:                 (len + sizeof(struct en_header)) );
 536:         goto setup;
 537:     }
 538: #else
 539:     default:
 540: #ifdef notdef
 541:         enproto.sp_protocol = en->en_type;
 542:         endst.sen_host = en->en_dhost;
 543:         endst.sen_net = ensrc.sen_net = es->es_if.if_net;
 544:         ensrc.sen_host = en->en_shost;
 545:         raw_input(m, &enproto,
 546:             (struct sockaddr *)&ensrc, (struct sockaddr *)&endst);
 547: #else
 548:         m_freem(m);
 549: #endif
 550:         goto setup;
 551: #endif NENETFILTER > 0
 552:     }
 553: 
 554:     s = splimp();
 555:     if (IF_QFULL(inq)) {
 556:         IF_DROP(inq);
 557:         m_freem(m);
 558:     } else
 559:         IF_ENQUEUE(inq, m);
 560:     splx(s);
 561: 
 562: setup:
 563:     /*
 564: 	 * Reset for next packet.
 565: 	 */
 566:     addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
 567:     addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
 568:     addr->en_istat = EN_IEN|EN_GO;
 569: }
 570: 
 571: /*
 572:  * Ethernet output routine.
 573:  * Encapsulate a packet of type family for the local net.
 574:  * Use trailer local net encapsulation if enough data in first
 575:  * packet leaves a multiple of 512 bytes of data in remainder.
 576:  */
 577: enoutput(ifp, m0, dst)
 578:     struct ifnet *ifp;
 579:     struct mbuf *m0;
 580:     struct sockaddr *dst;
 581: {
 582:     int type, dest, s, error;
 583:     register struct mbuf *m = m0;
 584:     register struct en_header *en;
 585:     register int off;
 586: 
 587:     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
 588:         error = ENETDOWN;
 589:         goto bad;
 590:     }
 591:     switch (dst->sa_family) {
 592: 
 593: #ifdef INET
 594:     case AF_INET:
 595:         {
 596:         struct in_addr in;
 597: 
 598:         in = ((struct sockaddr_in *)dst)->sin_addr;
 599:         if (in_broadcast(in))
 600:             dest = EN_BROADCAST;
 601:         else
 602:             dest = in_lnaof(in);
 603:         }
 604:         if (dest >= 0x100) {
 605:             error = EPERM;      /* ??? */
 606:             goto bad;
 607:         }
 608:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
 609:         /* need per host negotiation */
 610:         if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
 611:         if (off > 0 && (off & 0x1ff) == 0 &&
 612:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
 613:             type = ENTYPE_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)ENTYPE_IP);
 617:             *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
 618:             goto gottrailertype;
 619:         }
 620:         type = ENTYPE_IP;
 621:         off = 0;
 622:         goto gottype;
 623: #endif
 624: #ifdef NS
 625:     case AF_NS:
 626:     {
 627:         u_char *up;
 628: 
 629:         type = ETHERTYPE_NS;
 630:         up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host;
 631:         if (*up & 1)
 632:             dest = EN_BROADCAST;
 633:         else
 634:             dest = up[5];
 635: 
 636:         off = 0;
 637:         goto gottype;
 638:     }
 639: #endif
 640: #ifdef PUP
 641:     case AF_PUP:
 642:         dest = ((struct sockaddr_pup *)dst)->spup_host;
 643:         type = ENTYPE_PUP;
 644:         off = 0;
 645:         goto gottype;
 646: #endif
 647: 
 648: #if NENETFILTER > 0
 649:     case AF_IMPLINK:
 650:         en = mtod(m, struct en_header *);
 651: #ifdef  SWABALL
 652:         /*
 653: 		 * enstart doesn't swab header fields; en_type is in
 654: 		 * net order and interface expects host order.
 655: 		 */
 656:         en->en_type = ntohs(en->en_type);
 657: #endif	SWABALL
 658:         goto gotheader;
 659: #endif
 660: 
 661:     default:
 662:         printf("en%d: can't handle af%d\n", ifp->if_unit,
 663:             dst->sa_family);
 664:         error = EAFNOSUPPORT;
 665:         goto bad;
 666:     }
 667: 
 668: gottrailertype:
 669:     /*
 670: 	 * Packet to be sent as trailer: move first packet
 671: 	 * (control information) to end of chain.
 672: 	 */
 673:     while (m->m_next)
 674:         m = m->m_next;
 675:     m->m_next = m0;
 676:     m = m0->m_next;
 677:     m0->m_next = 0;
 678:     m0 = m;
 679: 
 680: gottype:
 681:     /*
 682: 	 * Add local net header.  If no space in first mbuf,
 683: 	 * allocate another.
 684: 	 */
 685:     if (m->m_off > MMAXOFF ||
 686:         MMINOFF + sizeof (struct en_header) > m->m_off) {
 687:         MGET(m, M_DONTWAIT, MT_HEADER);
 688:         if (m == 0) {
 689:             error = ENOBUFS;
 690:             goto bad;
 691:         }
 692:         m->m_next = m0;
 693:         m->m_off = MMINOFF;
 694:         m->m_len = sizeof (struct en_header);
 695:     } else {
 696:         m->m_off -= sizeof (struct en_header);
 697:         m->m_len += sizeof (struct en_header);
 698:     }
 699:     en = mtod(m, struct en_header *);
 700:     /* add en_shost later */
 701:     en->en_dhost = dest;
 702: #ifdef SWABALL
 703:     en->en_type = type;
 704: #else
 705:     en->en_type = htons((u_short)type);
 706: #endif
 707: #if NENETFILTER > 0
 708: gotheader:  /* will add en_shost later, in enstart() */
 709: #endif
 710:     /*
 711: 	 * Queue message on interface, and start output if interface
 712: 	 * not yet active.
 713: 	 */
 714:     s = splimp();
 715:     if (IF_QFULL(&ifp->if_snd)) {
 716:         IF_DROP(&ifp->if_snd);
 717:         error = ENOBUFS;
 718:         goto qfull;
 719:     }
 720:     IF_ENQUEUE(&ifp->if_snd, m);
 721:     if (en_softc[ifp->if_unit].es_oactive == 0)
 722:         enstart(ifp->if_unit);
 723:     splx(s);
 724:     return (0);
 725: qfull:
 726:     m0 = m;
 727:     splx(s);
 728: bad:
 729:     m_freem(m0);
 730:     return (error);
 731: }
 732: 
 733: /*
 734:  * Process an ioctl request.
 735:  */
 736: enioctl(ifp, cmd, data)
 737:     register struct ifnet *ifp;
 738:     int cmd;
 739:     caddr_t data;
 740: {
 741:     register struct en_softc *es = ((struct en_softc *)ifp);
 742:     struct ifaddr *ifa = (struct ifaddr *) data;
 743:     int s = splimp(), error = 0;
 744:     struct endevice *enaddr;
 745: 
 746:     switch (cmd) {
 747: 
 748:     case SIOCSIFADDR:
 749:         enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
 750:         es->es_host = (~enaddr->en_addr) & 0xff;
 751:         /*
 752: 		 * Attempt to check agreement of protocol address
 753: 		 * and board address.
 754: 		 */
 755:         switch (ifa->ifa_addr.sa_family) {
 756:         case AF_INET:
 757:             if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host)
 758:                 return (EADDRNOTAVAIL);
 759:             break;
 760: #ifdef NS
 761:         case AF_NS:
 762:             if (IA_SNS(ifa)->sns_addr.x_host.c_host[5]
 763:                             != es->es_host)
 764:                 return (EADDRNOTAVAIL);
 765:             es->es_nsactive = 1;
 766:             break;
 767: #endif
 768:         }
 769:         ifp->if_flags |= IFF_UP;
 770:         if ((ifp->if_flags & IFF_RUNNING) == 0)
 771:             eninit(ifp->if_unit);
 772:         break;
 773: 
 774:     default:
 775:         error = EINVAL;
 776:         break;
 777:     }
 778:     splx(s);
 779:     return (error);
 780: }
 781: 
 782: #if defined(SWABALL) || defined(ENF_SWABIPS)
 783: /*
 784:  * Swab bytes
 785:  * Jeffrey Mogul, Stanford
 786:  */
 787: enswab(from, to, n)
 788:     register unsigned char *from, *to;
 789:     register int n;
 790: {
 791:     register unsigned long temp;
 792: 
 793:     if ((n <= 0) || (n > 0xFFFF)) {
 794:         printf("enswab: bad len %d\n", n);
 795:         return;
 796:     }
 797: 
 798:     n >>= 1; n++;
 799: #define STEP    {temp = *from++;*to++ = *from++;*to++ = temp;}
 800:     /* round to multiple of 8 */
 801:     while ((--n) & 07)
 802:         STEP;
 803:     n >>= 3;
 804:     while (--n >= 0) {
 805:         STEP; STEP; STEP; STEP;
 806:         STEP; STEP; STEP; STEP;
 807:     }
 808: }
 809: #endif
 810: #endif

Defined functions

enattach defined in line 135; used 2 times
encollide defined in line 351; used 2 times
endocoll defined in line 362; used 2 times
eninit defined in line 198; used 4 times
enioctl defined in line 736; used 2 times
enoutput defined in line 577; used 2 times
enprobe defined in line 111; used 2 times
enreset defined in line 182; used 2 times
enrint defined in line 400; used 2 times
enstart defined in line 243; used 3 times
enswab defined in line 787; used 3 times
enxint defined in line 317; used 4 times

Defined variables

en_softc defined in line 105; used 8 times
enalldelay defined in line 231; used 1 times
endriver defined in line 66; never used
endst defined in line 388; used 3 times
eninfo defined in line 64; used 7 times
enlastdel defined in line 232; used 1 times
enlastmask defined in line 233; used 1 times
enproto defined in line 387; used 2 times
ensrc defined in line 389; used 3 times

Defined struct's

en_softc defined in line 92; used 18 times

Defined macros

ENF_SWABIPS defined in line 77; used 5 times
ENMRU defined in line 61; used 5 times
ENMTU defined in line 60; used 3 times
ENUNIT defined in line 68; used 1 times
STEP defined in line 799; used 9 times
endataaddr defined in line 443; used 4 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1808
Valid CSS Valid XHTML 1.0 Strict