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

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

unix.superglobalmegacorp.com

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