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

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)if_acc.c    7.1 (Berkeley) 6/5/86
                      7:  */
                      8: 
                      9: #include "acc.h"
                     10: #if NACC > 0
                     11: 
                     12: /*
                     13:  * ACC LH/DH ARPAnet IMP interface driver.
                     14:  */
                     15: #include "../machine/pte.h"
                     16: 
                     17: #include "param.h"
                     18: #include "systm.h"
                     19: #include "mbuf.h"
                     20: #include "buf.h"
                     21: #include "protosw.h"
                     22: #include "socket.h"
                     23: #include "vmmac.h"
                     24: 
                     25: #include "../net/if.h"
                     26: #include "../netimp/if_imp.h"
                     27: 
                     28: #include "../vax/cpu.h"
                     29: #include "../vax/mtpr.h"
                     30: #include "if_accreg.h"
                     31: #include "if_uba.h"
                     32: #include "../vaxuba/ubareg.h"
                     33: #include "../vaxuba/ubavar.h"
                     34: 
                     35: int     accprobe(), accattach(), accrint(), accxint();
                     36: struct  uba_device *accinfo[NACC];
                     37: u_short accstd[] = { 0 };
                     38: struct  uba_driver accdriver =
                     39:        { accprobe, 0, accattach, 0, accstd, "acc", accinfo };
                     40: #define        ACCUNIT(x)      minor(x)
                     41: 
                     42: int    accinit(), accstart(), accreset();
                     43: 
                     44: /*
                     45:  * "Lower half" of IMP interface driver.
                     46:  *
                     47:  * Each IMP interface is handled by a common module which handles
                     48:  * the IMP-host protocol and a hardware driver which manages the
                     49:  * hardware specific details of talking with the IMP.
                     50:  *
                     51:  * The hardware portion of the IMP driver handles DMA and related
                     52:  * management of UNIBUS resources.  The IMP protocol module interprets
                     53:  * contents of these messages and "controls" the actions of the
                     54:  * hardware module during IMP resets, but not, for instance, during
                     55:  * UNIBUS resets.
                     56:  *
                     57:  * The two modules are coupled at "attach time", and ever after,
                     58:  * through the imp interface structure.  Higher level protocols,
                     59:  * e.g. IP, interact with the IMP driver, rather than the ACC.
                     60:  */
                     61: struct acc_softc {
                     62:        struct  ifnet *acc_if;          /* pointer to IMP's ifnet struct */
                     63:        struct  impcb *acc_ic;          /* data structure shared with IMP */
                     64:        struct  ifuba acc_ifuba;        /* UNIBUS resources */
                     65:        struct  mbuf *acc_iq;           /* input reassembly queue */
                     66:        short   acc_olen;               /* size of last message sent */
                     67:        char    acc_flush;              /* flush remainder of message */
                     68: } acc_softc[NACC];
                     69: 
                     70: /*
                     71:  * Reset the IMP and cause a transmitter interrupt by
                     72:  * performing a null DMA.
                     73:  */
                     74: accprobe(reg)
                     75:        caddr_t reg;
                     76: {
                     77:        register int br, cvec;          /* r11, r10 value-result */
                     78:        register struct accdevice *addr = (struct accdevice *)reg;
                     79: 
                     80: #ifdef lint
                     81:        br = 0; cvec = br; br = cvec;
                     82:        accrint(0); accxint(0);
                     83: #endif
                     84:        addr->icsr = ACC_RESET; DELAY(5000);
                     85:        addr->ocsr = ACC_RESET; DELAY(5000);
                     86:        addr->ocsr = OUT_BBACK; DELAY(5000);
                     87:        addr->owc = 0;
                     88:        addr->ocsr = ACC_IE | ACC_GO; DELAY(5000);
                     89:        addr->ocsr = 0;
                     90:        if (cvec && cvec != 0x200)      /* transmit -> receive */
                     91:                cvec -= 4;
                     92:        return (1);
                     93: }
                     94: 
                     95: /*
                     96:  * Call the IMP module to allow it to set up its internal
                     97:  * state, then tie the two modules together by setting up
                     98:  * the back pointers to common data structures.
                     99:  */
                    100: accattach(ui)
                    101:        struct uba_device *ui;
                    102: {
                    103:        register struct acc_softc *sc = &acc_softc[ui->ui_unit];
                    104:        register struct impcb *ip;
                    105:        struct ifimpcb {
                    106:                struct  ifnet ifimp_if;
                    107:                struct  impcb ifimp_impcb;
                    108:        } *ifimp;
                    109: 
                    110:        if ((ifimp = (struct ifimpcb *)impattach(ui, accreset)) == 0)
                    111:                return;
                    112:        sc->acc_if = &ifimp->ifimp_if;
                    113:        ip = &ifimp->ifimp_impcb;
                    114:        sc->acc_ic = ip;
                    115:        ip->ic_init = accinit;
                    116:        ip->ic_start = accstart;
                    117:        sc->acc_ifuba.ifu_flags = UBA_CANTWAIT;
                    118: #ifdef notdef
                    119:        sc->acc_ifuba.ifu_flags |= UBA_NEEDBDP;
                    120: #endif
                    121: }
                    122: 
                    123: /*
                    124:  * Reset interface after UNIBUS reset.
                    125:  * If interface is on specified uba, reset its state.
                    126:  */
                    127: accreset(unit, uban)
                    128:        int unit, uban;
                    129: {
                    130:        register struct uba_device *ui;
                    131:        struct acc_softc *sc;
                    132: 
                    133:        if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    134:            ui->ui_ubanum != uban)
                    135:                return;
                    136:        printf(" acc%d", unit);
                    137:        sc = &acc_softc[unit];
                    138:        sc->acc_if->if_flags &= ~IFF_RUNNING;
                    139:        /* must go through IMP to allow it to set state */
                    140:        (*sc->acc_if->if_init)(unit);
                    141: }
                    142: 
                    143: /*
                    144:  * Initialize interface: clear recorded pending operations,
                    145:  * and retrieve, and initialize UNIBUS resources.  Note
                    146:  * return value is used by IMP init routine to mark IMP
                    147:  * unavailable for outgoing traffic.
                    148:  */
                    149: accinit(unit)
                    150:        int unit;
                    151: {      
                    152:        register struct acc_softc *sc;
                    153:        register struct uba_device *ui;
                    154:        register struct accdevice *addr;
                    155:        int info;
                    156: 
                    157:        if (unit >= NACC || (ui = accinfo[unit]) == 0 || ui->ui_alive == 0) {
                    158:                printf("acc%d: not alive\n", unit);
                    159:                return (0);
                    160:        }
                    161:        sc = &acc_softc[unit];
                    162:        /*
                    163:         * Header length is 0 since we have to passs
                    164:         * the IMP leader up to the protocol interpretation
                    165:         * routines.  If we had the header length as
                    166:         * sizeof(struct imp_leader), then the if_ routines
                    167:         * would asssume we handle it on input and output.
                    168:         */
                    169:        if (if_ubainit(&sc->acc_ifuba, ui->ui_ubanum, 0,
                    170:             (int)btoc(IMPMTU+2)) == 0) {
                    171:                printf("acc%d: can't initialize\n", unit);
                    172:                ui->ui_alive = 0;
                    173:                sc->acc_if->if_flags &= ~(IFF_UP | IFF_RUNNING);
                    174:                return (0);
                    175:        }
                    176:        sc->acc_if->if_flags |= IFF_RUNNING;
                    177:        addr = (struct accdevice *)ui->ui_addr;
                    178: 
                    179:        /*
                    180:         * Reset the imp interface;
                    181:         * the delays are pure guesswork.
                    182:         */
                    183:         addr->ocsr = ACC_RESET; DELAY(5000);
                    184:        addr->ocsr = OUT_BBACK; DELAY(5000);    /* reset host master ready */
                    185:        addr->ocsr = 0;
                    186:        if (accinputreset(addr, unit) == 0) {
                    187:                ui->ui_alive = 0;
                    188:                return (0);
                    189:        }
                    190: 
                    191:        /*
                    192:         * Put up a read.  We can't restart any outstanding writes
                    193:         * until we're back in synch with the IMP (i.e. we've flushed
                    194:         * the NOOPs it throws at us).
                    195:         * Note: IMPMTU includes the leader.
                    196:         */
                    197:        info = sc->acc_ifuba.ifu_r.ifrw_info;
                    198:        addr->iba = (u_short)info;
                    199:        addr->iwc = -((IMPMTU + 2) >> 1);
                    200: #ifdef LOOPBACK
                    201:        addr->ocsr |= OUT_BBACK;
                    202: #endif
                    203:        addr->icsr = 
                    204:                IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO;
                    205:        return (1);
                    206: }
                    207: 
                    208: accinputreset(addr, unit)
                    209:        register struct accdevice *addr;
                    210:        register int unit;
                    211: {
                    212:        register int i;
                    213: 
                    214:        addr->icsr = ACC_RESET; DELAY(5000);
                    215:        addr->icsr = IN_MRDY | IN_WEN;          /* close the relay */
                    216:        DELAY(10000);
                    217:        /* YECH!!! */
                    218:        for (i = 0; i < 500; i++) {
                    219:                if ((addr->icsr & IN_HRDY) ||
                    220:                    (addr->icsr & (IN_RMR | IN_IMPBSY)) == 0)
                    221:                        return (1);
                    222:                addr->icsr = IN_MRDY | IN_WEN; DELAY(10000);
                    223:                /* keep turning IN_RMR off */
                    224:        }
                    225:        printf("acc%d: imp doesn't respond, icsr=%b\n", unit,
                    226:                addr->icsr, ACC_INBITS);
                    227:        return (0);
                    228: }
                    229: 
                    230: /*
                    231:  * Start output on an interface.
                    232:  */
                    233: accstart(dev)
                    234:        dev_t dev;
                    235: {
                    236:        int unit = ACCUNIT(dev), info;
                    237:        register struct acc_softc *sc = &acc_softc[unit];
                    238:        register struct accdevice *addr;
                    239:        struct mbuf *m;
                    240:        u_short cmd;
                    241: 
                    242:        if (sc->acc_ic->ic_oactive)
                    243:                goto restart;
                    244:        
                    245:        /*
                    246:         * Not already active, deqeue a request and
                    247:         * map it onto the UNIBUS.  If no more
                    248:         * requeusts, just return.
                    249:         */
                    250:        IF_DEQUEUE(&sc->acc_if->if_snd, m);
                    251:        if (m == 0) {
                    252:                sc->acc_ic->ic_oactive = 0;
                    253:                return;
                    254:        }
                    255:        sc->acc_olen = if_wubaput(&sc->acc_ifuba, m);
                    256: 
                    257: restart:
                    258:        /*
                    259:         * Have request mapped to UNIBUS for
                    260:         * transmission; start the output.
                    261:         */
                    262:        if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP)
                    263:                UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_w.ifrw_bdp);
                    264:        addr = (struct accdevice *)accinfo[unit]->ui_addr;
                    265:        info = sc->acc_ifuba.ifu_w.ifrw_info;
                    266:        addr->oba = (u_short)info;
                    267:        addr->owc = -((sc->acc_olen + 1) >> 1);
                    268:        cmd = ACC_IE | OUT_ENLB | ((info & 0x30000) >> 12) | ACC_GO;
                    269: #ifdef LOOPBACK
                    270:        cmd |= OUT_BBACK;
                    271: #endif
                    272:        addr->ocsr = cmd;
                    273:        sc->acc_ic->ic_oactive = 1;
                    274: }
                    275: 
                    276: /*
                    277:  * Output interrupt handler.
                    278:  */
                    279: accxint(unit)
                    280:        int unit;
                    281: {
                    282:        register struct acc_softc *sc = &acc_softc[unit];
                    283:        register struct accdevice *addr;
                    284: 
                    285:        addr = (struct accdevice *)accinfo[unit]->ui_addr;
                    286:        if (sc->acc_ic->ic_oactive == 0) {
                    287:                printf("acc%d: stray xmit interrupt, csr=%b\n", unit,
                    288:                        addr->ocsr, ACC_OUTBITS);
                    289:                return;
                    290:        }
                    291:        sc->acc_if->if_opackets++;
                    292:        sc->acc_ic->ic_oactive = 0;
                    293:        if (addr->ocsr & ACC_ERR) {
                    294:                printf("acc%d: output error, ocsr=%b, icsr=%b\n", unit,
                    295:                        addr->ocsr, ACC_OUTBITS, addr->icsr, ACC_INBITS);
                    296:                sc->acc_if->if_oerrors++;
                    297:        }
                    298:        if (sc->acc_ifuba.ifu_xtofree) {
                    299:                m_freem(sc->acc_ifuba.ifu_xtofree);
                    300:                sc->acc_ifuba.ifu_xtofree = 0;
                    301:        }
                    302:        if (sc->acc_if->if_snd.ifq_head)
                    303:                accstart(unit);
                    304: }
                    305: 
                    306: /*
                    307:  * Input interrupt handler
                    308:  */
                    309: accrint(unit)
                    310:        int unit;
                    311: {
                    312:        register struct acc_softc *sc = &acc_softc[unit];
                    313:        register struct accdevice *addr;
                    314:        struct mbuf *m;
                    315:        int len, info;
                    316: 
                    317:        addr = (struct accdevice *)accinfo[unit]->ui_addr;
                    318:        sc->acc_if->if_ipackets++;
                    319: 
                    320:        /*
                    321:         * Purge BDP; flush message if error indicated.
                    322:         */
                    323:        if (sc->acc_ifuba.ifu_flags & UBA_NEEDBDP)
                    324:                UBAPURGE(sc->acc_ifuba.ifu_uba, sc->acc_ifuba.ifu_r.ifrw_bdp);
                    325:        if (addr->icsr & ACC_ERR) {
                    326:                printf("acc%d: input error, csr=%b\n", unit,
                    327:                    addr->icsr, ACC_INBITS);
                    328:                sc->acc_if->if_ierrors++;
                    329:                sc->acc_flush = 1;
                    330:        }
                    331: 
                    332:        if (sc->acc_flush) {
                    333:                if (addr->icsr & IN_EOM)
                    334:                        sc->acc_flush = 0;
                    335:                goto setup;
                    336:        }
                    337:        len = IMPMTU+2 + (addr->iwc << 1);
                    338:        if (len < 0 || len > IMPMTU+2) {
                    339:                printf("acc%d: bad length=%d\n", unit, len);
                    340:                sc->acc_if->if_ierrors++;
                    341:                goto setup;
                    342:        }
                    343: 
                    344:        /*
                    345:         * The offset parameter is always 0 since using
                    346:         * trailers on the ARPAnet is insane.
                    347:         */
                    348:        m = if_rubaget(&sc->acc_ifuba, len, 0, sc->acc_if);
                    349:        if (m == 0)
                    350:                goto setup;
                    351:        if ((addr->icsr & IN_EOM) == 0) {
                    352:                if (sc->acc_iq)
                    353:                        m_cat(sc->acc_iq, m);
                    354:                else
                    355:                        sc->acc_iq = m;
                    356:                goto setup;
                    357:        }
                    358:        if (sc->acc_iq) {
                    359:                m_cat(sc->acc_iq, m);
                    360:                m = sc->acc_iq;
                    361:                sc->acc_iq = 0;
                    362:        }
                    363:        impinput(unit, m);
                    364: 
                    365: setup:
                    366:        /*
                    367:         * Setup for next message.
                    368:         */
                    369:        info = sc->acc_ifuba.ifu_r.ifrw_info;
                    370:        addr->iba = (u_short)info;
                    371:        addr->iwc = -((IMPMTU + 2)>> 1);
                    372:        addr->icsr =
                    373:                IN_MRDY | ACC_IE | IN_WEN | ((info & 0x30000) >> 12) | ACC_GO;
                    374: }
                    375: #endif

unix.superglobalmegacorp.com

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