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

##### Functions

    de_setaddr        X
    deattach          X
    deinit            X
    deintr            X
    deioctl           X
    deoutput          X
    deprobe           X
    deread            X
    derecv            X
    dereset           X
    destart           X
    dewait            X

##### Variables

    de_softc          X
    dedebug           X
    dedriver          X
    deinfo            X
    destd             X

##### Macros

    DSF_LOCK          X
    DSF_RUNNING       X
    DSF_SETADDR       X
    INCORE_BASE       X
    INCORE_SIZE       X
    LVAL_OFF          X
    NRCV              X
    NXMT              X
    PCBB_OFFSET       X
    RRENT_OFFSET      X
    RVAL_OFF          X
    UDBBUF_OFFSET     X
    XRENT_OFFSET      X
    dedataaddr        X
    ds_addr           X
    ds_if             X

##### struct's

    de_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_de.c	7.2 (Berkeley) 7/18/86
       7:  */
       8: #include "de.h"
       9: #if NDE > 0
      10:
      11: /*
      12:  * DEC DEUNA interface
      13:  *
      14:  *	Lou Salkind
      15:  *	New York University
      16:  *
      17:  * TODO:
      18:  *	timeout routine (get statistics)
      19:  */
      20: #include "../machine/pte.h"
      21:
      22: #include "param.h"
      23: #include "systm.h"
      24: #include "mbuf.h"
      25: #include "buf.h"
      26: #include "protosw.h"
      27: #include "socket.h"
      28: #include "vmmac.h"
      29: #include "ioctl.h"
      30: #include "errno.h"
      31: #include "syslog.h"
      32:
      33: #include "../net/if.h"
      34: #include "../net/netisr.h"
      35: #include "../net/route.h"
      36:
      37: #ifdef INET
      38: #include "../netinet/in.h"
      39: #include "../netinet/in_systm.h"
      40: #include "../netinet/in_var.h"
      41: #include "../netinet/ip.h"
      42: #include "../netinet/if_ether.h"
      43: #endif
      44:
      45: #ifdef NS
      46: #include "../netns/ns.h"
      47: #include "../netns/ns_if.h"
      48: #endif
      49:
      50: #include "../vax/cpu.h"
      51: #include "../vax/mtpr.h"
      52: #include "if_dereg.h"
      53: #include "if_uba.h"
      54: #include "../vaxuba/ubareg.h"
      55: #include "../vaxuba/ubavar.h"
      56:
      57: #define NXMT    3   /* number of transmit buffers */
      58: #define NRCV    7   /* number of receive buffers (must be > 1) */
      59:
      60: int dedebug = 0;
      61:
      62: int deprobe(), deattach(), deintr();
      63: struct  uba_device *deinfo[NDE];
      64: u_short destd[] = { 0 };
      65: struct  uba_driver dedriver =
      66:     { deprobe, 0, deattach, 0, destd, "de", deinfo };
      67: int deinit(),deoutput(),deioctl(),dereset();
      68:
      69:
      70: /*
      71:  * Ethernet software status per interface.
      72:  *
      73:  * Each interface is referenced by a network interface structure,
      74:  * ds_if, which the routing code uses to locate the interface.
      75:  * This structure contains the output queue for the interface, its address, ...
      76:  * We also have, for each interface, a UBA interface structure, which
      77:  * contains information about the UNIBUS resources held by the interface:
      78:  * map registers, buffered data paths, etc.  Information is cached in this
      79:  * structure for use by the if_uba.c routines in running the interface
      80:  * efficiently.
      81:  */
      82: struct  de_softc {
      83:     struct  arpcom ds_ac;       /* Ethernet common part */
      84: #define ds_if   ds_ac.ac_if     /* network-visible interface */
      85: #define ds_addr ds_ac.ac_enaddr     /* hardware Ethernet address */
      86:     int ds_flags;
      87: #define DSF_LOCK    1       /* lock out destart */
      88: #define DSF_RUNNING 2       /* board is enabled */
      89: #define DSF_SETADDR 4       /* physical address is changed */
      90:     int ds_ubaddr;      /* map info for incore structs */
      91:     struct  ifubinfo ds_deuba;  /* unibus resource structure */
      92:     struct  ifrw ds_ifr[NRCV];  /* unibus receive maps */
      93:     struct  ifxmt ds_ifw[NXMT]; /* unibus xmt maps */
      94:     /* the following structures are always mapped in */
      95:     struct  de_pcbb ds_pcbb;    /* port control block */
      96:     struct  de_ring ds_xrent[NXMT]; /* transmit ring entrys */
      97:     struct  de_ring ds_rrent[NRCV]; /* receive ring entrys */
      98:     struct  de_udbbuf ds_udbbuf;    /* UNIBUS data buffer */
      99:     /* end mapped area */
     100: #define INCORE_BASE(p)  ((char *)&(p)->ds_pcbb)
     101: #define RVAL_OFF(n) ((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0]))
     102: #define LVAL_OFF(n) ((char *)de_softc[0].n - INCORE_BASE(&de_softc[0]))
     103: #define PCBB_OFFSET RVAL_OFF(ds_pcbb)
     104: #define XRENT_OFFSET    LVAL_OFF(ds_xrent)
     105: #define RRENT_OFFSET    LVAL_OFF(ds_rrent)
     106: #define UDBBUF_OFFSET   RVAL_OFF(ds_udbbuf)
     107: #define INCORE_SIZE RVAL_OFF(ds_xindex)
     108:     int ds_xindex;      /* UNA index into transmit chain */
     109:     int ds_rindex;      /* UNA index into receive chain */
     110:     int ds_xfree;       /* index for next transmit buffer */
     111:     int ds_nxmit;       /* # of transmits in progress */
     112: } de_softc[NDE];
     113:
     114: deprobe(reg)
     115:     caddr_t reg;
     116: {
     117:     register int br, cvec;      /* r11, r10 value-result */
     118:     register struct dedevice *addr = (struct dedevice *)reg;
     119:     register i;
     120:
     121: #ifdef lint
     122:     br = 0; cvec = br; br = cvec;
     123:     i = 0; derint(i); deintr(i);
     124: #endif
     125:
     126:     /*
     127: 	 * Make sure self-test is finished before we screw with the board.
     128: 	 * Self-test on a DELUA can take 15 seconds (argh).
     129: 	 */
     130:     for (i = 0;
     131:          i < 160 &&
     132:          (addr->pcsr0 & PCSR0_FATI) == 0 &&
     133:          (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET;
     134:          ++i)
     135:         DELAY(100000);
     136:     if ((addr->pcsr0 & PCSR0_FATI) != 0 ||
     137:         (addr->pcsr1 & PCSR1_STMASK) != STAT_READY)
     138:         return(0);
     139:
     140:     addr->pcsr0 = 0;
     141:     DELAY(100);
     142:     addr->pcsr0 = PCSR0_RSET;
     143:     while ((addr->pcsr0 & PCSR0_INTR) == 0)
     144:         ;
     145:     /* make board interrupt by executing a GETPCBB command */
     146:     addr->pcsr0 = PCSR0_INTE;
     147:     addr->pcsr2 = 0;
     148:     addr->pcsr3 = 0;
     149:     addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;
     150:     DELAY(100000);
     151:     return(1);
     152: }
     153:
     154: /*
     155:  * Interface exists: make available by filling in network interface
     156:  * record.  System will initialize the interface when it is ready
     157:  * to accept packets.  We get the ethernet address here.
     158:  */
     159: deattach(ui)
     160:     struct uba_device *ui;
     161: {
     162:     register struct de_softc *ds = &de_softc[ui->ui_unit];
     163:     register struct ifnet *ifp = &ds->ds_if;
     164:     register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
     165:     int csr1;
     166:
     167:     ifp->if_unit = ui->ui_unit;
     168:     ifp->if_name = "de";
     169:     ifp->if_mtu = ETHERMTU;
     170:     ifp->if_flags = IFF_BROADCAST;
     171:
     172:     /*
     173: 	 * What kind of a board is this?
     174: 	 * The error bits 4-6 in pcsr1 are a device id as long as
     175: 	 * the high byte is zero.
     176: 	 */
     177:     csr1 = addr->pcsr1;
     178:     if (csr1 & 0xff60)
     179:         printf("de%d: broken\n", ui->ui_unit);
     180:     else if (csr1 & 0x10)
     181:         printf("de%d: delua\n", ui->ui_unit);
     182:     else
     183:         printf("de%d: deuna\n", ui->ui_unit);
     184:
     185:     /*
     186: 	 * Reset the board and temporarily map
     187: 	 * the pcbb buffer onto the Unibus.
     188: 	 */
     189:     addr->pcsr0 = 0;        /* reset INTE */
     190:     DELAY(100);
     191:     addr->pcsr0 = PCSR0_RSET;
     192:     (void)dewait(ui, "reset");
     193:
     194:     ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb,
     195:         sizeof (struct de_pcbb), 0);
     196:     addr->pcsr2 = ds->ds_ubaddr & 0xffff;
     197:     addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
     198:     addr->pclow = CMD_GETPCBB;
     199:     (void)dewait(ui, "pcbb");
     200:
     201:     ds->ds_pcbb.pcbb0 = FC_RDPHYAD;
     202:     addr->pclow = CMD_GETCMD;
     203:     (void)dewait(ui, "read addr ");
     204:
     205:     ubarelse(ui->ui_ubanum, &ds->ds_ubaddr);
     206:     bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
     207:         sizeof (ds->ds_addr));
     208:     printf("de%d: hardware address %s\n", ui->ui_unit,
     209:         ether_sprintf(ds->ds_addr));
     210:     ifp->if_init = deinit;
     211:     ifp->if_output = deoutput;
     212:     ifp->if_ioctl = deioctl;
     213:     ifp->if_reset = dereset;
     214:     ds->ds_deuba.iff_flags = UBA_CANTWAIT;
     215: #ifdef notdef
     216:     /* CAN WE USE BDP's ??? */
     217:     ds->ds_deuba.iff_flags |= UBA_NEEDBDP;
     218: #endif
     219:     if_attach(ifp);
     220: }
     221:
     222: /*
     223:  * Reset of interface after UNIBUS reset.
     224:  * If interface is on specified uba, reset its state.
     225:  */
     226: dereset(unit, uban)
     227:     int unit, uban;
     228: {
     229:     register struct uba_device *ui;
     230:
     231:     if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 ||
     232:         ui->ui_ubanum != uban)
     233:         return;
     234:     printf(" de%d", unit);
     235:     de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
     236:     de_softc[unit].ds_flags &= ~(DSF_LOCK | DSF_RUNNING);
     237:     deinit(unit);
     238: }
     239:
     240: /*
     241:  * Initialization of interface; clear recorded pending
     242:  * operations, and reinitialize UNIBUS usage.
     243:  */
     244: deinit(unit)
     245:     int unit;
     246: {
     247:     register struct de_softc *ds = &de_softc[unit];
     248:     register struct uba_device *ui = deinfo[unit];
     249:     register struct dedevice *addr;
     250:     register struct ifrw *ifrw;
     251:     register struct ifxmt *ifxp;
     252:     struct ifnet *ifp = &ds->ds_if;
     253:     int s;
     254:     struct de_ring *rp;
     255:     int incaddr;
     256:
     257:     /* not yet, if address still unknown */
     258:     if (ifp->if_addrlist == (struct ifaddr *)0)
     259:         return;
     260:
     261:     if (ds->ds_flags & DSF_RUNNING)
     262:         return;
     263:     if ((ifp->if_flags & IFF_RUNNING) == 0) {
     264:         if (if_ubaminit(&ds->ds_deuba, ui->ui_ubanum,
     265:             sizeof (struct ether_header), (int)btoc(ETHERMTU),
     266:             ds->ds_ifr, NRCV, ds->ds_ifw, NXMT) == 0) {
     267:             printf("de%d: can't initialize\n", unit);
     268:             ds->ds_if.if_flags &= ~IFF_UP;
     269:             return;
     270:         }
     271:         ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds),
     272:             INCORE_SIZE, 0);
     273:     }
     274:     addr = (struct dedevice *)ui->ui_addr;
     275:
     276:     /* set the pcbb block address */
     277:     incaddr = ds->ds_ubaddr + PCBB_OFFSET;
     278:     addr->pcsr2 = incaddr & 0xffff;
     279:     addr->pcsr3 = (incaddr >> 16) & 0x3;
     280:     addr->pclow = 0;    /* reset INTE */
     281:     DELAY(100);
     282:     addr->pclow = CMD_GETPCBB;
     283:     (void)dewait(ui, "pcbb");
     284:
     285:     /* set the transmit and receive ring header addresses */
     286:     incaddr = ds->ds_ubaddr + UDBBUF_OFFSET;
     287:     ds->ds_pcbb.pcbb0 = FC_WTRING;
     288:     ds->ds_pcbb.pcbb2 = incaddr & 0xffff;
     289:     ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;
     290:
     291:     incaddr = ds->ds_ubaddr + XRENT_OFFSET;
     292:     ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;
     293:     ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;
     294:     ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);
     295:     ds->ds_udbbuf.b_trlen = NXMT;
     296:     incaddr = ds->ds_ubaddr + RRENT_OFFSET;
     297:     ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;
     298:     ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;
     299:     ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);
     300:     ds->ds_udbbuf.b_rrlen = NRCV;
     301:
     302:     addr->pclow = CMD_GETCMD;
     303:     (void)dewait(ui, "wtring");
     304:
     305:     /* initialize the mode - enable hardware padding */
     306:     ds->ds_pcbb.pcbb0 = FC_WTMODE;
     307:     /* let hardware do padding - set MTCH bit on broadcast */
     308:     ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;
     309:     addr->pclow = CMD_GETCMD;
     310:     (void)dewait(ui, "wtmode");
     311:
     312:     /* set up the receive and transmit ring entries */
     313:     ifxp = &ds->ds_ifw[0];
     314:     for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
     315:         rp->r_segbl = ifxp->ifw_info & 0xffff;
     316:         rp->r_segbh = (ifxp->ifw_info >> 16) & 0x3;
     317:         rp->r_flags = 0;
     318:         ifxp++;
     319:     }
     320:     ifrw = &ds->ds_ifr[0];
     321:     for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
     322:         rp->r_slen = sizeof (struct de_buf);
     323:         rp->r_segbl = ifrw->ifrw_info & 0xffff;
     324:         rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
     325:         rp->r_flags = RFLG_OWN;     /* hang receive */
     326:         ifrw++;
     327:     }
     328:
     329:     /* start up the board (rah rah) */
     330:     s = splimp();
     331:     ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0;
     332:     ds->ds_if.if_flags |= IFF_RUNNING;
     333:     addr->pclow = PCSR0_INTE;       /* avoid interlock */
     334:     destart(unit);              /* queue output packets */
     335:     ds->ds_flags |= DSF_RUNNING;        /* need before de_setaddr */
     336:     if (ds->ds_flags & DSF_SETADDR)
     337:         de_setaddr(ds->ds_addr, unit);
     338:     addr->pclow = CMD_START | PCSR0_INTE;
     339:     splx(s);
     340: }
     341:
     342: /*
     343:  * Setup output on interface.
     344:  * Get another datagram to send off of the interface queue,
     345:  * and map it to the interface before starting the output.
     346:  */
     347: destart(unit)
     348:     int unit;
     349: {
     350:         int len;
     351:     struct uba_device *ui = deinfo[unit];
     352:     struct dedevice *addr = (struct dedevice *)ui->ui_addr;
     353:     register struct de_softc *ds = &de_softc[unit];
     354:     register struct de_ring *rp;
     355:     struct mbuf *m;
     356:     register int nxmit;
     357:
     358:     /*
     359: 	 * the following test is necessary, since
     360: 	 * the code is not reentrant and we have
     361: 	 * multiple transmission buffers.
     362: 	 */
     363:     if (ds->ds_flags & DSF_LOCK)
     364:         return;
     365:     for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {
     366:         IF_DEQUEUE(&ds->ds_if.if_snd, m);
     367:         if (m == 0)
     368:             break;
     369:         rp = &ds->ds_xrent[ds->ds_xfree];
     370:         if (rp->r_flags & XFLG_OWN)
     371:             panic("deuna xmit in progress");
     372:         len = if_ubaput(&ds->ds_deuba, &ds->ds_ifw[ds->ds_xfree], m);
     373:         if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
     374:             UBAPURGE(ds->ds_deuba.iff_uba,
     375:             ds->ds_ifw[ds->ds_xfree].ifw_bdp);
     376:         rp->r_slen = len;
     377:         rp->r_tdrerr = 0;
     378:         rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
     379:
     380:         ds->ds_xfree++;
     381:         if (ds->ds_xfree == NXMT)
     382:             ds->ds_xfree = 0;
     383:     }
     384:     if (ds->ds_nxmit != nxmit) {
     385:         ds->ds_nxmit = nxmit;
     386:         if (ds->ds_flags & DSF_RUNNING)
     387:             addr->pclow = PCSR0_INTE|CMD_PDMD;
     388:     }
     389: }
     390:
     391: /*
     392:  * Command done interrupt.
     393:  */
     394: deintr(unit)
     395:     int unit;
     396: {
     397:     struct uba_device *ui = deinfo[unit];
     398:     register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
     399:     register struct de_softc *ds = &de_softc[unit];
     400:     register struct de_ring *rp;
     401:     register struct ifxmt *ifxp;
     402:     short csr0;
     403:
     404:     /* save flags right away - clear out interrupt bits */
     405:     csr0 = addr->pcsr0;
     406:     addr->pchigh = csr0 >> 8;
     407:
     408:
     409:     ds->ds_flags |= DSF_LOCK;   /* prevent entering destart */
     410:     /*
     411: 	 * if receive, put receive buffer on mbuf
     412: 	 * and hang the request again
     413: 	 */
     414:     derecv(unit);
     415:
     416:     /*
     417: 	 * Poll transmit ring and check status.
     418: 	 * Be careful about loopback requests.
     419: 	 * Then free buffer space and check for
     420: 	 * more transmit requests.
     421: 	 */
     422:     for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {
     423:         rp = &ds->ds_xrent[ds->ds_xindex];
     424:         if (rp->r_flags & XFLG_OWN)
     425:             break;
     426:         ds->ds_if.if_opackets++;
     427:         ifxp = &ds->ds_ifw[ds->ds_xindex];
     428:         /* check for unusual conditions */
     429:         if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
     430:             if (rp->r_flags & XFLG_ERRS) {
     431:                 /* output error */
     432:                 ds->ds_if.if_oerrors++;
     433:                 if (dedebug)
     434:             printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",
     435:                     unit, rp->r_flags, XFLG_BITS,
     436:                     rp->r_tdrerr, XERR_BITS, rp->r_slen);
     437:             } else if (rp->r_flags & XFLG_ONE) {
     438:                 /* one collision */
     439:                 ds->ds_if.if_collisions++;
     440:             } else if (rp->r_flags & XFLG_MORE) {
     441:                 /* more than one collision */
     442:                 ds->ds_if.if_collisions += 2;   /* guess */
     443:             } else if (rp->r_flags & XFLG_MTCH) {
     444:                 /* received our own packet */
     445:                 ds->ds_if.if_ipackets++;
     446:                 deread(ds, &ifxp->ifrw,
     447:                     rp->r_slen - sizeof (struct ether_header));
     448:             }
     449:         }
     450:         if (ifxp->ifw_xtofree) {
     451:             m_freem(ifxp->ifw_xtofree);
     452:             ifxp->ifw_xtofree = 0;
     453:         }
     454:         /* check if next transmit buffer also finished */
     455:         ds->ds_xindex++;
     456:         if (ds->ds_xindex == NXMT)
     457:             ds->ds_xindex = 0;
     458:     }
     459:     ds->ds_flags &= ~DSF_LOCK;
     460:     destart(unit);
     461:
     462:     if (csr0 & PCSR0_RCBI) {
     463:         if (dedebug)
     464:             log(LOG_WARNING, "de%d: buffer unavailable\n", unit);
     465:         addr->pclow = PCSR0_INTE|CMD_PDMD;
     466:     }
     467: }
     468:
     469: /*
     470:  * Ethernet interface receiver interface.
     471:  * If input error just drop packet.
     472:  * Otherwise purge input buffered data path and examine
     473:  * packet to determine type.  If can't determine length
     474:  * from type, then have to drop packet.  Othewise decapsulate
     475:  * packet based on type and pass to type specific higher-level
     476:  * input routine.
     477:  */
     478: derecv(unit)
     479:     int unit;
     480: {
     481:     register struct de_softc *ds = &de_softc[unit];
     482:     register struct de_ring *rp;
     483:     int len;
     484:
     485:     rp = &ds->ds_rrent[ds->ds_rindex];
     486:     while ((rp->r_flags & RFLG_OWN) == 0) {
     487:         ds->ds_if.if_ipackets++;
     488:         if (ds->ds_deuba.iff_flags & UBA_NEEDBDP)
     489:             UBAPURGE(ds->ds_deuba.iff_uba,
     490:             ds->ds_ifr[ds->ds_rindex].ifrw_bdp);
     491:         len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
     492:             - 4;    /* don't forget checksum! */
     493:         /* check for errors */
     494:         if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
     495:             (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
     496:             (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
     497:             len < ETHERMIN || len > ETHERMTU) {
     498:             ds->ds_if.if_ierrors++;
     499:             if (dedebug)
     500:             printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",
     501:                 unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,
     502:                 RERR_BITS, len);
     503:         } else
     504:             deread(ds, &ds->ds_ifr[ds->ds_rindex], len);
     505:
     506:         /* hang the receive buffer again */
     507:         rp->r_lenerr = 0;
     508:         rp->r_flags = RFLG_OWN;
     509:
     510:         /* check next receive buffer */
     511:         ds->ds_rindex++;
     512:         if (ds->ds_rindex == NRCV)
     513:             ds->ds_rindex = 0;
     514:         rp = &ds->ds_rrent[ds->ds_rindex];
     515:     }
     516: }
     517:
     518: /*
     519:  * Pass a packet to the higher levels.
     520:  * We deal with the trailer protocol here.
     521:  */
     522: deread(ds, ifrw, len)
     523:     register struct de_softc *ds;
     524:     struct ifrw *ifrw;
     525:     int len;
     526: {
     527:     struct ether_header *eh;
     528:         struct mbuf *m;
     529:     int off, resid;
     530:     int s;
     531:     register struct ifqueue *inq;
     532:
     533:     /*
     534: 	 * Deal with trailer protocol: if type is trailer type
     535: 	 * get true type from first 16-bit word past data.
     536: 	 * Remember that type was trailer by setting off.
     537: 	 */
     538:     eh = (struct ether_header *)ifrw->ifrw_addr;
     539:     eh->ether_type = ntohs((u_short)eh->ether_type);
     540: #define dedataaddr(eh, off, type)   ((type)(((caddr_t)((eh)+1)+(off))))
     541:     if (eh->ether_type >= ETHERTYPE_TRAIL &&
     542:         eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
     543:         off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
     544:         if (off >= ETHERMTU)
     545:             return;     /* sanity */
     546:         eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
     547:         resid = ntohs(*(dedataaddr(eh, off+2, u_short *)));
     548:         if (off + resid > len)
     549:             return;     /* sanity */
     550:         len = off + resid;
     551:     } else
     552:         off = 0;
     553:     if (len == 0)
     554:         return;
     555:
     556:     /*
     557: 	 * Pull packet off interface.  Off is nonzero if packet
     558: 	 * has trailing header; if_ubaget will then force this header
     559: 	 * information to be at the front, but we still have to drop
     560: 	 * the type and length which are at the front of any trailer data.
     561: 	 */
     562:     m = if_ubaget(&ds->ds_deuba, ifrw, len, off, &ds->ds_if);
     563:     if (m == 0)
     564:         return;
     565:     if (off) {
     566:         struct ifnet *ifp;
     567:
     568:         ifp = *(mtod(m, struct ifnet **));
     569:         m->m_off += 2 * sizeof (u_short);
     570:         m->m_len -= 2 * sizeof (u_short);
     571:         *(mtod(m, struct ifnet **)) = ifp;
     572:     }
     573:     switch (eh->ether_type) {
     574:
     575: #ifdef INET
     576:     case ETHERTYPE_IP:
     577:         schednetisr(NETISR_IP);
     578:         inq = &ipintrq;
     579:         break;
     580:
     581:     case ETHERTYPE_ARP:
     582:         arpinput(&ds->ds_ac, m);
     583:         return;
     584: #endif
     585: #ifdef NS
     586:     case ETHERTYPE_NS:
     587:         schednetisr(NETISR_NS);
     588:         inq = &nsintrq;
     589:         break;
     590:
     591: #endif
     592:     default:
     593:         m_freem(m);
     594:         return;
     595:     }
     596:
     597:     s = splimp();
     598:     if (IF_QFULL(inq)) {
     599:         IF_DROP(inq);
     600:         splx(s);
     601:         m_freem(m);
     602:         return;
     603:     }
     604:     IF_ENQUEUE(inq, m);
     605:     splx(s);
     606: }
     607:
     608: /*
     609:  * Ethernet output routine.
     610:  * Encapsulate a packet of type family for the local net.
     611:  * Use trailer local net encapsulation if enough data in first
     612:  * packet leaves a multiple of 512 bytes of data in remainder.
     613:  */
     614: deoutput(ifp, m0, dst)
     615:     struct ifnet *ifp;
     616:     struct mbuf *m0;
     617:     struct sockaddr *dst;
     618: {
     619:     int type, s, error;
     620:     u_char edst[6];
     621:     struct in_addr idst;
     622:     register struct de_softc *ds = &de_softc[ifp->if_unit];
     623:     register struct mbuf *m = m0;
     624:     register struct ether_header *eh;
     625:     register int off;
     626:     int usetrailers;
     627:
     628:     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
     629:         error = ENETDOWN;
     630:         goto bad;
     631:     }
     632:     switch (dst->sa_family) {
     633:
     634: #ifdef INET
     635:     case AF_INET:
     636:         idst = ((struct sockaddr_in *)dst)->sin_addr;
     637:         if (!arpresolve(&ds->ds_ac, m, &idst, edst, &usetrailers))
     638:             return (0); /* if not yet resolved */
     639:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
     640:         if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
     641:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
     642:             type = ETHERTYPE_TRAIL + (off>>9);
     643:             m->m_off -= 2 * sizeof (u_short);
     644:             m->m_len += 2 * sizeof (u_short);
     645:             *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
     646:             *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
     647:             goto gottrailertype;
     648:         }
     649:         type = ETHERTYPE_IP;
     650:         off = 0;
     651:         goto gottype;
     652: #endif
     653: #ifdef NS
     654:     case AF_NS:
     655:         type = ETHERTYPE_NS;
     656:         bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
     657:         (caddr_t)edst, sizeof (edst));
     658:         off = 0;
     659:         goto gottype;
     660: #endif
     661:
     662:     case AF_UNSPEC:
     663:         eh = (struct ether_header *)dst->sa_data;
     664:         bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
     665:         type = eh->ether_type;
     666:         goto gottype;
     667:
     668:     default:
     669:         printf("de%d: can't handle af%d\n", ifp->if_unit,
     670:             dst->sa_family);
     671:         error = EAFNOSUPPORT;
     672:         goto bad;
     673:     }
     674:
     675: gottrailertype:
     676:     /*
     677: 	 * Packet to be sent as trailer: move first packet
     678: 	 * (control information) to end of chain.
     679: 	 */
     680:     while (m->m_next)
     681:         m = m->m_next;
     682:     m->m_next = m0;
     683:     m = m0->m_next;
     684:     m0->m_next = 0;
     685:     m0 = m;
     686:
     687: gottype:
     688:     /*
     689: 	 * Add local net header.  If no space in first mbuf,
     690: 	 * allocate another.
     691: 	 */
     692:     if (m->m_off > MMAXOFF ||
     693:         MMINOFF + sizeof (struct ether_header) > m->m_off) {
     694:         m = m_get(M_DONTWAIT, MT_HEADER);
     695:         if (m == 0) {
     696:             error = ENOBUFS;
     697:             goto bad;
     698:         }
     699:         m->m_next = m0;
     700:         m->m_off = MMINOFF;
     701:         m->m_len = sizeof (struct ether_header);
     702:     } else {
     703:         m->m_off -= sizeof (struct ether_header);
     704:         m->m_len += sizeof (struct ether_header);
     705:     }
     706:     eh = mtod(m, struct ether_header *);
     707:     eh->ether_type = htons((u_short)type);
     708:     bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
     709:     /* DEUNA fills in source address */
     710:
     711:     /*
     712: 	 * Queue message on interface, and start output if interface
     713: 	 * not yet active.
     714: 	 */
     715:     s = splimp();
     716:     if (IF_QFULL(&ifp->if_snd)) {
     717:         IF_DROP(&ifp->if_snd);
     718:         splx(s);
     719:         m_freem(m);
     720:         return (ENOBUFS);
     721:     }
     722:     IF_ENQUEUE(&ifp->if_snd, m);
     723:     destart(ifp->if_unit);
     724:     splx(s);
     725:     return (0);
     726:
     727: bad:
     728:     m_freem(m0);
     729:     return (error);
     730: }
     731:
     732: /*
     733:  * Process an ioctl request.
     734:  */
     735: deioctl(ifp, cmd, data)
     736:     register struct ifnet *ifp;
     737:     int cmd;
     738:     caddr_t data;
     739: {
     740:     register struct ifaddr *ifa = (struct ifaddr *)data;
     741:     register struct de_softc *ds = &de_softc[ifp->if_unit];
     742:     int s = splimp(), error = 0;
     743:
     744:     switch (cmd) {
     745:
     746:     case SIOCSIFADDR:
     747:         ifp->if_flags |= IFF_UP;
     748:         deinit(ifp->if_unit);
     749:
     750:         switch (ifa->ifa_addr.sa_family) {
     751: #ifdef INET
     752:         case AF_INET:
     753:             ((struct arpcom *)ifp)->ac_ipaddr =
     754:                 IA_SIN(ifa)->sin_addr;
     755:             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
     756:             break;
     757: #endif
     758: #ifdef NS
     759:         case AF_NS:
     760:             {
     761:             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
     762:
     763:             if (ns_nullhost(*ina))
     764:                 ina->x_host = *(union ns_host *)(ds->ds_addr);
     765:             else
     766:                 de_setaddr(ina->x_host.c_host,ifp->if_unit);
     767:             break;
     768:             }
     769: #endif
     770:         }
     771:         break;
     772:
     773:     case SIOCSIFFLAGS:
     774:         if ((ifp->if_flags & IFF_UP) == 0 &&
     775:             ds->ds_flags & DSF_RUNNING) {
     776:             ((struct dedevice *)
     777:                (deinfo[ifp->if_unit]->ui_addr))->pclow = 0;
     778:             DELAY(100);
     779:             ((struct dedevice *)
     780:                (deinfo[ifp->if_unit]->ui_addr))->pclow = PCSR0_RSET;
     781:             ds->ds_flags &= ~(DSF_LOCK | DSF_RUNNING);
     782:         } else if (ifp->if_flags & IFF_UP &&
     783:             (ds->ds_flags & DSF_RUNNING) == 0)
     784:             deinit(ifp->if_unit);
     785:         break;
     786:
     787:     default:
     788:         error = EINVAL;
     789:     }
     790:     splx(s);
     791:     return (error);
     792: }
     793:
     794: /*
     795:  * set ethernet address for unit
     796:  */
     797: de_setaddr(physaddr, unit)
     798:     u_char *physaddr;
     799:     int unit;
     800: {
     801:     register struct de_softc *ds = &de_softc[unit];
     802:     struct uba_device *ui = deinfo[unit];
     803:     register struct dedevice *addr= (struct dedevice *)ui->ui_addr;
     804:
     805:     if (! (ds->ds_flags & DSF_RUNNING))
     806:         return;
     807:
     808:     bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6);
     809:     ds->ds_pcbb.pcbb0 = FC_WTPHYAD;
     810:     addr->pclow = PCSR0_INTE|CMD_GETCMD;
     811:     if (dewait(ui, "address change") == 0) {
     812:         ds->ds_flags |= DSF_SETADDR;
     813:         bcopy(physaddr, ds->ds_addr, 6);
     814:     }
     815: }
     816:
     817: /*
     818:  * Await completion of the named function
     819:  * and check for errors.
     820:  */
     821: dewait(ui, fn)
     822:     register struct uba_device *ui;
     823:     char *fn;
     824: {
     825:     register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
     826:     register csr0;
     827:
     828:     while ((addr->pcsr0 & PCSR0_INTR) == 0)
     829:         ;
     830:     csr0 = addr->pcsr0;
     831:     addr->pchigh = csr0 >> 8;
     832:     if (csr0 & PCSR0_PCEI)
     833:         printf("de%d: %s failed, csr0=%b csr1=%b\n",
     834:             ui->ui_unit, fn, csr0, PCSR0_BITS,
     835:             addr->pcsr1, PCSR1_BITS);
     836:     return (csr0 & PCSR0_PCEI);
     837: }
     838: #endif

#### Defined functions

de_setaddr defined in line 797; used 2 times

- in line 337, 766

deattach defined in line 159; used 2 times

- in line 62-66(2)

deinit defined in line 244; used 5 times

- in line 67, 210, 237, 748, 784

deintr defined in line 394; used 2 times

- in line 62, 123

deioctl defined in line 735; used 2 times

- in line 67, 212

deoutput defined in line 614; used 2 times

- in line 67, 211

deprobe defined in line 114; used 2 times

- in line 62-66(2)

deread defined in line 522; used 2 times

- in line 446, 504

derecv defined in line 478; used 1 times

- in line 414

dereset defined in line 226; used 2 times

- in line 67, 213

destart defined in line 347; used 3 times

- in line 334, 460, 723

dewait defined in line 821; used 7 times

- in line 192, 199-203(2), 283, 303, 310, 811

#### Defined variables

de_softc defined in line 112; used 14 times

- in line 101-102(4), 162, 235-236(2), 247, 353, 399, 481, 622, 741, 801

dedebug defined in line 60; used 3 times

- in line 433, 463, 499

dedriver defined in line 65; never used
deinfo defined in line 63; used 8 times

- in line 66, 231, 248, 351, 397, 777-780(2), 802

destd defined in line 64; used 1 times

- in line 66

#### Defined struct's

de_softc defined in line 82; used 18 times

- in line 162(2), 247(2), 353(2), 399(2), 481(2), 523(2), 622(2), 741(2), 801(2)

#### Defined macros

DSF_LOCK defined in line 87; used 5 times

- in line 236, 363, 409, 459, 781

DSF_RUNNING defined in line 88; used 8 times

- in line 236, 261, 335, 386, 775, 781-783(2), 805

DSF_SETADDR defined in line 89; used 2 times

- in line 336, 812

INCORE_BASE defined in line 100; used 3 times

- in line 101-102(2), 271

INCORE_SIZE defined in line 107; used 1 times

- in line 272

LVAL_OFF defined in line 102; used 2 times

- in line 104-105(2)

NRCV defined in line 58; used 6 times

- in line 92-97(2), 266, 300, 321, 512

NXMT defined in line 57; used 8 times

- in line 93-96(2), 266, 295, 314, 365, 381, 456

PCBB_OFFSET defined in line 103; used 1 times

- in line 277

RRENT_OFFSET defined in line 105; used 1 times

- in line 296

RVAL_OFF defined in line 101; used 3 times

- in line 103-107(3)

UDBBUF_OFFSET defined in line 106; used 1 times

- in line 286

XRENT_OFFSET defined in line 104; used 1 times

- in line 291

dedataaddr defined in line 540; used 2 times

- in line 546-547(2)

ds_addr defined in line 85; used 6 times

- in line 206-209(3), 337, 764, 813

ds_if defined in line 84; used 14 times

- in line 163, 235, 252, 268, 332, 366, 426, 432, 439-445(3), 487, 498, 562

Last modified: 1987-08-22 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 296 |