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

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

unix.superglobalmegacorp.com

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