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

1.1       root        1: /*
                      2:  * Copyright (c) 1986 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Micom-Interlan Inc.
                      7:  *
                      8:  * Redistribution is only permitted until one year after the first shipment
                      9:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                     10:  * binary forms are permitted provided that: (1) source distributions retain
                     11:  * this entire copyright notice and comment, and (2) distributions including
                     12:  * binaries display the following acknowledgement:  This product includes
                     13:  * software developed by the University of California, Berkeley and its
                     14:  * contributors'' in the documentation or other materials provided with the
                     15:  * distribution and in all advertising materials mentioning features or use
                     16:  * of this software.  Neither the name of the University nor the names of
                     17:  * its contributors may be used to endorse or promote products derived from
                     18:  * this software without specific prior written permission.
                     19:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     20:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     21:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     22:  *
                     23:  *     @(#)if_ix.c     7.7 (Berkeley) 6/28/90
                     24:  */
                     25: 
                     26: #include "np.h"
                     27: #if NNP > 0
                     28: 
                     29: /*
                     30:  * Interlan NP100 Ethernet Communications Controller interface
                     31:  */
                     32: #include "machine/pte.h"
                     33: 
                     34: #include "param.h"
                     35: #include "systm.h"
                     36: #include "mbuf.h"
                     37: #include "buf.h"
                     38: #include "protosw.h"
                     39: #include "socket.h"
                     40: #include "vmmac.h"
                     41: #include "ioctl.h"
                     42: #include "errno.h"
                     43: 
                     44: #include "../net/if.h"
                     45: #include "../net/netisr.h"
                     46: #include "../net/route.h"
                     47: 
                     48: #ifdef INET
                     49: #include "../netinet/in.h"
                     50: #include "../netinet/in_systm.h"
                     51: #include "../netinet/in_var.h"
                     52: #include "../netinet/ip.h"
                     53: #include "../netinet/if_ether.h"
                     54: #endif
                     55: 
                     56: #ifdef NS
                     57: #include "../netns/ns.h"
                     58: #include "../netns/ns_if.h"
                     59: #endif
                     60: 
                     61: #include "../vax/cpu.h"
                     62: #include "../vax/mtpr.h"
                     63: #include "../vaxif/if_uba.h"
                     64: #include "../vaxuba/ubareg.h"
                     65: #include "../vaxuba/ubavar.h"
                     66: #include "../vaxuba/npreg.h"
                     67: #include "../vaxif/if_ix.h"
                     68: 
                     69: int    ixattach(), ixrint(), ixcint();
                     70: #define        ILUNIT(x)       minor(x)
                     71: int    ixinit(), ixioctl(), ixreset(), ixwatch(), ixstart();
                     72: int (*IxAttach)() = ixattach;
                     73: int (*IxReset)() = ixreset;
                     74: 
                     75: /*
                     76:  * Ethernet software status per interface.
                     77:  *
                     78:  * Each interface is referenced by a network interface structure,
                     79:  * ix_if, which the routing code uses to locate the interface.
                     80:  * This structure contains the output queue for the interface, its address, ...
                     81:  * We also have, for each interface, a UBA interface structure, which
                     82:  * contains information about the UNIBUS resources held by the interface:
                     83:  * map registers, buffered data paths, etc.  Information is cached in this
                     84:  * structure for use by the if_uba.c routines in running the interface
                     85:  * efficiently.
                     86:  */
                     87: struct ix_softc {
                     88:        struct  arpcom ix_ac;           /* Ethernet common part */
                     89: #define        ix_if   ix_ac.ac_if             /* network-visible interface */
                     90: #define        ix_addr ix_ac.ac_enaddr         /* hardware Ethernet address */
                     91:        int     ix_flags;
                     92: #define        IXF_OACTIVE     0x1             /* output is active */
                     93: #define        IXF_RCVPENDING  0x2             /* start rcv in ilcint */
                     94: #define        IXF_GOTUBA      0x4             /* unibus resources mapped */
                     95: #define        IXF_RUNNING     0x8             /* board is running */
                     96: #define        IXF_SETADDR     0x10            /* physical address is changed */
                     97: #define        IXF_STATPENDING 0x20            /* stat cmd pending */
                     98: #define        IXF_GOTCQE      0x40            /* np resources available */
                     99: #define        IXF_OWATCH      0x80            /* is output hung? */
                    100: #define        IXF_RWATCH      0x100           /* is input hung? */
                    101:        struct  ifuba ix_ifuba;         /* unibus resources */
                    102:        u_short ix_aid;                 /* Access Id returned by open DDL */
                    103:        u_short ix_badcqe;
                    104:        struct  npmaster *ix_mp;        /* Board physio request header */
                    105:        struct  npreq *ix_rrp;          /* Cached npreq for recv */
                    106:        struct  npreq *ix_wrp;          /* Cached npreq for xmit */
                    107:        short   ix_scaninterval;        /* interval of stat collection */
                    108: #define        IXWATCHINTERVAL 60              /* once every 60 seconds */
                    109:        union   ix_stats ix_stats;      /* holds on-board statistics */
                    110:        int     ix_ubaddr;              /* mapping registers of ix_stats */
                    111: } ix_softc[NNP];
                    112: extern struct uba_device *npdinfo[];
                    113: 
                    114: /*
                    115:  * Interface exists: make available by filling in network interface
                    116:  * record.  System will initialize the interface when it is ready
                    117:  * to accept packets.  We can't even get the ethernet address
                    118:  * or other interesting data until the board has been downloaded.
                    119:  * running ifconfig will attempt to start unit.
                    120:  */
                    121: ixattach(ui)
                    122:        struct uba_device *ui;
                    123: {
                    124:        register struct ix_softc *ix = &ix_softc[ui->ui_unit];
                    125:        register struct ifnet *ifp = &ix->ix_if;
                    126:        extern struct npmaster npmasters[];
                    127: 
                    128:        ifp->if_unit = ui->ui_unit;
                    129:        ifp->if_name = "ix";
                    130:        ifp->if_mtu = ETHERMTU;
                    131:        ifp->if_flags = IFF_BROADCAST;
                    132: 
                    133:        ifp->if_init = ixinit;
                    134:        ifp->if_output = ether_output;
                    135:        ifp->if_start = ixstart;
                    136:        ifp->if_ioctl = ixioctl;
                    137:        ifp->if_reset = ixreset;
                    138: 
                    139:        ix->ix_mp = npmasters + ui->ui_unit;
                    140:        ix->ix_ifuba.ifu_flags = UBA_CANTWAIT;
                    141: 
                    142:        if_attach(ifp);
                    143: }
                    144: 
                    145: struct npreq *
                    146: ix_GetReq(mp, addr, len)
                    147:        struct npmaster *mp;
                    148:        caddr_t addr;
                    149: {
                    150:        int unit = mp->unit;
                    151:        register struct npreq *rp;
                    152:        register struct CQE *ep;
                    153:        struct ix_softc *ix = ix_softc + unit;
                    154:        extern struct npreq *NpGetReq();
                    155: 
                    156:        while ((rp = NpGetReq(mp->reqtab)) == NULL) {
                    157:                mp->reqtab->flags |= WANTREQ;
                    158:                sleep((caddr_t)(mp->reqtab), PZERO - 1);
                    159:        }
                    160:        rp->flags = KERNREQ;                    /* Clear flags */
                    161: 
                    162:        ep = rp->element;                       /* Associated CQE */
                    163:        ep->cqe_famid = (unsign32)ix;           /* Process ID */
                    164:        ep->cqe_wind = 0;                       /* Amount of buffer mapped */
                    165:        ep->cqe_nbuf = 1;                       /* Must be 1, no buffer chain */
                    166:        ep->cqe_char = 1;                       /* Driver owns this CQE */
                    167:        ep->cqe_prot = NPDLA;                   /* Data Link Access  protocol */
                    168:        ep->cqe_bcnt = len;                     /* Byte count */
                    169:        rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */
                    170:        ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr);
                    171:        ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr);
                    172:        return (rp);
                    173: }
                    174: 
                    175: ix_DoReq(mp, rp, cmd, addr, len, rpb, routine)
                    176:        struct npmaster *mp;
                    177:        register struct npreq *rp;
                    178:        u_short cmd;
                    179:        caddr_t addr;
                    180:        int len;
                    181:        register u_short *rpb;
                    182:        int (*routine)();
                    183: {
                    184:        register struct CQE *ep = rp->element;
                    185:        register u_short *p = &ep->rpb1;
                    186:        u_short cnt = *rpb++;
                    187:        extern long NpDebug;
                    188:        int pri;
                    189:        int result = 0;
                    190: 
                    191:        ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR;  /* Clear status */
                    192:        ep->cqe_bcnt = len;                     /* Byte count */
                    193:        rp->flags = KERNREQ | REQALOC;                  /* Clear flags */
                    194:        rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */
                    195:        rp->intr = routine;
                    196:        rp->user = (caddr_t) (ep->cqe_func = cmd);/* In case pissed on in CQE */
                    197:        ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr);
                    198:        ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr);
                    199:        ep->cqe_lenrpb = cnt + cnt;
                    200:        for (; cnt > 0; cnt--) *p++ = *rpb++;
                    201: 
                    202:        if (NpDebug & DEBCQE)
                    203:                printf("Function is %x ep %x reqid %x\n", ep->cqe_func, ep, ep->cqe_reqid);
                    204:        if (NpDebug & DEBCQE)
                    205:                printf("irp len = %x rp = %x\n", ep->cqe_lenrpb, rp);
                    206:        if (routine == 0) {
                    207:                NpAddReq(mp->reqtab, rp);       /* Queue onto active list */
                    208:                while (!(rp->flags & REQDONE)) {
                    209:                        pri = spl5();
                    210:                        NpAddCQE(ep, &mp->shmemp->devcq, mp);
                    211:                        sleep((caddr_t)rp, PZERO - 1);
                    212:                        splx(pri);
                    213:                }
                    214:                if (rp->flags & IOABORT || ep->cqe_sts != NPDONE
                    215:                    || ep->cqe_ust0 != NPDONE
                    216:                    || ep->cqe_ust1 != NPOK) {
                    217:                        struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid;
                    218:                        printf("ix%d: Req failed, cmd %x, stat %x, flags %x, ",
                    219:                                ix->ix_if.if_unit, rp->user,
                    220:                                ep->cqe_sts, rp->flags);
                    221:                        printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);
                    222:                        result = 1;
                    223:                }
                    224:                NpRemReq(rp);                   /* Clear request */
                    225:        } else {
                    226:                pri = spl5();
                    227:                NpAddCQE(ep, &mp->shmemp->devcq, mp);
                    228:                splx(pri);
                    229:        }
                    230:        return(result);
                    231: }
                    232: /*
                    233:  * Reset of interface after UNIBUS reset.
                    234:  * If interface is on specified uba, reset its state.
                    235:  */
                    236: ixreset(unit, uban, softp)
                    237:        int unit, uban;
                    238:        caddr_t softp;
                    239: {
                    240:        register struct uba_device *ui;
                    241:        int mask = IXF_SETADDR;         /* Only remember new physaddr */
                    242: 
                    243:        if (unit >= NNP || (ui = npdinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    244:            ui->ui_ubanum != uban)
                    245:                return;
                    246:        printf(" ix%d reset", unit);
                    247:        if (softp) 
                    248:                mask |= IXF_GOTUBA;     /* UBA mapping regs still valid; */
                    249:        ix_softc[unit].ix_if.if_flags &= ~IFF_RUNNING;
                    250:        ix_softc[unit].ix_flags &= mask;
                    251: }
                    252: 
                    253: int ix_MacLoop = 0;
                    254: 
                    255: /*
                    256:  * Initialization of interface; clear recorded pending
                    257:  * operations, and reinitialize UNIBUS usage.
                    258:  */
                    259: ixinit(unit)
                    260:        int unit;
                    261: {
                    262:        register struct ix_softc *ix = &ix_softc[unit];
                    263:        struct uba_device *ui = npdinfo[unit];
                    264:        register struct ifnet *ifp = &ix->ix_if;
                    265:        register struct CQE *ep;
                    266:        struct npreq *rp;
                    267:        struct npmaster *mp = ix->ix_mp;
                    268:        register u_short *dpmp = & mp->shmemp->statblock.sb_dpm;
                    269:        u_short rpb[7];
                    270:        int s;
                    271: 
                    272:        /* not yet, if address still unknown */
                    273:        if ((ifp->if_addrlist == (struct ifaddr *)0) ||
                    274:            (ix->ix_flags & IXF_RUNNING))
                    275:                return;
                    276:        if ((mp->flags & AVAILABLE) == 0 || (*dpmp & PROTOMASK(NPDLA)) == 0) {
                    277:                ifp->if_flags &= ~IFF_UP;
                    278:                return;
                    279:        }
                    280:        if ((ix->ix_flags & IXF_GOTUBA) == 0) {
                    281:                ix->ix_ifuba.ifu_flags = UBA_CANTWAIT;
                    282:                if (if_ubainit(&ix->ix_ifuba, ui->ui_ubanum,
                    283:                    sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 
                    284:                        printf("ix%d: can't initialize\n", unit);
                    285:                        ix->ix_if.if_flags &= ~IFF_UP;
                    286:                        return;
                    287:                }
                    288:                ix->ix_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ix->ix_stats,
                    289:                        sizeof (union ix_stats), 0);
                    290:                ix->ix_flags |= IXF_GOTUBA;
                    291:        }
                    292:        if ((ix->ix_flags & IXF_GOTCQE) == 0) {
                    293:                ix->ix_rrp = ix_GetReq(mp, ix->ix_ifuba.ifu_r.ifrw_info,
                    294:                                                                ETHERMTU);
                    295:                ix->ix_wrp = ix_GetReq(mp, 0, 0);
                    296:                ix->ix_flags |= IXF_GOTCQE;
                    297:        }
                    298: 
                    299:        rp = ix->ix_wrp;
                    300:        ep = rp->element;
                    301: 
                    302:        /* Changing the ethernet address resets the dla module,
                    303:           so must do it before opening the channel */
                    304:        if (ix->ix_flags & IXF_SETADDR) {
                    305:                register char *cp = (char *) &ix->ix_stats;
                    306:                int spincount;
                    307:                int x;
                    308:                /* Try Issuing an open channel request before reprogramming
                    309:                   the physical address */
                    310:                rpb[0] = 6;             /* RPB length */
                    311:                rpb[2] = 0x10;          /* Share with any smart users */
                    312:                rpb[3] = 0;             /* Take (a copy of) all frames */
                    313:                rpb[5] = 8;             /* On board rcv queue length */
                    314:                rpb[6] = 0;             /* XMT packets as is */
                    315:                if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0))
                    316:                        return;
                    317:                /* Proceed with LDPA */
                    318:                *cp++ = 1;
                    319:                bcopy(ix->ix_addr, (caddr_t)cp, 6);
                    320:                rpb[0] = 1;                             /* RPB length */
                    321:                if (ix_DoReq(mp, rp, IXC_LDPA, ix->ix_ubaddr, 7, rpb, 0))
                    322:                        return;
                    323: #ifndef TheyFinallyFixedTheBoard
                    324:                /* Board requires some time to reinitialize its protocols */
                    325:                x = spl1();
                    326:                spincount = 2000000;
                    327:                while (((*dpmp & PROTOMASK(NPDLA))==0) && spincount > 0)
                    328:                        spincount--;
                    329:                if (spincount==0) {
                    330:                        printf("ix%d: failed to reinitialize DLA module\n",
                    331:                                        unit);
                    332:                        splx(x);
                    333:                }
                    334:                splx(x);
                    335: #endif
                    336:        }
                    337:        rpb[0] = 6;             /* RPB length */
                    338:        rpb[2] = 0x10;          /* Share with any smart users */
                    339:        if (ix_MacLoop) rpb[2] |= 0x8;
                    340:                                /* Enable software loopback on board */
                    341:        rpb[3] = 0;             /* Take (a copy of) all frames */
                    342:        rpb[5] = 8;             /* On board rcv queue length */
                    343:        rpb[6] = 0;             /* XMT packets as is */
                    344:        if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0))
                    345:                return;
                    346: 
                    347:        ix->ix_aid = ep->rpb1;
                    348: 
                    349:        /* Here we request our ethernet address, if we didn't reset it*/
                    350:        if ((ix->ix_flags & IXF_SETADDR)==0) {
                    351:                rpb[0] = 2;
                    352:                rpb[1] = ix->ix_aid;
                    353:                rpb[2] = 0;             /* get all stats */
                    354:                if (ix_DoReq(mp, rp, IXC_GSTAT, /* Get Stats */
                    355:                         (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8,
                    356:                         rpb, 0))
                    357:                                return;
                    358:                bcopy((caddr_t) &ix->ix_stats, (caddr_t) ix->ix_addr, 6);
                    359:        }
                    360:        ix->ix_if.if_flags |= IFF_RUNNING;
                    361:        ix->ix_flags |= IXF_RUNNING;
                    362:        ifp->if_watchdog = ixwatch;
                    363:        ifp->if_timer = ix->ix_scaninterval = IXWATCHINTERVAL;
                    364:        ixrint(mp, 0);
                    365: }
                    366: 
                    367: /*
                    368:  * Start output on interface.
                    369:  * Get another datagram to send off of the interface queue,
                    370:  * and map it to the interface before starting the output.
                    371:  */
                    372: ixstart(ifp)
                    373: struct ifnet *ifp;
                    374: {
                    375:         int len = 0;
                    376:        int unit = ifp->if_unit;
                    377:        register struct ix_softc *ix = &ix_softc[unit];
                    378:        register struct mbuf *n;
                    379:        struct mbuf *m;
                    380:        int s, error = 0;
                    381:        struct npmaster *mp = ix->ix_mp;
                    382:        struct npreq *rp = ix->ix_wrp;
                    383:        struct CQE *ep;
                    384:        u_short rpb[8];
                    385: 
                    386:        IF_DEQUEUE(&ix->ix_if.if_snd, m);
                    387:        if (m == 0) {
                    388:                if (ix->ix_flags & IXF_STATPENDING) {
                    389:                        ix->ix_flags &= ~IXF_STATPENDING;
                    390:                        ix->ix_if.if_flags |= IFF_OACTIVE;
                    391:                        rpb[0] = 2;
                    392:                        rpb[1] = ix->ix_aid;
                    393:                        rpb[2] = 0;                     /* get all stats */
                    394:                        ix_DoReq(mp, rp, IXC_GSTAT,     /* general Stats */
                    395:                                 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8,
                    396:                                 rpb, ixcint);
                    397:                }
                    398:                return (0);
                    399:        }
                    400:        /*
                    401:         * Ensure minimum packet length.
                    402:         * This makes the safe assumtion that there are no virtual holes
                    403:         * after the data.
                    404:         * For security, it might be wise to zero out the added bytes,
                    405:         * but we're mainly interested in speed at the moment.
                    406:         */
                    407:        len = if_wubaput(&ix->ix_ifuba, m);
                    408:        if (len - sizeof(struct ether_header) < ETHERMIN)
                    409:                len = ETHERMIN + sizeof(struct ether_header);
                    410: 
                    411:        ix->ix_if.if_flags |= IFF_OACTIVE;
                    412: 
                    413:        /* Now setup to call np driver */
                    414:        rpb[0] = 8;
                    415:        rpb[1] = ix->ix_aid;
                    416:        ix_DoReq(mp, rp, IXC_XMIT,                       /* send frame */
                    417:                    ix->ix_ifuba.ifu_w.ifrw_info, len, rpb, ixcint);
                    418:        return (0);
                    419: }
                    420: 
                    421: /*
                    422:  * Command done interrupt. (almost)
                    423:  */
                    424: ixcint(mp, rp)
                    425:        struct npmaster *mp;
                    426:        struct npreq *rp;
                    427: {
                    428:        struct CQE *ep;
                    429:        register struct ix_softc *ix;
                    430:        int s = splimp();
                    431: 
                    432:        ep = rp->element;
                    433:        ix = (struct ix_softc *)ep->cqe_famid;
                    434:        ix->ix_flags &= ~IXF_OWATCH;
                    435:        if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) {
                    436:                printf("ix%d: stray xmit interrupt, npreq=%x\n",
                    437:                        ix->ix_if.if_unit, rp);
                    438:        }
                    439:        ix->ix_if.if_flags &= ~IFF_OACTIVE;
                    440:        if (rp->flags & IOABORT || ep->cqe_sts != NPDONE
                    441:            || ep->cqe_ust0 != NPDONE || ep->cqe_ust1 != NPOK) {
                    442:                if (ep->cqe_ust1 == 0x48)
                    443:                        ix->ix_if.if_oerrors++;
                    444:                else {
                    445:                        struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid;
                    446:                        printf(
                    447:                           "ix%d: ixcint failed, cmd %x, stat %x, flags %x, ",
                    448:                                ix->ix_if.if_unit, rp->user,
                    449:                                ep->cqe_sts, rp->flags);
                    450:                        printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);
                    451:                        if (++ix->ix_badcqe > 65) {
                    452:                                ix->ix_badcqe = 0;
                    453:                                printf("ixcint: shutting down unix dla\n");
                    454:                                ix->ix_if.if_flags &= ~IFF_UP;
                    455:                        }
                    456:                 }
                    457:        }
                    458:        else switch (ep->cqe_func) {
                    459: 
                    460:        case IXC_XMIT:
                    461:                ix->ix_if.if_opackets++;
                    462:                break;
                    463: 
                    464:        case IXC_GSTAT:
                    465:                ix->ix_if.if_collisions += ix->ix_stats.ixg.macg_xrty;
                    466:        }
                    467: done:
                    468:        if (ix->ix_ifuba.ifu_xtofree) {
                    469:                m_freem(ix->ix_ifuba.ifu_xtofree);
                    470:                ix->ix_ifuba.ifu_xtofree = 0;
                    471:        }
                    472:        if ((ix->ix_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
                    473:                (void) ixstart(&ix->ix_if);
                    474:        splx(s);
                    475: }
                    476: 
                    477: /*
                    478:  * Ethernet interface receiver interrupt.
                    479:  * If input error just drop packet.
                    480:  * Otherwise purge input buffered data path and examine 
                    481:  * packet to determine type.  If can't determine length
                    482:  * from type, then have to drop packet.  Othewise decapsulate
                    483:  * packet based on type and pass to type specific higher-level
                    484:  * input routine.
                    485:  */
                    486: ixrint(mp, rp)
                    487:        struct npmaster *mp;
                    488:        struct npreq *rp;
                    489: {
                    490:        struct CQE *ep;
                    491:        register struct ix_softc *ix = ix_softc + mp->unit;
                    492:        register struct ether_header *il;
                    493:        struct mbuf *m;
                    494:        int len, off, resid, s;
                    495:        register struct ifqueue *inq;
                    496: 
                    497:        if ((ix->ix_flags & IXF_RUNNING) == 0)
                    498:                return;
                    499:        if (rp == 0)
                    500:                goto setup;
                    501:        ix->ix_flags &= ~(IXF_RCVPENDING|IXF_RWATCH);
                    502:        ep = rp->element;
                    503:        ix->ix_if.if_ipackets++;
                    504:        if (ix->ix_ifuba.ifu_flags & UBA_NEEDBDP)
                    505:                UBAPURGE(ix->ix_ifuba.ifu_uba, ix->ix_ifuba.ifu_r.ifrw_bdp);
                    506:        il = (struct ether_header *)(ix->ix_ifuba.ifu_r.ifrw_addr);
                    507:        len = ep->cqe_bcnt - sizeof (struct ether_header);
                    508:        if (ep->cqe_sts != NPDONE || rp->flags & IOABORT
                    509:            || ep->cqe_ust0 != NPDONE
                    510:            || ep->cqe_ust1 != NPOK) {
                    511:                printf("ix%drint: cqe error, cmd %x, stat %x, flags %x, ",
                    512:                        ix->ix_if.if_unit, rp->user, ep->cqe_sts, rp->flags);
                    513:                printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);
                    514:                if (++ix->ix_badcqe > 50) {
                    515:                        ix->ix_badcqe = 0;
                    516:                        printf("ixrint: shutting down unix dla\n");
                    517:                        ix->ix_if.if_flags &= ~IFF_UP;
                    518:                        return;
                    519:                }
                    520:                goto setup;
                    521:        }
                    522: 
                    523:        if ( len < 46 || len > ETHERMTU) {
                    524:                ix->ix_if.if_ierrors++;
                    525: #ifdef notdef
                    526:                if (ix->ix_if.if_ierrors % 100 == 0)
                    527:                        printf("ix%d: += 100 input errors\n", unit);
                    528: #endif
                    529:                goto setup;
                    530:        }
                    531: 
                    532:        /*
                    533:         * Deal with trailer protocol: if type is trailer type
                    534:         * get true type from first 16-bit word past data.
                    535:         * Remember that type was trailer by setting off.
                    536:         */
                    537:        il->ether_type = ntohs((u_short)il->ether_type);
                    538: #define        ildataaddr(il, off, type)       ((type)(((caddr_t)((il)+1)+(off))))
                    539:        if (il->ether_type >= ETHERTYPE_TRAIL &&
                    540:            il->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                    541:                off = (il->ether_type - ETHERTYPE_TRAIL) * 512;
                    542:                if (off >= ETHERMTU)
                    543:                        goto setup;             /* sanity */
                    544:                il->ether_type = ntohs(*ildataaddr(il, off, u_short *));
                    545:                resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
                    546:                if (off + resid > len)
                    547:                        goto setup;             /* sanity */
                    548:                len = off + resid;
                    549:        } else
                    550:                off = 0;
                    551:        if (len == 0)
                    552:                goto setup;
                    553: 
                    554:        /*
                    555:         * Pull packet off interface.  Off is nonzero if packet
                    556:         * has trailing header; ilget will then force this header
                    557:         * information to be at the front, but we still have to drop
                    558:         * the type and length which are at the front of any trailer data.
                    559:         */
                    560:        m = if_rubaget(&ix->ix_ifuba, len, off, &ix->ix_if);
                    561:        if (m)
                    562:                ether_input(&ix->ix_if, il, m);
                    563: 
                    564: setup:
                    565:        /*
                    566:         * Reset for next packet if possible.
                    567:         * If waiting for transmit command completion, set flag
                    568:         * and wait until command completes.
                    569:         */
                    570:        if (rp == 0) {
                    571:                rp = ix->ix_rrp;
                    572:                rp->intr = ixrint;
                    573:                ep = rp->element;
                    574:        }
                    575:        len = ETHERMTU + sizeof(struct ether_header);
                    576: 
                    577:        /* Now setup to call np driver */
                    578:        /* Initializations of request structure */
                    579: 
                    580:        ep->cqe_func = IXC_RECV;                        /* get frame */
                    581:        ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR;          /* Clear status */
                    582:        ep->cqe_bcnt = len;                             /* Byte count */
                    583:        ep->cqe_lenrpb = 10;                            /* RPB length */
                    584:        ep->rpb1 = ix->ix_aid;                          /* which channel */
                    585:        ep->rpb2 = 65535;                               /* Timeout */
                    586: 
                    587:        ix->ix_flags |= IXF_RCVPENDING;
                    588: 
                    589:        s = spl5();
                    590:        NpAddCQE(ep, &mp->shmemp->devcq, mp); /* Add CQE to device's queue */
                    591:        splx(s);
                    592: }
                    593: 
                    594: 
                    595: long ixwatchcount;
                    596: /*
                    597:  * Watchdog routine, request statistics from board.
                    598:  */
                    599: ixwatch(unit)
                    600:        int unit;
                    601: {
                    602:        register struct ix_softc *ix = &ix_softc[unit];
                    603:        register struct ifnet *ifp = &ix->ix_if;
                    604:        int s;
                    605: 
                    606:        ixwatchcount++;
                    607:        if (ix->ix_badcqe > 1) {
                    608:                ix->ix_badcqe--; /* If errors aren't happening too fast,
                    609:                                give the board a reprieve */
                    610:        }
                    611:        s = splimp();
                    612:        if (ix->ix_flags & IXF_STATPENDING) {
                    613:                ifp->if_timer = ix->ix_scaninterval;
                    614:                ix->ix_flags |= IXF_OWATCH;
                    615:                splx(s);
                    616:                return;
                    617:        }
                    618:        ix->ix_flags |= IXF_STATPENDING;
                    619:        if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0)
                    620:                (void) ixstart(ifp);
                    621:        else
                    622:                ix->ix_flags |= IXF_OWATCH;
                    623:        if (ix->ix_flags & IXF_RCVPENDING)
                    624:                ix->ix_flags |= IXF_RWATCH;
                    625:        splx(s);
                    626:        ifp->if_timer = ix->ix_scaninterval;
                    627: }
                    628: /*
                    629:  * Process an ioctl request.
                    630:  */
                    631: ixioctl(ifp, cmd, data)
                    632:        register struct ifnet *ifp;
                    633:        int cmd;
                    634:        caddr_t data;
                    635: {
                    636:        register struct ifaddr *ifa = (struct ifaddr *)data;
                    637:        register struct ix_softc *ix = &ix_softc[ifp->if_unit];
                    638:        int s = splimp(), error = 0;
                    639: 
                    640:        switch (cmd) {
                    641: 
                    642:        case SIOCSIFADDR:
                    643:                ifp->if_flags |= IFF_UP;
                    644:                ixinit(ifp->if_unit);
                    645:                if ((ifp->if_flags & IFF_UP) == 0)
                    646:                        return (EBUSY);
                    647: 
                    648:                switch (ifa->ifa_addr->sa_family) {
                    649: #ifdef INET
                    650:                case AF_INET:
                    651:                        ((struct arpcom *)ifp)->ac_ipaddr =
                    652:                                IA_SIN(ifa)->sin_addr;
                    653:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                    654:                        break;
                    655: #endif
                    656: #ifdef NS
                    657:                case AF_NS:
                    658:                    {
                    659:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
                    660:                        
                    661:                        if (ns_nullhost(*ina)) {
                    662:                                ina->x_host = * (union ns_host *) 
                    663:                                     (ix_softc[ifp->if_unit].ix_addr);
                    664:                        } else {
                    665:                            return
                    666:                                ix_setaddr(ina->x_host.c_host, ifp->if_unit);
                    667:                        }
                    668:                        break;
                    669:                    }
                    670: #endif
                    671:                }
                    672:                break;
                    673: 
                    674:        case SIOCSIFFLAGS:
                    675:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    676:                    ix->ix_flags & IXF_RUNNING) {
                    677:                        ix->ix_flags &= ~IXF_RUNNING;
                    678:                        NpReset(ix->ix_mp, 0);
                    679:                } else if (ifp->if_flags & IFF_UP &&
                    680:                    (ix->ix_flags & IXF_RUNNING) == 0)
                    681:                        ixinit(ifp->if_unit);
                    682:                break;
                    683: 
                    684:        default:
                    685:                error = EINVAL;
                    686:        }
                    687:        splx(s);
                    688:        return (error);
                    689: }
                    690: 
                    691: /*
                    692:  * set ethernet address for unit
                    693:  */
                    694: ix_setaddr(physaddr, unit)
                    695: u_char *physaddr;
                    696: int unit;
                    697: {
                    698:        register struct ix_softc *ix = &ix_softc[unit];
                    699:        
                    700:        if (! (ix->ix_flags & IXF_RUNNING))
                    701:                return (EBUSY);
                    702: 
                    703:        /* The following is a big cop out due to the fact that
                    704:           Changing the ethernet address resets the dla module,
                    705:           so must re-open the channel, anyway. */
                    706: 
                    707: 
                    708:        bcopy((caddr_t)physaddr, (caddr_t)ix->ix_addr, sizeof ix->ix_addr);
                    709:        ix->ix_flags &= ~IXF_RUNNING;
                    710:        ix->ix_flags |= IXF_SETADDR;
                    711:        ixinit(unit);
                    712:        NpKill(ix->ix_mp, ix->ix_rrp);
                    713: }
                    714: static showme() {
                    715:        return ((int) &(ix_softc->ix_badcqe));
                    716: }
                    717: #endif

unix.superglobalmegacorp.com

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