Annotation of 42BSD/sys/vaxif/if_dmc.c, revision 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.