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

unix.superglobalmegacorp.com

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