Annotation of 43BSD/sys/vaxif/if_dmc.c, revision 1.1.1.1

1.1       root        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_dmc.c    7.1 (Berkeley) 6/5/86
                      7:  */
                      8: 
                      9: #include "dmc.h"
                     10: #if NDMC > 0
                     11: 
                     12: /*
                     13:  * DMC11 device driver, internet version
                     14:  *
                     15:  *     Bill Nesheim
                     16:  *     Cornell University
                     17:  *
                     18:  *     Lou Salkind
                     19:  *     New York University
                     20:  */
                     21: 
                     22: /* #define DEBUG       /* for base table dump on fatal error */
                     23: 
                     24: #include "../machine/pte.h"
                     25: 
                     26: #include "param.h"
                     27: #include "systm.h"
                     28: #include "mbuf.h"
                     29: #include "buf.h"
                     30: #include "ioctl.h"             /* must precede tty.h */
                     31: #include "tty.h"
                     32: #include "protosw.h"
                     33: #include "socket.h"
                     34: #include "syslog.h"
                     35: #include "vmmac.h"
                     36: #include "errno.h"
                     37: 
                     38: #include "../net/if.h"
                     39: #include "../net/netisr.h"
                     40: #include "../net/route.h"
                     41: 
                     42: #ifdef INET
                     43: #include "../netinet/in.h"
                     44: #include "../netinet/in_systm.h"
                     45: #include "../netinet/in_var.h"
                     46: #include "../netinet/ip.h"
                     47: #endif
                     48: 
                     49: #include "../vax/cpu.h"
                     50: #include "../vax/mtpr.h"
                     51: #include "if_uba.h"
                     52: #include "if_dmc.h"
                     53: #include "../vaxuba/ubareg.h"
                     54: #include "../vaxuba/ubavar.h"
                     55: 
                     56: #include "../h/time.h"
                     57: #include "../h/kernel.h"
                     58: 
                     59: int    dmctimer;                       /* timer started? */
                     60: int    dmc_timeout = 8;                /* timeout value */
                     61: int    dmcwatch();
                     62: 
                     63: /*
                     64:  * Driver information for auto-configuration stuff.
                     65:  */
                     66: int    dmcprobe(), dmcattach(), dmcinit(), dmcioctl();
                     67: int    dmcoutput(), dmcreset();
                     68: struct uba_device *dmcinfo[NDMC];
                     69: u_short        dmcstd[] = { 0 };
                     70: struct uba_driver dmcdriver =
                     71:        { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
                     72: 
                     73: #define NRCV 7
                     74: #define NXMT 3 
                     75: #define NCMDS  (NRCV+NXMT+4)   /* size of command queue */
                     76: 
                     77: #define printd if(dmcdebug)printf
                     78: int dmcdebug = 0;
                     79: 
                     80: /* error reporting intervals */
                     81: #define DMC_RPNBFS     50
                     82: #define DMC_RPDSC      1
                     83: #define DMC_RPTMO      10
                     84: #define DMC_RPDCK      10
                     85: 
                     86: struct  dmc_command {
                     87:        char    qp_cmd;         /* command */
                     88:        short   qp_ubaddr;      /* buffer address */
                     89:        short   qp_cc;          /* character count || XMEM */
                     90:        struct  dmc_command *qp_next;   /* next command on queue */
                     91: };
                     92: 
                     93: struct dmcbufs {
                     94:        int     ubinfo;         /* from uballoc */
                     95:        short   cc;             /* buffer size */
                     96:        short   flags;          /* access control */
                     97: };
                     98: #define        DBUF_OURS       0       /* buffer is available */
                     99: #define        DBUF_DMCS       1       /* buffer claimed by somebody */
                    100: #define        DBUF_XMIT       4       /* transmit buffer */
                    101: #define        DBUF_RCV        8       /* receive buffer */
                    102: 
                    103: 
                    104: /*
                    105:  * DMC software status per interface.
                    106:  *
                    107:  * Each interface is referenced by a network interface structure,
                    108:  * sc_if, which the routing code uses to locate the interface.
                    109:  * This structure contains the output queue for the interface, its address, ...
                    110:  * We also have, for each interface, a  set of 7 UBA interface structures
                    111:  * for each, which
                    112:  * contain information about the UNIBUS resources held by the interface:
                    113:  * map registers, buffered data paths, etc.  Information is cached in this
                    114:  * structure for use by the if_uba.c routines in running the interface
                    115:  * efficiently.
                    116:  */
                    117: struct dmc_softc {
                    118:        struct  ifnet sc_if;            /* network-visible interface */
                    119:        struct  dmcbufs sc_rbufs[NRCV]; /* receive buffer info */
                    120:        struct  dmcbufs sc_xbufs[NXMT]; /* transmit buffer info */
                    121:        struct  ifubinfo sc_ifuba;      /* UNIBUS resources */
                    122:        struct  ifrw sc_ifr[NRCV];      /* UNIBUS receive buffer maps */
                    123:        struct  ifxmt sc_ifw[NXMT];     /* UNIBUS receive buffer maps */
                    124:        short   sc_oused;               /* output buffers currently in use */
                    125:        short   sc_iused;               /* input buffers given to DMC */
                    126:        short   sc_flag;                /* flags */
                    127:        int     sc_nticks;              /* seconds since last interrupt */
                    128:        int     sc_ubinfo;              /* UBA mapping info for base table */
                    129:        int     sc_errors[4];           /* non-fatal error counters */
                    130: #define sc_datck sc_errors[0]
                    131: #define sc_timeo sc_errors[1]
                    132: #define sc_nobuf sc_errors[2]
                    133: #define sc_disc  sc_errors[3]
                    134:        /* command queue stuff */
                    135:        struct  dmc_command sc_cmdbuf[NCMDS];
                    136:        struct  dmc_command *sc_qhead;  /* head of command queue */
                    137:        struct  dmc_command *sc_qtail;  /* tail of command queue */
                    138:        struct  dmc_command *sc_qactive;        /* command in progress */
                    139:        struct  dmc_command *sc_qfreeh; /* head of list of free cmd buffers */
                    140:        struct  dmc_command *sc_qfreet; /* tail of list of free cmd buffers */
                    141:        /* end command queue stuff */
                    142: } dmc_softc[NDMC];
                    143: 
                    144: /* flags */
                    145: #define DMC_ALLOC      0x01            /* unibus resources allocated */
                    146: #define DMC_BMAPPED    0x02            /* base table mapped */
                    147: #define DMC_RESTART    0x04            /* software restart in progress */
                    148: #define DMC_ACTIVE     0x08            /* device active */
                    149: #define DMC_RUNNING    0x20            /* device initialized */
                    150: 
                    151: struct dmc_base {
                    152:        short   d_base[128];            /* DMC base table */
                    153: } dmc_base[NDMC];
                    154: 
                    155: /* queue manipulation macros */
                    156: #define        QUEUE_AT_HEAD(qp, head, tail) \
                    157:        (qp)->qp_next = (head); \
                    158:        (head) = (qp); \
                    159:        if ((tail) == (struct dmc_command *) 0) \
                    160:                (tail) = (head) 
                    161: 
                    162: #define QUEUE_AT_TAIL(qp, head, tail) \
                    163:        if ((tail)) \
                    164:                (tail)->qp_next = (qp); \
                    165:        else \
                    166:                (head) = (qp); \
                    167:        (qp)->qp_next = (struct dmc_command *) 0; \
                    168:        (tail) = (qp)
                    169: 
                    170: #define DEQUEUE(head, tail) \
                    171:        (head) = (head)->qp_next;\
                    172:        if ((head) == (struct dmc_command *) 0)\
                    173:                (tail) = (head)
                    174: 
                    175: dmcprobe(reg)
                    176:        caddr_t reg;
                    177: {
                    178:        register int br, cvec;
                    179:        register struct dmcdevice *addr = (struct dmcdevice *)reg;
                    180:        register int i;
                    181: 
                    182: #ifdef lint
                    183:        br = 0; cvec = br; br = cvec;
                    184:        dmcrint(0); dmcxint(0);
                    185: #endif
                    186:        addr->bsel1 = DMC_MCLR;
                    187:        for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
                    188:                ;
                    189:        if ((addr->bsel1 & DMC_RUN) == 0) {
                    190:                printf("dmcprobe: can't start device\n" );
                    191:                return (0);
                    192:        }
                    193:        addr->bsel0 = DMC_RQI|DMC_IEI;
                    194:        /* let's be paranoid */
                    195:        addr->bsel0 |= DMC_RQI|DMC_IEI;
                    196:        DELAY(1000000);
                    197:        addr->bsel1 = DMC_MCLR;
                    198:        for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
                    199:                ;
                    200:        return (1);
                    201: }
                    202: 
                    203: /*
                    204:  * Interface exists: make available by filling in network interface
                    205:  * record.  System will initialize the interface when it is ready
                    206:  * to accept packets.
                    207:  */
                    208: dmcattach(ui)
                    209:        register struct uba_device *ui;
                    210: {
                    211:        register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
                    212: 
                    213:        sc->sc_if.if_unit = ui->ui_unit;
                    214:        sc->sc_if.if_name = "dmc";
                    215:        sc->sc_if.if_mtu = DMCMTU;
                    216:        sc->sc_if.if_init = dmcinit;
                    217:        sc->sc_if.if_output = dmcoutput;
                    218:        sc->sc_if.if_ioctl = dmcioctl;
                    219:        sc->sc_if.if_reset = dmcreset;
                    220:        sc->sc_if.if_flags = IFF_POINTOPOINT;
                    221:        sc->sc_ifuba.iff_flags = UBA_CANTWAIT;
                    222: 
                    223:        if (dmctimer == 0) {
                    224:                dmctimer = 1;
                    225:                timeout(dmcwatch, (caddr_t) 0, hz);
                    226:        }
                    227:        if_attach(&sc->sc_if);
                    228: }
                    229: 
                    230: /*
                    231:  * Reset of interface after UNIBUS reset.
                    232:  * If interface is on specified UBA, reset its state.
                    233:  */
                    234: dmcreset(unit, uban)
                    235:        int unit, uban;
                    236: {
                    237:        register struct uba_device *ui;
                    238:        register struct dmc_softc *sc = &dmc_softc[unit];
                    239: 
                    240:        if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    241:            ui->ui_ubanum != uban)
                    242:                return;
                    243:        printf(" dmc%d", unit);
                    244:        sc->sc_flag = 0;
                    245:        sc->sc_if.if_flags &= ~IFF_RUNNING;
                    246:        dmcinit(unit);
                    247: }
                    248: 
                    249: /*
                    250:  * Initialization of interface; reinitialize UNIBUS usage.
                    251:  */
                    252: dmcinit(unit)
                    253:        int unit;
                    254: {
                    255:        register struct dmc_softc *sc = &dmc_softc[unit];
                    256:        register struct uba_device *ui = dmcinfo[unit];
                    257:        register struct dmcdevice *addr;
                    258:        register struct ifnet *ifp = &sc->sc_if;
                    259:        register struct ifrw *ifrw;
                    260:        register struct ifxmt *ifxp;
                    261:        register struct dmcbufs *rp;
                    262:        register struct dmc_command *qp;
                    263:        struct ifaddr *ifa;
                    264:        int base;
                    265:        int s;
                    266: 
                    267:        addr = (struct dmcdevice *)ui->ui_addr;
                    268: 
                    269:        /*
                    270:         * Check to see that an address has been set
                    271:         * (both local and destination for an address family).
                    272:         */
                    273:        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
                    274:                if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family)
                    275:                        break;
                    276:        if (ifa == (struct ifaddr *) 0)
                    277:                return;
                    278: 
                    279:        if ((addr->bsel1&DMC_RUN) == 0) {
                    280:                printf("dmcinit: DMC not running\n");
                    281:                ifp->if_flags &= ~IFF_UP;
                    282:                return;
                    283:        }
                    284:        /* map base table */
                    285:        if ((sc->sc_flag & DMC_BMAPPED) == 0) {
                    286:                sc->sc_ubinfo = uballoc(ui->ui_ubanum,
                    287:                        (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0);
                    288:                sc->sc_flag |= DMC_BMAPPED;
                    289:        }
                    290:        /* initialize UNIBUS resources */
                    291:        sc->sc_iused = sc->sc_oused = 0;
                    292:        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                    293:                if (if_ubaminit(&sc->sc_ifuba, ui->ui_ubanum,
                    294:                    sizeof(struct dmc_header), (int)btoc(DMCMTU),
                    295:                    sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) {
                    296:                        printf("dmc%d: can't allocate uba resources\n", unit);
                    297:                        ifp->if_flags &= ~IFF_UP;
                    298:                        return;
                    299:                }
                    300:                ifp->if_flags |= IFF_RUNNING;
                    301:        }
                    302:        sc->sc_flag |= DMC_RUNNING;
                    303: 
                    304:        /* initialize buffer pool */
                    305:        /* receives */
                    306:        ifrw = &sc->sc_ifr[0];
                    307:        for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
                    308:                rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
                    309:                rp->cc = DMCMTU + sizeof (struct dmc_header);
                    310:                rp->flags = DBUF_OURS|DBUF_RCV;
                    311:                ifrw++; 
                    312:        }
                    313:        /* transmits */
                    314:        ifxp = &sc->sc_ifw[0];
                    315:        for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
                    316:                rp->ubinfo = ifxp->ifw_info & 0x3ffff;
                    317:                rp->cc = 0;
                    318:                rp->flags = DBUF_OURS|DBUF_XMIT;
                    319:                ifxp++; 
                    320:        }
                    321: 
                    322:        /* set up command queues */
                    323:        sc->sc_qfreeh = sc->sc_qfreet
                    324:                 = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive =
                    325:                (struct dmc_command *)0;
                    326:        /* set up free command buffer list */
                    327:        for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) {
                    328:                QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
                    329:        }
                    330: 
                    331:        /* base in */
                    332:        base = sc->sc_ubinfo & 0x3ffff;
                    333:        dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM);
                    334:        /* specify half duplex operation, flags tell if primary */
                    335:        /* or secondary station */
                    336:        if (ui->ui_flags == 0)
                    337:                /* use DDCMP mode in full duplex */
                    338:                dmcload(sc, DMC_CNTLI, 0, 0);
                    339:        else if (ui->ui_flags == 1)
                    340:                /* use MAINTENENCE mode */
                    341:                dmcload(sc, DMC_CNTLI, 0, DMC_MAINT );
                    342:        else if (ui->ui_flags == 2)
                    343:                /* use DDCMP half duplex as primary station */
                    344:                dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX);
                    345:        else if (ui->ui_flags == 3)
                    346:                /* use DDCMP half duplex as secondary station */
                    347:                dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC);
                    348: 
                    349:        /* enable operation done interrupts */
                    350:        sc->sc_flag &= ~DMC_ACTIVE;
                    351:        while ((addr->bsel2 & DMC_IEO) == 0)
                    352:                addr->bsel2 |= DMC_IEO;
                    353:        s = spl5();
                    354:        /* queue first NRCV buffers for DMC to fill */
                    355:        for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
                    356:                rp->flags |= DBUF_DMCS;
                    357:                dmcload(sc, DMC_READ, rp->ubinfo,
                    358:                        (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc));
                    359:                sc->sc_iused++;
                    360:        }
                    361:        splx(s);
                    362: }
                    363: 
                    364: /*
                    365:  * Start output on interface.  Get another datagram
                    366:  * to send from the interface queue and map it to
                    367:  * the interface before starting output.
                    368:  *
                    369:  * Must be called at spl 5
                    370:  */
                    371: dmcstart(dev)
                    372:        dev_t dev;
                    373: {
                    374:        int unit = minor(dev);
                    375:        register struct dmc_softc *sc = &dmc_softc[unit];
                    376:        struct mbuf *m;
                    377:        register struct dmcbufs *rp;
                    378:        register int n;
                    379: 
                    380:        /*
                    381:         * Dequeue up to NXMT requests and map them to the UNIBUS.
                    382:         * If no more requests, or no dmc buffers available, just return.
                    383:         */
                    384:        n = 0;
                    385:        for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) {
                    386:                /* find an available buffer */
                    387:                if ((rp->flags & DBUF_DMCS) == 0) {
                    388:                        IF_DEQUEUE(&sc->sc_if.if_snd, m);
                    389:                        if (m == 0)
                    390:                                return;
                    391:                        /* mark it dmcs */
                    392:                        rp->flags |= (DBUF_DMCS);
                    393:                        /*
                    394:                         * Have request mapped to UNIBUS for transmission
                    395:                         * and start the output.
                    396:                         */
                    397:                        rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m);
                    398:                        rp->cc &= DMC_CCOUNT;
                    399:                        sc->sc_oused++;
                    400:                        dmcload(sc, DMC_WRITE, rp->ubinfo, 
                    401:                                rp->cc | ((rp->ubinfo>>2)&DMC_XMEM));
                    402:                }
                    403:                n++;
                    404:        }
                    405: }
                    406: 
                    407: /*
                    408:  * Utility routine to load the DMC device registers.
                    409:  */
                    410: dmcload(sc, type, w0, w1)
                    411:        register struct dmc_softc *sc;
                    412:        int type, w0, w1;
                    413: {
                    414:        register struct dmcdevice *addr;
                    415:        register int unit, sps;
                    416:        register struct dmc_command *qp;
                    417: 
                    418:        unit = sc - dmc_softc;
                    419:        addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
                    420:        sps = spl5();
                    421: 
                    422:        /* grab a command buffer from the free list */
                    423:        if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0)
                    424:                panic("dmc command queue overflow");
                    425:        DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);
                    426: 
                    427:        /* fill in requested info */
                    428:        qp->qp_cmd = (type | DMC_RQI);
                    429:        qp->qp_ubaddr = w0;
                    430:        qp->qp_cc = w1;
                    431:        
                    432:        if (sc->sc_qactive) {   /* command in progress */
                    433:                if (type == DMC_READ) {
                    434:                        QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail);
                    435:                } else {
                    436:                        QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail);
                    437:                }
                    438:        } else {        /* command port free */
                    439:                sc->sc_qactive = qp;
                    440:                addr->bsel0 = qp->qp_cmd;
                    441:                dmcrint(unit);
                    442:        }
                    443:        splx(sps);
                    444: }
                    445: 
                    446: /*
                    447:  * DMC interface receiver interrupt.
                    448:  * Ready to accept another command,
                    449:  * pull one off the command queue.
                    450:  */
                    451: dmcrint(unit)
                    452:        int unit;
                    453: {
                    454:        register struct dmc_softc *sc;
                    455:        register struct dmcdevice *addr;
                    456:        register struct dmc_command *qp;
                    457:        register int n;
                    458: 
                    459:        addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
                    460:        sc = &dmc_softc[unit];
                    461:        if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) {
                    462:                printf("dmc%d: dmcrint no command\n", unit);
                    463:                return;
                    464:        }
                    465:        while (addr->bsel0&DMC_RDYI) {
                    466:                addr->sel4 = qp->qp_ubaddr;
                    467:                addr->sel6 = qp->qp_cc;
                    468:                addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
                    469:                /* free command buffer */
                    470:                QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
                    471:                while (addr->bsel0 & DMC_RDYI) {
                    472:                        /*
                    473:                         * Can't check for RDYO here 'cause
                    474:                         * this routine isn't reentrant!
                    475:                         */
                    476:                        DELAY(5);
                    477:                }
                    478:                /* move on to next command */
                    479:                if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0)
                    480:                        break;          /* all done */
                    481:                /* more commands to do, start the next one */
                    482:                qp = sc->sc_qactive;
                    483:                DEQUEUE(sc->sc_qhead, sc->sc_qtail);
                    484:                addr->bsel0 = qp->qp_cmd;
                    485:                n = RDYSCAN;
                    486:                while (n-- > 0)
                    487:                        if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO))
                    488:                                break;
                    489:        }
                    490:        if (sc->sc_qactive) {
                    491:                addr->bsel0 |= DMC_IEI|DMC_RQI;
                    492:                /* VMS does it twice !*$%@# */
                    493:                addr->bsel0 |= DMC_IEI|DMC_RQI;
                    494:        }
                    495: 
                    496: }
                    497: 
                    498: /*
                    499:  * DMC interface transmitter interrupt.
                    500:  * A transfer may have completed, check for errors.
                    501:  * If it was a read, notify appropriate protocol.
                    502:  * If it was a write, pull the next one off the queue.
                    503:  */
                    504: dmcxint(unit)
                    505:        int unit;
                    506: {
                    507:        register struct dmc_softc *sc;
                    508:        register struct ifnet *ifp;
                    509:        struct uba_device *ui = dmcinfo[unit];
                    510:        struct dmcdevice *addr;
                    511:        struct mbuf *m;
                    512:        struct ifqueue *inq;
                    513:        int arg, pkaddr, cmd, len, s;
                    514:        register struct ifrw *ifrw;
                    515:        register struct dmcbufs *rp;
                    516:        register struct ifxmt *ifxp;
                    517:        struct dmc_header *dh;
                    518:        int off, resid;
                    519: 
                    520:        addr = (struct dmcdevice *)ui->ui_addr;
                    521:        sc = &dmc_softc[unit];
                    522:        ifp = &sc->sc_if;
                    523: 
                    524:        while (addr->bsel2 & DMC_RDYO) {
                    525: 
                    526:                cmd = addr->bsel2 & 0xff;
                    527:                arg = addr->sel6 & 0xffff;
                    528:                /* reconstruct UNIBUS address of buffer returned to us */
                    529:                pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff);
                    530:                /* release port */
                    531:                addr->bsel2 &= ~DMC_RDYO;
                    532:                switch (cmd & 07) {
                    533: 
                    534:                case DMC_OUR:
                    535:                        /*
                    536:                         * A read has completed.  
                    537:                         * Pass packet to type specific
                    538:                         * higher-level input routine.
                    539:                         */
                    540:                        ifp->if_ipackets++;
                    541:                        /* find location in dmcuba struct */
                    542:                        ifrw= &sc->sc_ifr[0];
                    543:                        for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
                    544:                                if(rp->ubinfo == pkaddr)
                    545:                                        break;
                    546:                                ifrw++;
                    547:                        }
                    548:                        if (rp >= &sc->sc_rbufs[NRCV])
                    549:                                panic("dmc rcv");
                    550:                        if ((rp->flags & DBUF_DMCS) == 0)
                    551:                                printf("dmc%d: done unalloc rbuf\n", unit);
                    552: 
                    553:                        len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header);
                    554:                        if (len < 0 || len > DMCMTU) {
                    555:                                ifp->if_ierrors++;
                    556:                                printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n",
                    557:                                    unit, pkaddr, len);
                    558:                                goto setup;
                    559:                        }
                    560:                        /*
                    561:                         * Deal with trailer protocol: if type is trailer
                    562:                         * get true type from first 16-bit word past data.
                    563:                         * Remember that type was trailer by setting off.
                    564:                         */
                    565:                        dh = (struct dmc_header *)ifrw->ifrw_addr;
                    566:                        dh->dmc_type = ntohs((u_short)dh->dmc_type);
                    567: #define dmcdataaddr(dh, off, type)     ((type)(((caddr_t)((dh)+1)+(off))))
                    568:                        if (dh->dmc_type >= DMC_TRAILER &&
                    569:                            dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) {
                    570:                                off = (dh->dmc_type - DMC_TRAILER) * 512;
                    571:                                if (off >= DMCMTU)
                    572:                                        goto setup;             /* sanity */
                    573:                                dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *));
                    574:                                resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *)));
                    575:                                if (off + resid > len)
                    576:                                        goto setup;             /* sanity */
                    577:                                len = off + resid;
                    578:                        } else
                    579:                                off = 0;
                    580:                        if (len == 0)
                    581:                                goto setup;
                    582: 
                    583:                        /*
                    584:                         * Pull packet off interface.  Off is nonzero if
                    585:                         * packet has trailing header; dmc_get will then
                    586:                         * force this header information to be at the front,
                    587:                         * but we still have to drop the type and length
                    588:                         * which are at the front of any trailer data.
                    589:                         */
                    590:                        m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp);
                    591:                        if (m == 0)
                    592:                                goto setup;
                    593:                        if (off) {
                    594:                                ifp = *(mtod(m, struct ifnet **));
                    595:                                m->m_off += 2 * sizeof (u_short);
                    596:                                m->m_len -= 2 * sizeof (u_short);
                    597:                                *(mtod(m, struct ifnet **)) = ifp;
                    598:                        }
                    599:                        switch (dh->dmc_type) {
                    600: 
                    601: #ifdef INET
                    602:                        case DMC_IPTYPE:
                    603:                                schednetisr(NETISR_IP);
                    604:                                inq = &ipintrq;
                    605:                                break;
                    606: #endif
                    607:                        default:
                    608:                                m_freem(m);
                    609:                                goto setup;
                    610:                        }
                    611: 
                    612:                        s = splimp();
                    613:                        if (IF_QFULL(inq)) {
                    614:                                IF_DROP(inq);
                    615:                                m_freem(m);
                    616:                        } else
                    617:                                IF_ENQUEUE(inq, m);
                    618:                        splx(s);
                    619: 
                    620:        setup:
                    621:                        /* is this needed? */
                    622:                        rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
                    623: 
                    624:                        dmcload(sc, DMC_READ, rp->ubinfo, 
                    625:                            ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc);
                    626:                        break;
                    627: 
                    628:                case DMC_OUX:
                    629:                        /*
                    630:                         * A write has completed, start another
                    631:                         * transfer if there is more data to send.
                    632:                         */
                    633:                        ifp->if_opackets++;
                    634:                        /* find associated dmcbuf structure */
                    635:                        ifxp = &sc->sc_ifw[0];
                    636:                        for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
                    637:                                if(rp->ubinfo == pkaddr)
                    638:                                        break;
                    639:                                ifxp++;
                    640:                        }
                    641:                        if (rp >= &sc->sc_xbufs[NXMT]) {
                    642:                                printf("dmc%d: bad packet address 0x%x\n",
                    643:                                    unit, pkaddr);
                    644:                                break;
                    645:                        }
                    646:                        if ((rp->flags & DBUF_DMCS) == 0)
                    647:                                printf("dmc%d: unallocated packet 0x%x\n",
                    648:                                    unit, pkaddr);
                    649:                        /* mark buffer free */
                    650:                        if (ifxp->ifw_xtofree) {
                    651:                                (void)m_freem(ifxp->ifw_xtofree);
                    652:                                ifxp->ifw_xtofree = 0;
                    653:                        }
                    654:                        rp->flags &= ~DBUF_DMCS;
                    655:                        sc->sc_oused--;
                    656:                        sc->sc_nticks = 0;
                    657:                        sc->sc_flag |= DMC_ACTIVE;
                    658:                        break;
                    659: 
                    660:                case DMC_CNTLO:
                    661:                        arg &= DMC_CNTMASK;
                    662:                        if (arg & DMC_FATAL) {
                    663:                                log(LOG_ERR, "dmc%d: fatal error, flags=%b\n",
                    664:                                    unit, arg, CNTLO_BITS);
                    665:                                dmcrestart(unit);
                    666:                                break;
                    667:                        }
                    668:                        /* ACCUMULATE STATISTICS */
                    669:                        switch(arg) {
                    670:                        case DMC_NOBUFS:
                    671:                                ifp->if_ierrors++;
                    672:                                if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0)
                    673:                                        goto report;
                    674:                                break;
                    675:                        case DMC_DISCONN:
                    676:                                if ((sc->sc_disc++ % DMC_RPDSC) == 0)
                    677:                                        goto report;
                    678:                                break;
                    679:                        case DMC_TIMEOUT:
                    680:                                if ((sc->sc_timeo++ % DMC_RPTMO) == 0)
                    681:                                        goto report;
                    682:                                break;
                    683:                        case DMC_DATACK:
                    684:                                ifp->if_oerrors++;
                    685:                                if ((sc->sc_datck++ % DMC_RPDCK) == 0)
                    686:                                        goto report;
                    687:                                break;
                    688:                        default:
                    689:                                goto report;
                    690:                        }
                    691:                        break;
                    692:                report:
                    693:                        printd("dmc%d: soft error, flags=%b\n", unit,
                    694:                            arg, CNTLO_BITS);
                    695:                        if ((sc->sc_flag & DMC_RESTART) == 0) {
                    696:                                /*
                    697:                                 * kill off the dmc to get things
                    698:                                 * going again by generating a
                    699:                                 * procedure error
                    700:                                 */
                    701:                                sc->sc_flag |= DMC_RESTART;
                    702:                                arg = sc->sc_ubinfo & 0x3ffff;
                    703:                                dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);
                    704:                        }
                    705:                        break;
                    706: 
                    707:                default:
                    708:                        printf("dmc%d: bad control %o\n", unit, cmd);
                    709:                        break;
                    710:                }
                    711:        }
                    712:        dmcstart(unit);
                    713:        return;
                    714: }
                    715: 
                    716: /*
                    717:  * DMC output routine.
                    718:  * Encapsulate a packet of type family for the dmc.
                    719:  * Use trailer local net encapsulation if enough data in first
                    720:  * packet leaves a multiple of 512 bytes of data in remainder.
                    721:  */
                    722: dmcoutput(ifp, m0, dst)
                    723:        register struct ifnet *ifp;
                    724:        register struct mbuf *m0;
                    725:        struct sockaddr *dst;
                    726: {
                    727:        int type, error, s;
                    728:        register struct mbuf *m = m0;
                    729:        register struct dmc_header *dh;
                    730:        register int off;
                    731: 
                    732:        switch (dst->sa_family) {
                    733: #ifdef INET
                    734:        case AF_INET:
                    735:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                    736:                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
                    737:                if (off > 0 && (off & 0x1ff) == 0 &&
                    738:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                    739:                        type = DMC_TRAILER + (off>>9);
                    740:                        m->m_off -= 2 * sizeof (u_short);
                    741:                        m->m_len += 2 * sizeof (u_short);
                    742:                        *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE);
                    743:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                    744:                        goto gottrailertype;
                    745:                }
                    746:                type = DMC_IPTYPE;
                    747:                off = 0;
                    748:                goto gottype;
                    749: #endif
                    750: 
                    751:        case AF_UNSPEC:
                    752:                dh = (struct dmc_header *)dst->sa_data;
                    753:                type = dh->dmc_type;
                    754:                goto gottype;
                    755: 
                    756:        default:
                    757:                printf("dmc%d: can't handle af%d\n", ifp->if_unit,
                    758:                        dst->sa_family);
                    759:                error = EAFNOSUPPORT;
                    760:                goto bad;
                    761:        }
                    762: 
                    763: gottrailertype:
                    764:        /*
                    765:         * Packet to be sent as a trailer; move first packet
                    766:         * (control information) to end of chain.
                    767:         */
                    768:        while (m->m_next)
                    769:                m = m->m_next;
                    770:        m->m_next = m0;
                    771:        m = m0->m_next;
                    772:        m0->m_next = 0;
                    773:        m0 = m;
                    774: 
                    775: gottype:
                    776:        /*
                    777:         * Add local network header
                    778:         * (there is space for a uba on a vax to step on)
                    779:         */
                    780:        if (m->m_off > MMAXOFF ||
                    781:            MMINOFF + sizeof(struct dmc_header) > m->m_off) {
                    782:                m = m_get(M_DONTWAIT, MT_HEADER);
                    783:                if (m == 0) {
                    784:                        error = ENOBUFS;
                    785:                        goto bad;
                    786:                }
                    787:                m->m_next = m0;
                    788:                m->m_off = MMINOFF;
                    789:                m->m_len = sizeof (struct dmc_header);
                    790:        } else {
                    791:                m->m_off -= sizeof (struct dmc_header);
                    792:                m->m_len += sizeof (struct dmc_header);
                    793:        }
                    794:        dh = mtod(m, struct dmc_header *);
                    795:        dh->dmc_type = htons((u_short)type);
                    796: 
                    797:        /*
                    798:         * Queue message on interface, and start output if interface
                    799:         * not yet active.
                    800:         */
                    801:        s = splimp();
                    802:        if (IF_QFULL(&ifp->if_snd)) {
                    803:                IF_DROP(&ifp->if_snd);
                    804:                m_freem(m);
                    805:                splx(s);
                    806:                return (ENOBUFS);
                    807:        }
                    808:        IF_ENQUEUE(&ifp->if_snd, m);
                    809:        dmcstart(ifp->if_unit);
                    810:        splx(s);
                    811:        return (0);
                    812: 
                    813: bad:
                    814:        m_freem(m0);
                    815:        return (error);
                    816: }
                    817: 
                    818: 
                    819: /*
                    820:  * Process an ioctl request.
                    821:  */
                    822: /* ARGSUSED */
                    823: dmcioctl(ifp, cmd, data)
                    824:        register struct ifnet *ifp;
                    825:        int cmd;
                    826:        caddr_t data;
                    827: {
                    828:        int s = splimp(), error = 0;
                    829:        register struct dmc_softc *sc = &dmc_softc[ifp->if_unit];
                    830: 
                    831:        switch (cmd) {
                    832: 
                    833:        case SIOCSIFADDR:
                    834:                ifp->if_flags |= IFF_UP;
                    835:                if ((ifp->if_flags & IFF_RUNNING) == 0)
                    836:                        dmcinit(ifp->if_unit); 
                    837:                break;
                    838: 
                    839:        case SIOCSIFDSTADDR:
                    840:                if ((ifp->if_flags & IFF_RUNNING) == 0)
                    841:                        dmcinit(ifp->if_unit); 
                    842:                break;
                    843:                
                    844:        case SIOCSIFFLAGS:
                    845:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    846:                    sc->sc_flag & DMC_RUNNING) {
                    847:                        ((struct dmcdevice *)
                    848:                           (dmcinfo[ifp->if_unit]->ui_addr))->bsel1 = DMC_MCLR;
                    849:                        sc->sc_flag &= ~DMC_RUNNING;
                    850:                } else if (ifp->if_flags & IFF_UP &&
                    851:                    (sc->sc_flag & DMC_RUNNING) == 0)
                    852:                        dmcrestart(ifp->if_unit);
                    853:                break;
                    854: 
                    855:        default:
                    856:                error = EINVAL;
                    857:        }
                    858:        splx(s);
                    859:        return (error);
                    860: }
                    861: 
                    862: /*
                    863:  * Restart after a fatal error.
                    864:  * Clear device and reinitialize.
                    865:  */
                    866: dmcrestart(unit)
                    867:        int unit;
                    868: {
                    869:        register struct dmc_softc *sc = &dmc_softc[unit];
                    870:        register struct uba_device *ui = dmcinfo[unit];
                    871:        register struct dmcdevice *addr;
                    872:        register struct ifxmt *ifxp;
                    873:        register int i;
                    874:        
                    875:        addr = (struct dmcdevice *)ui->ui_addr;
                    876: #ifdef DEBUG
                    877:        /* dump base table */
                    878:        printf("dmc%d base table:\n", unit);
                    879:        for (i = 0; i < sizeof (struct dmc_base); i++)
                    880:                printf("%o\n" ,dmc_base[unit].d_base[i]);
                    881: #endif
                    882:        /*
                    883:         * Let the DMR finish the MCLR.  At 1 Mbit, it should do so
                    884:         * in about a max of 6.4 milliseconds with diagnostics enabled.
                    885:         */
                    886:        addr->bsel1 = DMC_MCLR;
                    887:        for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
                    888:                ;
                    889:        /* Did the timer expire or did the DMR finish? */
                    890:        if ((addr->bsel1 & DMC_RUN) == 0) {
                    891:                log(LOG_ERR, "dmc%d: M820 Test Failed\n", unit);
                    892:                return;
                    893:        }
                    894: 
                    895:        for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) {
                    896:                if (ifxp->ifw_xtofree) {
                    897:                        (void) m_freem(ifxp->ifw_xtofree);
                    898:                        ifxp->ifw_xtofree = 0;
                    899:                }
                    900:        }
                    901: 
                    902:        /* restart DMC */
                    903:        dmcinit(unit);
                    904:        sc->sc_flag &= ~DMC_RESTART;
                    905:        sc->sc_if.if_collisions++;      /* why not? */
                    906: }
                    907: 
                    908: /*
                    909:  * Check to see that transmitted packets don't
                    910:  * lose interrupts.  The device has to be active.
                    911:  */
                    912: dmcwatch()
                    913: {
                    914:        register struct uba_device *ui;
                    915:        register struct dmc_softc *sc;
                    916:        struct dmcdevice *addr;
                    917:        register int i;
                    918: 
                    919:        for (i = 0; i < NDMC; i++) {
                    920:                sc = &dmc_softc[i];
                    921:                if ((sc->sc_flag & DMC_ACTIVE) == 0)
                    922:                        continue;
                    923:                if ((ui = dmcinfo[i]) == 0 || ui->ui_alive == 0)
                    924:                        continue;
                    925:                if (sc->sc_oused) {
                    926:                        sc->sc_nticks++;
                    927:                        if (sc->sc_nticks > dmc_timeout) {
                    928:                                sc->sc_nticks = 0;
                    929:                                addr = (struct dmcdevice *)ui->ui_addr;
                    930:                                log(LOG_ERR, "dmc%d hung: bsel0=%b bsel2=%b\n",
                    931:                                    i, addr->bsel0 & 0xff, DMC0BITS,
                    932:                                    addr->bsel2 & 0xff, DMC2BITS);
                    933:                                dmcrestart(i);
                    934:                        }
                    935:                }
                    936:        }
                    937:        timeout(dmcwatch, (caddr_t) 0, hz);
                    938: }
                    939: #endif

unix.superglobalmegacorp.com

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