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

1.1       root        1: /*     if_dmc.c        6.1     83/07/29        */
                      2: 
                      3: #include "dmc.h"
                      4: #if NDMC > 0
                      5: #define printd if(dmcdebug)printf
                      6: int dmcdebug = 0;
                      7: /*
                      8:  * DMC11 device driver, internet version
                      9:  *
                     10:  * TODO
                     11:  *     allow more than one outstanding read or write.
                     12:  *
                     13:  * UNTESTED WITH 4.2
                     14:  */
                     15: #include "../machine/pte.h"
                     16: 
                     17: #include "../h/param.h"
                     18: #include "../h/systm.h"
                     19: #include "../h/mbuf.h"
                     20: #include "../h/buf.h"
                     21: #include "../h/ioctl.h"                        /* must precede tty.h */
                     22: #include "../h/tty.h"
                     23: #include "../h/protosw.h"
                     24: #include "../h/socket.h"
                     25: #include "../h/vmmac.h"
                     26: #include "../h/errno.h"
                     27: 
                     28: #include "../net/if.h"
                     29: #include "../net/netisr.h"
                     30: #include "../net/route.h"
                     31: #include "../netinet/in.h"
                     32: #include "../netinet/in_systm.h"
                     33: 
                     34: #include "../vax/cpu.h"
                     35: #include "../vax/mtpr.h"
                     36: #include "../vaxif/if_uba.h"
                     37: #include "../vaxif/if_dmc.h"
                     38: #include "../vaxuba/ubareg.h"
                     39: #include "../vaxuba/ubavar.h"
                     40: 
                     41: #ifndef DMC_USEMAINT
                     42: #define        DMC_USEMAINT    1       /* use maintenance mode */
                     43: #endif
                     44: 
                     45: /*
                     46:  * Driver information for auto-configuration stuff.
                     47:  */
                     48: int    dmcprobe(), dmcattach(), dmcinit(), dmcioctl();
                     49: int    dmcoutput(), dmcreset();
                     50: struct uba_device *dmcinfo[NDMC];
                     51: u_short        dmcstd[] = { 0 };
                     52: struct uba_driver dmcdriver =
                     53:        { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
                     54: 
                     55: /*
                     56:  * DMC software status per interface.
                     57:  *
                     58:  * Each interface is referenced by a network interface structure,
                     59:  * sc_if, which the routing code uses to locate the interface.
                     60:  * This structure contains the output queue for the interface, its address, ...
                     61:  * We also have, for each interface, a UBA interface structure, which
                     62:  * contains information about the UNIBUS resources held by the interface:
                     63:  * map registers, buffered data paths, etc.  Information is cached in this
                     64:  * structure for use by the if_uba.c routines in running the interface
                     65:  * efficiently.
                     66:  */
                     67: struct dmc_softc {
                     68:        struct  ifnet sc_if;            /* network-visible interface */
                     69:        struct  ifuba sc_ifuba;         /* UNIBUS resources */
                     70:        short   sc_flag;                /* flags */
                     71:        short   sc_oactive;             /* output active */
                     72:        int     sc_ubinfo;              /* UBA mapping info for base table */
                     73:        struct clist sc_que;            /* command queue */
                     74: } dmc_softc[NDMC];
                     75: 
                     76: /* flags */
                     77: #define        DMCRUN          01
                     78: #define        DMCBMAPPED      02              /* base table mapped */
                     79: 
                     80: struct dmc_base {
                     81:        short   d_base[128];            /* DMC base table */
                     82: } dmc_base[NDMC];
                     83: 
                     84: #define        loword(x)       ((short *)&x)[0]
                     85: #define        hiword(x)       ((short *)&x)[1]
                     86: 
                     87: dmcprobe(reg)
                     88:        caddr_t reg;
                     89: {
                     90:        register int br, cvec;
                     91:        register struct dmcdevice *addr = (struct dmcdevice *)reg;
                     92:        register int i;
                     93: 
                     94: #ifdef lint
                     95:        br = 0; cvec = br; br = cvec;
                     96:        dmcrint(0); dmcxint(0);
                     97: #endif
                     98:        addr->bsel1 = DMC_MCLR;
                     99:        for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
                    100:                ;
                    101:        if ((addr->bsel1 & DMC_RUN) == 0)
                    102:                return (0);
                    103:        addr->bsel1 &= ~DMC_MCLR;
                    104:        addr->bsel0 = DMC_RQI|DMC_IEI;
                    105:        DELAY(100000);
                    106:        addr->bsel1 = DMC_MCLR;
                    107:        for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
                    108:                ;
                    109:        return (1);
                    110: }
                    111: 
                    112: /*
                    113:  * Interface exists: make available by filling in network interface
                    114:  * record.  System will initialize the interface when it is ready
                    115:  * to accept packets.
                    116:  */
                    117: dmcattach(ui)
                    118:        register struct uba_device *ui;
                    119: {
                    120:        register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
                    121: 
                    122:        sc->sc_if.if_unit = ui->ui_unit;
                    123:        sc->sc_if.if_name = "dmc";
                    124:        sc->sc_if.if_mtu = DMCMTU;
                    125:        sc->sc_if.if_init = dmcinit;
                    126:        sc->sc_if.if_output = dmcoutput;
                    127:        sc->sc_if.if_ioctl = dmcioctl;
                    128:        sc->sc_if.if_reset = dmcreset;
                    129:        /* DON'T KNOW IF THIS WILL WORK WITH A BDP AT HIGH SPEEDS */
                    130:        sc->sc_ifuba.ifu_flags = UBA_NEEDBDP | UBA_CANTWAIT;
                    131:        if_attach(&sc->sc_if);
                    132: }
                    133: 
                    134: /*
                    135:  * Reset of interface after UNIBUS reset.
                    136:  * If interface is on specified UBA, reset it's state.
                    137:  */
                    138: dmcreset(unit, uban)
                    139:        int unit, uban;
                    140: {
                    141:        register struct uba_device *ui;
                    142: 
                    143:        if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    144:            ui->ui_ubanum != uban)
                    145:                return;
                    146:        printf(" dmc%d", unit);
                    147:        dmcinit(unit);
                    148: }
                    149: 
                    150: /*
                    151:  * Initialization of interface; reinitialize UNIBUS usage.
                    152:  */
                    153: dmcinit(unit)
                    154:        int unit;
                    155: {
                    156:        register struct dmc_softc *sc = &dmc_softc[unit];
                    157:        register struct uba_device *ui = dmcinfo[unit];
                    158:        register struct dmcdevice *addr;
                    159:        register struct ifnet *ifp = &sc->sc_if;
                    160:        struct sockaddr_in *sin;
                    161:        int base;
                    162: 
                    163:        printd("dmcinit\n");
                    164:        sin = (struct sockaddr_in *)&ifp->if_addr;
                    165:        if (sin->sin_addr.s_addr == 0)
                    166:                return;
                    167:        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                    168:                if ((sc->sc_flag&DMCBMAPPED) == 0) {
                    169:                        sc->sc_ubinfo = uballoc(ui->ui_ubanum,
                    170:                            (caddr_t)&dmc_base[unit],
                    171:                            sizeof (struct dmc_base), 0);
                    172:                        sc->sc_flag |= DMCBMAPPED;
                    173:                }
                    174:                if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0,
                    175:                    (int)btoc(DMCMTU)) == 0) {
                    176:                        printf("dmc%d: can't initialize\n", unit);
                    177:                        ifp->if_flags &= ~IFF_UP;
                    178:                        return;
                    179:                }
                    180:                addr = (struct dmcdevice *)ui->ui_addr;
                    181:                addr->bsel2 |= DMC_IEO;
                    182:                base = sc->sc_ubinfo & 0x3ffff;
                    183:                printd("  base 0x%x\n", base);
                    184:                dmcload(sc, DMC_BASEI, base, (base>>2)&DMC_XMEM);
                    185:                dmcload(sc, DMC_CNTLI, 0, DMC_USEMAINT ? DMC_MAINT : 0);
                    186:                base = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff;
                    187:                dmcload(sc, DMC_READ, base, ((base>>2)&DMC_XMEM)|DMCMTU);
                    188:                printd("  first read queued, addr 0x%x\n", base);
                    189:                ifp->if_flags |= IFF_UP|IFF_RUNNING;
                    190:        }
                    191:        /* set up routing table entry */
                    192:        if ((ifp->if_flags & IFF_ROUTE) == 0) {
                    193:                rtinit((struct sockaddr *)sin, (struct sockaddr *)sin,
                    194:                    RTF_HOST|RTF_UP);
                    195:                ifp->if_flags |= IFF_ROUTE;
                    196:        }
                    197: }
                    198: 
                    199: /*
                    200:  * Start output on interface.  Get another datagram
                    201:  * to send from the interface queue and map it to
                    202:  * the interface before starting output.
                    203:  */
                    204: dmcstart(dev)
                    205:        dev_t dev;
                    206: {
                    207:        int unit = minor(dev);
                    208:        register struct dmc_softc *sc = &dmc_softc[unit];
                    209:        int addr, len;
                    210:        struct mbuf *m;
                    211: 
                    212:        printd("dmcstart\n");
                    213:        /*
                    214:         * Dequeue a request and map it to the UNIBUS.
                    215:         * If no more requests, just return.
                    216:         */
                    217:        IF_DEQUEUE(&sc->sc_if.if_snd, m);
                    218:        if (m == 0)
                    219:                return;
                    220:        len = if_wubaput(&sc->sc_ifuba, m);
                    221: 
                    222:        /*
                    223:         * Have request mapped to UNIBUS for transmission.
                    224:         * Purge any stale data from this BDP and start the output.
                    225:         */
                    226:        if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP)
                    227:                UBAPURGE(sc->sc_ifuba.ifu_uba, sc->sc_ifuba.ifu_w.ifrw_bdp);
                    228:        addr = sc->sc_ifuba.ifu_w.ifrw_info & 0x3ffff;
                    229:        printd("  len %d, addr 0x%x, ", len, addr);
                    230:        printd("mr 0x%x\n", sc->sc_ifuba.ifu_w.ifrw_mr[0]);
                    231:        dmcload(sc, DMC_WRITE, addr, (len&DMC_CCOUNT)|((addr>>2)&DMC_XMEM));
                    232:        sc->sc_oactive = 1;
                    233: }
                    234: 
                    235: /*
                    236:  * Utility routine to load the DMC device registers.
                    237:  */
                    238: dmcload(sc, type, w0, w1)
                    239:        register struct dmc_softc *sc;
                    240:        int type, w0, w1;
                    241: {
                    242:        register struct dmcdevice *addr;
                    243:        register int unit, sps, n;
                    244: 
                    245:        printd("dmcload: 0x%x 0x%x 0x%x\n", type, w0, w1);
                    246:        unit = sc - dmc_softc;
                    247:        addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
                    248:        sps = spl5();
                    249:        if ((n = sc->sc_que.c_cc) == 0)
                    250:                addr->bsel0 = type | DMC_RQI;
                    251:        else
                    252:                (void) putc(type | DMC_RQI, &sc->sc_que);
                    253:        (void) putw(w0, &sc->sc_que);
                    254:        (void) putw(w1, &sc->sc_que);
                    255:        if (n == 0)
                    256:                dmcrint(unit);
                    257:        splx(sps);
                    258: }
                    259: 
                    260: /*
                    261:  * DMC interface receiver interrupt.
                    262:  * Ready to accept another command,
                    263:  * pull one off the command queue.
                    264:  */
                    265: dmcrint(unit)
                    266:        int unit;
                    267: {
                    268:        register struct dmc_softc *sc;
                    269:        register struct dmcdevice *addr;
                    270:        register int n;
                    271: 
                    272:        addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
                    273:        sc = &dmc_softc[unit];
                    274:        while (addr->bsel0&DMC_RDYI) {
                    275:                addr->sel4 = getw(&sc->sc_que);
                    276:                addr->sel6 = getw(&sc->sc_que);
                    277:                addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
                    278:                while (addr->bsel0&DMC_RDYI)
                    279:                        ;
                    280:                if (sc->sc_que.c_cc == 0)
                    281:                        goto out;
                    282:                addr->bsel0 = getc(&sc->sc_que);
                    283:                n = RDYSCAN;
                    284:                while (n-- && (addr->bsel0&DMC_RDYI) == 0)
                    285:                        ;
                    286:        }
                    287:        if (sc->sc_que.c_cc)
                    288:                addr->bsel0 |= DMC_IEI;
                    289: out:
                    290:        dmcxint(unit);
                    291: }
                    292: 
                    293: /*
                    294:  * DMC interface transmitter interrupt.
                    295:  * A transfer has completed, check for errors.
                    296:  * If it was a read, notify appropriate protocol.
                    297:  * If it was a write, pull the next one off the queue.
                    298:  */
                    299: dmcxint(unit)
                    300:        int unit;
                    301: {
                    302:        register struct dmc_softc *sc;
                    303:        register struct ifnet *ifp;
                    304:        struct uba_device *ui = dmcinfo[unit];
                    305:        struct dmcdevice *addr;
                    306:        struct mbuf *m;
                    307:        register struct ifqueue *inq;
                    308:        int arg, cmd, len;
                    309: 
                    310:        addr = (struct dmcdevice *)ui->ui_addr;
                    311:        cmd = addr->bsel2 & 0xff;
                    312:        if ((cmd & DMC_RDYO) == 0)
                    313:                return;
                    314: #ifdef notdef
                    315:        arg2 = addr->sel4;
                    316: #endif
                    317:        arg = addr->sel6;
                    318:        addr->bsel2 &= ~DMC_RDYO;
                    319:        sc = &dmc_softc[unit];
                    320:        ifp = &sc->sc_if;
                    321:        printd("dmcxint\n");
                    322:        switch (cmd & 07) {
                    323: 
                    324:        case DMC_OUR:
                    325:                /*
                    326:                 * A read has completed.  Purge input buffered
                    327:                 * data path.  Pass packet to type specific
                    328:                 * higher-level input routine.
                    329:                 */
                    330:                ifp->if_ipackets++;
                    331:                if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP)
                    332:                        UBAPURGE(sc->sc_ifuba.ifu_uba,
                    333:                                sc->sc_ifuba.ifu_r.ifrw_bdp);
                    334:                len = arg & DMC_CCOUNT;
                    335:                printd("  read done, len %d\n", len);
                    336:                switch (ifp->if_addr.sa_family) {
                    337: #ifdef INET
                    338:                case AF_INET:
                    339:                        schednetisr(NETISR_IP);
                    340:                        inq = &ipintrq;
                    341:                        break;
                    342: #endif
                    343: 
                    344:                default:
                    345:                        printf("dmc%d: unknown address type %d\n", unit,
                    346:                            ifp->if_addr.sa_family);
                    347:                        goto setup;
                    348:                }
                    349:                m = if_rubaget(&sc->sc_ifuba, len, 0);
                    350:                if (m == 0)
                    351:                        goto setup;
                    352:                if (IF_QFULL(inq)) {
                    353:                        IF_DROP(inq);
                    354:                        m_freem(m);
                    355:                } else
                    356:                        IF_ENQUEUE(inq, m);
                    357: 
                    358: setup:
                    359:                arg = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff;
                    360:                dmcload(sc, DMC_READ, arg, ((arg >> 2) & DMC_XMEM) | DMCMTU);
                    361:                return;
                    362: 
                    363:        case DMC_OUX:
                    364:                /*
                    365:                 * A write has completed, start another
                    366:                 * transfer if there is more data to send.
                    367:                 */
                    368:                if (sc->sc_oactive == 0)
                    369:                        return;         /* SHOULD IT BE A FATAL ERROR? */
                    370:                printd("  write done\n");
                    371:                ifp->if_opackets++;
                    372:                sc->sc_oactive = 0;
                    373:                if (sc->sc_ifuba.ifu_xtofree) {
                    374:                        m_freem(sc->sc_ifuba.ifu_xtofree);
                    375:                        sc->sc_ifuba.ifu_xtofree = 0;
                    376:                }
                    377:                if (ifp->if_snd.ifq_head == 0)
                    378:                        return;
                    379:                dmcstart(unit);
                    380:                return;
                    381: 
                    382:        case DMC_CNTLO:
                    383:                arg &= DMC_CNTMASK;
                    384:                if (arg&DMC_FATAL) {
                    385:                        addr->bsel1 = DMC_MCLR;
                    386:                        sc->sc_flag &= ~DMCRUN;
                    387:                        /*** DO SOMETHING TO RESTART DEVICE ***/
                    388:                        printf("DMC FATAL ERROR 0%o\n", arg);
                    389:                } else {
                    390:                        /* ACCUMULATE STATISTICS */
                    391:                        printf("DMC SOFT ERROR 0%o\n", arg);
                    392:                }
                    393:                return;
                    394: 
                    395:        default:
                    396:                printf("dmc%d: bad control %o\n", unit, cmd);
                    397:        }
                    398: }
                    399: 
                    400: /*
                    401:  * DMC output routine.
                    402:  * Just send the data, header was supplied by
                    403:  * upper level protocol routines.
                    404:  */
                    405: dmcoutput(ifp, m, dst)
                    406:        register struct ifnet *ifp;
                    407:        register struct mbuf *m;
                    408:        struct sockaddr *dst;
                    409: {
                    410:        int s;
                    411: 
                    412:        printd("dmcoutput\n");
                    413:        if (dst->sa_family != ifp->if_addr.sa_family) {
                    414:                printf("dmc%d: af%d not supported\n", ifp->if_unit,
                    415:                    dst->sa_family);
                    416:                m_freem(m);
                    417:                return (EAFNOSUPPORT);
                    418:        }
                    419:        s = splimp();
                    420:        if (IF_QFULL(&ifp->if_snd)) {
                    421:                IF_DROP(&ifp->if_snd);
                    422:                m_freem(m);
                    423:                splx(s);
                    424:                return (ENOBUFS);
                    425:        }
                    426:        IF_ENQUEUE(&ifp->if_snd, m);
                    427:        if (dmc_softc[ifp->if_unit].sc_oactive == 0)
                    428:                dmcstart(ifp->if_unit);
                    429:        splx(s);
                    430:        return (0);
                    431: }
                    432: 
                    433: /*
                    434:  * Process an ioctl request.
                    435:  */
                    436: dmcioctl(ifp, cmd, data)
                    437:        register struct ifnet *ifp;
                    438:        int cmd;
                    439:        caddr_t data;
                    440: {
                    441:        struct ifreq *ifr = (struct ifreq *)data;
                    442:        struct sockaddr_in *sin;
                    443:        int s = splimp(), error = 0;
                    444: 
                    445:        switch (cmd) {
                    446: 
                    447:        case SIOCSIFADDR:
                    448:                if (ifp->if_flags & IFF_RUNNING)
                    449:                        if_rtinit(ifp, -1);     /* delete previous route */
                    450:                sin = (struct sockaddr_in *)&ifr->ifr_addr;
                    451:                ifp->if_addr = *(struct sockaddr *)sin;
                    452:                ifp->if_net = in_netof(sin->sin_addr);
                    453:                ifp->if_host[0] = in_lnaof(sin->sin_addr);
                    454:                dmcinit(ifp->if_unit);
                    455:                break;
                    456: 
                    457:        case SIOCSIFDSTADDR:
                    458:                ifp->if_dstaddr = ifr->ifr_dstaddr;
                    459:                break;
                    460: 
                    461:        default:
                    462:                error = EINVAL;
                    463:        }
                    464:        splx(s);
                    465:        return (error);
                    466: }
                    467: #endif

unix.superglobalmegacorp.com

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