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_ec.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "ec.h"
  10: #include "enetfilter.h"
  11: #if NEC > 0
  12: 
  13: /*
  14:  * 3Com Ethernet Controller interface
  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 "syslog.h"
  25: #include "vmmac.h"
  26: #include "ioctl.h"
  27: #include "errno.h"
  28: 
  29: #include "../net/if.h"
  30: #include "../net/netisr.h"
  31: #include "../net/route.h"
  32: 
  33: #ifdef INET
  34: #include "../netinet/in.h"
  35: #include "../netinet/in_systm.h"
  36: #include "../netinet/in_var.h"
  37: #include "../netinet/ip.h"
  38: #include "../netinet/if_ether.h"
  39: #endif
  40: 
  41: #ifdef NS
  42: #include "../netns/ns.h"
  43: #include "../netns/ns_if.h"
  44: #endif
  45: 
  46: #include "../vax/cpu.h"
  47: #include "../vax/mtpr.h"
  48: #include "if_ecreg.h"
  49: #include "if_uba.h"
  50: #if NENETFILTER > 0
  51: #include "../net/enet.h"
  52: #endif	NENETFILTER > 0
  53: #include "../vaxuba/ubareg.h"
  54: #include "../vaxuba/ubavar.h"
  55: 
  56: #if CLSIZE == 2
  57: #define ECBUFSIZE   32      /* on-board memory, clusters */
  58: #endif
  59: 
  60: int ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
  61: struct  uba_device *ecinfo[NEC];
  62: u_short ecstd[] = { 0 };
  63: struct  uba_driver ecdriver =
  64:     { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, ecubamem };
  65: 
  66: int ecinit(),ecioctl(),ecoutput(),ecreset();
  67: struct  mbuf *ecget();
  68: 
  69: extern struct ifnet loif;
  70: 
  71: /*
  72:  * Ethernet software status per interface.
  73:  *
  74:  * Each interface is referenced by a network interface structure,
  75:  * es_if, which the routing code uses to locate the interface.
  76:  * This structure contains the output queue for the interface, its address, ...
  77:  * We also have, for each interface, a UBA interface structure, which
  78:  * contains information about the UNIBUS resources held by the interface:
  79:  * map registers, buffered data paths, etc.  Information is cached in this
  80:  * structure for use by the if_uba.c routines in running the interface
  81:  * efficiently.
  82:  */
  83: struct  ec_softc {
  84:     struct  arpcom es_ac;       /* common Ethernet structures */
  85: #define es_if   es_ac.ac_if     /* network-visible interface */
  86: #define es_addr es_ac.ac_enaddr     /* hardware Ethernet address */
  87:     struct  ifuba es_ifuba;     /* UNIBUS resources */
  88:     short   es_mask;        /* mask for current output delay */
  89:     short   es_oactive;     /* is output active? */
  90: #if NENETFILTER > 0
  91:     short   es_enetunit;        /* unit number for enet filtering */
  92: #endif	NENETFILTER > 0
  93:     u_char  *es_buf[16];        /* virtual addresses of buffers */
  94: } ec_softc[NEC];
  95: 
  96: /*
  97:  * Configure on-board memory for an interface.
  98:  * Called from autoconfig and after a uba reset.
  99:  * The address of the memory on the uba is supplied in the device flags.
 100:  */
 101: ecubamem(ui, uban)
 102:     register struct uba_device *ui;
 103: {
 104:     register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags];
 105:     register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
 106: 
 107:     /*
 108: 	 * Make sure csr is there (we run before ecprobe).
 109: 	 */
 110:     if (badaddr((caddr_t)addr, 2))
 111:         return (-1);
 112: #if VAX780
 113:     if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
 114:         uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
 115:         return (-1);
 116:     }
 117: #endif
 118:     /*
 119: 	 * Make sure memory is turned on
 120: 	 */
 121:     addr->ec_rcr = EC_AROM;
 122:     /*
 123: 	 * Tell the system that the board has memory here, so it won't
 124: 	 * attempt to allocate the addresses later.
 125: 	 */
 126:     if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) {
 127:         printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit);
 128:         addr->ec_rcr = EC_MDISAB;   /* disable memory */
 129:         return (-1);
 130:     }
 131:     /*
 132: 	 * Check for existence of buffers on Unibus.
 133: 	 */
 134:     if (badaddr((caddr_t)ecbuf, 2)) {
 135: bad:
 136:         printf("ec%d: buffer mem not found\n", ui->ui_unit);
 137:         (void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0);
 138:         addr->ec_rcr = EC_MDISAB;   /* disable memory */
 139:         return (-1);
 140:     }
 141: #if VAX780
 142:     if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
 143:         uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
 144:         goto bad;
 145:     }
 146: #endif
 147:     if (ui->ui_alive == 0)      /* Only printf from autoconfig */
 148:         printf("ec%d: mem %x-%x\n", ui->ui_unit,
 149:             ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1);
 150:     ui->ui_type = 1;        /* Memory on, allocated */
 151:     return (0);
 152: }
 153: 
 154: /*
 155:  * Do output DMA to determine interface presence and
 156:  * interrupt vector.  DMA is too short to disturb other hosts.
 157:  */
 158: ecprobe(reg, ui)
 159:     caddr_t reg;
 160:     struct uba_device *ui;
 161: {
 162:     register int br, cvec;      /* r11, r10 value-result */
 163:     register struct ecdevice *addr = (struct ecdevice *)reg;
 164:     register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags];
 165: 
 166: #ifdef lint
 167:     br = 0; cvec = br; br = cvec;
 168:     ecrint(0); ecxint(0); eccollide(0);
 169: #endif
 170: 
 171:     /*
 172: 	 * Check that buffer memory was found and enabled.
 173: 	 */
 174:     if (ui->ui_type == 0)
 175:         return(0);
 176:     /*
 177: 	 * Make a one byte packet in what should be buffer #0.
 178: 	 * Submit it for sending.  This should cause an xmit interrupt.
 179: 	 * The xmit interrupt vector is 8 bytes after the receive vector,
 180: 	 * so adjust for this before returning.
 181: 	 */
 182:     *(u_short *)ecbuf = (u_short) 03777;
 183:     ecbuf[03777] = '\0';
 184:     addr->ec_xcr = EC_XINTEN|EC_XWBN;
 185:     DELAY(100000);
 186:     addr->ec_xcr = EC_XCLR;
 187:     if (cvec > 0 && cvec != 0x200) {
 188:         if (cvec & 04) {    /* collision interrupt */
 189:             cvec -= 04;
 190:             br += 1;        /* rcv is collision + 1 */
 191:         } else {        /* xmit interrupt */
 192:             cvec -= 010;
 193:             br += 2;        /* rcv is xmit + 2 */
 194:         }
 195:     }
 196:     return (1);
 197: }
 198: 
 199: /*
 200:  * Interface exists: make available by filling in network interface
 201:  * record.  System will initialize the interface when it is ready
 202:  * to accept packets.
 203:  */
 204: ecattach(ui)
 205:     struct uba_device *ui;
 206: {
 207:     struct ec_softc *es = &ec_softc[ui->ui_unit];
 208:     register struct ifnet *ifp = &es->es_if;
 209:     register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
 210:     int i, j;
 211:     u_char *cp;
 212: 
 213:     ifp->if_unit = ui->ui_unit;
 214:     ifp->if_name = "ec";
 215:     ifp->if_mtu = ETHERMTU;
 216: 
 217:     /*
 218: 	 * Read the ethernet address off the board, one nibble at a time.
 219: 	 */
 220:     addr->ec_xcr = EC_UECLR; /* zero address pointer */
 221:     addr->ec_rcr = EC_AROM;
 222:     cp = es->es_addr;
 223: #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
 224:     for (i=0; i < sizeof (es->es_addr); i++) {
 225:         *cp = 0;
 226:         for (j=0; j<=4; j+=4) {
 227:             *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
 228:             NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
 229:         }
 230:         cp++;
 231:     }
 232:     printf("ec%d: hardware address %s\n", ui->ui_unit,
 233:         ether_sprintf(es->es_addr));
 234:     ifp->if_init = ecinit;
 235:     ifp->if_ioctl = ecioctl;
 236:     ifp->if_output = ecoutput;
 237:     ifp->if_reset = ecreset;
 238:     ifp->if_flags = IFF_BROADCAST;
 239:     for (i=0; i<16; i++)
 240:         es->es_buf[i]
 241:             = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i];
 242: #if NENETFILTER > 0
 243:     {
 244:         struct endevp enp;
 245: 
 246:         enp.end_dev_type = ENDT_10MB;
 247:         enp.end_addr_len = sizeof(es->es_addr);
 248:         enp.end_hdr_len = sizeof(struct ether_header);
 249:         enp.end_MTU = ETHERMTU;
 250:         bcopy((caddr_t)es->es_addr,
 251:                 (caddr_t)(enp.end_addr), sizeof(es->es_addr));
 252:         bcopy((caddr_t)etherbroadcastaddr,
 253:                 (caddr_t)(enp.end_broadaddr), sizeof(es->es_addr));
 254: 
 255:         es->es_enetunit = enetattach(&es->es_if, &enp);
 256:     }
 257: #endif NENETFILTER > 0
 258:     if_attach(ifp);
 259: }
 260: 
 261: /*
 262:  * Reset of interface after UNIBUS reset.
 263:  * If interface is on specified uba, reset its state.
 264:  */
 265: ecreset(unit, uban)
 266:     int unit, uban;
 267: {
 268:     register struct uba_device *ui;
 269: 
 270:     if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
 271:         ui->ui_ubanum != uban)
 272:         return;
 273:     printf(" ec%d", unit);
 274:     ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING;
 275:     ecinit(unit);
 276: }
 277: 
 278: /*
 279:  * Initialization of interface; clear recorded pending
 280:  * operations, and reinitialize UNIBUS usage.
 281:  */
 282: ecinit(unit)
 283:     int unit;
 284: {
 285:     struct ec_softc *es = &ec_softc[unit];
 286:     struct ecdevice *addr;
 287:     register struct ifnet *ifp = &es->es_if;
 288:     int i, s;
 289: 
 290:     /* not yet, if address still unknown */
 291:     if (ifp->if_addrlist == (struct ifaddr *)0)
 292:         return;
 293: 
 294:     /*
 295: 	 * Hang receive buffers and start any pending writes.
 296: 	 * Writing into the rcr also makes sure the memory
 297: 	 * is turned on.
 298: 	 */
 299:     if ((ifp->if_flags & IFF_RUNNING) == 0) {
 300:         addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 301:         s = splimp();
 302:         /*
 303: 		 * write our ethernet address into the address recognition ROM
 304: 		 * so we can always use the same EC_READ bits (referencing ROM),
 305: 		 * in case we change the address sometime.
 306: 		 * Note that this is safe here as the receiver is NOT armed.
 307: 		 */
 308:         ec_setaddr(es->es_addr, unit);
 309:         /*
 310: 		 * Arm the receiver
 311: 		 */
 312:         for (i = ECRHBF; i >= ECRLBF; i--)
 313:             addr->ec_rcr = EC_READ | i;
 314:         es->es_oactive = 0;
 315:         es->es_mask = ~0;
 316:         es->es_if.if_flags |= IFF_RUNNING;
 317:         if (es->es_if.if_snd.ifq_head)
 318:             ecstart(unit);
 319:         splx(s);
 320:     }
 321: }
 322: 
 323: /*
 324:  * Start output on interface.  Get another datagram to send
 325:  * off of the interface queue, and copy it to the interface
 326:  * before starting the output.
 327:  */
 328: ecstart(unit)
 329: {
 330:     register struct ec_softc *es = &ec_softc[unit];
 331:     struct ecdevice *addr;
 332:     struct mbuf *m;
 333: 
 334:     if ((es->es_if.if_flags & IFF_RUNNING) == 0)
 335:         return;
 336:     IF_DEQUEUE(&es->es_if.if_snd, m);
 337:     if (m == 0)
 338:         return;
 339:     ecput(es->es_buf[ECTBF], m);
 340:     addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 341:     addr->ec_xcr = EC_WRITE|ECTBF;
 342:     es->es_oactive = 1;
 343: }
 344: 
 345: /*
 346:  * Ethernet interface transmitter interrupt.
 347:  * Start another output if more data to send.
 348:  */
 349: ecxint(unit)
 350:     int unit;
 351: {
 352:     register struct ec_softc *es = &ec_softc[unit];
 353:     register struct ecdevice *addr =
 354:         (struct ecdevice *)ecinfo[unit]->ui_addr;
 355: 
 356:     if (es->es_oactive == 0)
 357:         return;
 358:     if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {
 359:         printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,
 360:             addr->ec_xcr, EC_XBITS);
 361:         es->es_oactive = 0;
 362:         addr->ec_xcr = EC_XCLR;
 363:         return;
 364:     }
 365:     es->es_if.if_opackets++;
 366:     es->es_oactive = 0;
 367:     es->es_mask = ~0;
 368:     addr->ec_xcr = EC_XCLR;
 369:     if (es->es_if.if_snd.ifq_head)
 370:         ecstart(unit);
 371: }
 372: 
 373: /*
 374:  * Collision on ethernet interface.  Do exponential
 375:  * backoff, and retransmit.  If have backed off all
 376:  * the way print warning diagnostic, and drop packet.
 377:  */
 378: eccollide(unit)
 379:     int unit;
 380: {
 381:     register struct ec_softc *es = &ec_softc[unit];
 382:     register struct ecdevice *addr =
 383:         (struct ecdevice *)ecinfo[unit]->ui_addr;
 384:     register i;
 385:     int delay;
 386: 
 387:     es->es_if.if_collisions++;
 388:     if (es->es_oactive == 0)
 389:         return;
 390: 
 391:     /*
 392: 	 * Es_mask is a 16 bit number with n low zero bits, with
 393: 	 * n the number of backoffs.  When es_mask is 0 we have
 394: 	 * backed off 16 times, and give up.
 395: 	 */
 396:     if (es->es_mask == 0) {
 397:         es->es_if.if_oerrors++;
 398:         log(LOG_ERR, "ec%d: send error\n", unit);
 399:         /*
 400: 		 * Reset interface, then requeue rcv buffers.
 401: 		 * Some incoming packets may be lost, but that
 402: 		 * can't be helped.
 403: 		 */
 404:         addr->ec_xcr = EC_UECLR;
 405:         for (i=ECRHBF; i>=ECRLBF; i--)
 406:             addr->ec_rcr = EC_READ|i;
 407:         /*
 408: 		 * Reset and transmit next packet (if any).
 409: 		 */
 410:         es->es_oactive = 0;
 411:         es->es_mask = ~0;
 412:         if (es->es_if.if_snd.ifq_head)
 413:             ecstart(unit);
 414:         return;
 415:     }
 416:     /*
 417: 	 * Do exponential backoff.  Compute delay based on low bits
 418: 	 * of the interval timer (1 bit for each transmission attempt,
 419: 	 * but at most 5 bits).  Then delay for that number of
 420: 	 * slot times.  A slot time is 51.2 microseconds (rounded to 51).
 421: 	 * This does not take into account the time already used to
 422: 	 * process the interrupt.
 423: 	 */
 424:     es->es_mask <<= 1;
 425:     delay = mfpr(ICR) & 0x1f &~ es->es_mask;
 426:     DELAY(delay * 51);
 427:     /*
 428: 	 * Clear the controller's collision flag, thus enabling retransmit.
 429: 	 */
 430:     addr->ec_xcr = EC_CLEAR;
 431: }
 432: 
 433: /*
 434:  * Ethernet interface receiver interrupt.
 435:  * If input error just drop packet.
 436:  * Otherwise examine
 437:  * packet to determine type.  If can't determine length
 438:  * from type, then have to drop packet.  Othewise decapsulate
 439:  * packet based on type and pass to type specific higher-level
 440:  * input routine.
 441:  */
 442: ecrint(unit)
 443:     int unit;
 444: {
 445:     struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 446: 
 447:     while (addr->ec_rcr & EC_RDONE)
 448:         ecread(unit);
 449: }
 450: 
 451: ecread(unit)
 452:     int unit;
 453: {
 454:     register struct ec_softc *es = &ec_softc[unit];
 455:     struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 456:     register struct ether_header *ec;
 457:         struct mbuf *m;
 458:     int len, off, resid, ecoff, rbuf;
 459:     register struct ifqueue *inq;
 460:     u_char *ecbuf;
 461: 
 462:     es->es_if.if_ipackets++;
 463:     rbuf = addr->ec_rcr & EC_RBN;
 464:     if (rbuf < ECRLBF || rbuf > ECRHBF)
 465:         panic("ecrint");
 466:     ecbuf = es->es_buf[rbuf];
 467:     ecoff = *(short *)ecbuf;
 468:     if (ecoff <= ECRDOFF || ecoff > 2046) {
 469:         es->es_if.if_ierrors++;
 470: #ifdef notdef
 471:         if (es->es_if.if_ierrors % 100 == 0)
 472:             printf("ec%d: += 100 input errors\n", unit);
 473: #endif
 474:         goto setup;
 475:     }
 476: 
 477:     /*
 478: 	 * Get input data length.
 479: 	 * Get pointer to ethernet header (in input buffer).
 480: 	 * Deal with trailer protocol: if type is trailer type
 481: 	 * get true type from first 16-bit word past data.
 482: 	 * Remember that type was trailer by setting off.
 483: 	 */
 484:     len = ecoff - ECRDOFF - sizeof (struct ether_header);
 485:     ec = (struct ether_header *)(ecbuf + ECRDOFF);
 486:     ec->ether_type = ntohs((u_short)ec->ether_type);
 487: #define ecdataaddr(ec, off, type)   ((type)(((caddr_t)((ec)+1)+(off))))
 488:     if (ec->ether_type >= ETHERTYPE_TRAIL &&
 489:         ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
 490:         off = (ec->ether_type - ETHERTYPE_TRAIL) * 512;
 491:         if (off >= ETHERMTU)
 492:             goto setup;     /* sanity */
 493:         ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
 494:         resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
 495:         if (off + resid > len)
 496:             goto setup;     /* sanity */
 497:         len = off + resid;
 498:     } else
 499:         off = 0;
 500:     if (len == 0)
 501:         goto setup;
 502: 
 503:     /*
 504: 	 * Pull packet off interface.  Off is nonzero if packet
 505: 	 * has trailing header; ecget will then force this header
 506: 	 * information to be at the front, but we still have to drop
 507: 	 * the type and length which are at the front of any trailer data.
 508: 	 */
 509:     m = ecget(ecbuf, len, off, &es->es_if);
 510:     if (m == 0)
 511:         goto setup;
 512:     if (off) {
 513:         struct ifnet *ifp;
 514: 
 515:         ifp = *(mtod(m, struct ifnet **));
 516:         m->m_off += 2 * sizeof (u_short);
 517:         m->m_len -= 2 * sizeof (u_short);
 518:         *(mtod(m, struct ifnet **)) = ifp;
 519:     }
 520:     switch (ec->ether_type) {
 521: 
 522: #ifdef INET
 523:     case ETHERTYPE_IP:
 524:         schednetisr(NETISR_IP);
 525:         inq = &ipintrq;
 526:         break;
 527: 
 528:     case ETHERTYPE_ARP:
 529:         arpinput(&es->es_ac, m);
 530:         goto setup;
 531: #endif
 532: #ifdef NS
 533:     case ETHERTYPE_NS:
 534:         schednetisr(NETISR_NS);
 535:         inq = &nsintrq;
 536:         break;
 537: 
 538: #endif
 539: #if NENETFILTER > 0
 540:     default:
 541:     {
 542:         register struct mbuf *mtop;
 543:         register short *sp,*sp2;
 544:         int i;
 545:         /*
 546: 		 * We need the local net header after all.  Oh well,
 547: 		 * this could be improved.
 548: 		 */
 549:         MGET(mtop, M_DONTWAIT, MT_DATA);
 550:         if (mtop == 0) {    /* no more mbufs? */
 551:             m_freem(m);     /* wasted effort */
 552:             goto setup;
 553:         }
 554:         ec->ether_type = htons((u_short)ec->ether_type);
 555:         sp = (short *) ec;
 556:         sp2 = mtod(mtop, short *);
 557:         for (i = 0 ; i < (sizeof(struct ether_header)/2) ; i++)
 558:             *sp2++ = *sp++;
 559:         mtop->m_len = sizeof(struct ether_header);
 560:         IF_ADJ(m);
 561:         mtop->m_next = m;
 562:         enetFilter(es->es_enetunit, mtop,
 563:                 (len + sizeof(struct ether_header)) );
 564:         goto setup;
 565:     }
 566: #else
 567:     default:
 568:         m_freem(m);
 569:         goto setup;
 570: #endif NENETFILTER > 0
 571:     }
 572: 
 573:     if (IF_QFULL(inq)) {
 574:         IF_DROP(inq);
 575:         m_freem(m);
 576:         goto setup;
 577:     }
 578:     IF_ENQUEUE(inq, m);
 579: 
 580: setup:
 581:     /*
 582: 	 * Reset for next packet.
 583: 	 */
 584:     addr->ec_rcr = EC_READ|EC_RCLR|rbuf;
 585: }
 586: 
 587: /*
 588:  * Ethernet output routine.
 589:  * Encapsulate a packet of type family for the local net.
 590:  * Use trailer local net encapsulation if enough data in first
 591:  * packet leaves a multiple of 512 bytes of data in remainder.
 592:  * If destination is this address or broadcast, send packet to
 593:  * loop device to kludge around the fact that 3com interfaces can't
 594:  * talk to themselves.
 595:  */
 596: ecoutput(ifp, m0, dst)
 597:     struct ifnet *ifp;
 598:     struct mbuf *m0;
 599:     struct sockaddr *dst;
 600: {
 601:     int type, s, error;
 602:     u_char edst[6];
 603:     struct in_addr idst;
 604:     register struct ec_softc *es = &ec_softc[ifp->if_unit];
 605:     register struct mbuf *m = m0;
 606:     register struct ether_header *ec;
 607:     register int off;
 608:     struct mbuf *mcopy = (struct mbuf *)0;
 609: #if NENETFILTER > 0
 610:     struct mbuf *enetcopy = (struct mbuf *)0;
 611: #endif	NENETFILTER
 612:     int usetrailers;
 613: 
 614:     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
 615:         error = ENETDOWN;
 616:         goto bad;
 617:     }
 618:     switch (dst->sa_family) {
 619: 
 620: #ifdef INET
 621:     case AF_INET:
 622:         idst = ((struct sockaddr_in *)dst)->sin_addr;
 623:         if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers))
 624:             return (0); /* if not yet resolved */
 625:         if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
 626:             sizeof(edst)))
 627:             mcopy = m_copy(m, 0, (int)M_COPYALL);
 628:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
 629:         /* need per host negotiation */
 630:         if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
 631:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
 632:             type = ETHERTYPE_TRAIL + (off>>9);
 633:             m->m_off -= 2 * sizeof (u_short);
 634:             m->m_len += 2 * sizeof (u_short);
 635:             *mtod(m, u_short *) = ntohs((u_short)ETHERTYPE_IP);
 636:             *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
 637:             goto gottrailertype;
 638:         }
 639:         type = ETHERTYPE_IP;
 640:         off = 0;
 641:         goto gottype;
 642: #endif
 643: #ifdef NS
 644:     case AF_NS:
 645:         bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
 646:             (caddr_t)edst, sizeof (edst));
 647: 
 648:         if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,
 649:             sizeof(edst))) {
 650: 
 651:                 mcopy = m_copy(m, 0, (int)M_COPYALL);
 652:         } else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
 653:             sizeof(edst))) {
 654: 
 655:                 return(looutput(&loif, m, dst));
 656:         }
 657:         type = ETHERTYPE_NS;
 658:         off = 0;
 659:         goto gottype;
 660: #endif
 661: #if NENETFILTER > 0
 662:     case AF_IMPLINK:
 663:         ec = mtod(m, struct ether_header *);
 664:         /* see if we need to fake loopback */
 665:         if (        /* is packet to us? */
 666:             (!bcmp((caddr_t)ec->ether_dhost,
 667:                         (caddr_t)es->es_addr,
 668:                         sizeof(ec->ether_dhost)))
 669:             ||      /* or is it a broadcast? */
 670:             (!bcmp((caddr_t)ec->ether_dhost,
 671:                         (caddr_t)etherbroadcastaddr,
 672:                             sizeof(ec->ether_dhost)))
 673:         ) {
 674:             enetcopy = m_copy(m, 0, (int)M_COPYALL);
 675:         }
 676:         goto gotheader;
 677: #endif	NENETFILTER
 678: 
 679:     case AF_UNSPEC:
 680:         ec = (struct ether_header *)dst->sa_data;
 681:         bcopy((caddr_t)ec->ether_dhost, (caddr_t)edst, sizeof (edst));
 682:         type = ec->ether_type;
 683:         goto gottype;
 684: 
 685:     default:
 686:         printf("ec%d: can't handle af%d\n", ifp->if_unit,
 687:             dst->sa_family);
 688:         error = EAFNOSUPPORT;
 689:         goto bad;
 690:     }
 691: 
 692: gottrailertype:
 693:     /*
 694: 	 * Packet to be sent as trailer: move first packet
 695: 	 * (control information) to end of chain.
 696: 	 */
 697:     while (m->m_next)
 698:         m = m->m_next;
 699:     m->m_next = m0;
 700:     m = m0->m_next;
 701:     m0->m_next = 0;
 702:     m0 = m;
 703: 
 704: gottype:
 705:     /*
 706: 	 * Add local net header.  If no space in first mbuf,
 707: 	 * allocate another.
 708: 	 */
 709:     if (m->m_off > MMAXOFF ||
 710:         MMINOFF + sizeof (struct ether_header) > m->m_off) {
 711:         m = m_get(M_DONTWAIT, MT_HEADER);
 712:         if (m == 0) {
 713:             error = ENOBUFS;
 714:             goto bad;
 715:         }
 716:         m->m_next = m0;
 717:         m->m_off = MMINOFF;
 718:         m->m_len = sizeof (struct ether_header);
 719:     } else {
 720:         m->m_off -= sizeof (struct ether_header);
 721:         m->m_len += sizeof (struct ether_header);
 722:     }
 723:     ec = mtod(m, struct ether_header *);
 724:     ec->ether_type = htons((u_short)type);
 725:     bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst));
 726: #if NENETFILTER > 0
 727: gotheader:
 728: #endif	NENETFILTER
 729:     bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost,
 730:         sizeof(ec->ether_shost));
 731: 
 732:     /*
 733: 	 * Queue message on interface, and start output if interface
 734: 	 * not yet active.
 735: 	 */
 736:     s = splimp();
 737:     if (IF_QFULL(&ifp->if_snd)) {
 738:         IF_DROP(&ifp->if_snd);
 739:         error = ENOBUFS;
 740:         goto qfull;
 741:     }
 742:     IF_ENQUEUE(&ifp->if_snd, m);
 743:     if (es->es_oactive == 0)
 744:         ecstart(ifp->if_unit);
 745: #if NENETFILTER > 0
 746:     if (enetcopy) { /* we have a loopback that isn't an IP */
 747:         register int count = 0;
 748:         register struct mbuf *mt = enetcopy;
 749: 
 750:         /* figure out how long the packet is */
 751:         do {
 752:             count += mt->m_len;
 753:             mt = mt->m_next;
 754:         } while (mt);
 755: 
 756:         /*
 757: 		 * should perhaps reject certain packet types here,
 758: 		 * but probably less total effort to let enetFilter
 759: 		 * reject them.
 760: 		 */
 761:         enetFilter(es->es_enetunit, enetcopy, count);
 762:     }
 763: #endif	NENETFILTER
 764:     splx(s);
 765:     return (mcopy ? looutput(&loif, mcopy, dst) : 0);
 766: 
 767: qfull:
 768:     m0 = m;
 769:     splx(s);
 770: bad:
 771:     m_freem(m0);
 772:     if (mcopy)
 773:         m_freem(mcopy);
 774: #if NENETFILTER > 0
 775:     if (enetcopy)
 776:         m_freem(enetcopy);
 777: #endif	NENETFILTER
 778:     return (error);
 779: }
 780: 
 781: /*
 782:  * Routine to copy from mbuf chain to transmit
 783:  * buffer in UNIBUS memory.
 784:  * If packet size is less than the minimum legal size,
 785:  * the buffer is expanded.  We probably should zero out the extra
 786:  * bytes for security, but that would slow things down.
 787:  */
 788: ecput(ecbuf, m)
 789:     u_char *ecbuf;
 790:     struct mbuf *m;
 791: {
 792:     register struct mbuf *mp;
 793:     register int off;
 794:     u_char *bp;
 795: 
 796:     for (off = 2048, mp = m; mp; mp = mp->m_next)
 797:         off -= mp->m_len;
 798:     if (2048 - off < ETHERMIN + sizeof (struct ether_header))
 799:         off = 2048 - ETHERMIN - sizeof (struct ether_header);
 800:     *(u_short *)ecbuf = off;
 801:     bp = (u_char *)(ecbuf + off);
 802:     for (mp = m; mp; mp = mp->m_next) {
 803:         register unsigned len = mp->m_len;
 804:         u_char *mcp;
 805: 
 806:         if (len == 0)
 807:             continue;
 808:         mcp = mtod(mp, u_char *);
 809:         if ((unsigned)bp & 01) {
 810:             *bp++ = *mcp++;
 811:             len--;
 812:         }
 813:         if (off = (len >> 1)) {
 814:             register u_short *to, *from;
 815: 
 816:             to = (u_short *)bp;
 817:             from = (u_short *)mcp;
 818:             do
 819:                 *to++ = *from++;
 820:             while (--off > 0);
 821:             bp = (u_char *)to,
 822:             mcp = (u_char *)from;
 823:         }
 824:         if (len & 01)
 825:             *bp++ = *mcp++;
 826:     }
 827:     m_freem(m);
 828: }
 829: 
 830: /*
 831:  * Routine to copy from UNIBUS memory into mbufs.
 832:  * Similar in spirit to if_rubaget.
 833:  *
 834:  * Warning: This makes the fairly safe assumption that
 835:  * mbufs have even lengths.
 836:  */
 837: struct mbuf *
 838: ecget(ecbuf, totlen, off0, ifp)
 839:     u_char *ecbuf;
 840:     int totlen, off0;
 841:     struct ifnet *ifp;
 842: {
 843:     register struct mbuf *m;
 844:     struct mbuf *top = 0, **mp = &top;
 845:     register int off = off0, len;
 846:     u_char *cp;
 847: 
 848:     cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
 849:     while (totlen > 0) {
 850:         register int words;
 851:         u_char *mcp;
 852: 
 853:         MGET(m, M_DONTWAIT, MT_DATA);
 854:         if (m == 0)
 855:             goto bad;
 856:         if (off) {
 857:             len = totlen - off;
 858:             cp = ecbuf + ECRDOFF +
 859:                 sizeof (struct ether_header) + off;
 860:         } else
 861:             len = totlen;
 862:         if (ifp)
 863:             len += sizeof(ifp);
 864:         if (len >= NBPG) {
 865:             MCLGET(m);
 866:             if (m->m_len == CLBYTES)
 867:                 m->m_len = len = MIN(len, CLBYTES);
 868:             else
 869:                 m->m_len = len = MIN(MLEN, len);
 870:         } else {
 871:             m->m_len = len = MIN(MLEN, len);
 872:             m->m_off = MMINOFF;
 873:         }
 874:         mcp = mtod(m, u_char *);
 875:         if (ifp) {
 876:             /*
 877: 			 * Prepend interface pointer to first mbuf.
 878: 			 */
 879:             *(mtod(m, struct ifnet **)) = ifp;
 880:             mcp += sizeof(ifp);
 881:             len -= sizeof(ifp);
 882:             ifp = (struct ifnet *)0;
 883:         }
 884:         if (words = (len >> 1)) {
 885:             register u_short *to, *from;
 886: 
 887:             to = (u_short *)mcp;
 888:             from = (u_short *)cp;
 889:             do
 890:                 *to++ = *from++;
 891:             while (--words > 0);
 892:             mcp = (u_char *)to;
 893:             cp = (u_char *)from;
 894:         }
 895:         if (len & 01)
 896:             *mcp++ = *cp++;
 897:         *mp = m;
 898:         mp = &m->m_next;
 899:         if (off == 0) {
 900:             totlen -= len;
 901:             continue;
 902:         }
 903:         off += len;
 904:         if (off == totlen) {
 905:             cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
 906:             off = 0;
 907:             totlen = off0;
 908:         }
 909:     }
 910:     return (top);
 911: bad:
 912:     m_freem(top);
 913:     return (0);
 914: }
 915: 
 916: /*
 917:  * Process an ioctl request.
 918:  */
 919: ecioctl(ifp, cmd, data)
 920:     register struct ifnet *ifp;
 921:     int cmd;
 922:     caddr_t data;
 923: {
 924:     register struct ifaddr *ifa = (struct ifaddr *)data;
 925:     struct ec_softc *es = &ec_softc[ifp->if_unit];
 926:     struct ecdevice *addr;
 927:     int s = splimp(), error = 0;
 928: 
 929:     addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr);
 930: 
 931:     switch (cmd) {
 932: 
 933:     case SIOCSIFADDR:
 934:         ifp->if_flags |= IFF_UP;
 935: 
 936:         switch (ifa->ifa_addr.sa_family) {
 937: #ifdef INET
 938:         case AF_INET:
 939:             ecinit(ifp->if_unit);   /* before arpwhohas */
 940:             ((struct arpcom *)ifp)->ac_ipaddr =
 941:                 IA_SIN(ifa)->sin_addr;
 942:             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
 943:             break;
 944: #endif
 945: #ifdef NS
 946:         case AF_NS:
 947:             {
 948:             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 949: 
 950:             if (ns_nullhost(*ina))
 951:                 ina->x_host = *(union ns_host *)(es->es_addr);
 952:             else {
 953:                 /*
 954: 				 * The manual says we can't change the address
 955: 				 * while the receiver is armed,
 956: 				 * so reset everything
 957: 				 */
 958:                 ifp->if_flags &= ~IFF_RUNNING;
 959:                 bcopy((caddr_t)ina->x_host.c_host,
 960:                     (caddr_t)es->es_addr, sizeof(es->es_addr));
 961:             }
 962:             ecinit(ifp->if_unit); /* does ec_setaddr() */
 963:             break;
 964:             }
 965: #endif
 966:         default:
 967:             ecinit(ifp->if_unit);
 968:             break;
 969:         }
 970:         break;
 971: 
 972:     case SIOCSIFFLAGS:
 973:         if ((ifp->if_flags & IFF_UP) == 0 &&
 974:             ifp->if_flags & IFF_RUNNING) {
 975:             addr->ec_xcr = EC_UECLR;
 976:             ifp->if_flags &= ~IFF_RUNNING;
 977:         } else if (ifp->if_flags & IFF_UP &&
 978:             (ifp->if_flags & IFF_RUNNING) == 0)
 979:             ecinit(ifp->if_unit);
 980:         break;
 981: 
 982:     default:
 983:         error = EINVAL;
 984:     }
 985:     splx(s);
 986:     return (error);
 987: }
 988: 
 989: ec_setaddr(physaddr,unit)
 990:     u_char *physaddr;
 991:     int unit;
 992: {
 993:     struct ec_softc *es = &ec_softc[unit];
 994:     struct uba_device *ui = ecinfo[unit];
 995:     register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
 996:     register char nibble;
 997:     register int i, j;
 998: 
 999:     /*
1000: 	 * Use the ethernet address supplied
1001: 	 * Note that we do a UECLR here, so the receive buffers
1002: 	 * must be requeued.
1003: 	 */
1004: 
1005: #ifdef DEBUG
1006:     printf("ec_setaddr: setting address for unit %d = %s",
1007:         unit, ether_sprintf(physaddr));
1008: #endif
1009:     addr->ec_xcr = EC_UECLR;
1010:     addr->ec_rcr = 0;
1011:     /* load requested address */
1012:     for (i = 0; i < 6; i++) { /* 6 bytes of address */
1013:         es->es_addr[i] = physaddr[i];
1014:         nibble = physaddr[i] & 0xf; /* lower nibble */
1015:         addr->ec_rcr = (nibble << 8);
1016:         addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
1017:         addr->ec_rcr = (nibble << 8);
1018:         for (j=0; j < 4; j++) {
1019:         addr->ec_rcr = 0;
1020:         addr->ec_rcr = EC_ASTEP; /* step counter */
1021:         addr->ec_rcr = 0;
1022:         }
1023:         nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */
1024:         addr->ec_rcr = (nibble << 8);
1025:         addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
1026:         addr->ec_rcr = (nibble << 8);
1027:         for (j=0; j < 4; j++) {
1028:         addr->ec_rcr = 0;
1029:         addr->ec_rcr = EC_ASTEP; /* step counter */
1030:         addr->ec_rcr = 0;
1031:         }
1032:     }
1033: #ifdef DEBUG
1034:     /*
1035: 	 * Read the ethernet address off the board, one nibble at a time.
1036: 	 */
1037:     addr->ec_xcr = EC_UECLR;
1038:     addr->ec_rcr = 0; /* read RAM */
1039:     cp = es->es_addr;
1040: #undef NEXTBIT
1041: #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0
1042:     for (i=0; i < sizeof (es->es_addr); i++) {
1043:         *cp = 0;
1044:         for (j=0; j<=4; j+=4) {
1045:             *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
1046:             NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
1047:         }
1048:         cp++;
1049:     }
1050:     printf("ec_setaddr: RAM address for unit %d = %s",
1051:         unit, ether_sprintf(physaddr));
1052: #endif
1053: }
1054: #endif

Defined functions

ec_setaddr defined in line 989; used 1 times
ecattach defined in line 204; used 2 times
eccollide defined in line 378; used 2 times
ecget defined in line 837; used 2 times
ecinit defined in line 282; used 7 times
ecioctl defined in line 919; used 2 times
ecoutput defined in line 596; used 2 times
ecprobe defined in line 158; used 2 times
ecput defined in line 788; used 1 times
ecread defined in line 451; used 1 times
ecreset defined in line 265; used 2 times
ecrint defined in line 442; used 2 times
ecstart defined in line 328; used 4 times
ecubamem defined in line 101; used 2 times
ecxint defined in line 349; used 2 times

Defined variables

ec_softc defined in line 94; used 10 times
ecdriver defined in line 63; never used
ecinfo defined in line 61; used 10 times

Defined struct's

ec_softc defined in line 83; used 18 times

Defined macros

ECBUFSIZE defined in line 57; used 3 times
NEXTBIT defined in line 1041; used 9 times
ecdataaddr defined in line 487; used 2 times
es_addr defined in line 86; used 16 times
es_if defined in line 85; used 17 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1759
Valid CSS Valid XHTML 1.0 Strict