# 2.11BSD#431 - /usr/src/sys/pdpif/if_ec.c

##### Functions

    ec_setaddr        X
    ecattach          X
    eccollide         X
    ecget             X
    ecinit            X
    ecioctl           X
    ecoutput          X
    ecput             X
    ecread            X
    ecrint            X
    ecstart           X
    ecunjam           X
    ecxint            X

##### Variables

    ec_softc          X
    ecdriver          X
    ecinfo            X
    ecstd             X

##### Macros

    BUFP              X
    ECNUMBUFS         X
    ECRHBF            X
    MAPBUFDESC        X
    NEXTBIT           X
    ecdataaddr        X
    es_addr           X
    es_if             X

##### struct's

    ec_softc          X

       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

- in line 189

ecattach defined in line 116; used 2 times

- in line 88-92(2)

eccollide defined in line 262; never used
ecget defined in line 646; used 2 times

- in line 93, 412

ecinit defined in line 162; used 6 times

- in line 88, 146, 735, 762-767(2), 780

ecioctl defined in line 716; used 2 times

- in line 88, 147

ecoutput defined in line 470; used 2 times

- in line 88, 148

ecput defined in line 615; used 1 times

- in line 221

ecread defined in line 332; used 1 times

- in line 329

ecrint defined in line 323; never used
ecstart defined in line 209; used 4 times

- in line 199, 253, 291, 594

ecunjam defined in line 304; used 2 times

- in line 88, 301

ecxint defined in line 231; never used

#### Defined variables

ec_softc defined in line 109; used 9 times

- in line 119, 165, 212, 234, 265, 335, 478, 722, 793

ecdriver defined in line 91; never used
ecinfo defined in line 89; used 9 times

- in line 92, 181, 222, 235, 266, 326, 338, 726, 794

ecstd defined in line 90; used 1 times

- in line 92

#### Defined struct's

ec_softc defined in line 102; used 18 times

- in line 119(2), 165(2), 212(2), 234(2), 265(2), 335(2), 478(2), 722(2), 793(2)

#### Defined macros

BUFP defined in line 82; never used
ECNUMBUFS defined in line 85; used 2 times

- in line 108, 154

ECRHBF defined in line 84; used 5 times

- in line 83-85(2), 193, 283, 346

MAPBUFDESC defined in line 81; used 2 times

- in line 355, 628

NEXTBIT defined in line 844; used 9 times

- in line 141(4), 843, 851(4)

ecdataaddr defined in line 378; used 2 times

- in line 385-386(2)

es_addr defined in line 105; used 11 times

- in line 133-135(2), 145, 189, 578, 749, 759-760(2), 814, 842-845(2)

es_if defined in line 104; used 15 times

- in line 120, 167, 197-198(2), 216-218(2), 247-252(2), 270-275(2), 290, 344, 360, 400, 412

Last modified: 1988-09-04 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1874 |