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:  *			1.0 (2.10BSD  EATON IMSD sms@etn-wlv.eaton.com 12/28/87)
   8: */
   9: 
  10: #include "ec.h"
  11: #if NEC > 0
  12: 
  13: /*
  14:  * 3Com Ethernet Controller interface
  15:  *
  16:  * Adapted from the 4.3BSD version to run on 2.10BSD.  Major differences:
  17:  *
  18:  *	1) static instead of autoconfiguration, 'autoconfig' has problems with
  19:  *	   our triple vector.
  20:  *	2) reduction of the number of buffers from 16 to 12, this is because
  21:  *	   the unibus memory for this device is 'enabled' by clipping resistors
  22:  *	   on the cpu board and must start on a mod 4 UMR boundary and we only
  23:  *	   have UMRs 28, 29 and 30.  The number of UMRs available has to be
  24:  *	   reduced in ubinit() (/sys/pdp/machdep2.c) if this driver is to
  25:  *	   be used.
  26:  *	3) Buffers are mapped thru APR5, copyv() is used to go to/from mbufs.
  27:  *	4) Exponential backup redone to use a count instead of a mask.
  28:  *	5) The ec_softc structure reduced in size to remove unused fields.
  29:  *	6) Modified to run in supervisor mode, about all this required was
  30:  * 	   changing the macros in seg.h to use supervisor registers if
  31:  *	   SUPERVISOR is defined (from the makefiles) AND changing where
  32:  *	   SEG5 is mapped in/out.  Use mbcopyin/out instead of copyv.
  33:  *	7) Broken ethernet cable showed up a problem in collision handling,
  34:  *	   the backoff being done via a DELAY loop effectively hangs the system.
  35:  *	   Changed to use a timeout with the number of ticks being the number
  36:  *	   of collisions (up to 16 max).
  37:  *
  38:  * Who knows if trailers and NS work, i don't.  Coding style changed to reflect
  39:  * personal preferences, conditional vax code removed to improve readability.
  40:  *
  41:  * Oh, one more thing.  The 3Com board is hardwired to interrupt at spl6 for
  42:  * the receiver, spl5 for the collision detect, and spl4 for the transmitter.
  43:  * References to splimp() have been replaced in this driver with splhigh().
  44:  * you'll have to change splimp() to be spl6 and recompile the whole kernel
  45:  * in order to avoid recursive interrupts caused by the receiver using splimp
  46:  * anywhere in its path.  TRUST ME, you crash if you don't do this.  Better
  47:  * to lose a few clock ticks than the system!
  48: */
  49: 
  50: #include "param.h"
  51: #include "../machine/seg.h"
  52: #include "mbuf.h"
  53: #include "buf.h"
  54: #include "domain.h"
  55: #include "protosw.h"
  56: #include "socket.h"
  57: #include "ioctl.h"
  58: #include "errno.h"
  59: 
  60: #include "../net/if.h"
  61: #include "../net/netisr.h"
  62: #include "../net/route.h"
  63: 
  64: #ifdef INET
  65: #include "../netinet/in.h"
  66: #include "../netinet/in_systm.h"
  67: #include "../netinet/in_var.h"
  68: #include "../netinet/ip.h"
  69: #include "../netinet/if_ether.h"
  70: #endif
  71: 
  72: #ifdef NS
  73: #include "../netns/ns.h"
  74: #include "../netns/ns_if.h"
  75: #endif
  76: 
  77: #include "if_ecreg.h"
  78: #include "if_uba.h"
  79: #include "../pdpuba/ubavar.h"
  80: 
  81: #define MAPBUFDESC  (((btoc(2048) - 1) << 8 ) | RW)
  82: #define BUFP        ((caddr_t)0120000)
  83: #undef  ECRHBF
  84: #define ECRHBF      11
  85: #define ECNUMBUFS   (ECRHBF + 1)
  86: 
  87: extern  struct  ifnet loif;
  88:     int ecattach(), ecinit(), ecioctl(), ecoutput(), ecunjam();
  89:     struct  uba_device *ecinfo[NEC];
  90:     u_short ecstd[] = { 0 };
  91:     struct  uba_driver ecdriver =
  92:         { 0, 0, ecattach, 0, ecstd, "ec", ecinfo };
  93:     struct  mbuf *ecget();
  94: 
  95: /*
  96:  * Ethernet software status per interface.
  97:  *
  98:  * Each interface is referenced by a network interface structure,
  99:  * es_if, which the routing code uses to locate the interface.
 100:  * This structure contains the output queue for the interface, its address, ...
 101: */
 102:     struct  ec_softc {
 103:         struct  arpcom es_ac;   /* common Ethernet structures */
 104: #define es_if   es_ac.ac_if     /* network-visible interface */
 105: #define es_addr es_ac.ac_enaddr     /* hardware Ethernet address */
 106:         u_char  es_mask;    /* mask for current output delay */
 107:         u_char  es_oactive; /* is output active? */
 108:         memaddr es_buf[ECNUMBUFS]; /* virtual click buffer addresses */
 109:         } ec_softc[NEC];
 110: 
 111: /*
 112:  * Interface exists: make available by filling in network interface
 113:  * record.  System will initialize the interface when it is ready
 114:  * to accept packets.
 115:  */
 116: ecattach(ui)
 117:     struct uba_device *ui;
 118:     {
 119:     struct ec_softc *es = &ec_softc[ui->ui_unit];
 120: register struct ifnet *ifp = &es->es_if;
 121: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
 122:     int i, j;
 123:     u_char *cp;
 124: 
 125:     ifp->if_unit = ui->ui_unit;
 126:     ifp->if_name = "ec";
 127:     ifp->if_mtu = ETHERMTU;
 128: 
 129: /* Read the ethernet address off the board, one nibble at a time.  */
 130: 
 131:     addr->ec_xcr = EC_UECLR; /* zero address pointer */
 132:     addr->ec_rcr = EC_AROM;
 133:     cp = es->es_addr;
 134: #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
 135:     for (i=0; i < sizeof (es->es_addr); i++)
 136:         {
 137:         *cp = 0;
 138:         for (j=0; j<=4; j+=4)
 139:             {
 140:             *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
 141:             NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
 142:             }
 143:         cp++;
 144:         }
 145:     printf("ec%d: addr %s\n", ui->ui_unit, ether_sprintf(es->es_addr));
 146:     ifp->if_init = ecinit;
 147:     ifp->if_ioctl = ecioctl;
 148:     ifp->if_output = ecoutput;
 149:     ifp->if_reset = 0;
 150:     ifp->if_flags = IFF_BROADCAST;
 151: /*
 152:  * the (memaddr)(0177000) below is UMR28 translated into clicks.
 153: */
 154:     for (i = 0; i < ECNUMBUFS; i++)
 155:         es->es_buf[i] = (memaddr)(0177000) + (memaddr)(btoc(2048) * i);
 156:     if_attach(ifp);
 157:     }
 158: 
 159: /*
 160:  * Initialization of interface; clear recorded pending operations.
 161: */
 162: ecinit(unit)
 163:     int unit;
 164:     {
 165:     struct  ec_softc *es = &ec_softc[unit];
 166:     struct  ecdevice *addr;
 167: register struct ifnet *ifp = &es->es_if;
 168:     int i, s;
 169: 
 170:     /* not yet, if address still unknown */
 171:     if  (ifp->if_addrlist == (struct ifaddr *)0)
 172:         return;
 173: 
 174:     /*
 175: 	 * Hang receive buffers and start any pending writes.
 176: 	 * Writing into the rcr also makes sure the memory
 177: 	 * is turned on.
 178: 	 */
 179:     if  ((ifp->if_flags & IFF_RUNNING) == 0)
 180:         {
 181:         addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 182:         s = splhigh();
 183:         /*
 184: 		 * write our ethernet address into the address recognition ROM
 185: 		 * so we can always use the same EC_READ bits (referencing ROM),
 186: 		 * in case we change the address sometime.
 187: 		 * Note that this is safe here as the receiver is NOT armed.
 188: 		 */
 189:         ec_setaddr(es->es_addr, unit);
 190:         /*
 191: 		 * Arm the receiver
 192: 		 */
 193:         for (i = ECRHBF; i >= ECRLBF; i--)
 194:             addr->ec_rcr = EC_READ | i;
 195:         es->es_oactive = 0;
 196:         es->es_mask = 1;
 197:         es->es_if.if_flags |= IFF_RUNNING;
 198:         if  (es->es_if.if_snd.ifq_head)
 199:             ecstart(unit);
 200:         splx(s);
 201:         }
 202:     }
 203: 
 204: /*
 205:  * Start output on interface.  Get another datagram to send
 206:  * off of the interface queue, and copy it to the interface
 207:  * before starting the output.
 208:  */
 209: ecstart(unit)
 210:     int unit;
 211:     {
 212: register struct ec_softc *es = &ec_softc[unit];
 213:     struct  ecdevice *addr;
 214:     struct  mbuf *m;
 215: 
 216:     if  ((es->es_if.if_flags & IFF_RUNNING) == 0)
 217:         return;
 218:     IF_DEQUEUE(&es->es_if.if_snd, m);
 219:     if  (m == 0)
 220:         return;
 221:     ecput(es->es_buf[ECTBF], m);
 222:     addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 223:     addr->ec_xcr = EC_WRITE|ECTBF;
 224:     es->es_oactive = 1;
 225:     }
 226: 
 227: /*
 228:  * Ethernet interface transmitter interrupt.
 229:  * Start another output if more data to send.
 230:  */
 231: ecxint(unit)
 232:     int unit;
 233:     {
 234: register struct ec_softc *es = &ec_softc[unit];
 235: register struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 236: register int s;
 237: 
 238:     if  (es->es_oactive == 0)
 239:         return;
 240:     if  (!(addr->ec_xcr&EC_XDONE) || (addr->ec_xcr&EC_XBN) != ECTBF)
 241:         {
 242:         printf("ec%d: stray xint, xcr=%b\n",unit,addr->ec_xcr,EC_XBITS);
 243:         es->es_oactive = 0;
 244:         addr->ec_xcr = EC_XCLR;
 245:         return;
 246:         }
 247:     es->es_if.if_opackets++;
 248:     es->es_oactive = 0;
 249:     es->es_mask = 1;
 250:     addr->ec_xcr = EC_XCLR;
 251:     s = splimp();
 252:     if  (es->es_if.if_snd.ifq_head)
 253:         ecstart(unit);
 254:     splx(s);
 255:     }
 256: 
 257: /*
 258:  * Collision on ethernet interface.  Do exponential
 259:  * backoff, and retransmit.  If have backed off all
 260:  * the way print warning diagnostic, and drop packet.
 261:  */
 262: eccollide(unit)
 263:     int unit;
 264:     {
 265: register struct ec_softc *es = &ec_softc[unit];
 266: register struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 267: register int    i;
 268:     long    delay;
 269: 
 270:     es->es_if.if_collisions++;
 271:     if  (es->es_oactive == 0)
 272:         return;
 273:     if  (es->es_mask++ >= 16)
 274:         {
 275:         es->es_if.if_oerrors++;
 276:         printf("ec%d: send err\n", unit);
 277:         /*
 278: 		 * Reset interface, then requeue rcv buffers.
 279: 		 * Some incoming packets may be lost, but that
 280: 		 * can't be helped.
 281: 		 */
 282:         addr->ec_xcr = EC_UECLR;
 283:         for (i=ECRHBF; i>=ECRLBF; i--)
 284:             addr->ec_rcr = EC_READ|i;
 285:         /*
 286: 		 * Reset and transmit next packet (if any).
 287: 		 */
 288:         es->es_oactive = 0;
 289:         es->es_mask = 1;
 290:         if  (es->es_if.if_snd.ifq_head)
 291:             ecstart(unit);
 292:         return;
 293:         }
 294:     /*
 295: 	 * use a timeout instead of a delay loop - the loop hung the system
 296: 	 * when someone unscrewed a terminator on the net.
 297: 	 *
 298: 	 * this isn't exponential, but it sure beats a hung up system in the
 299: 	 * face of a broken cable.
 300: 	 */
 301:     TIMEOUT(ecunjam, addr, es->es_mask);
 302:     }
 303: 
 304: ecunjam(addr)
 305:     struct  ecdevice *addr;
 306:     {
 307: 
 308:     /*
 309: 	 * Clear the controller's collision flag, thus enabling retransmit.
 310: 	 */
 311:     addr->ec_xcr = EC_CLEAR;
 312:     }
 313: 
 314: /*
 315:  * Ethernet interface receiver interrupt.
 316:  * If input error just drop packet.
 317:  * Otherwise examine packet to determine type.  If can't determine length
 318:  * from type, then have to drop packet.  Othewise decapsulate
 319:  * packet based on type and pass to type specific higher-level
 320:  * input routine.
 321:  */
 322: 
 323: ecrint(unit)
 324:     int unit;
 325:     {
 326:     struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 327: 
 328:     while   (addr->ec_rcr & EC_RDONE)
 329:         ecread(unit);
 330:     }
 331: 
 332: ecread(unit)
 333:     int unit;
 334:     {
 335: register struct ec_softc *es = &ec_softc[unit];
 336: register struct ether_header *ec;
 337: register struct ifqueue *inq;
 338:     struct  ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 339:         struct  mbuf *m;
 340:     int len, off = 0, resid, ecoff, rbuf, type;
 341:     u_char  *ecbuf;
 342:     segm    sav5;
 343: 
 344:     es->es_if.if_ipackets++;
 345:     rbuf = addr->ec_rcr & EC_RBN;
 346:     if  (rbuf < ECRLBF || rbuf > ECRHBF)
 347:         panic("ecrint");    /* sanity */
 348: /*
 349:  * we change SDSA5 only while NOT looking at mbufs (there might be some on SEG5)
 350:  * and carefully restore it before calling 'ecget' who uses mbcopyin().
 351:  * the save/restore seg routines are ifdef'd on SUPERVISOR (which had better
 352:  * be set when compiling the network stuff!!).
 353: */
 354:     saveseg5(sav5);
 355:     mapseg5(es->es_buf[rbuf], MAPBUFDESC);
 356:     ecbuf = (u_char *)SEG5;
 357:     ecoff = *(short *)SEG5;
 358:     if  (ecoff <= ECRDOFF || ecoff > 2046)
 359:         {
 360:         es->es_if.if_ierrors++;
 361: #ifdef  notyet
 362:         printf("ec%d ecoff=0%o rbuf=0%o\n", unit, ecoff, rbuf);
 363: #endif
 364:         goto setup;
 365:         }
 366: 
 367:     /*
 368: 	 * Get input data length.
 369: 	 * Get pointer to ethernet header (in input buffer).
 370: 	 * Deal with trailer protocol: if type is trailer type
 371: 	 * get true type from first 16-bit word past data.
 372: 	 * Remember that type was trailer by setting off.
 373: 	 */
 374:     len = ecoff - ECRDOFF - sizeof (struct ether_header);
 375:     ec = (struct ether_header *)(ecbuf + ECRDOFF);
 376:     ec->ether_type = ntohs((u_short)ec->ether_type);
 377: #ifdef weliketrailers
 378: #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off))))
 379:     if  (ec->ether_type >= ETHERTYPE_TRAIL &&
 380:             ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)
 381:         {
 382:         off = (ec->ether_type - ETHERTYPE_TRAIL) * 512;
 383:         if  (off >= ETHERMTU)
 384:             goto setup;     /* sanity */
 385:         ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
 386:         resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
 387:         if  (off + resid > len)
 388:             goto setup;     /* sanity */
 389:         len = off + resid;
 390:         }
 391:     else
 392:         off = 0;
 393:     if  (!len)
 394:         goto setup;
 395: #else
 396:     if  (!len || (ec->ether_type >= ETHERTYPE_TRAIL &&
 397:             ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER))
 398:         {
 399:         printf("ec%d type=%x len=%d\n", unit, ec->ether_type,len);
 400:         es->es_if.if_ierrors++;
 401:         goto setup;
 402:         }
 403: #endif
 404:     /*
 405: 	 * Pull packet off interface.  Off is nonzero if packet
 406: 	 * has trailing header; ecget will then force this header
 407: 	 * information to be at the front, but we still have to drop
 408: 	 * the type and length which are at the front of any trailer data.
 409: 	 */
 410:     type = ec->ether_type;      /* save before restoring mapping */
 411:     restorseg5(sav5);       /* put it back now! */
 412:     m = ecget(es->es_buf[rbuf], len, off, &es->es_if);
 413:     if  (m == 0)
 414:         goto setup;
 415: #ifdef weliketrailers
 416:     if  (off)
 417:         {
 418:         struct  ifnet *ifp;
 419: 
 420:         ifp = *(mtod(m, struct ifnet **));
 421:         m->m_off += 2 * sizeof (u_short);
 422:         m->m_len -= 2 * sizeof (u_short);
 423:         *(mtod(m, struct ifnet **)) = ifp;
 424:         }
 425: #endif
 426:     switch  (type)
 427:         {
 428: #ifdef INET
 429:         case    ETHERTYPE_IP:
 430:             schednetisr(NETISR_IP);
 431:             inq = &ipintrq;
 432:             break;
 433:         case    ETHERTYPE_ARP:
 434:             arpinput(&es->es_ac, m);
 435:             goto setup;
 436: #endif
 437: #ifdef NS
 438:         case    ETHERTYPE_NS:
 439:             schednetisr(NETISR_NS);
 440:             inq = &nsintrq;
 441:             break;
 442: #endif
 443:         default:
 444:             m_freem(m);
 445:             goto setup;
 446:         }
 447:     if  (IF_QFULL(inq))
 448:         {
 449:         IF_DROP(inq);
 450:         m_freem(m);
 451:         goto setup;
 452:         }
 453:     IF_ENQUEUE(inq, m);
 454: setup:
 455:     /* Reset for next packet. */
 456:     restorseg5(sav5);       /* put it back before leaving */
 457:     addr->ec_rcr = EC_READ|EC_RCLR|rbuf;
 458:     }
 459: 
 460: /*
 461:  * Ethernet output routine.
 462:  * Encapsulate a packet of type family for the local net.
 463:  * Use trailer local net encapsulation if enough data in first
 464:  * packet leaves a multiple of 512 bytes of data in remainder and trailers
 465:  * are allowed (which we should NEVER do).
 466:  * If destination is this address or broadcast, send packet to
 467:  * loop device to kludge around the fact that 3com interfaces can't
 468:  * talk to themselves.
 469:  */
 470: ecoutput(ifp, m0, dst)
 471:     struct  ifnet *ifp;
 472:     struct  mbuf *m0;
 473:     struct  sockaddr *dst;
 474:     {
 475:     int type, s, error, usetrailers;
 476:     u_char  edst[6];
 477:     struct  in_addr idst;
 478:     struct  ec_softc *es = &ec_softc[ifp->if_unit];
 479: register struct mbuf *m = m0;
 480: register struct ether_header *ec;
 481: register int off;
 482:     u_short *p;
 483:     struct  mbuf *mcopy = (struct mbuf *)0;
 484: 
 485:     if  ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 486:         {
 487:         error = ENETDOWN;
 488:         goto bad;
 489:         }
 490:     switch  (dst->sa_family)
 491:         {
 492: #ifdef INET
 493:         case    AF_INET:
 494:             idst = ((struct sockaddr_in *)dst)->sin_addr;
 495:             if  (!arpresolve(&es->es_ac, m, &idst, edst,
 496:                     &usetrailers))
 497:                 return(0);  /* if not yet resolved */
 498:             if  (!bcmp(edst, etherbroadcastaddr, sizeof(edst)))
 499:                 mcopy = m_copy(m, 0, (int)M_COPYALL);
 500:             off = ntohs((u_short)mtod(m, struct ip *)->ip_len)
 501:                     - m->m_len;
 502:         /* need per host negotiation */
 503:             if  (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
 504:                     m->m_off >= MMINOFF + 2 * sizeof (u_short))
 505:                 {
 506:                 type = ETHERTYPE_TRAIL + (off>>9);
 507:                 m->m_off -= 2 * sizeof (u_short);
 508:                 m->m_len += 2 * sizeof (u_short);
 509:                 p = mtod(m, u_short *);
 510:                 *p++ =ntohs((u_short)ETHERTYPE_IP);
 511:                 *p = ntohs((u_short)m->m_len);
 512:                 goto gottrailertype;
 513:                 }
 514:             type = ETHERTYPE_IP;
 515:             off = 0;
 516:             goto gottype;
 517: #endif
 518: #ifdef NS
 519:         case    AF_NS:
 520:             bcopy(&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
 521:                     edst, sizeof (edst));
 522:             if  (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,
 523:                     sizeof(edst)))
 524:                 mcopy = m_copy(m, 0, (int)M_COPYALL);
 525:             else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
 526:                     sizeof(edst)))
 527:                 return(looutput(&loif, m, dst));
 528:             type = ETHERTYPE_NS;
 529:             off = 0;
 530:             goto gottype;
 531: #endif
 532:         case    AF_UNSPEC:
 533:             ec = (struct ether_header *)dst->sa_data;
 534:             bcopy(ec->ether_dhost, (caddr_t)edst, sizeof (edst));
 535:             type = ec->ether_type;
 536:             goto gottype;
 537:         default:
 538:             printf("ec%d: af%d\n", ifp->if_unit, dst->sa_family);
 539:             error = EAFNOSUPPORT;
 540:             goto bad;
 541:         }
 542: gottrailertype:
 543:     /*
 544: 	 * Packet to be sent as trailer: move first packet
 545: 	 * (control information) to end of chain.
 546: 	 */
 547:     while   (m->m_next)
 548:         m = m->m_next;
 549:     m->m_next = m0;
 550:     m = m0->m_next;
 551:     m0->m_next = 0;
 552:     m0 = m;
 553: gottype:
 554:     /*
 555: 	 * Add local net header.  If no space in first mbuf,
 556: 	 * allocate another.
 557: 	 */
 558:     if  (m->m_off > MMAXOFF ||
 559:             MMINOFF + sizeof (struct ether_header) > m->m_off)
 560:         {
 561:         m = m_get(M_DONTWAIT, MT_HEADER);
 562:         if  (m == 0)
 563:             {
 564:             error = ENOBUFS;
 565:             goto bad;
 566:             }
 567:         m->m_next = m0;
 568:         m->m_off = MMINOFF;
 569:         m->m_len = sizeof (struct ether_header);
 570:         }
 571:     else
 572:         {
 573:         m->m_off -= sizeof (struct ether_header);
 574:         m->m_len += sizeof (struct ether_header);
 575:         }
 576:     ec = mtod(m, struct ether_header *);
 577:     bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst));
 578:     bcopy(es->es_addr, (caddr_t)ec->ether_shost, sizeof(ec->ether_shost));
 579:     ec->ether_type = htons((u_short)type);
 580: 
 581:     /*
 582: 	 * Queue message on interface, and start output if interface
 583: 	 * not yet active.
 584: 	 */
 585:     s = splhigh();
 586:     if  (IF_QFULL(&ifp->if_snd))
 587:         {
 588:         IF_DROP(&ifp->if_snd);
 589:         error = ENOBUFS;
 590:         goto qfull;
 591:         }
 592:     IF_ENQUEUE(&ifp->if_snd, m);
 593:     if  (es->es_oactive == 0)
 594:         ecstart(ifp->if_unit);
 595:     splx(s);
 596:     error = mcopy ? looutput(&loif, mcopy, dst) : 0;
 597:     return(error);
 598: qfull:
 599:     m0 = m;
 600:     splx(s);
 601: bad:
 602:     m_freem(m0);
 603:     if  (mcopy)
 604:         m_freem(mcopy);
 605:     return(error);
 606:     }
 607: 
 608: /*
 609:  * Routine to copy from mbuf chain to transmit
 610:  * buffer in UNIBUS memory.
 611:  * If packet size is less than the minimum legal size,
 612:  * the buffer is expanded.  We probably should zero out the extra
 613:  * bytes for security, but that would slow things down.
 614:  */
 615: ecput(ecbuf, m)
 616:     memaddr ecbuf;
 617:     struct  mbuf *m;
 618:     {
 619: register struct mbuf *mp;
 620: register u_short off;
 621:     segm    sav5;
 622: 
 623:     for (off = 2048, mp = m; mp; mp = mp->m_next)
 624:         off -= mp->m_len;
 625:     if  (2048 - off < ETHERMIN + sizeof (struct ether_header))
 626:         off = 2048 - ETHERMIN - sizeof (struct ether_header);
 627:     saveseg5(sav5);
 628:     mapseg5(ecbuf, MAPBUFDESC);
 629:     *(u_short *)SEG5 = off;
 630:     restorseg5(sav5);
 631:     for (mp = m; mp; mp = mp->m_next)
 632:         {
 633:         register unsigned len = mp->m_len;
 634: 
 635:         if  (len == 0)
 636:             continue;
 637:         mbcopyout(mtod(mp, caddr_t), ecbuf, off, len);
 638:         off += len;
 639:         }
 640:     m_freem(m);
 641:     }
 642: 
 643: /*
 644:  * Routine to copy from UNIBUS memory into mbufs.
 645: */
 646: struct mbuf *
 647: ecget(ecbuf, totlen, off0, ifp)
 648:     memaddr ecbuf;
 649:     int totlen, off0;
 650:     struct  ifnet *ifp;
 651:     {
 652: register struct mbuf *m;
 653: register int off = off0, len;
 654:     struct  mbuf *top = 0, **mp = &top;
 655:     u_short distance;
 656: 
 657:     distance = ECRDOFF + sizeof (struct ether_header);
 658:     while   (totlen > 0)
 659:         {
 660:         MGET(m, M_DONTWAIT, MT_DATA);
 661:         if  (m == 0)
 662:             goto bad;
 663:         if  (off)
 664:             {
 665:             len = totlen - off;
 666:             distance = ECRDOFF + off + sizeof (struct ether_header);
 667:             }
 668:         else
 669:             len = totlen;
 670:         if  (ifp)
 671:             len += sizeof(ifp);
 672:         if  (len >= NBPG)
 673:             {
 674:             MCLGET(m);
 675:             if  (m->m_len == CLBYTES)
 676:                 m->m_len = len = MIN(len, CLBYTES);
 677:             else
 678:                 m->m_len = len = MIN(MLEN, len);
 679:             }
 680:         else
 681:             m->m_len = len = MIN(MLEN, len);
 682:         if  (ifp)
 683:             {
 684:             /* Prepend interface pointer to first mbuf.  */
 685:             *(mtod(m, struct ifnet **)) = ifp;
 686:             len -= sizeof(ifp);
 687:             }
 688:         mbcopyin(ecbuf, distance,
 689:               ifp ? mtod(m,caddr_t)+sizeof(ifp) : mtod(m,caddr_t), len);
 690:         ifp = (struct ifnet *)0;
 691:         distance += len;
 692:         *mp = m;
 693:         mp = &m->m_next;
 694:         if  (off == 0)
 695:             {
 696:             totlen -= len;
 697:             continue;
 698:             }
 699:         off += len;
 700:         if  (off == totlen)
 701:             {
 702:             distance = ECRDOFF + sizeof (struct ether_header);
 703:             off = 0;
 704:             totlen = off0;
 705:             }
 706:         }
 707:     return(top);
 708: bad:
 709:     m_freem(top);
 710:     return(0);
 711:     }
 712: 
 713: /*
 714:  * Process an ioctl request.
 715:  */
 716: ecioctl(ifp, cmd, data)
 717: register struct ifnet *ifp;
 718:     int cmd;
 719:     caddr_t data;
 720:     {
 721: register struct ifaddr *ifa = (struct ifaddr *)data;
 722:     struct  ec_softc *es = &ec_softc[ifp->if_unit];
 723:     struct  ecdevice *addr;
 724:     int s = splhigh(), error = 0;
 725: 
 726:     addr = (struct ecdevice *)ecinfo[ifp->if_unit]->ui_addr;
 727:     switch  (cmd)
 728:         {
 729:         case    SIOCSIFADDR:
 730:             ifp->if_flags |= IFF_UP;
 731:             switch  (ifa->ifa_addr.sa_family)
 732:                 {
 733: #ifdef INET
 734:                 case    AF_INET:
 735:                     ecinit(ifp->if_unit);
 736:                     ((struct arpcom *)ifp)->ac_ipaddr =
 737:                         IA_SIN(ifa)->sin_addr;
 738:                     arpwhohas((struct arpcom *)ifp,
 739:                         &IA_SIN(ifa)->sin_addr);
 740:                     break;
 741: #endif
 742: #ifdef NS
 743:                 case    AF_NS:
 744:                     {
 745:             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 746: 
 747:                     if  (ns_nullhost(*ina))
 748:                     ina->x_host = *(union ns_host *)
 749:                             (es->es_addr);
 750:                     else
 751:                         {
 752:                 /*
 753: 				 * The manual says we can't change the address
 754: 				 * while the receiver is armed,
 755: 				 * so reset everything
 756: 				 */
 757:                         ifp->if_flags &= ~IFF_RUNNING;
 758:                         bcopy(ina->x_host.c_host,
 759:                             es->es_addr,
 760:                             sizeof(es->es_addr));
 761:                         }
 762:                     ecinit(ifp->if_unit); /* do ec_setaddr*/
 763:                     break;
 764:                     }
 765: #endif
 766:                 default:
 767:                     ecinit(ifp->if_unit);
 768:                     break;
 769:                 }
 770:             break;
 771:         case    SIOCSIFFLAGS:
 772:             if  ((ifp->if_flags & IFF_UP) == 0 &&
 773:                   ifp->if_flags & IFF_RUNNING)
 774:                 {
 775:                 addr->ec_xcr = EC_UECLR;
 776:                 ifp->if_flags &= ~IFF_RUNNING;
 777:                 }
 778:             else if (ifp->if_flags & IFF_UP &&
 779:                   (ifp->if_flags & IFF_RUNNING) == 0)
 780:                 ecinit(ifp->if_unit);
 781:             break;
 782:         default:
 783:             error = EINVAL;
 784:         }
 785:     splx(s);
 786:     return(error);
 787:     }
 788: 
 789: ec_setaddr(physaddr,unit)
 790:     u_char  *physaddr;
 791:     int unit;
 792:     {
 793:     struct  ec_softc *es = &ec_softc[unit];
 794:     struct  uba_device *ui = ecinfo[unit];
 795:     struct  ecdevice *addr = (struct ecdevice *)ui->ui_addr;
 796: register char nibble;
 797: register int i, j;
 798: 
 799:     /*
 800: 	 * Use the ethernet address supplied
 801: 	 * Note that we do a UECLR here, so the receive buffers
 802: 	 * must be requeued.
 803: 	 */
 804: 
 805: #ifdef DEBUG
 806:     printf("ec_setaddr: setting address for unit %d = %s",
 807:         unit, ether_sprintf(physaddr));
 808: #endif
 809:     addr->ec_xcr = EC_UECLR;
 810:     addr->ec_rcr = 0;
 811:     /* load requested address */
 812:     for (i = 0; i < 6; i++)
 813:         { /* 6 bytes of address */
 814:         es->es_addr[i] = physaddr[i];
 815:         nibble = physaddr[i] & 0xf; /* lower nibble */
 816:         addr->ec_rcr = (nibble << 8);
 817:         addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
 818:         addr->ec_rcr = (nibble << 8);
 819:         for (j=0; j < 4; j++)
 820:             {
 821:             addr->ec_rcr = 0;
 822:             addr->ec_rcr = EC_ASTEP; /* step counter */
 823:             addr->ec_rcr = 0;
 824:             }
 825:         nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */
 826:         addr->ec_rcr = (nibble << 8);
 827:         addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
 828:         addr->ec_rcr = (nibble << 8);
 829:         for (j=0; j < 4; j++)
 830:             {
 831:             addr->ec_rcr = 0;
 832:             addr->ec_rcr = EC_ASTEP; /* step counter */
 833:             addr->ec_rcr = 0;
 834:             }
 835:         }
 836: #ifdef DEBUG
 837:     /*
 838: 	 * Read the ethernet address off the board, one nibble at a time.
 839: 	 */
 840:     addr->ec_xcr = EC_UECLR;
 841:     addr->ec_rcr = 0; /* read RAM */
 842:     cp = es->es_addr;
 843: #undef NEXTBIT
 844: #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0
 845:     for (i=0; i < sizeof (es->es_addr); i++)
 846:         {
 847:         *cp = 0;
 848:         for (j=0; j<=4; j+=4)
 849:             {
 850:             *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
 851:             NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
 852:             }
 853:         cp++;
 854:         }
 855:     printf("ec_setaddr: RAM address for unit %d = %s",
 856:         unit, ether_sprintf(physaddr));
 857: #endif
 858:     }
 859: #endif

Defined functions

ec_setaddr defined in line 789; used 1 times
ecattach defined in line 116; used 2 times
eccollide defined in line 262; never used
ecget defined in line 646; used 2 times
ecinit defined in line 162; used 6 times
ecioctl defined in line 716; used 2 times
ecoutput defined in line 470; used 2 times
ecput defined in line 615; used 1 times
ecread defined in line 332; used 1 times
ecrint defined in line 323; never used
ecstart defined in line 209; used 4 times
ecunjam defined in line 304; used 2 times
ecxint defined in line 231; never used

Defined variables

ec_softc defined in line 109; used 9 times
ecdriver defined in line 91; never used
ecinfo defined in line 89; used 9 times
ecstd defined in line 90; used 1 times
  • in line 92

Defined struct's

ec_softc defined in line 102; used 18 times

Defined macros

BUFP defined in line 82; never used
ECNUMBUFS defined in line 85; used 2 times
ECRHBF defined in line 84; used 5 times
MAPBUFDESC defined in line 81; used 2 times
NEXTBIT defined in line 844; used 9 times
ecdataaddr defined in line 378; used 2 times
es_addr defined in line 105; used 11 times
es_if defined in line 104; used 15 times
Last modified: 1988-09-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4775
Valid CSS Valid XHTML 1.0 Strict