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

Defined functions

enattach defined in line 128; used 2 times
encollide defined in line 327; used 3 times
endocoll defined in line 338; used 2 times
eninit defined in line 170; used 4 times
enioctl defined in line 661; used 2 times
enoutput defined in line 513; used 2 times
enprobe defined in line 104; used 2 times
enreset defined in line 154; used 2 times
enrint defined in line 376; used 3 times
enstart defined in line 215; used 3 times
enswab defined in line 712; used 2 times
enxint defined in line 293; used 5 times

Defined variables

en_softc defined in line 98; used 8 times
enalldelay defined in line 203; used 1 times
endriver defined in line 62; used 1 times
endst defined in line 364; used 3 times
eninfo defined in line 60; used 7 times
enlastdel defined in line 204; used 1 times
enlastmask defined in line 205; used 1 times
enproto defined in line 363; used 2 times
ensrc defined in line 365; used 3 times
enstd defined in line 61; used 1 times
  • in line 63

Defined struct's

en_softc defined in line 88; used 18 times

Defined macros

ENF_SWABIPS defined in line 73; used 5 times
ENMRU defined in line 57; used 5 times
ENMTU defined in line 56; used 2 times
ENUNIT defined in line 64; used 1 times
STEP defined in line 724; used 9 times
endataaddr defined in line 415; used 2 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2656
Valid CSS Valid XHTML 1.0 Strict