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

unix.superglobalmegacorp.com

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