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

unix.superglobalmegacorp.com

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