Annotation of 43BSDReno/sys/vaxif/if_de.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.