Annotation of 43BSDTahoe/sys/tahoevba/mp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Computer Consoles Inc.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms are permitted
        !             9:  * provided that the above copyright notice and this paragraph are
        !            10:  * duplicated in all such forms and that any documentation,
        !            11:  * advertising materials, and other materials related to such
        !            12:  * distribution and use acknowledge that the software was developed
        !            13:  * by the University of California, Berkeley.  The name of the
        !            14:  * University may not be used to endorse or promote products derived
        !            15:  * from this software without specific prior written permission.
        !            16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            18:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            19:  *
        !            20:  *     @(#)mp.c        7.6 (Berkeley) 7/9/88
        !            21:  */
        !            22: 
        !            23: #include "mp.h"
        !            24: #if NMP > 0
        !            25: /*
        !            26:  * Multi Protocol Communications Controller (MPCC).
        !            27:  * Asynchronous Terminal Protocol Support.
        !            28:  */
        !            29: #include "param.h"
        !            30: #include "ioctl.h"
        !            31: #include "tty.h"
        !            32: #include "dir.h"
        !            33: #include "user.h"
        !            34: #include "map.h"
        !            35: #include "buf.h"
        !            36: #include "conf.h"
        !            37: #include "file.h"
        !            38: #include "uio.h"
        !            39: #include "errno.h"
        !            40: #include "syslog.h"
        !            41: #include "vmmac.h"
        !            42: #include "kernel.h"
        !            43: #include "clist.h"
        !            44: 
        !            45: #include "../machine/pte.h"
        !            46: #include "../machine/mtpr.h"
        !            47: 
        !            48: #include "../tahoevba/vbavar.h"
        !            49: #include "../tahoevba/mpreg.h"
        !            50: 
        !            51: #define        MPCHUNK 16
        !            52: #define        MPPORT(n)       ((n) & 0xf)
        !            53: #define        MPUNIT(n)       ((n) >> 4)
        !            54: 
        !            55: /*
        !            56:  * Driver information for auto-configuration stuff.
        !            57:  */
        !            58: int     mpprobe(), mpattach(), mpintr();
        !            59: struct  vba_device *mpinfo[NMP];
        !            60: long    mpstd[] = { 0 };
        !            61: struct  vba_driver mpdriver =
        !            62:     { mpprobe, 0, mpattach, 0, mpstd, "mp", mpinfo };
        !            63: 
        !            64: int    mpstart();
        !            65: struct mpevent *mpparam();
        !            66: struct mpevent *mp_getevent();
        !            67: 
        !            68: /*
        !            69:  * The following structure is needed to deal with mpcc's convoluted
        !            70:  * method for locating it's mblok structures (hold your stomach).
        !            71:  * When an mpcc is reset at boot time it searches host memory
        !            72:  * looking for a string that says ``ThIs Is MpCc''.  The mpcc
        !            73:  * then reads the structure to locate the pointer to it's mblok
        !            74:  * structure (you can wretch now).
        !            75:  */
        !            76: struct mpbogus {
        !            77:        char    s[12];                  /* `ThIs Is MpCc'' */
        !            78:        u_char  status;
        !            79:        u_char  unused;
        !            80:        u_short magic;
        !            81:        struct  mblok *mb;
        !            82:        struct  mblok *mbloks[NMP];     /* can support at most 16 mpcc's */
        !            83: } mpbogus = { 'T','h','I','s',' ','I','s',' ','M','p','C','c' };
        !            84: 
        !            85: /*
        !            86:  * Software state per unit.
        !            87:  */
        !            88: struct mpsoftc {
        !            89:        u_int   ms_ivec;                /* interrupt vector */
        !            90:        u_int   ms_softCAR;             /* software carrier for async */
        !            91:        struct  mblok *ms_mb;           /* mpcc status area */
        !            92:        struct  vb_buf ms_buf;          /* vba resources for ms_mb */
        !            93:        struct  hxmtl ms_hxl[MPMAXPORT];/* host transmit list */
        !            94:        struct  asyncparam ms_async[MPMAXPORT][MPINSET];/* async structs */
        !            95:        char    ms_cbuf[MPMAXPORT][MPOUTSET][CBSIZE];/* input character buffers */
        !            96: } mp_softc[NMP];
        !            97: 
        !            98: struct tty mp_tty[NMP*MPCHUNK];
        !            99: #ifndef lint
        !           100: int    nmp = NMP*MPCHUNK;
        !           101: #endif
        !           102: 
        !           103: int    ttrstrt();
        !           104: 
        !           105: mpprobe(reg, vi)
        !           106:        caddr_t reg;
        !           107:        struct vba_device *vi;
        !           108: {
        !           109:        register int br, cvec;
        !           110:        register struct mpsoftc *ms;
        !           111: 
        !           112: #ifdef lint
        !           113:        br = 0; cvec = br; br = cvec;
        !           114:        mpintr(0);
        !           115:        mpdlintr(0);
        !           116: #endif
        !           117:        if (badaddr(reg, 2))
        !           118:                return (0);
        !           119:        ms = &mp_softc[vi->ui_unit];
        !           120:        /*
        !           121:         * Allocate page tables and mblok
        !           122:         * structure (mblok in non-cached memory).
        !           123:         */
        !           124:        if (vbainit(&ms->ms_buf, sizeof (struct mblok), VB_32BIT) == 0) {
        !           125:                printf("mp%d: vbainit failed\n", vi->ui_unit);
        !           126:                return (0);
        !           127:        }
        !           128:        ms->ms_mb = (struct mblok *)ms->ms_buf.vb_rawbuf;
        !           129:        ms->ms_ivec = MPINTRBASE + 2*vi->ui_unit;       /* XXX */
        !           130:        br = 0x14, cvec = ms->ms_ivec;                  /* XXX */
        !           131:        return (sizeof (*reg));
        !           132: }
        !           133: 
        !           134: mpattach(vi)
        !           135:        register struct vba_device *vi;
        !           136: {
        !           137:        register struct mpsoftc *ms = &mp_softc[vi->ui_unit];
        !           138: 
        !           139:        ms->ms_softCAR = vi->ui_flags;
        !           140:        /*
        !           141:         * Setup pointer to mblok, initialize bogus
        !           142:         * status block used by mpcc to locate the pointer
        !           143:         * and then poke the mpcc to get it to search host
        !           144:         * memory to find mblok pointer.
        !           145:         */
        !           146:        mpbogus.mbloks[vi->ui_unit] = (struct mblok *)ms->ms_buf.vb_physbuf;
        !           147:        *(short *)vi->ui_addr = 0x100;          /* magic */
        !           148: }
        !           149: 
        !           150: /*
        !           151:  * Open an mpcc port.
        !           152:  */
        !           153: /* ARGSUSED */
        !           154: mpopen(dev, mode)
        !           155:        dev_t dev;
        !           156: {
        !           157:        register struct tty *tp;
        !           158:        register struct mpsoftc *ms;
        !           159:        int error, s, port, unit, mpu;
        !           160:        struct vba_device *vi;
        !           161:        struct mpport *mp;
        !           162:        struct mpevent *ev;
        !           163: 
        !           164:        unit = minor(dev);
        !           165:        mpu = MPUNIT(unit);
        !           166:        if (mpu >= NMP || (vi = mpinfo[mpu]) == 0 || vi->ui_alive == 0)
        !           167:                return (ENXIO);
        !           168:        tp = &mp_tty[unit];
        !           169:        if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
        !           170:                return (EBUSY);
        !           171:        ms = &mp_softc[mpu];
        !           172:        port = MPPORT(unit);
        !           173:        if (ms->ms_mb->mb_proto[port] != MPPROTO_ASYNC ||
        !           174:            ms->ms_mb->mb_status != MP_OPOPEN)
        !           175:                return (ENXIO);
        !           176:        mp = &ms->ms_mb->mb_port[port];         /* host mpcc struct */
        !           177:        s = spl8();
        !           178:        while (mp->mp_flags & MP_PROGRESS)
        !           179:                sleep((caddr_t)&tp->t_canq, TTIPRI);
        !           180:        while (tp->t_state & TS_WOPEN) 
        !           181:                sleep((caddr_t)&tp->t_canq, TTIPRI);
        !           182:        tp->t_state |= TS_WOPEN;
        !           183:        tp->t_addr = (caddr_t)ms;
        !           184:        tp->t_oproc = mpstart;
        !           185:        tp->t_dev = dev;
        !           186:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           187:                ttychars(tp);
        !           188:                if (tp->t_ispeed == 0) {
        !           189:                        tp->t_ispeed = B9600;
        !           190:                        tp->t_ospeed = B9600;
        !           191:                        tp->t_flags = ODDP|EVENP|ECHO;
        !           192:                }
        !           193:                /*
        !           194:                 * Initialize port state: init MPCC interface
        !           195:                 * structures for port and setup modem control.
        !           196:                 */
        !           197:                mp->mp_proto = MPPROTO_ASYNC;           /* XXX */
        !           198:                error = mpportinit(ms, mp, port);
        !           199:                if (error)
        !           200:                        goto bad;
        !           201:                ev = mpparam(unit);
        !           202:                if (ev == 0) {
        !           203:                        error = ENOBUFS;
        !           204:                        goto bad;
        !           205:                }
        !           206:                mpcmd(ev, EVCMD_OPEN, 0, ms->ms_mb, port);
        !           207:        }
        !           208:        while ((tp->t_state & TS_CARR_ON) == 0)
        !           209:                sleep((caddr_t)&tp->t_rawq, TTIPRI);
        !           210:        error = (*linesw[tp->t_line].l_open)(dev,tp);
        !           211: done:
        !           212:        splx(s);
        !           213:        /* wakeup anyone waiting for open to complete */
        !           214:        wakeup((caddr_t)&tp->t_canq);
        !           215: 
        !           216:        return (error);
        !           217: bad:
        !           218:        tp->t_state &= ~TS_WOPEN;
        !           219:        goto done;
        !           220: }
        !           221: 
        !           222: /*
        !           223:  * Close an mpcc port.
        !           224:  */
        !           225: /* ARGSUSED */
        !           226: mpclose(dev, flag)
        !           227:        dev_t dev;
        !           228: {
        !           229:        register struct tty *tp;
        !           230:        register struct mpport *mp;
        !           231:        register struct mpevent *ev;
        !           232:        int s, port, unit, error;
        !           233:        struct mblok *mb;
        !           234: 
        !           235:        unit = minor(dev);
        !           236:        tp = &mp_tty[unit];
        !           237:        port = MPPORT(unit);
        !           238:        mb = mp_softc[MPUNIT(unit)].ms_mb;
        !           239:        mp = &mb->mb_port[port];
        !           240:        s = spl8();
        !           241:        if (mp->mp_flags & MP_PROGRESS) {       /* close in progress??? */
        !           242:                if (mp->mp_flags & MP_REMBSY) {
        !           243:                        mp->mp_flags &= ~MP_REMBSY;
        !           244:                        splx(s);
        !           245:                        return (0);
        !           246:                }
        !           247:                while (mp->mp_flags & MP_PROGRESS)
        !           248:                        sleep((caddr_t)&tp->t_canq,TTIPRI);
        !           249:        }
        !           250:        error = 0;
        !           251:        mp->mp_flags |= MP_PROGRESS;
        !           252:        (*linesw[tp->t_line].l_close)(tp);
        !           253:        ev = mp_getevent(mp, unit);
        !           254:        if (ev == 0) {
        !           255:                error = ENOBUFS;
        !           256:                mp->mp_flags &= ~MP_PROGRESS;
        !           257:                goto out;
        !           258:        }
        !           259:        if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)
        !           260:                mpmodem(unit, MMOD_OFF);
        !           261:        else
        !           262:                mpmodem(unit, MMOD_ON);
        !           263:        mpcmd(ev, EVCMD_CLOSE, 0, mb, port);
        !           264:        ttyclose(tp);
        !           265: out:
        !           266:        if (mp->mp_flags & MP_REMBSY)
        !           267:                mpclean(mb, port);
        !           268:        splx(s);
        !           269:        return (error);
        !           270: }
        !           271: 
        !           272: /*
        !           273:  * Read from an mpcc port.
        !           274:  */
        !           275: mpread(dev, uio)
        !           276:        dev_t dev;
        !           277:        struct uio *uio;
        !           278: {
        !           279:        struct tty *tp;
        !           280: 
        !           281:        tp = &mp_tty[minor(dev)];
        !           282:        return ((*linesw[tp->t_line].l_read)(tp, uio));
        !           283: }
        !           284: 
        !           285: /*
        !           286:  * Write to an mpcc port.
        !           287:  */
        !           288: mpwrite(dev, uio)
        !           289:        dev_t dev;
        !           290:        struct uio *uio;
        !           291: {
        !           292:        struct tty *tp;
        !           293: 
        !           294:        tp = &mp_tty[minor(dev)];
        !           295:        return ((*linesw[tp->t_line].l_write)(tp, uio));
        !           296: }
        !           297: 
        !           298: /*
        !           299:  * Ioctl for a mpcc port
        !           300:  */
        !           301: mpioctl(dev, cmd, data, flag)
        !           302:        dev_t dev;
        !           303:        caddr_t data;
        !           304: {
        !           305:        register struct tty *tp;
        !           306:        register struct mpsoftc *ms;
        !           307:        register struct mpevent *ev;
        !           308:        register struct mpport *mp;
        !           309:        int s, port, error, unit;
        !           310:        struct mblok *mb;
        !           311: 
        !           312:        unit = minor(dev);
        !           313:        tp = &mp_tty[unit];
        !           314:        ms = &mp_softc[MPUNIT(unit)];
        !           315:        mb = ms->ms_mb;
        !           316:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        !           317:        if (error >= 0)
        !           318:                return (error);
        !           319:        error = ttioctl(tp, cmd, data, flag);
        !           320:        if (error >= 0) {
        !           321:                if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
        !           322:                    cmd == TIOCLBIC || cmd == TIOCLSET || cmd == TIOCSETC) {
        !           323:                        ev = mpparam(unit);
        !           324:                        if (ev == 0)
        !           325:                                error = ENOBUFS;
        !           326:                        else
        !           327:                                mpcmd(ev, EVCMD_IOCTL, A_CHGALL, mb,
        !           328:                                    MPPORT(unit));
        !           329:                }
        !           330:                return (error);
        !           331:        }
        !           332:        switch (cmd) {
        !           333:        case TIOCSBRK:                  /* send break */
        !           334:        case TIOCCBRK:                  /* clear break */
        !           335:                port = MPPORT(unit);
        !           336:                mp = &mb->mb_port[port];
        !           337:                s = spl8();
        !           338:                ev = mp_getevent(mp, unit);
        !           339:                if (ev)
        !           340:                        mpcmd(ev, EVCMD_IOCTL,
        !           341:                            (cmd == TIOCSBRK ? A_BRKON : A_BRKOFF),
        !           342:                            mb, port);
        !           343:                else
        !           344:                        error = ENOBUFS;
        !           345:                splx(s);
        !           346:                break;
        !           347:        case TIOCSDTR:                  /* set dtr control line */
        !           348:                break;
        !           349:        case TIOCCDTR:                  /* clear dtr control line */
        !           350:                break;
        !           351:        default:
        !           352:                error = ENOTTY;
        !           353:                break;
        !           354:        }
        !           355:        return (error);
        !           356: }
        !           357: 
        !           358: struct mpevent *
        !           359: mpparam(unit)
        !           360:        int unit;
        !           361: {
        !           362:        register struct mpevent *ev;
        !           363:        register struct mpport *mp;
        !           364:        register struct tty *tp;
        !           365:        struct mblok *mb;
        !           366:        struct mpsoftc *ms;
        !           367:        register struct asyncparam *asp;
        !           368:        int port;
        !           369: 
        !           370:        ms = &mp_softc[MPUNIT(unit)];
        !           371:        mb = ms->ms_mb;
        !           372:        port = MPPORT(unit);
        !           373:        mp = &mb->mb_port[port];
        !           374:        ev = mp_getevent(mp, unit);     /* XXX */
        !           375:        if (ev == 0)
        !           376:                return (ev);
        !           377:        tp = &mp_tty[unit];
        !           378:        /* YUCK */
        !           379:        asp = &ms->ms_async[port][mp->mp_on?mp->mp_on-1:MPINSET-1];
        !           380:        asp->ap_xon = (u_char)tp->t_startc;
        !           381:        asp->ap_xoff = (u_char)tp->t_stopc;
        !           382:        if ((tp->t_flags & RAW) || (tp->t_stopc == -1) || (tp->t_startc == -1))
        !           383:                asp->ap_xena = MPA_DIS;
        !           384:        else
        !           385:                asp->ap_xena = MPA_ENA;
        !           386:        asp->ap_xany = ((tp->t_flags & DECCTQ) ? MPA_DIS : MPA_ENA);
        !           387: #ifdef notnow
        !           388:        if (tp->t_flags & (RAW|LITOUT|PASS8)) {
        !           389: #endif
        !           390:                asp->ap_data = MPCHAR_8;
        !           391:                asp->ap_parity = MPPAR_NONE;
        !           392: #ifdef notnow
        !           393:        } else {
        !           394:                asp->ap_data = MPCHAR_7;
        !           395:                if ((tp->t_flags & (EVENP|ODDP)) == ODDP)
        !           396:                        asp->ap_parity = MPPAR_ODD;
        !           397:                else
        !           398:                        asp->ap_parity = MPPAR_EVEN;
        !           399:        }
        !           400: #endif
        !           401:        if (tp->t_ospeed == B110)
        !           402:                asp->ap_stop = MPSTOP_2;
        !           403:        else
        !           404:                asp->ap_stop = MPSTOP_1;
        !           405:        if (tp->t_ospeed == EXTA || tp->t_ospeed == EXTB)
        !           406:                asp->ap_baud = M19200;
        !           407:        else
        !           408:                asp->ap_baud = tp->t_ospeed;
        !           409:        asp->ap_loop = MPA_DIS;         /* disable loopback */
        !           410:        asp->ap_rtimer = A_RCVTIM;      /* default receive timer */
        !           411:        if (ms->ms_softCAR & (1<<port))
        !           412:                setm(&asp->ap_modem, A_DTR, ASSERT);
        !           413:        else
        !           414:                setm(&asp->ap_modem, A_DTR, AUTO);
        !           415:        seti(&asp->ap_intena, A_DCD);
        !           416:        return (ev);
        !           417: }
        !           418: 
        !           419: mpstart(tp)
        !           420:        register struct tty *tp;
        !           421: {
        !           422:        register struct mpevent *ev;
        !           423:        register struct mpport *mp;
        !           424:        struct mblok *mb;
        !           425:        struct mpsoftc *ms;
        !           426:        int port, unit, xcnt, n, s, i;
        !           427:        struct  hxmtl *hxp;
        !           428:        struct clist outq;
        !           429: 
        !           430:        s = spl8();
        !           431:        unit = minor(tp->t_dev);
        !           432:        ms = &mp_softc[MPUNIT(unit)];
        !           433:        mb = ms->ms_mb;
        !           434:        port = MPPORT(unit);
        !           435:        mp = &mb->mb_port[port];
        !           436:        hxp = &ms->ms_hxl[port];
        !           437:        xcnt = 0;
        !           438:        outq = tp->t_outq;
        !           439:        for (i = 0; i < MPXMIT; i++) {
        !           440:                if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
        !           441:                        break;
        !           442:                if (outq.c_cc <= TTLOWAT(tp)) {
        !           443:                        if (tp->t_state & TS_ASLEEP) {
        !           444:                                tp->t_state &= ~TS_ASLEEP;
        !           445:                                wakeup((caddr_t)&tp->t_outq);
        !           446:                        }
        !           447:                        if (tp->t_wsel) {
        !           448:                                selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
        !           449:                                tp->t_wsel = 0;
        !           450:                                tp->t_state &= ~TS_WCOLL;
        !           451:                        }
        !           452:                }
        !           453:                if (outq.c_cc == 0)
        !           454:                        break;
        !           455:                /*
        !           456:                 * If we're not currently busy outputting,
        !           457:                 * and there is data to be output, set up
        !           458:                 * port transmit structure to send to mpcc.
        !           459:                 */
        !           460:                if (tp->t_flags & (RAW|LITOUT))
        !           461:                        n = ndqb(&outq, 0);
        !           462:                else {
        !           463:                        n = ndqb(&outq, 0200);
        !           464:                        if (n == 0) {
        !           465:                                n = getc(&outq);
        !           466:                                timeout(ttrstrt, (caddr_t)tp, (n&0177)+6);
        !           467:                                tp->t_state |= TS_TIMEOUT;
        !           468:                                break;
        !           469:                        }
        !           470:                }
        !           471:                hxp->dblock[i] = (caddr_t)kvtophys(outq.c_cf);
        !           472:                hxp->size[i] = n;
        !           473:                xcnt++;         /* count of xmts to send */
        !           474:                ndadvance(&outq, n);
        !           475:        }
        !           476:        /*
        !           477:         * If data to send, poke mpcc.
        !           478:         */
        !           479:        if (xcnt) {
        !           480:                ev = mp_getevent(mp, unit);
        !           481:                if (ev == 0) {
        !           482:                        tp->t_state &= ~(TS_BUSY|TS_TIMEOUT);
        !           483:                } else {
        !           484:                        tp->t_state |= TS_BUSY;
        !           485:                        ev->ev_count = xcnt;
        !           486:                        mpcmd(ev, EVCMD_WRITE, 0, mb, MPPORT(unit));
        !           487:                }
        !           488:        }
        !           489:        splx(s);
        !           490: }
        !           491: 
        !           492: /*
        !           493:  * Advance cc bytes from q  but don't free memory.
        !           494:  */
        !           495: ndadvance(q, cc)
        !           496:        register struct clist *q;
        !           497:        register cc;
        !           498: {
        !           499:        register struct cblock *bp;
        !           500:        char *end;
        !           501:        int rem, s;
        !           502: 
        !           503:        s = spltty();
        !           504:        if (q->c_cc <= 0)
        !           505:                goto out;
        !           506:        while (cc>0 && q->c_cc) {
        !           507:                bp = (struct cblock *)((int)q->c_cf & ~CROUND);
        !           508:                if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
        !           509:                        end = q->c_cl;
        !           510:                } else {
        !           511:                        end = (char *)((int)bp + sizeof (struct cblock));
        !           512:                }
        !           513:                rem = end - q->c_cf;
        !           514:                if (cc >= rem) {
        !           515:                        cc -= rem;
        !           516:                        q->c_cc -= rem;
        !           517:                        q->c_cf = bp->c_next->c_info;
        !           518:                } else {
        !           519:                        q->c_cc -= cc;
        !           520:                        q->c_cf += cc;
        !           521:                        break;
        !           522:                }
        !           523:        }
        !           524:        if (q->c_cc <= 0) {
        !           525:                q->c_cf = q->c_cl = NULL;
        !           526:                q->c_cc = 0;
        !           527:        }
        !           528: out:
        !           529:        splx(s);
        !           530: }
        !           531: 
        !           532: /*
        !           533:  * Stop output on a line, e.g. for ^S/^Q or output flush.
        !           534:  */
        !           535: /* ARGSUSED */
        !           536: mpstop(tp, rw)
        !           537:        register struct tty *tp;
        !           538:        int rw;
        !           539: {
        !           540:        int s;
        !           541: 
        !           542:        s = spl8();
        !           543:        /* XXX: DISABLE TRANSMITTER */
        !           544:        if (tp->t_state & TS_BUSY) {
        !           545:                if ((tp->t_state & TS_TTSTOP) == 0)
        !           546:                        tp->t_state |= TS_FLUSH;
        !           547:        }
        !           548:        splx(s);
        !           549: }
        !           550: 
        !           551: /*
        !           552:  * Initialize an async port's MPCC state.
        !           553:  */
        !           554: mpportinit(ms, mp, port)
        !           555:        register struct mpsoftc *ms;
        !           556:        register struct mpport *mp;
        !           557:        int port;
        !           558: {
        !           559:        register struct mpevent *ev;
        !           560:        register int i;
        !           561:        caddr_t ptr;
        !           562: 
        !           563:        mp->mp_on = mp->mp_off = 0;
        !           564:        mp->mp_nextrcv = 0;
        !           565:        mp->mp_flags = 0;
        !           566:        ev = &mp->mp_recvq[0];
        !           567:        for (i = 0; ev < &mp->mp_recvq[MPINSET]; ev++, i++) {
        !           568:                ev->ev_status = EVSTATUS_FREE;
        !           569:                ev->ev_cmd = 0;
        !           570:                ev->ev_opts = 0;
        !           571:                ev->ev_error = 0;
        !           572:                ev->ev_flags = 0;
        !           573:                ev->ev_count = 0;
        !           574:                ev->ev_un.hxl = (struct hxmtl *) kvtophys(&ms->ms_hxl[port]);
        !           575:                ev->ev_params = (caddr_t) kvtophys(&ms->ms_async[port][i]);
        !           576:        }
        !           577:        ev = &mp->mp_sendq[0];
        !           578:        for (i = 0; ev < &mp->mp_sendq[MPOUTSET]; ev++, i++) {
        !           579:                /* init so that L2 can't send any events */
        !           580:                /* to host until open has completed      */
        !           581:                ev->ev_status = EVSTATUS_FREE;
        !           582:                ev->ev_cmd = 0;
        !           583:                ev->ev_error = 0;
        !           584:                ev->ev_flags = 0;
        !           585:                ev->ev_count = 0;
        !           586:                ptr = (caddr_t) &ms->ms_cbuf[port][i][0];
        !           587:                ev->ev_un.rcvblk = (u_char *)kvtophys(ptr);
        !           588:                ev->ev_params = (caddr_t) kvtophys(ptr);
        !           589:        }
        !           590:        return (0);
        !           591: }
        !           592: 
        !           593: /*
        !           594:  * Send an event to an mpcc.
        !           595:  */
        !           596: mpcmd(ev, cmd, flags, mb, port)
        !           597:        register struct mpevent *ev;
        !           598:        struct mblok *mb;
        !           599: {       
        !           600:        int s;
        !           601: 
        !           602:        s = spl8();
        !           603:        /* move host values to inbound entry */
        !           604:        ev->ev_cmd = cmd;
        !           605:        ev->ev_opts = flags;
        !           606:        /* show event ready for mpcc */
        !           607:        ev->ev_status = EVSTATUS_GO;
        !           608:        mpintmpcc(mb, port);
        !           609:        splx(s);
        !           610: }
        !           611: 
        !           612: /*
        !           613:  * Return the next available event entry for the indicated port.
        !           614:  */
        !           615: struct mpevent *
        !           616: mp_getevent(mp, unit)
        !           617:        register struct mpport *mp;
        !           618:        int unit;
        !           619: {
        !           620:        register struct mpevent *ev;
        !           621:        int i, s;
        !           622: 
        !           623:        s = spl8();
        !           624:        ev = &mp->mp_recvq[mp->mp_on];
        !           625:        if (ev->ev_status != EVSTATUS_FREE)
        !           626:                goto bad;
        !           627:        /*
        !           628:         * If not a close request, verify one extra
        !           629:         * event is available for closing the port.
        !           630:         */
        !           631:        if ((mp->mp_flags & MP_PROGRESS) == 0) {
        !           632:                if ((i = mp->mp_on + 1) >= MPINSET)
        !           633:                        i = 0;
        !           634:                if (mp->mp_recvq[i].ev_status != EVSTATUS_FREE)
        !           635:                        goto bad;
        !           636:        }
        !           637:        /* init inbound fields marking this entry as busy */
        !           638:        ev->ev_error = 0;
        !           639:        ev->ev_flags = 0;
        !           640:        ev->ev_count = 0;
        !           641:        ev->ev_status = EVSTATUS_BUSY;
        !           642:        /* adjust pointer to next available inbound entry */
        !           643:        adjptr(mp->mp_on, MPINSET);
        !           644:        splx(s);
        !           645:        return (ev);
        !           646: bad:
        !           647:        splx(s);
        !           648:        log(LOG_ERR, "mp%d: port%d, out of events", MPUNIT(unit), MPPORT(unit));
        !           649:        return ((struct mpevent *)0);
        !           650: }
        !           651: 
        !           652: mpmodem(unit, flag)
        !           653:        int unit, flag;
        !           654: {
        !           655:        struct mpsoftc *ms = &mp_softc[MPUNIT(unit)];
        !           656:        int port = MPPORT(unit);
        !           657:        register struct mpport *mp;
        !           658:        register struct asyncparam *asp;
        !           659: 
        !           660:        mp = &ms->ms_mb->mb_port[port];
        !           661:        asp = &ms->ms_async[port][mp->mp_on?mp->mp_on-1:MPINSET-1];
        !           662:        if (flag == MMOD_ON) {
        !           663:                if (ms->ms_softCAR & (1 << port))
        !           664:                        setm(&asp->ap_modem, A_DTR, ASSERT);
        !           665:                else
        !           666:                        setm(&asp->ap_modem, A_DTR, AUTO);
        !           667:                seti(&asp->ap_intena, A_DCD);
        !           668:        } else {
        !           669:                setm(&asp->ap_modem, 0, DROP);
        !           670:                seti(&asp->ap_intena, 0);
        !           671:        }
        !           672: }
        !           673: 
        !           674: /*
        !           675:  * Set up the modem control structure according to mask.
        !           676:  * Each set bit in the mask means assert the corresponding
        !           677:  * modem control line, otherwise, it will be dropped.  
        !           678:  * RTS is special since it can either be asserted, dropped
        !           679:  * or put in auto mode for auto modem control.
        !           680:  */
        !           681: static
        !           682: setm(mc, mask, rts)
        !           683:        register struct mdmctl *mc;
        !           684:        register int mask;
        !           685: {
        !           686: 
        !           687:        mc->mc_rngdsr = (mask & A_RNGDSR) ? ASSERT : DROP;
        !           688:        mc->mc_rate = (mask & A_RATE) ? ASSERT : DROP;
        !           689:        mc->mc_dcd = (mask & A_DCD) ? ASSERT : DROP;
        !           690:        mc->mc_sectx = (mask & A_SECTX) ? ASSERT : DROP;
        !           691:        mc->mc_cts = (mask & A_CTS) ? ASSERT : DROP;
        !           692:        mc->mc_secrx = (mask & A_SECRX) ? ASSERT : DROP;
        !           693:        mc->mc_dtr = (mask & A_DTR) ? ASSERT : DROP;
        !           694:        mc->mc_rts = rts;
        !           695: }
        !           696: 
        !           697: /*
        !           698:  * Set up the status change enable field from mask.
        !           699:  * When a signal is enabled in this structure and
        !           700:  * and a change in state on a corresponding modem
        !           701:  * control line occurs, a status change event will
        !           702:  * be delivered to the host.
        !           703:  */
        !           704: static
        !           705: seti(mc, mask)
        !           706:        register struct mdmctl *mc;
        !           707:        register int mask;
        !           708: {
        !           709: 
        !           710:        mc->mc_rngdsr = (mask & A_RNGDSR) ? MDM_ON : MDM_OFF;
        !           711:        mc->mc_rate = (mask & A_RATE) ? MDM_ON : MDM_OFF;
        !           712:        mc->mc_dcd = (mask & A_DCD) ? MDM_ON : MDM_OFF;
        !           713:        mc->mc_sectx = (mask & A_SECTX) ? MDM_ON : MDM_OFF;
        !           714:        mc->mc_cts = (mask & A_CTS) ? MDM_ON : MDM_OFF;
        !           715:        mc->mc_secrx = (mask & A_SECRX) ? MDM_ON : MDM_OFF;
        !           716:        mc->mc_dtr = (mask & A_DTR) ? MDM_ON : MDM_OFF;
        !           717:        mc->mc_rts = (mask & A_RTS) ? MDM_ON : MDM_OFF;
        !           718: }
        !           719: 
        !           720: mpcleanport(mb, port)
        !           721:        struct mblok *mb;
        !           722:        int port;
        !           723: {
        !           724:        register struct mpport *mp;
        !           725:        register struct tty *tp;
        !           726: 
        !           727:        mp = &mb->mb_port[port];
        !           728:        if (mp->mp_proto == MPPROTO_ASYNC) {
        !           729:                mp->mp_flags = MP_REMBSY;
        !           730:                /* signal loss of carrier and close */
        !           731:                tp = &mp_tty[mb->mb_unit*MPCHUNK+port];
        !           732:                ttyflush(tp, FREAD|FWRITE);
        !           733:                (void) (*linesw[tp->t_line].l_modem)(tp, 0);
        !           734:                (void) mpclose(tp->t_dev, 0);
        !           735:        }
        !           736: }
        !           737: 
        !           738: mpclean(mb, port)
        !           739:        register struct mblok *mb;
        !           740:        int port;
        !           741: {
        !           742:        register struct mpport *mp;
        !           743:        register struct mpevent *ev;
        !           744:        register int i;
        !           745:        u_char list[2];
        !           746:        int unit;
        !           747: 
        !           748:        mp = &mb->mb_port[port];
        !           749:        unit = mb->mb_unit;
        !           750:        for (i = mp->mp_off; i != mp->mp_on; i = (i+1 % MPINSET)) {
        !           751:                ev = &mp->mp_recvq[i];
        !           752:                ev->ev_error = ENXIO;
        !           753:                ev->ev_status = EVSTATUS_DONE;
        !           754:        }
        !           755:        list[0] = port, list[1] = MPPORT_EOL;
        !           756:        mpxintr(unit, list);
        !           757:        mprintr(unit, list);
        !           758:        /* Clear async for port */
        !           759:        mp->mp_proto = MPPROTO_UNUSED;
        !           760:        mp->mp_flags = 0;
        !           761:        mp->mp_on = 0;
        !           762:        mp->mp_off = 0;
        !           763:        mp->mp_nextrcv = 0;
        !           764: 
        !           765:        mp_tty[unit*MPCHUNK + port].t_state = 0;
        !           766:        for (ev = &mp->mp_sendq[0]; ev < &mp->mp_sendq[MPOUTSET]; ev++) {
        !           767:                ev->ev_status = EVSTATUS_FREE;
        !           768:                ev->ev_cmd = 0;
        !           769:                ev->ev_error = 0;
        !           770:                ev->ev_un.rcvblk = 0;
        !           771:                ev->ev_params = 0;
        !           772:        }
        !           773:        for (ev = &mp->mp_recvq[0]; ev < &mp->mp_recvq[MPINSET]; ev++) {
        !           774:                ev->ev_status = EVSTATUS_FREE;
        !           775:                ev->ev_cmd = 0;
        !           776:                ev->ev_error = 0;
        !           777:                ev->ev_params = 0;
        !           778:        }
        !           779: }
        !           780: 
        !           781: /*
        !           782:  * MPCC interrupt handler.
        !           783:  */
        !           784: mpintr(mpcc)
        !           785:        int mpcc;
        !           786: {
        !           787:        register struct mblok *mb;
        !           788:        register struct his *his;
        !           789: 
        !           790:        mb = mp_softc[mpcc].ms_mb;
        !           791:        if (mb == 0) {
        !           792:                printf("mp%d: stray interrupt\n", mpcc);
        !           793:                return;
        !           794:        }
        !           795:        his = &mb->mb_hostint;
        !           796:        his->semaphore &= ~MPSEMA_AVAILABLE;
        !           797:        /*
        !           798:         * Check for events to be processed.
        !           799:         */
        !           800:        if (his->proto[MPPROTO_ASYNC].outbdone[0] != MPPORT_EOL)
        !           801:                mprintr(mpcc, his->proto[MPPROTO_ASYNC].outbdone);
        !           802:        if (his->proto[MPPROTO_ASYNC].inbdone[0] != MPPORT_EOL)
        !           803:                mpxintr(mpcc, his->proto[MPPROTO_ASYNC].inbdone);
        !           804:        if (mb->mb_harderr || mb->mb_softerr)
        !           805:                mperror(mb, mpcc);
        !           806:        his->semaphore |= MPSEMA_AVAILABLE;
        !           807: }
        !           808: 
        !           809: /*
        !           810:  * Handler for processing completion of transmitted events.
        !           811:  */
        !           812: mpxintr(unit, list)
        !           813:        register u_char *list;
        !           814: {
        !           815:        register struct mpport *mp;
        !           816:        register struct mpevent *ev;
        !           817:        register struct mblok *mb;
        !           818:        register struct tty *tp;
        !           819:        register struct asyncparam *ap;
        !           820:        struct mpsoftc *ms;
        !           821:        int port, i, j;
        !           822: 
        !           823:        ms = &mp_softc[unit];
        !           824:        mb = mp_softc[unit].ms_mb;
        !           825:        for (j = 0; j < MPMAXPORT && ((port = *list++) != MPPORT_EOL); j++) {
        !           826:                /*
        !           827:                 * Process each completed entry in the inbound queue.
        !           828:                 */
        !           829:                mp = &mb->mb_port[port];
        !           830:                tp = &mp_tty[unit*MPCHUNK + port];
        !           831: #define        nextevent(mp)   &mp->mp_recvq[mp->mp_off]
        !           832:                ev = nextevent(mp);
        !           833:                for(; ev->ev_status & EVSTATUS_DONE; ev = nextevent(mp)) {
        !           834:                        /* YUCK */
        !           835:                        ap = &ms->ms_async[port][mp->mp_off];
        !           836:                        mppurge((caddr_t)ap, (int)sizeof (*ap));
        !           837:                        switch (ev->ev_cmd) {
        !           838:                        case EVCMD_OPEN:
        !           839:                                /*
        !           840:                                 * Open completion, start all reads and
        !           841:                                 * assert modem status information.
        !           842:                                 */
        !           843:                                for (i = 0; i < MPOUTSET; i++) 
        !           844:                                        mp->mp_sendq[i].ev_status = EVSTATUS_GO;
        !           845:                                (*linesw[tp->t_line].l_modem)
        !           846:                                    (tp, ap->ap_modem.mc_dcd == ASSERT);
        !           847:                                break;
        !           848:                        case EVCMD_CLOSE:
        !           849:                                /*
        !           850:                                 * Close completion, flush all pending
        !           851:                                 * transmissions, free resources, and
        !           852:                                 * cleanup mpcc port state.
        !           853:                                 */
        !           854:                                for (i = 0; i < MPOUTSET; i++) {
        !           855:                                        mp->mp_sendq[i].ev_status =
        !           856:                                            EVSTATUS_FREE;
        !           857:                                        mp->mp_sendq[i].ev_un.rcvblk = 0;
        !           858:                                        mp->mp_sendq[i].ev_params = 0;
        !           859:                                }
        !           860:                                tp->t_state &= ~TS_CARR_ON;
        !           861:                                mp->mp_on = mp->mp_off = mp->mp_nextrcv = 0;
        !           862:                                mp->mp_flags &= ~MP_PROGRESS;
        !           863:                                mp->mp_proto = MPPROTO_UNUSED;
        !           864:                                wakeup((caddr_t)&tp->t_canq);
        !           865:                                goto done;
        !           866:                        case EVCMD_IOCTL:
        !           867:                                /*
        !           868:                                 * Nothing to do, just pitch.
        !           869:                                 */
        !           870:                                break;
        !           871:                        case EVCMD_WRITE:
        !           872:                                /*
        !           873:                                 * Transmission completed, update tty
        !           874:                                 * state and restart output.
        !           875:                                 */
        !           876:                                tp->t_state &= ~TS_BUSY;
        !           877:                                if (tp->t_state & TS_FLUSH)
        !           878:                                        tp->t_state &= ~TS_FLUSH;
        !           879:                                else {
        !           880:                                        register int cc = 0, n;
        !           881:                                        struct hxmtl *hxp;
        !           882: 
        !           883:                                        hxp = &ms->ms_hxl[port];
        !           884:                                        for(n = 0; n < ev->ev_count; n++)
        !           885:                                                cc += hxp->size[n];
        !           886:                                        ndflush(&tp->t_outq, cc);
        !           887:                                }
        !           888:                                switch (ev->ev_error) {
        !           889:                                case A_SIZERR:  /*# error in xmt data size */
        !           890:                                        mplog(unit, port, A_XSIZE, 0);
        !           891:                                        break;
        !           892:                                case A_NXBERR:  /*# no more xmt evt buffers */
        !           893:                                        mplog(unit, port, A_NOXBUF, 0);
        !           894:                                        break;
        !           895:                                }
        !           896:                                mpstart(tp);
        !           897:                                break;
        !           898:                        default:
        !           899:                                mplog(unit, port, A_INVCMD, (int)ev->ev_cmd);  
        !           900:                                break;
        !           901:                        }
        !           902:                        /* re-init all values in this entry */
        !           903:                        ev->ev_cmd = 0;
        !           904:                        ev->ev_opts = 0;
        !           905:                        ev->ev_error = 0;
        !           906:                        ev->ev_flags = 0;
        !           907:                        ev->ev_count = 0;
        !           908:                        /* show this entry is available for use */
        !           909:                        ev->ev_status = EVSTATUS_FREE;
        !           910:                        adjptr(mp->mp_off, MPINSET);
        !           911: #undef nextevent
        !           912:                }
        !           913: done:
        !           914:                ;
        !           915:        }
        !           916: }
        !           917: 
        !           918: /*
        !           919:  * Handler for processing received events.
        !           920:  */
        !           921: mprintr(unit, list)
        !           922:        u_char *list;
        !           923: {
        !           924:        register struct tty *tp;
        !           925:        register struct mpport *mp;
        !           926:        register struct mpevent *ev;
        !           927:        struct mblok *mb;
        !           928:        register int cc;
        !           929:        register char *cp;
        !           930:        struct mpsoftc *ms;
        !           931:        caddr_t ptr;
        !           932:        char *rcverr;
        !           933:        int port, i;
        !           934: 
        !           935:        ms = &mp_softc[unit];
        !           936:        mb = mp_softc[unit].ms_mb;
        !           937:        for (i = 0; i < MPMAXPORT && (port = *list++) != MPPORT_EOL; i++) {
        !           938:                tp = &mp_tty[unit*MPCHUNK + port];
        !           939:                mp = &mb->mb_port[port];
        !           940:                ev = &mp->mp_sendq[mp->mp_nextrcv];
        !           941:                while (ev->ev_status & EVSTATUS_DONE) {
        !           942:                        if (ev->ev_cmd != EVCMD_READ &&
        !           943:                            ev->ev_cmd != EVCMD_STATUS) {
        !           944:                                mplog(unit, port, "unexpected command",
        !           945:                                    (int)ev->ev_cmd);
        !           946:                                goto next;
        !           947:                        }
        !           948:                        if (ev->ev_cmd == EVCMD_STATUS) {
        !           949:                                /*
        !           950:                                 * Status change, look for carrier changes.
        !           951:                                 */
        !           952:                                if (ev->ev_opts == DCDASRT ||
        !           953:                                    ev->ev_opts == DCDDROP)
        !           954:                                        (*linesw[tp->t_line].l_modem)
        !           955:                                            (tp, ev->ev_opts == DCDASRT);
        !           956:                                else
        !           957:                                        mplog(unit, port,
        !           958:                                            "unexpect status command",
        !           959:                                            (int)ev->ev_opts);
        !           960:                                goto next;
        !           961:                        }
        !           962:                        /*
        !           963:                         * Process received data.
        !           964:                         */
        !           965:                        if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0)
        !           966:                                goto next;
        !           967:                        cc = ev->ev_count;
        !           968:                        if (cc == 0)
        !           969:                                goto next;
        !           970:                        /* YUCK */
        !           971:                        cp = ms->ms_cbuf[port][mp->mp_nextrcv];
        !           972:                        mppurge(cp, CBSIZE);
        !           973:                        while (cc-- > 0) {
        !           974:                                /*
        !           975:                                 * A null character is inserted, potentially
        !           976:                                 * when a break or framing error occurs.  If
        !           977:                                 * we're not in raw mode, substitute the
        !           978:                                 * interrupt character.
        !           979:                                 */
        !           980:                                if (*cp == 0 &&
        !           981:                                    (ev->ev_error == BRKASRT ||
        !           982:                                     ev->ev_error == FRAMERR))
        !           983:                                        if ((tp->t_flags&RAW) == 0)
        !           984:                                                *cp = tp->t_intrc;
        !           985:                                (*linesw[tp->t_line].l_rint)(*cp++, tp);
        !           986:                        }
        !           987:                        /* setup for next read */
        !           988:                        ptr = (caddr_t)&mp_softc[unit].ms_cbuf[port][mp->mp_nextrcv][0];
        !           989:                        ev->ev_un.rcvblk = (u_char *)kvtophys(ptr);
        !           990:                        ev->ev_params = (caddr_t) kvtophys(ptr);
        !           991:                        switch(ev->ev_error) {
        !           992:                        case RCVDTA:    /* Normal (good) rcv data */
        !           993:                                        /* do not report the following */
        !           994:                                        /* they are "normal" errors */
        !           995:                        case FRAMERR:   /* frame error */
        !           996:                        case BRKASRT:   /* Break condition */
        !           997:                        case PARERR:    /* parity error */
        !           998:                                rcverr = (char *)0;
        !           999:                                break;
        !          1000:                        case OVRNERR:   /* Overrun error */
        !          1001:                                rcverr = "overrun error";
        !          1002:                                break;
        !          1003:                        case OVFERR:    /* Overflow error */
        !          1004:                                rcverr = "overflow error";
        !          1005:                                break;
        !          1006:                        default:
        !          1007:                                rcverr = "undefined rcv error";
        !          1008:                        }
        !          1009:                        if (rcverr != (char *)0)
        !          1010:                                mplog(unit, port, rcverr, (int)ev->ev_error);
        !          1011:                next:
        !          1012:                        ev->ev_cmd = 0;
        !          1013:                        ev->ev_opts = 0;
        !          1014:                        ev->ev_error = 0;
        !          1015:                        ev->ev_flags = 0;
        !          1016:                        ev->ev_status = EVSTATUS_GO;    /* start next read */
        !          1017:                        adjptr(mp->mp_nextrcv, MPOUTSET);
        !          1018:                        ev = &mp->mp_sendq[mp->mp_nextrcv];
        !          1019:                }
        !          1020:        }
        !          1021: }
        !          1022: 
        !          1023: /*
        !          1024:  * Log an mpcc diagnostic.
        !          1025:  */
        !          1026: mplog(unit, port, cp, flags)
        !          1027:        char *cp;
        !          1028: {
        !          1029: 
        !          1030:        if (flags)
        !          1031:                log(LOG_ERR, "mp%d: port%d, %s (%d)\n",
        !          1032:                    unit, port, cp, flags);
        !          1033:        else
        !          1034:                log(LOG_ERR, "mp%d: port%d, %s\n", unit, port, cp);
        !          1035: }
        !          1036: 
        !          1037: int    MPHOSTINT = 1;
        !          1038: 
        !          1039: mptimeint(mb)
        !          1040:        register struct mblok *mb;
        !          1041: {
        !          1042: 
        !          1043:         mb->mb_mpintcnt = 0;
        !          1044:         mb->mb_mpintclk = (caddr_t)0;
        !          1045:        *(u_short *)mpinfo[mb->mb_unit]->ui_addr = 2;
        !          1046: }
        !          1047: 
        !          1048: /*
        !          1049:  * Interupt mpcc
        !          1050:  */
        !          1051: mpintmpcc(mb, port)
        !          1052:        register struct mblok *mb;
        !          1053: {
        !          1054: 
        !          1055:         mb->mb_intr[port] |= MPSEMA_WORK;
        !          1056:         if (++mb->mb_mpintcnt == MPHOSTINT) {
        !          1057:                 mb->mb_mpintcnt = 0;
        !          1058:                *(u_short *)mpinfo[mb->mb_unit]->ui_addr = 2;
        !          1059:                 if (mb->mb_mpintclk) {
        !          1060:                         untimeout(mptimeint, (caddr_t)mb);
        !          1061:                         mb->mb_mpintclk = 0;
        !          1062:                 }
        !          1063:         } else {
        !          1064:                 if (mb->mb_mpintclk == 0) {
        !          1065:                         timeout(mptimeint, (caddr_t)mb, 4);
        !          1066:                         mb->mb_mpintclk = (caddr_t)1;
        !          1067:                 }
        !          1068:         }
        !          1069: }
        !          1070: 
        !          1071: static char *mpherrmsg[] = {
        !          1072:        "",
        !          1073:        "Bus error",                            /* MPBUSERR */
        !          1074:        "Address error",                        /* ADDRERR */
        !          1075:        "Undefined ecc interrupt",              /* UNDECC */
        !          1076:        "Undefined interrupt",                  /* UNDINT */
        !          1077:        "Power failure occurred",               /* PWRFL */
        !          1078:        "Stray transmit done interrupt",        /* NOXENTRY */
        !          1079:        "Two fast timers on one port",          /* TWOFTMRS */
        !          1080:        "Interrupt queue full",                 /* INTQFULL */
        !          1081:        "Interrupt queue ack error",            /* INTQERR */
        !          1082:        "Uncorrectable dma parity error",       /* CBPERR */
        !          1083:        "32 port ACAP failed power up",         /* ACPDEAD */
        !          1084: };
        !          1085: #define        NHERRS  (sizeof (mpherrmsg) / sizeof (mpherrmsg[0]))
        !          1086: 
        !          1087: mperror(mb, unit)
        !          1088:        register struct mblok *mb;
        !          1089:        int unit;
        !          1090: {
        !          1091:        register char *cp;
        !          1092:        register int i;
        !          1093: 
        !          1094:        if (mb->mb_softerr) {
        !          1095:                switch (mb->mb_softerr) {
        !          1096:                case DMAPERR:   /* dma parity error */
        !          1097:                        cp = "dma parity error";
        !          1098:                        break;
        !          1099:                case ECCERR:
        !          1100:                        cp = "local memory ecc error";
        !          1101:                        break;
        !          1102:                default:
        !          1103:                        cp = "unknown error";
        !          1104:                        break;
        !          1105:                }
        !          1106:                log(LOG_ERR, "mp%d: soft error, %s", unit, cp);
        !          1107:                mb->mb_softerr = 0;
        !          1108:        }
        !          1109:        if (mb->mb_harderr) {
        !          1110:                if (mb->mb_harderr < NHERRS)
        !          1111:                        cp = mpherrmsg[mb->mb_harderr];
        !          1112:                else
        !          1113:                        cp = "unknown error";
        !          1114:                log(LOG_ERR, "mp%d: hard error, %s", unit, cp);
        !          1115:                if (mb->mb_status == MP_OPOPEN) {
        !          1116:                        for (i = 0; i < MPMAXPORT; i++) {
        !          1117:                                mpcleanport(mb, i);
        !          1118:                                mb->mb_proto[i] = MPPROTO_UNUSED;
        !          1119:                        }
        !          1120:                }
        !          1121:                mb->mb_harderr = 0;
        !          1122:                mb->mb_status = 0;
        !          1123:        }
        !          1124: }
        !          1125: 
        !          1126: mppurge(addr, cc)
        !          1127:        register caddr_t addr;
        !          1128:        register int cc;
        !          1129: {
        !          1130: 
        !          1131:        for (; cc >= 0; addr += NBPG, cc -= NBPG)
        !          1132:                mtpr(P1DC, addr);
        !          1133: }
        !          1134: 
        !          1135: /*
        !          1136:  * MPCC Download Pseudo-device.
        !          1137:  */
        !          1138: char   mpdlbuf[MPDLBUFSIZE];
        !          1139: int    mpdlbusy;               /* interlock on download buffer */
        !          1140: int    mpdlerr;
        !          1141: 
        !          1142: mpdlopen(dev)
        !          1143:        dev_t dev;
        !          1144: {
        !          1145:        int unit, mpu;
        !          1146:        struct vba_device *vi;
        !          1147: 
        !          1148:        unit = minor(dev);
        !          1149:        mpu = MPUNIT(unit);
        !          1150:        if (mpu >= NMP || (vi = mpinfo[mpu]) == 0 || vi->ui_alive == 0)
        !          1151:                return (ENODEV);
        !          1152:        return (0);
        !          1153: }
        !          1154: 
        !          1155: mpdlwrite(dev, uio)
        !          1156:        dev_t dev;
        !          1157:        struct uio *uio;
        !          1158: {
        !          1159:        register struct mpsoftc *ms = &mp_softc[MPUNIT(minor(dev))];
        !          1160:        register struct mpdl *dl;
        !          1161:        int error;
        !          1162: 
        !          1163:        if (ms->ms_mb == 0 || ms->ms_mb->mb_status != MP_DLOPEN)
        !          1164:                return (EFAULT);
        !          1165:        dl = &ms->ms_mb->mb_dl;
        !          1166:        dl->mpdl_count = uio->uio_iov->iov_len;
        !          1167:        dl->mpdl_data = (caddr_t) kvtophys(mpdlbuf);
        !          1168:        if (error = uiomove(mpdlbuf, (int)dl->mpdl_count, UIO_WRITE, uio))
        !          1169:                return (error);
        !          1170:        uio->uio_resid -= dl->mpdl_count;    /* set up return from write */
        !          1171:        dl->mpdl_cmd = MPDLCMD_NORMAL;
        !          1172:        error = mpdlwait(dl);
        !          1173:        return (error);
        !          1174: }
        !          1175: 
        !          1176: mpdlclose(dev)
        !          1177:        dev_t dev;
        !          1178: {
        !          1179:        register struct mblok *mb = mp_softc[MPUNIT(minor(dev))].ms_mb;
        !          1180: 
        !          1181:        if (mb == 0 || mb->mb_status != MP_DLDONE) {
        !          1182:                mpbogus.status = 0;
        !          1183:                if (mpbogus.mb == mpbogus.mbloks[MPUNIT(minor(dev))])
        !          1184:                        mpdlbusy--;
        !          1185:                return (EEXIST);
        !          1186:        }
        !          1187:        mb->mb_status = MP_OPOPEN;
        !          1188:        mpbogus.status = 0;
        !          1189:        /* set to dead, for board handshake */
        !          1190:        mb->mb_hostint.imok = MPIMOK_DEAD;
        !          1191:        return (0);
        !          1192: }
        !          1193: 
        !          1194: int    mpdltimeout();
        !          1195: 
        !          1196: /* ARGSUSED */
        !          1197: mpdlioctl(dev, cmd, data, flag)
        !          1198:        dev_t dev;
        !          1199:        caddr_t data;
        !          1200: {
        !          1201:        register struct mblok *mb;
        !          1202:        register struct mpdl *dl;
        !          1203:        int unit, error, s, i;
        !          1204: 
        !          1205:        mb = mp_softc[unit=MPUNIT(minor(dev))].ms_mb;
        !          1206:        if (mb == 0)
        !          1207:                return (EEXIST);
        !          1208:        dl = &mb->mb_dl;
        !          1209:        error = 0;
        !          1210:        switch (cmd) {
        !          1211:        case MPIOPORTMAP:
        !          1212:                bcopy(data, (caddr_t)mb->mb_proto, sizeof (mb->mb_proto));
        !          1213:                break;
        !          1214:        case MPIOHILO:
        !          1215:                bcopy(data, (caddr_t)&mb->mb_hiport, 2*(sizeof(mb->mb_hiport)));
        !          1216:                break;
        !          1217:        case MPIOENDDL:
        !          1218:                dl->mpdl_count = 0;
        !          1219:                dl->mpdl_data = 0;
        !          1220:                dl->mpdl_cmd = MPIOENDDL&IOCPARM_MASK;
        !          1221:                error = mpdlwait(dl);
        !          1222:                mpccinit(unit);
        !          1223:                mb->mb_status = MP_DLDONE;
        !          1224:                mpdlbusy--;
        !          1225:                break;
        !          1226:        case MPIOENDCODE:
        !          1227:                dl->mpdl_count = 0;
        !          1228:                dl->mpdl_data = 0;
        !          1229:                dl->mpdl_cmd = MPIOENDCODE&IOCPARM_MASK;
        !          1230:                error = mpdlwait(dl);
        !          1231:                break;
        !          1232:        case MPIOASYNCNF:
        !          1233:                bcopy(data, mpdlbuf, sizeof (struct abdcf));
        !          1234:                dl->mpdl_data = (caddr_t) kvtophys(mpdlbuf);
        !          1235:                dl->mpdl_count = sizeof (struct abdcf);
        !          1236:                dl->mpdl_cmd = MPIOASYNCNF&IOCPARM_MASK;
        !          1237:                error = mpdlwait(dl);
        !          1238:                break;
        !          1239:        case MPIOSTARTDL:
        !          1240:                while (mpdlbusy)
        !          1241:                        sleep((caddr_t)&mpdlbusy, PZERO+1);
        !          1242:                mpdlbusy++;
        !          1243:                /* initialize the downloading interface */
        !          1244:                mpbogus.magic = MPMAGIC;
        !          1245:                mpbogus.mb = mpbogus.mbloks[unit];
        !          1246:                mpbogus.status = 1;
        !          1247:                dl->mpdl_status = EVSTATUS_FREE;
        !          1248:                dl->mpdl_count = 0;
        !          1249:                dl->mpdl_cmd = 0;
        !          1250:                dl->mpdl_data = (char *) 0;
        !          1251:                mpdlerr = 0;
        !          1252:                mb->mb_magic = MPMAGIC;
        !          1253:                mb->mb_ivec = mp_softc[unit].ms_ivec+1; /* download vector */
        !          1254:                mb->mb_status = MP_DLPEND;
        !          1255:                mb->mb_diagswitch[0] = 'A';
        !          1256:                mb->mb_diagswitch[1] = 'P';
        !          1257:                s = spl8();
        !          1258:                *(u_short *)mpinfo[unit]->ui_addr = 2;
        !          1259:                timeout(mpdltimeout, (caddr_t)mb, 30*hz);
        !          1260:                sleep((caddr_t)&mb->mb_status, PZERO+1);
        !          1261:                splx(s);
        !          1262:                if (mb->mb_status == MP_DLOPEN) {
        !          1263:                        untimeout(mpdltimeout, (caddr_t)mb);
        !          1264:                } else if (mb->mb_status == MP_DLTIME) {
        !          1265:                        mpbogus.status = 0;
        !          1266:                        error = ETIMEDOUT;
        !          1267:                } else {
        !          1268:                        mpbogus.status = 0;
        !          1269:                        error = ENXIO;
        !          1270:                        log(LOG_ERR, "mp%d: start download: unknown status %x",
        !          1271:                            unit, mb->mb_status);
        !          1272:                }
        !          1273:                bzero((caddr_t)mb->mb_port, sizeof (mb->mb_port));
        !          1274:                break;
        !          1275:        case MPIORESETBOARD:
        !          1276:                s = spl8();
        !          1277:                if (mb->mb_imokclk)
        !          1278:                        mb->mb_imokclk = 0;
        !          1279:                *(u_short *)mpinfo[unit]->ui_addr = 0x100;
        !          1280:                if (mb->mb_status == MP_DLOPEN || mb->mb_status == MP_DLDONE) {
        !          1281:                        mpdlerr = MP_DLERROR;
        !          1282:                        dl->mpdl_status = EVSTATUS_FREE;
        !          1283:                        wakeup((caddr_t)&dl->mpdl_status);
        !          1284:                        mpbogus.status = 0;
        !          1285:                }
        !          1286:                for (i = 0; i < MPMAXPORT; i++) {
        !          1287:                        if (mb->mb_harderr || mb->mb_softerr)
        !          1288:                                mperror(mb, i);
        !          1289:                        mpcleanport(mb, i);
        !          1290:                        mb->mb_proto[i] = MPPROTO_UNUSED;
        !          1291:                }
        !          1292:                mb->mb_status = 0;
        !          1293:                splx(s);
        !          1294:                break;
        !          1295:        default:
        !          1296:                error = EINVAL;
        !          1297:                break;
        !          1298:        }
        !          1299:        return (error);
        !          1300: }
        !          1301: 
        !          1302: mpccinit(unit)
        !          1303:        int unit;
        !          1304: {
        !          1305:         register struct mblok *mb = mp_softc[unit].ms_mb;
        !          1306:         register struct his *his;
        !          1307:         register int i, j;
        !          1308: 
        !          1309:         mb->mb_status = MP_DLDONE;
        !          1310:         mb->mb_ivec = mp_softc[unit].ms_ivec;
        !          1311:         mb->mb_magic = MPMAGIC;
        !          1312:         /* Init host interface structure */
        !          1313:         his = &mb->mb_hostint;
        !          1314:         his->semaphore = MPSEMA_AVAILABLE;
        !          1315:         for (i = 0; i < NMPPROTO; i++)
        !          1316:                 for (j = 0; j < MPMAXPORT; j++) {
        !          1317:                         his->proto[i].inbdone[j] = MPPORT_EOL;
        !          1318:                         his->proto[i].outbdone[j] = MPPORT_EOL;
        !          1319:                 }
        !          1320:         mb->mb_unit = unit;
        !          1321: }
        !          1322: 
        !          1323: mpdlintr(mpcc)
        !          1324:        int mpcc;
        !          1325: {
        !          1326:        register struct mblok *mb;
        !          1327:        register struct mpdl *dl;
        !          1328: 
        !          1329:        mb = mp_softc[mpcc].ms_mb;
        !          1330:        if (mb == 0) {
        !          1331:                printf("mp%d: stray download interrupt\n", mpcc);
        !          1332:                return;
        !          1333:        }
        !          1334:        dl = &mb->mb_dl;
        !          1335:        switch (mb->mb_status) {
        !          1336:        case MP_DLOPEN:
        !          1337:                if (dl->mpdl_status != EVSTATUS_DONE)
        !          1338:                        mpdlerr = MP_DLERROR;
        !          1339:                dl->mpdl_status = EVSTATUS_FREE;
        !          1340:                wakeup((caddr_t)&dl->mpdl_status);
        !          1341:                return;
        !          1342:        case MP_DLPEND:
        !          1343:                mb->mb_status = MP_DLOPEN;
        !          1344:                wakeup((caddr_t)&mb->mb_status);
        !          1345:                /* fall thru... */
        !          1346:        case MP_DLTIME:
        !          1347:                return;
        !          1348:        case MP_OPOPEN:
        !          1349:                if (mb->mb_imokclk)
        !          1350:                        mb->mb_imokclk = 0;
        !          1351:                mb->mb_nointcnt = 0;            /* reset no interrupt count */
        !          1352:                mb->mb_hostint.imok = MPIMOK_DEAD;
        !          1353:                mb->mb_imokclk = (caddr_t)1;
        !          1354:                break;
        !          1355:        default:
        !          1356:                log(LOG_ERR, "mp%d: mpdlintr, status %x\n",
        !          1357:                    mpcc, mb->mb_status);
        !          1358:                break;
        !          1359:        }
        !          1360: }
        !          1361: 
        !          1362: mpdltimeout(mp)
        !          1363:        struct mblok *mp;
        !          1364: {
        !          1365: 
        !          1366:        mp->mb_status = MP_DLTIME;
        !          1367:        wakeup((caddr_t)&mp->mb_status);
        !          1368: }
        !          1369: 
        !          1370: /* 
        !          1371:  * Wait for a transfer to complete or a timeout to occur.
        !          1372:  */
        !          1373: mpdlwait(dl)
        !          1374:        register struct mpdl *dl;
        !          1375: {
        !          1376:        int s, error = 0;
        !          1377: 
        !          1378:        s = spl8();
        !          1379:        dl->mpdl_status = EVSTATUS_GO;
        !          1380:        while (dl->mpdl_status != EVSTATUS_FREE) {
        !          1381:                sleep((caddr_t)&dl->mpdl_status, PZERO+1);
        !          1382:                if (mpdlerr == MP_DLERROR)
        !          1383:                        error = EIO;
        !          1384:        }
        !          1385:        splx(s);
        !          1386:        return (error);
        !          1387: }
        !          1388: #endif

unix.superglobalmegacorp.com

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