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

##### Functions

    ec_setaddr        X
    ecattach          X
    eccollide         X
    ecget             X
    ecinit            X
    ecioctl           X
    ecoutput          X
    ecprobe           X
    ecput             X
    ecread            X
    ecreset           X
    ecrint            X
    ecstart           X
    ecubamem          X
    ecxint            X

##### Variables

    ec_softc          X
    ecdriver          X
    ecinfo            X
    ecstd             X

##### Macros

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

#### Defined functions

ec_setaddr defined in line 891; used 1 times

- in line 285

ecattach defined in line 197; used 2 times

- in line 56-60(2)

eccollide defined in line 355; used 2 times

- in line 56, 161

ecget defined in line 739; used 2 times

- in line 63, 486

ecinit defined in line 259; used 7 times

- in line 62, 227, 252, 841, 864-869(2), 881

ecioctl defined in line 821; used 2 times

- in line 62, 228

ecoutput defined in line 544; used 2 times

- in line 62, 229

ecprobe defined in line 151; used 2 times

- in line 56-60(2)

ecput defined in line 690; used 1 times

- in line 316

ecread defined in line 428; used 1 times

- in line 425

ecreset defined in line 242; used 2 times

- in line 62, 230

ecrint defined in line 419; used 2 times

- in line 56, 161

ecstart defined in line 305; used 4 times

- in line 295, 347, 390, 669

ecubamem defined in line 94; used 2 times

- in line 56-60(2)

ecxint defined in line 326; used 2 times

- in line 56, 161

#### Defined variables

ec_softc defined in line 87; used 10 times

- in line 200, 251, 262, 307, 329, 358, 431, 552, 827, 895

ecdriver defined in line 59; never used
ecinfo defined in line 57; used 10 times

- in line 60, 247, 277, 317, 331, 360, 422, 432, 831, 896

ecstd defined in line 58; used 1 times

- in line 60

#### Defined struct's

ec_softc defined in line 79; used 18 times

- in line 200(2), 262(2), 307(2), 329(2), 358(2), 431(2), 552(2), 827(2), 895(2)

#### Defined macros

ECBUFSIZE defined in line 53; used 3 times

- in line 119, 130, 142

NEXTBIT defined in line 943; used 9 times

- in line 221(4), 942, 948(4)

ecdataaddr defined in line 464; used 2 times

- in line 470-471(2)

es_addr defined in line 82; used 11 times

- in line 215-217(2), 226, 285, 653, 853, 862(2), 915, 941-944(2)

es_if defined in line 81; used 16 times

- in line 201, 251, 264, 293-294(2), 311-313(2), 342-346(2), 364, 374, 389, 439, 446-448(2), 486

Last modified: 1986-06-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 302 |