Annotation of Net2/arch/tahoe/vba/vx.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, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)vx.c        7.13 (Berkeley) 5/16/91
        !            37:  */
        !            38: 
        !            39: #include "vx.h"
        !            40: #if NVX > 0
        !            41: /*
        !            42:  * VIOC-X driver
        !            43:  */
        !            44: #ifdef VXPERF
        !            45: #define        DOSCOPE
        !            46: #endif
        !            47: 
        !            48: #include "sys/param.h"
        !            49: #include "sys/ioctl.h"
        !            50: #include "sys/tty.h"
        !            51: #include "sys/user.h"
        !            52: #include "sys/map.h"
        !            53: #include "sys/buf.h"
        !            54: #include "sys/conf.h"
        !            55: #include "sys/file.h"
        !            56: #include "sys/proc.h"
        !            57: #include "sys/vm.h"
        !            58: #include "sys/kernel.h"
        !            59: #include "sys/syslog.h"
        !            60: 
        !            61: #include "../include/pte.h"
        !            62: 
        !            63: #include "../vba/vbavar.h"
        !            64: #include "../vba/vbaparam.h"
        !            65: #include "../vba/vxreg.h"
        !            66: #include "../vba/scope.h"
        !            67: 
        !            68: #ifdef VX_DEBUG
        !            69: long   vxintr4 = 0;
        !            70: #define        VXERR4  1
        !            71: #define        VXNOBUF 2
        !            72: long   vxdebug = 0;
        !            73: #define        VXVCM   1
        !            74: #define        VXVCC   2
        !            75: #define        VXVCX   4
        !            76: #endif
        !            77: 
        !            78: /*
        !            79:  * Interrupt type bits passed to vinthandl().
        !            80:  */
        !            81: #define        CMDquals 0              /* command completed interrupt */
        !            82: #define        RSPquals 1              /* command response interrupt */
        !            83: #define        UNSquals 2              /* unsolicited interrupt */
        !            84: 
        !            85: #define        VXUNIT(n)       ((n) >> 4)
        !            86: #define        VXPORT(n)       ((n) & 0xf)
        !            87: 
        !            88: struct tty vx_tty[NVX*16];
        !            89: #ifndef lint
        !            90: int    nvx = NVX*16;
        !            91: #endif
        !            92: int    vxstart(), ttrstrt();
        !            93: struct vxcmd *vobtain(), *nextcmd();
        !            94: 
        !            95: /*
        !            96:  * Driver information for auto-configuration stuff.
        !            97:  */
        !            98: int    vxprobe(), vxattach(), vxrint();
        !            99: struct vba_device *vxinfo[NVX];
        !           100: long   vxstd[] = { 0 };
        !           101: struct vba_driver vxdriver =
        !           102:     { vxprobe, 0, vxattach, 0, vxstd, "vx", vxinfo };
        !           103: 
        !           104: struct vx_softc {
        !           105:        struct  vxdevice *vs_addr;      /* H/W address */
        !           106:        u_char  vs_type;        /* 0: viox-x/vioc-b, 1: vioc-bop */
        !           107:        u_char  vs_bop;         /* bop board # for vioc-bop's */
        !           108:        u_char  vs_loport;      /* low port nbr */
        !           109:        u_char  vs_hiport;      /* high port nbr */
        !           110:        u_short vs_nbr;         /* viocx number */
        !           111:        u_short vs_maxcmd;      /* max number of concurrent cmds */
        !           112:        u_short vs_silosiz;     /* silo size */
        !           113:        short   vs_vers;        /* vioc/pvioc version */
        !           114: #define        VXV_OLD 0               /* PVIOCX | VIOCX */
        !           115: #define        VXV_NEW 1               /* NPVIOCX | NVIOCX */
        !           116:        short   vs_state;       /* controller state */
        !           117: #define        VXS_READY       0       /* ready for commands */
        !           118: #define        VXS_RESET       1       /* in process of reseting */
        !           119:        u_short vs_softCAR;     /* soft carrier */
        !           120:        u_int   vs_ivec;        /* interrupt vector base */
        !           121:        caddr_t vs_mricmd;      /* most recent issued cmd */
        !           122:        /* The remaining fields are zeroed on reset... */
        !           123: #define vs_zero vs_xmtcnt
        !           124:        int     vs_xmtcnt;      /* xmit commands pending */
        !           125:        struct  vxcmd *vs_avail;/* next available command buffer */
        !           126:        struct  vxcmd *vs_build;
        !           127:        struct  vxcmd vs_lst[NVCXBUFS];
        !           128:        struct  vcmds vs_cmds;
        !           129: } vx_softc[NVX];
        !           130: 
        !           131: struct speedtab vxspeedtab[] = {
        !           132:        EXTA,   V19200,
        !           133:        EXTB,   V19200,
        !           134:        19200,  V19200,
        !           135:        9600,   13,
        !           136:        4800,   12,
        !           137:        2400,   11,
        !           138:        1800,   10,
        !           139:        1200,   9,
        !           140:        600,    8,
        !           141:        300,    7,
        !           142:        200,    6,
        !           143:        150,    5,
        !           144:        134,    4,
        !           145:        110,    3,
        !           146:        75,     2,
        !           147:        50,     1,
        !           148:        0,      0,
        !           149:        -1,     -1,
        !           150: };
        !           151: 
        !           152: vxprobe(reg, vi)
        !           153:        caddr_t reg;
        !           154:        struct vba_device *vi;
        !           155: {
        !           156:        register int br, cvec;                  /* must be r12, r11 */
        !           157:        register struct vxdevice *vp;
        !           158:        register struct vx_softc *vs;
        !           159:        struct pte *dummypte;
        !           160: 
        !           161: #ifdef lint
        !           162:        br = 0; cvec = br; br = cvec;
        !           163:        vackint(0); vunsol(0); vcmdrsp(0);
        !           164: #ifdef VX_DEBUG
        !           165:        vxfreset(0);
        !           166: #endif
        !           167: #endif /* lint */
        !           168:        /*
        !           169:         * If on an HCX-9, the device has a 32-bit address,
        !           170:         * and we receive that address so we can set up a map.
        !           171:         * On VERSAbus devices, the address is 24-bit, and is
        !           172:         * already mapped (into vmem[]) by autoconf.
        !           173:         */
        !           174:        if (!(reg >= vmem && reg < &vmem[ctob(VBIOSIZE)]) &&    /* XXX */
        !           175:            !vbmemalloc(16, reg, &dummypte, &reg)) {
        !           176:                printf("vx%d: vbmemalloc failed.\n", vi->ui_unit);
        !           177:                return(0);
        !           178:        }
        !           179:        vp = (struct vxdevice *)reg;
        !           180:        if (badaddr((caddr_t)vp, 1))
        !           181:                return (0);
        !           182:        vp->v_fault = 0;
        !           183:        vp->v_vioc = V_BSY;
        !           184:        vp->v_hdwre = V_RESET;          /* reset interrupt */
        !           185:        DELAY(4000000);
        !           186:        if (vp->v_fault != VXF_READY)
        !           187:                return (0);
        !           188:        vs = &vx_softc[vi->ui_unit];
        !           189: #ifdef notdef
        !           190:        /*
        !           191:         * Align vioc interrupt vector base to 4 vector
        !           192:         * boundary and fitting in 8 bits (is this necessary,
        !           193:         * wish we had documentation).
        !           194:         */
        !           195:        if ((vi->ui_hd->vh_lastiv -= 3) > 0xff)
        !           196:                vi->ui_hd->vh_lastiv = 0xff;
        !           197:        vs->vs_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x3;
        !           198: #else
        !           199:        vs->vs_ivec = 0x40+vi->ui_unit*4;
        !           200: #endif
        !           201:        br = 0x18, cvec = vs->vs_ivec;  /* XXX */
        !           202:        return (sizeof (struct vxdevice));
        !           203: }
        !           204: 
        !           205: vxattach(vi)
        !           206:        register struct vba_device *vi;
        !           207: {
        !           208:        register struct vx_softc *vs = &vx_softc[vi->ui_unit];
        !           209: 
        !           210:        vs->vs_softCAR = vi->ui_flags;
        !           211:        vs->vs_addr = (struct vxdevice *)vi->ui_addr;
        !           212:        vxinit(vi->ui_unit, 1);
        !           213: }
        !           214: 
        !           215: /*
        !           216:  * Open a VX line.
        !           217:  */
        !           218: /*ARGSUSED*/
        !           219: vxopen(dev, flag)
        !           220:        dev_t dev;
        !           221:        int flag;
        !           222: {
        !           223:        register struct tty *tp;        /* pointer to tty struct for port */
        !           224:        register struct vx_softc *vs;
        !           225:        register struct vba_device *vi;
        !           226:        int unit, vx, s, error = 0;
        !           227:        int vxparam();
        !           228: 
        !           229:        unit = minor(dev);
        !           230:        vx = VXUNIT(unit);
        !           231:        if (vx >= NVX || (vi = vxinfo[vx])== 0 || vi->ui_alive == 0)
        !           232:                return (ENXIO);
        !           233:        vs = &vx_softc[vx];
        !           234:        tp = &vx_tty[unit];
        !           235:        unit = VXPORT(unit);
        !           236:        if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
        !           237:                return (EBUSY);
        !           238:        if (unit < vs->vs_loport || unit > vs->vs_hiport)
        !           239:                return (ENXIO);
        !           240:        tp->t_addr = (caddr_t)vs;
        !           241:        tp->t_oproc = vxstart;
        !           242:        tp->t_param = vxparam;
        !           243:        tp->t_dev = dev;
        !           244:        s = spl8();
        !           245:        if ((tp->t_state&TS_ISOPEN) == 0) {
        !           246:                tp->t_state |= TS_WOPEN;
        !           247:                ttychars(tp);
        !           248:                if (tp->t_ispeed == 0) {
        !           249:                        tp->t_iflag = TTYDEF_IFLAG;
        !           250:                        tp->t_oflag = TTYDEF_OFLAG;
        !           251:                        tp->t_lflag = TTYDEF_LFLAG;
        !           252:                        tp->t_cflag = TTYDEF_CFLAG;
        !           253:                        tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
        !           254:                }
        !           255:                vxparam(tp, &tp->t_termios);
        !           256:                ttsetwater(tp);
        !           257:        }
        !           258:        vcmodem(dev, VMOD_ON);
        !           259:        while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 
        !           260:              (tp->t_state&TS_CARR_ON) == 0) {
        !           261:                tp->t_state |= TS_WOPEN;
        !           262:                if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
        !           263:                    ttopen, 0))
        !           264:                        break;
        !           265:        }
        !           266:        if (error == 0)
        !           267:                error = (*linesw[tp->t_line].l_open)(dev,tp);
        !           268:        splx(s);
        !           269:        return (error);
        !           270: }
        !           271: 
        !           272: /*
        !           273:  * Close a VX line.
        !           274:  */
        !           275: /*ARGSUSED*/
        !           276: vxclose(dev, flag, mode, p)
        !           277:        dev_t dev;
        !           278:        int flag, mode;
        !           279:        struct proc *p;
        !           280: {
        !           281:        register struct tty *tp;
        !           282:        int unit, s, error = 0;
        !           283: 
        !           284:        unit = minor(dev);
        !           285:        tp = &vx_tty[unit];
        !           286:        s = spl8();
        !           287:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           288:        if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0)
        !           289:                vcmodem(dev, VMOD_OFF);
        !           290:        /* wait for the last response */
        !           291:        while (tp->t_state&TS_FLUSH && error == 0)
        !           292:                error = tsleep((caddr_t)&tp->t_state, TTOPRI | PCATCH,
        !           293:                    ttclos, 0);
        !           294:        splx(s);
        !           295:        if (error)
        !           296:                return (error);
        !           297:        return (ttyclose(tp));
        !           298: }
        !           299: 
        !           300: /*
        !           301:  * Read from a VX line.
        !           302:  */
        !           303: vxread(dev, uio, flag)
        !           304:        dev_t dev;
        !           305:        struct uio *uio;
        !           306: {
        !           307:        struct tty *tp = &vx_tty[minor(dev)];
        !           308: 
        !           309:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
        !           310: }
        !           311: 
        !           312: /*
        !           313:  * write on a VX line
        !           314:  */
        !           315: vxwrite(dev, uio, flag)
        !           316:        dev_t dev;
        !           317:        struct uio *uio;
        !           318: {
        !           319:        register struct tty *tp = &vx_tty[minor(dev)];
        !           320: 
        !           321:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           322: }
        !           323: 
        !           324: /*
        !           325:  * VIOCX unsolicited interrupt.
        !           326:  */
        !           327: vxrint(vx)
        !           328:        register vx;
        !           329: {
        !           330:        register struct tty *tp, *tp0;
        !           331:        register struct vxdevice *addr;
        !           332:        register struct vx_softc *vs;
        !           333:        struct vba_device *vi;
        !           334:        register int nc, c;
        !           335:        register struct silo {
        !           336:                u_char  data, port;
        !           337:        } *sp;
        !           338:        short *osp;
        !           339:        int overrun = 0;
        !           340: 
        !           341:        vi = vxinfo[vx];
        !           342:        if (vi == 0 || vi->ui_alive == 0)
        !           343:                return;
        !           344:        addr = (struct vxdevice *)vi->ui_addr;
        !           345:        switch (addr->v_uqual&037) {
        !           346:        case 0:
        !           347:                break;
        !           348:        case 2:
        !           349:                if (addr->v_ustat == VP_SILO_OFLOW)
        !           350:                        log(LOG_ERR, "vx%d: input silo overflow\n", vx);
        !           351:                else {
        !           352:                        printf("vx%d: vc proc err, ustat %x\n",
        !           353:                            vx, addr->v_ustat);
        !           354:                        vxstreset(vx);
        !           355:                }
        !           356:                return;
        !           357:        case 3:
        !           358:                vcmintr(vx);
        !           359:                return;
        !           360:        case 4:
        !           361:                return;
        !           362:        default:
        !           363:                printf("vx%d: vc uqual err, uqual %x\n", vx, addr->v_uqual);
        !           364:                vxstreset(vx);
        !           365:                return;
        !           366:        }
        !           367:        vs = &vx_softc[vx];
        !           368:        if (vs->vs_vers == VXV_NEW)
        !           369:                sp = (struct silo *)((caddr_t)addr + *(short *)addr->v_usdata);
        !           370:        else
        !           371:                sp = (struct silo *)((caddr_t)addr+VX_SILO+(addr->v_usdata[0]<<6));
        !           372:        nc = *(osp = (short *)sp);
        !           373:        if (nc == 0)
        !           374:                return;
        !           375:        if (vs->vs_vers == VXV_NEW && nc > vs->vs_silosiz) {
        !           376:                printf("vx%d: %d exceeds silo size\n", nc);
        !           377:                nc = vs->vs_silosiz;
        !           378:        }
        !           379:        tp0 = &vx_tty[vx*16];
        !           380:        sp = (struct silo *)(((short *)sp)+1);
        !           381:        for (; nc > 0; nc--, sp = (struct silo *)(((short *)sp)+1)) {
        !           382:                c = sp->port & 017;
        !           383:                if (vs->vs_loport > c || c > vs->vs_hiport)
        !           384:                        continue;
        !           385:                tp = tp0 + c;
        !           386:                if( (tp->t_state&TS_ISOPEN) == 0) {
        !           387:                        wakeup((caddr_t)&tp->t_rawq);
        !           388:                        continue;
        !           389:                }
        !           390:                c = sp->data&((tp->t_cflag&CSIZE)==CS8 ? 0xff : 0x7f);
        !           391:                if ((sp->port&VX_RO) == VX_RO && !overrun) {
        !           392:                        log(LOG_ERR, "vx%d: receiver overrun\n", vi->ui_unit);
        !           393:                        overrun = 1;
        !           394:                        continue;
        !           395:                }
        !           396:                if (sp->port&VX_PE)
        !           397:                        c |= TTY_PE;
        !           398:                if (sp->port&VX_FE) 
        !           399:                        c |= TTY_FE;
        !           400:                (*linesw[tp->t_line].l_rint)(c, tp);
        !           401:        }
        !           402:        *osp = 0;
        !           403: }
        !           404: 
        !           405: /*
        !           406:  * Ioctl for VX.
        !           407:  */
        !           408: vxioctl(dev, cmd, data, flag)
        !           409:        dev_t dev;
        !           410:        caddr_t data;
        !           411: {
        !           412:        register struct tty *tp;
        !           413:        int error;
        !           414: 
        !           415:        tp = &vx_tty[minor(dev)];
        !           416:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        !           417:        if (error >= 0)
        !           418:                return (error);
        !           419:        error = ttioctl(tp, cmd, data, flag);
        !           420:        if (error >= 0) 
        !           421:                return (error);
        !           422:        return (ENOTTY);
        !           423: }
        !           424: 
        !           425: vxparam(tp, t)
        !           426:        struct tty *tp;
        !           427:        struct termios *t;
        !           428: {
        !           429: 
        !           430:        return (vxcparam(tp, t, 1));
        !           431: }
        !           432: 
        !           433: /*
        !           434:  * Set parameters from open or stty into the VX hardware
        !           435:  * registers.
        !           436:  */
        !           437: vxcparam(tp, t, wait)
        !           438:        struct tty *tp;
        !           439:        struct termios *t;
        !           440:        int wait;
        !           441: {
        !           442:        register struct vx_softc *vs;
        !           443:        register struct vxcmd *cp;
        !           444:        int s, error = 0;
        !           445:        int speedcode = ttspeedtab(t->c_ospeed, vxspeedtab);
        !           446: 
        !           447:        if (speedcode < 0 || (t->c_ispeed != t->c_ospeed && t->c_ispeed))
        !           448:                return (EINVAL);
        !           449:        vs = (struct vx_softc *)tp->t_addr;
        !           450:        cp = vobtain(vs);
        !           451:        s = spl8();
        !           452:        /*
        !           453:         * Construct ``load parameters'' command block
        !           454:         * to setup baud rates, xon-xoff chars, parity,
        !           455:         * and stop bits for the specified port.
        !           456:         */
        !           457:        cp->cmd = VXC_LPARAX;
        !           458:        cp->par[1] = VXPORT(minor(tp->t_dev));
        !           459:        /*
        !           460:         * note: if the hardware does flow control, ^V doesn't work
        !           461:         * to escape ^S
        !           462:         */
        !           463:        if (t->c_iflag&IXON) {
        !           464:                if (t->c_cc[VSTART] == _POSIX_VDISABLE)
        !           465:                        cp->par[2] = 0;
        !           466:                else
        !           467:                        cp->par[2] = t->c_cc[VSTART];
        !           468:                if (t->c_cc[VSTOP] == _POSIX_VDISABLE)
        !           469:                        cp->par[3] = 0;
        !           470:                else
        !           471:                        cp->par[3] = t->c_cc[VSTOP];
        !           472:        } else 
        !           473:                cp->par[2] = cp->par[3] = 0;
        !           474: #ifdef notnow
        !           475:        switch (t->c_cflag & CSIZE) {   /* XXX */
        !           476:        case CS8:
        !           477: #endif
        !           478:                cp->par[4] = BITS8;             /* 8 bits of data */
        !           479: #ifdef notnow
        !           480:                break;
        !           481:        case CS7:
        !           482:                cp->par[4] = BITS7;             /* 7 bits of data */
        !           483:                break;
        !           484:        case CS6:
        !           485:                cp->par[4] = BITS6;             /* 6 bits of data */
        !           486:                break;
        !           487:        case CS5:
        !           488:                cp->par[4] = BITS5;             /* 5 bits of data */
        !           489:                break;
        !           490:        }
        !           491:        if ((t->c_cflag & PARENB) == 0)         /* XXX */
        !           492: #endif
        !           493:                cp->par[7] = VNOPARITY;         /* no parity */
        !           494: #ifdef notnow
        !           495:        else if (t->c_cflag&PARODD)
        !           496:                cp->par[7] = VODDP;     /* odd parity */
        !           497:        else
        !           498:                cp->par[7] = VEVENP;    /* even parity */
        !           499: #endif
        !           500:        cp->par[5] = (t->c_cflag&CSTOPB) ? VSTOP2 : VSTOP1;
        !           501:        cp->par[6] = speedcode;
        !           502:        if (vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd) && wait)
        !           503:                error = tsleep((caddr_t)cp, TTIPRI | PCATCH, ttyout, 0);
        !           504:        if ((t->c_ospeed)==0) {
        !           505:                tp->t_cflag |= HUPCL;
        !           506:                vcmodem(tp->t_dev, VMOD_OFF);
        !           507:        }
        !           508:        splx(s);
        !           509:        return (error);
        !           510: }
        !           511: 
        !           512: /*
        !           513:  * VIOCX command response interrupt.
        !           514:  * For transmission, restart output to any active port.
        !           515:  * For all other commands, just clean up.
        !           516:  */
        !           517: vxxint(vx, cp)
        !           518:        register int vx;
        !           519:        register struct vxcmd *cp;
        !           520: {
        !           521:        register struct vxmit *vp;
        !           522:        register struct tty *tp, *tp0;
        !           523:        register struct vx_softc *vs;
        !           524: 
        !           525:        vs = &vx_softc[vx];
        !           526:        cp = (struct vxcmd *)((long *)cp-1);
        !           527: 
        !           528:        switch (cp->cmd&0xff00) {
        !           529: 
        !           530:        case VXC_LIDENT:        /* initialization complete */
        !           531:                if (vs->vs_state == VXS_RESET) {
        !           532:                        vxfnreset(vx, cp);
        !           533:                        vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);
        !           534:                }
        !           535:                cp->cmd++;
        !           536:                return;
        !           537: 
        !           538:        case VXC_XMITDTA:
        !           539:        case VXC_XMITIMM:
        !           540:                break;
        !           541: 
        !           542:        case VXC_LPARAX:
        !           543:                wakeup((caddr_t)cp);
        !           544:                /* fall thru... */
        !           545:        default:        /* VXC_MDMCTL or VXC_FDTATOX */
        !           546:                vrelease(vs, cp);
        !           547:                if (vs->vs_state == VXS_RESET)
        !           548:                        vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);
        !           549:                return;
        !           550:        }
        !           551:        tp0 = &vx_tty[vx*16];
        !           552:        vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit));
        !           553:        for (; vp >= (struct vxmit *)cp->par; vp--) {
        !           554:                tp = tp0 + (vp->line & 017);
        !           555:                tp->t_state &= ~TS_BUSY;
        !           556:                if (tp->t_state & TS_FLUSH) {
        !           557:                        tp->t_state &= ~TS_FLUSH;
        !           558:                        wakeup((caddr_t)&tp->t_state);
        !           559:                } else
        !           560:                        ndflush(&tp->t_outq, vp->bcount+1);
        !           561:        }
        !           562:        vrelease(vs, cp);
        !           563:        if (vs->vs_vers == VXV_NEW)
        !           564:                (*linesw[tp->t_line].l_start)(tp);
        !           565:        else {
        !           566:                tp0 = &vx_tty[vx*16 + vs->vs_hiport];
        !           567:                for(tp = &vx_tty[vx*16 + vs->vs_loport]; tp <= tp0; tp++)
        !           568:                        (*linesw[tp->t_line].l_start)(tp);
        !           569:                if ((cp = nextcmd(vs)) != NULL) {       /* command to send? */
        !           570:                        vs->vs_xmtcnt++;
        !           571:                        (void) vcmd(vx, (caddr_t)&cp->cmd);
        !           572:                }
        !           573:        }
        !           574:        vs->vs_xmtcnt--;
        !           575: }
        !           576: 
        !           577: /*
        !           578:  * Force out partial XMIT command after timeout
        !           579:  */
        !           580: vxforce(vs)
        !           581:        register struct vx_softc *vs;
        !           582: {
        !           583:        register struct vxcmd *cp;
        !           584:        int s;
        !           585: 
        !           586:        s = spl8();
        !           587:        if ((cp = nextcmd(vs)) != NULL) {
        !           588:                vs->vs_xmtcnt++;
        !           589:                (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd);
        !           590:        }
        !           591:        splx(s);
        !           592: }
        !           593: 
        !           594: /*
        !           595:  * Start (restart) transmission on the given VX line.
        !           596:  */
        !           597: vxstart(tp)
        !           598:        register struct tty *tp;
        !           599: {
        !           600:        register short n;
        !           601:        register struct vx_softc *vs;
        !           602:        int s, port;
        !           603: 
        !           604:        s = spl8();
        !           605:        port = VXPORT(minor(tp->t_dev));
        !           606:        vs = (struct vx_softc *)tp->t_addr;
        !           607:        if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) == 0) {
        !           608:                if (tp->t_outq.c_cc <= tp->t_lowat) {
        !           609:                        if (tp->t_state&TS_ASLEEP) {
        !           610:                                tp->t_state &= ~TS_ASLEEP;
        !           611:                                wakeup((caddr_t)&tp->t_outq);
        !           612:                        }
        !           613:                        if (tp->t_wsel) {
        !           614:                                selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
        !           615:                                tp->t_wsel = 0;
        !           616:                                tp->t_state &= ~TS_WCOLL;
        !           617:                        }
        !           618:                }
        !           619:                if (tp->t_outq.c_cc == 0) {
        !           620:                        splx(s);
        !           621:                        return;
        !           622:                }
        !           623:                scope_out(3);
        !           624:                if (1 || !(tp->t_oflag&OPOST))  /* XXX */
        !           625:                        n = ndqb(&tp->t_outq, 0);
        !           626:                else {
        !           627:                        n = ndqb(&tp->t_outq, 0200);
        !           628:                        if (n == 0) {
        !           629:                                n = getc(&tp->t_outq);
        !           630:                                timeout(ttrstrt, (caddr_t)tp, (n&0177)+6);
        !           631:                                tp->t_state |= TS_TIMEOUT;
        !           632:                                n = 0;
        !           633:                        }
        !           634:                }
        !           635:                if (n) {
        !           636:                        tp->t_state |= TS_BUSY;
        !           637:                        vsetq(vs, port, (char *)tp->t_outq.c_cf, n);
        !           638:                }
        !           639:        }
        !           640:        splx(s);
        !           641: }
        !           642: 
        !           643: /*
        !           644:  * Stop output on a line.
        !           645:  */
        !           646: vxstop(tp)
        !           647:        register struct tty *tp;
        !           648: {
        !           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:        splx(s);
        !           656: }
        !           657: 
        !           658: static int vxbbno = -1;
        !           659: /*
        !           660:  * VIOCX Initialization.  Makes free lists of command buffers.
        !           661:  * Resets all viocx's.  Issues a LIDENT command to each
        !           662:  * viocx to establish interrupt vectors and logical port numbers.
        !           663:  */
        !           664: vxinit(vx, wait)
        !           665:        register int vx;
        !           666:        int wait;
        !           667: {
        !           668:        register struct vx_softc *vs;
        !           669:        register struct vxdevice *addr;
        !           670:        register struct vxcmd *cp;
        !           671:        register char *resp;
        !           672:        register int j;
        !           673:        char type, *typestring;
        !           674: 
        !           675:        vs = &vx_softc[vx];
        !           676:        addr = vs->vs_addr;
        !           677:        type = addr->v_ident;
        !           678:        vs->vs_vers = (type&VXT_NEW) ? VXV_NEW : VXV_OLD;
        !           679:        if (vs->vs_vers == VXV_NEW)
        !           680:                vs->vs_silosiz = addr->v_maxsilo;
        !           681:        switch (type) {
        !           682: 
        !           683:        case VXT_VIOCX:
        !           684:        case VXT_VIOCX|VXT_NEW:
        !           685:                typestring = "VIOC-X";
        !           686:                /* set soft carrier for printer ports */
        !           687:                for (j = 0; j < 16; j++)
        !           688:                        if (vs->vs_softCAR & (1 << j) ||
        !           689:                            addr->v_portyp[j] == VXT_PARALLEL) {
        !           690:                                vs->vs_softCAR |= 1 << j;
        !           691:                                addr->v_dcd |= 1 << j;
        !           692:                        }
        !           693:                break;
        !           694: 
        !           695:        case VXT_PVIOCX:
        !           696:        case VXT_PVIOCX|VXT_NEW:
        !           697:                typestring = "VIOC-X (old connector panel)";
        !           698:                break;
        !           699:        case VXT_VIOCBOP:               /* VIOC-BOP */
        !           700:                vs->vs_type = 1;
        !           701:                vs->vs_bop = ++vxbbno;
        !           702:                printf("VIOC-BOP no. %d at %x\n", vs->vs_bop, addr);
        !           703:                goto unsup;
        !           704:        default:
        !           705:                printf("vx%d: unknown type %x\n", vx, type);
        !           706:        unsup:
        !           707:                vxinfo[vx]->ui_alive = 0;
        !           708:                return;
        !           709:        }
        !           710:        vs->vs_nbr = vx;                /* assign board number */
        !           711:        vs->vs_maxcmd = (vs->vs_vers == VXV_NEW) ? 24 : 4;
        !           712:        /*
        !           713:         * Initialize all cmd buffers by linking them
        !           714:         * into a free list.
        !           715:         */
        !           716:        for (j = 0; j < NVCXBUFS; j++) {
        !           717:                cp = &vs->vs_lst[j];
        !           718:                cp->c_fwd = &vs->vs_lst[j+1];
        !           719:        }
        !           720:        vs->vs_avail = &vs->vs_lst[0];  /* set idx to 1st free buf */
        !           721:        cp->c_fwd = (struct vxcmd *)0;  /* mark last buf in free list */
        !           722: 
        !           723:        /*
        !           724:         * Establish the interrupt vectors and define the port numbers.
        !           725:         */
        !           726:        cp = vobtain(vs);
        !           727:        cp->cmd = VXC_LIDENT;
        !           728:        cp->par[0] = vs->vs_ivec;       /* ack vector */
        !           729:        cp->par[1] = cp->par[0]+1;      /* cmd resp vector */
        !           730:        cp->par[3] = cp->par[0]+2;      /* unsol intr vector */
        !           731:        cp->par[4] = 15;                /* max ports, no longer used */
        !           732:        cp->par[5] = 0;                 /* set 1st port number */
        !           733:        (void) vcmd(vx, (caddr_t)&cp->cmd);
        !           734:        if (!wait)
        !           735:                return;
        !           736: 
        !           737:        for (j = 0; cp->cmd == VXC_LIDENT && j < 4000000; j++)
        !           738:                ;
        !           739:        if (j >= 4000000)
        !           740:                printf("vx%d: didn't respond to LIDENT\n", vx); 
        !           741: 
        !           742:        /* calculate address of response buffer */
        !           743:        resp = (char *)addr + (addr->v_rspoff&0x3fff);
        !           744:        if (resp[0] != 0 && (resp[0]&0177) != 3) {
        !           745:                vrelease(vs, cp);       /* init failed */
        !           746:                return;
        !           747:        }
        !           748:        vs->vs_loport = cp->par[5];
        !           749:        vs->vs_hiport = cp->par[7];
        !           750:        printf("vx%d: %s%s, ports %d-%d\n", vx,
        !           751:            (vs->vs_vers == VXV_NEW) ? "" : "old ", typestring,
        !           752:            vs->vs_loport, vs->vs_hiport);
        !           753:        vrelease(vs, cp);
        !           754: }
        !           755: 
        !           756: /*
        !           757:  * Obtain a command buffer
        !           758:  */
        !           759: struct vxcmd *
        !           760: vobtain(vs)
        !           761:        register struct vx_softc *vs;
        !           762: {
        !           763:        register struct vxcmd *p;
        !           764:        int s;
        !           765: 
        !           766:        s = spl8();
        !           767:        p = vs->vs_avail;
        !           768:        if (p == (struct vxcmd *)0) {
        !           769: #ifdef VX_DEBUG
        !           770:                if (vxintr4&VXNOBUF)
        !           771:                        vxintr4 &= ~VXNOBUF;
        !           772: #endif
        !           773:                printf("vx%d: no buffers\n", vs->vs_nbr);
        !           774:                vxstreset(vs->vs_nbr);
        !           775:                splx(s);
        !           776:                return (vobtain(vs));
        !           777:        }
        !           778:        vs->vs_avail = p->c_fwd;
        !           779:        splx(s);
        !           780:        return ((struct vxcmd *)p);
        !           781: }
        !           782: 
        !           783: /*
        !           784:  * Release a command buffer
        !           785:  */
        !           786: vrelease(vs, cp)
        !           787:        register struct vx_softc *vs;
        !           788:        register struct vxcmd *cp;
        !           789: {
        !           790:        int s;
        !           791: 
        !           792: #ifdef VX_DEBUG
        !           793:        if (vxintr4&VXNOBUF)
        !           794:                return;
        !           795: #endif
        !           796:        s = spl8();
        !           797:        cp->c_fwd = vs->vs_avail;
        !           798:        vs->vs_avail = cp;
        !           799:        splx(s);
        !           800: }
        !           801: 
        !           802: struct vxcmd *
        !           803: nextcmd(vs)
        !           804:        register struct vx_softc *vs;
        !           805: {
        !           806:        register struct vxcmd *cp;
        !           807:        int s;
        !           808: 
        !           809:        s = spl8();
        !           810:        cp = vs->vs_build;
        !           811:        vs->vs_build = (struct vxcmd *)0;
        !           812:        splx(s);
        !           813:        return (cp);
        !           814: }
        !           815: 
        !           816: /*
        !           817:  * Assemble transmits into a multiple command;
        !           818:  * up to 8 transmits to 8 lines can be assembled together
        !           819:  * (on PVIOCX only).
        !           820:  */
        !           821: vsetq(vs, line, addr, n)
        !           822:        register struct vx_softc *vs;
        !           823:        caddr_t addr;
        !           824: {
        !           825:        register struct vxcmd *cp;
        !           826:        register struct vxmit *mp;
        !           827: 
        !           828:        /*
        !           829:         * Grab a new command buffer or append
        !           830:         * to the current one being built.
        !           831:         */
        !           832:        cp = vs->vs_build;
        !           833:        if (cp == (struct vxcmd *)0) {
        !           834:                cp = vobtain(vs);
        !           835:                vs->vs_build = cp;
        !           836:                cp->cmd = VXC_XMITDTA;
        !           837:        } else {
        !           838:                if ((cp->cmd & 07) == 07 || vs->vs_vers == VXV_NEW) {
        !           839:                        printf("vx%d: setq overflow\n", vs-vx_softc);
        !           840:                        vxstreset((int)vs->vs_nbr);
        !           841:                        return;
        !           842:                }
        !           843:                cp->cmd++;
        !           844:        }
        !           845:        /*
        !           846:         * Select the next vxmit buffer and copy the
        !           847:         * characters into the buffer (if there's room
        !           848:         * and the device supports ``immediate mode'',
        !           849:         * or store an indirect pointer to the data.
        !           850:         */
        !           851:        mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit));
        !           852:        mp->bcount = n-1;
        !           853:        mp->line = line;
        !           854:        if (vs->vs_vers == VXV_NEW && n <= sizeof (mp->ostream)) {
        !           855:                cp->cmd = VXC_XMITIMM;
        !           856:                bcopy(addr, mp->ostream, (unsigned)n);
        !           857:        } else {
        !           858:                /* get system address of clist block */
        !           859:                addr = (caddr_t)vtoph((struct proc *)0, (unsigned)addr);
        !           860:                bcopy((caddr_t)&addr, mp->ostream, sizeof (addr));
        !           861:        }
        !           862:        /*
        !           863:         * We send the data immediately if a VIOCX,
        !           864:         * the command buffer is full, or if we've nothing
        !           865:         * currently outstanding.  If we don't send it,
        !           866:         * set a timeout to force the data to be sent soon.
        !           867:         */
        !           868:        if (vs->vs_vers == VXV_NEW || (cp->cmd & 07) == 7 ||
        !           869:            vs->vs_xmtcnt == 0) {
        !           870:                vs->vs_xmtcnt++;
        !           871:                (void) vcmd((int)vs->vs_nbr, (char *)&cp->cmd);
        !           872:                vs->vs_build = 0;
        !           873:        } else
        !           874:                timeout(vxforce, (caddr_t)vs, 3);
        !           875: }
        !           876: 
        !           877: /*
        !           878:  * Write a command out to the VIOC
        !           879:  */
        !           880: vcmd(vx, cmdad)
        !           881:        register int vx;
        !           882:        register caddr_t cmdad;
        !           883: {
        !           884:        register struct vcmds *cp;
        !           885:        register struct vx_softc *vs = &vx_softc[vx];
        !           886:        int s;
        !           887: 
        !           888:        s = spl8();
        !           889:        /*
        !           890:         * When the vioc is resetting, don't process
        !           891:         * anything other than VXC_LIDENT commands.
        !           892:         */
        !           893:        if (vs->vs_state == VXS_RESET && cmdad != NULL) {
        !           894:                struct vxcmd *vcp = (struct vxcmd *)(cmdad-sizeof (vcp->c_fwd));
        !           895: 
        !           896:                if (vcp->cmd != VXC_LIDENT) {
        !           897:                        vrelease(vs, vcp);
        !           898:                        return (0);
        !           899:                }
        !           900:        }
        !           901:        cp = &vs->vs_cmds;
        !           902:        if (cmdad != (caddr_t)0) {
        !           903:                cp->cmdbuf[cp->v_fill] = cmdad;
        !           904:                if (++cp->v_fill >= VC_CMDBUFL)
        !           905:                        cp->v_fill = 0;
        !           906:                if (cp->v_fill == cp->v_empty) {
        !           907:                        printf("vx%d: cmd q overflow\n", vx);
        !           908:                        vxstreset(vx);
        !           909:                        splx(s);
        !           910:                        return (0);
        !           911:                }
        !           912:                cp->v_cmdsem++;
        !           913:        }
        !           914:        if (cp->v_cmdsem && cp->v_curcnt < vs->vs_maxcmd) {
        !           915:                cp->v_cmdsem--;
        !           916:                cp->v_curcnt++;
        !           917:                vinthandl(vx, ((V_BSY|CMDquals) << 8)|V_INTR);
        !           918:        }
        !           919:        splx(s);
        !           920:        return (1);
        !           921: }
        !           922: 
        !           923: /*
        !           924:  * VIOC acknowledge interrupt.  The VIOC has received the new
        !           925:  * command.  If no errors, the new command becomes one of 16 (max)
        !           926:  * current commands being executed.
        !           927:  */
        !           928: vackint(vx)
        !           929:        register vx;
        !           930: {
        !           931:        register struct vxdevice *vp;
        !           932:        register struct vcmds *cp;
        !           933:        struct vx_softc *vs;
        !           934:        int s;
        !           935: 
        !           936:        scope_out(5);
        !           937:        vs = &vx_softc[vx];
        !           938:        if (vs->vs_type)        /* Its a BOP */
        !           939:                return;
        !           940:        s = spl8();
        !           941:        vp = vs->vs_addr;
        !           942:        cp = &vs->vs_cmds;
        !           943:        if (vp->v_vcid&V_ERR) {
        !           944:                register char *resp;
        !           945:                register i;
        !           946: 
        !           947:                printf("vx%d: ackint error type %x v_dcd %x\n", vx,
        !           948:                    vp->v_vcid & 07, vp->v_dcd & 0xff);
        !           949:                resp = (char *)vs->vs_mricmd;
        !           950:                for (i = 0; i < 16; i++)
        !           951:                        printf("%x ", resp[i]&0xff);
        !           952:                printf("\n");
        !           953:                splx(s);
        !           954:                vxstreset(vx);
        !           955:                return;
        !           956:        }
        !           957:        if ((vp->v_hdwre&017) == CMDquals) {
        !           958: #ifdef VX_DEBUG
        !           959:                if (vxintr4 & VXERR4) { /* causes VIOC INTR ERR 4 */
        !           960:                        struct vxcmd *cp1, *cp0;
        !           961: 
        !           962:                        cp0 = (struct vxcmd *)
        !           963:                            ((caddr_t)cp->cmdbuf[cp->v_empty]-sizeof (cp0->c_fwd));
        !           964:                        if (cp0->cmd == VXC_XMITDTA || cp0->cmd == VXC_XMITIMM) {
        !           965:                                cp1 = vobtain(vs);
        !           966:                                *cp1 = *cp0;
        !           967:                                vxintr4 &= ~VXERR4;
        !           968:                                (void) vcmd(vx, &cp1->cmd);
        !           969:                        }
        !           970:                }
        !           971: #endif
        !           972:                cp->v_curcmd[vp->v_vcid & VCMDLEN-1] = cp->cmdbuf[cp->v_empty];
        !           973:                if (++cp->v_empty >= VC_CMDBUFL)
        !           974:                        cp->v_empty = 0;
        !           975:        }
        !           976:        if (++cp->v_itrempt >= VC_IQLEN)
        !           977:                cp->v_itrempt = 0;
        !           978:        vintempt(vx);
        !           979:        splx(s);
        !           980:        (void) vcmd(vx, (caddr_t)0);    /* queue next cmd, if any */
        !           981: }
        !           982: 
        !           983: /*
        !           984:  * Command Response interrupt.  The Vioc has completed
        !           985:  * a command.  The command may now be returned to
        !           986:  * the appropriate device driver.
        !           987:  */
        !           988: vcmdrsp(vx)
        !           989:        register vx;
        !           990: {
        !           991:        register struct vxdevice *vp;
        !           992:        register struct vcmds *cp;
        !           993:        register caddr_t cmd;
        !           994:        register struct vx_softc *vs;
        !           995:        register char *resp;
        !           996:        register k;
        !           997:        register int s;
        !           998: 
        !           999:        scope_out(6);
        !          1000:        vs = &vx_softc[vx];
        !          1001:        if (vs->vs_type) {      /* Its a BOP */
        !          1002:                printf("vx%d: vcmdrsp interrupt\n", vx);
        !          1003:                return;
        !          1004:        }
        !          1005:        s = spl8();
        !          1006:        vp = vs->vs_addr;
        !          1007:        cp = &vs->vs_cmds;
        !          1008:        resp = (char *)vp + (vp->v_rspoff&0x7fff);
        !          1009:        if (((k = resp[1])&V_UNBSY) == 0) {
        !          1010:                printf("vx%d: cmdresp debug\n", vx);
        !          1011:                splx(s);
        !          1012:                vxstreset(vx);
        !          1013:                return;
        !          1014:        }
        !          1015:        k &= VCMDLEN-1;
        !          1016:        cmd = cp->v_curcmd[k];
        !          1017:        cp->v_curcmd[k] = (caddr_t)0;
        !          1018:        cp->v_curcnt--;
        !          1019:        k = *((short *)&resp[4]);       /* cmd operation code */
        !          1020:        if ((k&0xff00) == VXC_LIDENT)   /* want hiport number */
        !          1021:                for (k = 0; k < VRESPLEN; k++)
        !          1022:                        cmd[k] = resp[k+4];
        !          1023:        resp[1] = 0;
        !          1024:        vxxint(vx, (struct vxcmd *)cmd);
        !          1025:        if (vs->vs_state == VXS_READY)
        !          1026:                vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR);
        !          1027:        splx(s);
        !          1028: }
        !          1029: 
        !          1030: /*
        !          1031:  * Unsolicited interrupt.
        !          1032:  */
        !          1033: vunsol(vx)
        !          1034:        register vx;
        !          1035: {
        !          1036:        register struct vxdevice *vp;
        !          1037:        struct vx_softc *vs;
        !          1038:        int s;
        !          1039: 
        !          1040:        scope_out(1);
        !          1041:        vs = &vx_softc[vx];
        !          1042:        if (vs->vs_type) {      /* Its a BOP */
        !          1043:                printf("vx%d: vunsol from BOP\n", vx);
        !          1044:                return;
        !          1045:        }
        !          1046:        s = spl8();
        !          1047:        vp = vs->vs_addr;
        !          1048:        if (vp->v_uqual&V_UNBSY) {
        !          1049:                vxrint(vx);
        !          1050:                vinthandl(vx, ((V_BSY|UNSquals) << 8)|V_INTR);
        !          1051: #ifdef notdef
        !          1052:        } else {
        !          1053:                printf("vx%d: unsolicited interrupt error\n", vx);
        !          1054:                splx(s);
        !          1055:                vxstreset(vx);
        !          1056: #endif
        !          1057:        }
        !          1058:        splx(s);
        !          1059: }
        !          1060: 
        !          1061: /*
        !          1062:  * Enqueue an interrupt.
        !          1063:  */
        !          1064: vinthandl(vx, item)
        !          1065:        register int vx;
        !          1066:        register item;
        !          1067: {
        !          1068:        register struct vcmds *cp;
        !          1069:        int empty;
        !          1070: 
        !          1071:        cp = &vx_softc[vx].vs_cmds;
        !          1072:        empty = (cp->v_itrfill == cp->v_itrempt);
        !          1073:        cp->v_itrqueu[cp->v_itrfill] = item;
        !          1074:        if (++cp->v_itrfill >= VC_IQLEN)
        !          1075:                cp->v_itrfill = 0;
        !          1076:        if (cp->v_itrfill == cp->v_itrempt) {
        !          1077:                printf("vx%d: interrupt q overflow\n", vx);
        !          1078:                vxstreset(vx);
        !          1079:        } else if (empty)
        !          1080:                vintempt(vx);
        !          1081: }
        !          1082: 
        !          1083: vintempt(vx)
        !          1084:        int vx;
        !          1085: {
        !          1086:        register struct vcmds *cp;
        !          1087:        register struct vxdevice *vp;
        !          1088:        register struct vx_softc *vs;
        !          1089:        register short item;
        !          1090:        register short *intr;
        !          1091: 
        !          1092:        vs = &vx_softc[vx];
        !          1093:        vp = vs->vs_addr;
        !          1094:        if (vp->v_vioc&V_BSY)
        !          1095:                return;
        !          1096:        cp = &vs->vs_cmds;
        !          1097:        if (cp->v_itrempt == cp->v_itrfill)
        !          1098:                return;
        !          1099:        item = cp->v_itrqueu[cp->v_itrempt];
        !          1100:        intr = (short *)&vp->v_vioc;
        !          1101:        switch ((item >> 8)&03) {
        !          1102: 
        !          1103:        case CMDquals: {                /* command */
        !          1104:                int phys;
        !          1105: 
        !          1106:                if (cp->v_empty == cp->v_fill || vp->v_vcbsy&V_BSY)
        !          1107:                        break;
        !          1108:                vs->vs_mricmd = (caddr_t)cp->cmdbuf[cp->v_empty];
        !          1109:                phys = vtoph((struct proc *)0, 
        !          1110:                    (unsigned)cp->cmdbuf[cp->v_empty]);
        !          1111:                vp->v_vcp[0] = ((short *)&phys)[0];
        !          1112:                vp->v_vcp[1] = ((short *)&phys)[1];
        !          1113:                vp->v_vcbsy = V_BSY;
        !          1114:                *intr = item;
        !          1115:                scope_out(4);
        !          1116:                break;
        !          1117:        }
        !          1118: 
        !          1119:        case RSPquals:          /* command response */
        !          1120:                *intr = item;
        !          1121:                scope_out(7);
        !          1122:                break;
        !          1123: 
        !          1124:        case UNSquals:          /* unsolicited interrupt */
        !          1125:                vp->v_uqual = 0;
        !          1126:                *intr = item;
        !          1127:                scope_out(2);
        !          1128:                break;
        !          1129:        }
        !          1130: }
        !          1131: 
        !          1132: /*
        !          1133:  * Start a reset on a vioc after error (hopefully)
        !          1134:  */
        !          1135: vxstreset(vx)
        !          1136:        register int vx;
        !          1137: {
        !          1138:        register struct vx_softc *vs;
        !          1139:        register struct vxdevice *vp;
        !          1140:        register struct vxcmd *cp;
        !          1141:        register int j;
        !          1142:        extern int vxinreset();
        !          1143:        int s;
        !          1144: 
        !          1145:        vs = &vx_softc[vx];
        !          1146:        s = spl8();
        !          1147:        if (vs->vs_state == VXS_RESET) {        /* avoid recursion */
        !          1148:                splx(s);
        !          1149:                return;
        !          1150:        }
        !          1151:        vp = vs->vs_addr;
        !          1152:        /*
        !          1153:         * Zero out the vioc structures, mark the vioc as being
        !          1154:         * reset, reinitialize the free command list, reset the vioc
        !          1155:         * and start a timer to check on the progress of the reset.
        !          1156:         */
        !          1157:        bzero((caddr_t)&vs->vs_zero,
        !          1158:            (unsigned)((caddr_t)(vs + 1) - (caddr_t)&vs->vs_zero));
        !          1159: 
        !          1160:        /*
        !          1161:         * Setting VXS_RESET prevents others from issuing
        !          1162:         * commands while allowing currently queued commands to
        !          1163:         * be passed to the VIOC.
        !          1164:         */
        !          1165:        vs->vs_state = VXS_RESET;
        !          1166:        /* init all cmd buffers */
        !          1167:        for (j = 0; j < NVCXBUFS; j++) {
        !          1168:                cp = &vs->vs_lst[j];
        !          1169:                cp->c_fwd = &vs->vs_lst[j+1];
        !          1170:        }
        !          1171:        vs->vs_avail = &vs->vs_lst[0];
        !          1172:        cp->c_fwd = (struct vxcmd *)0;
        !          1173:        printf("vx%d: reset...", vx);
        !          1174:        vp->v_fault = 0;
        !          1175:        vp->v_vioc = V_BSY;
        !          1176:        vp->v_hdwre = V_RESET;          /* generate reset interrupt */
        !          1177:        timeout(vxinreset, (caddr_t)vx, hz*5);
        !          1178:        splx(s);
        !          1179: }
        !          1180: 
        !          1181: /* continue processing a reset on a vioc after an error (hopefully) */
        !          1182: vxinreset(vx)
        !          1183:        int vx;
        !          1184: {
        !          1185:        register struct vxdevice *vp;
        !          1186:        int s = spl8();
        !          1187: 
        !          1188:        vp = vx_softc[vx].vs_addr;
        !          1189:        /*
        !          1190:         * See if the vioc has reset.
        !          1191:         */
        !          1192:        if (vp->v_fault != VXF_READY) {
        !          1193:                printf(" vxreset failed\n");
        !          1194:                splx(s);
        !          1195:                return;
        !          1196:        }
        !          1197:        /*
        !          1198:         * Send a LIDENT to the vioc and mess with carrier flags
        !          1199:         * on parallel printer ports.
        !          1200:         */
        !          1201:        vxinit(vx, 0);
        !          1202:        splx(s);
        !          1203: }
        !          1204: 
        !          1205: /*
        !          1206:  * Finish the reset on the vioc after an error (hopefully).
        !          1207:  *
        !          1208:  * Restore modem control, parameters and restart output.
        !          1209:  * Since the vioc can handle no more then 24 commands at a time
        !          1210:  * and we could generate as many as 48 commands, we must do this in
        !          1211:  * phases, issuing no more then 16 commands at a time.
        !          1212:  */
        !          1213: vxfnreset(vx, cp)
        !          1214:        register int vx;
        !          1215:        register struct vxcmd *cp;
        !          1216: {
        !          1217:        register struct vx_softc *vs;
        !          1218:        register struct vxdevice *vp;
        !          1219:        register struct tty *tp, *tp0;
        !          1220:        register int i;
        !          1221: #ifdef notdef
        !          1222:        register int on;
        !          1223: #endif
        !          1224:        extern int vxrestart();
        !          1225:        int s = spl8();
        !          1226: 
        !          1227:        vs = &vx_softc[vx];
        !          1228:        vrelease(vs, cp);
        !          1229:        vs->vs_state = VXS_READY;
        !          1230: 
        !          1231:        vp = vs->vs_addr;
        !          1232:        vp->v_vcid = 0;
        !          1233: 
        !          1234:        /*
        !          1235:         * Restore modem information and control.
        !          1236:         */
        !          1237:        tp0 = &vx_tty[vx*16];
        !          1238:        for (i = vs->vs_loport; i <= vs->vs_hiport; i++) {
        !          1239:                tp = tp0 + i;
        !          1240:                if (tp->t_state&(TS_ISOPEN|TS_WOPEN)) {
        !          1241:                        tp->t_state &= ~TS_CARR_ON;
        !          1242:                        vcmodem(tp->t_dev, VMOD_ON);
        !          1243:                        if (tp->t_state&TS_CARR_ON)
        !          1244:                                (void)(*linesw[tp->t_line].l_modem)(tp, 1);
        !          1245:                        else if (tp->t_state & TS_ISOPEN)
        !          1246:                                (void)(*linesw[tp->t_line].l_modem)(tp, 0);
        !          1247:                }
        !          1248: #ifdef notdef
        !          1249:                /*
        !          1250:                 * If carrier has changed while we were resetting,
        !          1251:                 * take appropriate action.
        !          1252:                 */
        !          1253:                on = vp->v_dcd & 1<<i;
        !          1254:                if (on && (tp->t_state&TS_CARR_ON) == 0)
        !          1255:                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
        !          1256:                else if (!on && tp->t_state&TS_CARR_ON)
        !          1257:                        (void)(*linesw[tp->t_line].l_modem)(tp, 0);
        !          1258: #endif
        !          1259:        }
        !          1260:        vs->vs_state = VXS_RESET;
        !          1261:        timeout(vxrestart, (caddr_t)vx, hz);
        !          1262:        splx(s);
        !          1263: }
        !          1264: 
        !          1265: /*
        !          1266:  * Restore a particular aspect of the VIOC.
        !          1267:  */
        !          1268: vxrestart(vx)
        !          1269:        int vx;
        !          1270: {
        !          1271:        register struct tty *tp, *tp0;
        !          1272:        register struct vx_softc *vs;
        !          1273:        register int i, count;
        !          1274:        int s = spl8();
        !          1275: 
        !          1276:        count = vx >> 8;
        !          1277:        vx &= 0xff;
        !          1278:        vs = &vx_softc[vx];
        !          1279:        vs->vs_state = VXS_READY;
        !          1280:        tp0 = &vx_tty[vx*16];
        !          1281:        for (i = vs->vs_loport; i <= vs->vs_hiport; i++) {
        !          1282:                tp = tp0 + i;
        !          1283:                if (count != 0) {
        !          1284:                        tp->t_state &= ~(TS_BUSY|TS_TIMEOUT);
        !          1285:                        if (tp->t_state&(TS_ISOPEN|TS_WOPEN))
        !          1286:                                vxstart(tp);    /* restart pending output */
        !          1287:                } else {
        !          1288:                        if (tp->t_state&(TS_WOPEN|TS_ISOPEN))
        !          1289:                                vxcparam(tp, &tp->t_termios, 0);
        !          1290:                }
        !          1291:        }
        !          1292:        if (count == 0) {
        !          1293:                vs->vs_state = VXS_RESET;
        !          1294:                timeout(vxrestart, (caddr_t)(vx + 1*256), hz);
        !          1295:        } else
        !          1296:                printf(" vx reset done\n");
        !          1297:        splx(s);
        !          1298: }
        !          1299: 
        !          1300: vxreset(dev)
        !          1301:        dev_t dev;
        !          1302: {
        !          1303: 
        !          1304:        vxstreset((int)VXUNIT(minor(dev)));     /* completes asynchronously */
        !          1305: }
        !          1306: 
        !          1307: #ifdef VX_DEBUG
        !          1308: vxfreset(vx)
        !          1309:        register int vx;
        !          1310: {
        !          1311:        struct vba_device *vi;
        !          1312: 
        !          1313:        if ((unsigned)vx > NVX || (vi = vxinfo[vx]) == 0 || vi->ui_addr == 0)
        !          1314:                return (ENODEV);
        !          1315:        vx_softc[vx].vs_state = VXS_READY;
        !          1316:        vxstreset(vx);
        !          1317:        return (0);             /* completes asynchronously */
        !          1318: }
        !          1319: #endif
        !          1320: 
        !          1321: vcmodem(dev, flag)
        !          1322:        dev_t dev;
        !          1323: {
        !          1324:        struct tty *tp;
        !          1325:        register struct vxcmd *cp;
        !          1326:        register struct vx_softc *vs;
        !          1327:        register struct vxdevice *kp;
        !          1328:        register port;
        !          1329:        int unit;
        !          1330: 
        !          1331:        unit = minor(dev);
        !          1332:        tp = &vx_tty[unit];
        !          1333:        vs = (struct vx_softc *)tp->t_addr;
        !          1334:        if (vs->vs_state != VXS_READY)
        !          1335:                return;
        !          1336:        cp = vobtain(vs);
        !          1337:        kp = vs->vs_addr;
        !          1338: 
        !          1339:        port = VXPORT(unit);
        !          1340:        /*
        !          1341:         * Issue MODEM command
        !          1342:         */
        !          1343:        cp->cmd = VXC_MDMCTL;
        !          1344:        if (flag == VMOD_ON) {
        !          1345:                if (vs->vs_softCAR & (1 << port)) {
        !          1346:                        cp->par[0] = V_MANUAL | V_DTR_ON | V_RTS;
        !          1347:                        kp->v_dcd |= (1 << port);
        !          1348:                } else
        !          1349:                        cp->par[0] = V_AUTO | V_DTR_ON;
        !          1350:        } else
        !          1351:                cp->par[0] = V_DTR_OFF;
        !          1352:        cp->par[1] = port;
        !          1353:        (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd);
        !          1354:        if ((kp->v_dcd | vs->vs_softCAR) & (1 << port) && flag == VMOD_ON)
        !          1355:                tp->t_state |= TS_CARR_ON;
        !          1356: }
        !          1357: 
        !          1358: /*
        !          1359:  * VCMINTR called when an unsolicited interrupt occurs signaling
        !          1360:  * some change of modem control state.
        !          1361:  */
        !          1362: vcmintr(vx)
        !          1363:        register vx;
        !          1364: {
        !          1365:        register struct vxdevice *kp;
        !          1366:        register struct tty *tp;
        !          1367:        register port;
        !          1368:        register struct vx_softc *vs;
        !          1369: 
        !          1370:        vs = &vx_softc[vx];
        !          1371:        kp = vs->vs_addr;
        !          1372:        port = kp->v_usdata[0] & 017;
        !          1373:        tp = &vx_tty[vx*16+port];
        !          1374: 
        !          1375:        if (kp->v_ustat & DCD_ON)
        !          1376:                (void)(*linesw[tp->t_line].l_modem)(tp, 1);
        !          1377:        else if ((kp->v_ustat & DCD_OFF) &&
        !          1378:            ((vs->vs_softCAR & (1 << port))) == 0 &&
        !          1379:            (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
        !          1380:                register struct vcmds *cp;
        !          1381:                register struct vxcmd *cmdp;
        !          1382: 
        !          1383:                /* clear all pending transmits */
        !          1384:                if (tp->t_state&(TS_BUSY|TS_FLUSH) &&
        !          1385:                    vs->vs_vers == VXV_NEW) {
        !          1386:                        int i, cmdfound = 0;
        !          1387: 
        !          1388:                        cp = &vs->vs_cmds;
        !          1389:                        for (i = cp->v_empty; i != cp->v_fill; ) {
        !          1390:                                cmdp = (struct vxcmd *)((long *)cp->cmdbuf[i]-1);
        !          1391:                                if ((cmdp->cmd == VXC_XMITDTA ||
        !          1392:                                    cmdp->cmd == VXC_XMITIMM) &&
        !          1393:                                    ((struct vxmit *)cmdp->par)->line == port) {
        !          1394:                                        cmdfound++;
        !          1395:                                        cmdp->cmd = VXC_FDTATOX;
        !          1396:                                        cmdp->par[1] = port;
        !          1397:                                }
        !          1398:                                if (++i >= VC_CMDBUFL)
        !          1399:                                        i = 0;
        !          1400:                        }
        !          1401:                        if (cmdfound)
        !          1402:                                tp->t_state &= ~(TS_BUSY|TS_FLUSH);
        !          1403:                        /* cmd is already in vioc, have to flush it */
        !          1404:                        else {
        !          1405:                                cmdp = vobtain(vs);
        !          1406:                                cmdp->cmd = VXC_FDTATOX;
        !          1407:                                cmdp->par[1] = port;
        !          1408:                                (void) vcmd(vx, (caddr_t)&cmdp->cmd);
        !          1409:                        }
        !          1410:                }
        !          1411:        } else if ((kp->v_ustat&BRK_CHR) && (tp->t_state&TS_ISOPEN)) {
        !          1412:                (*linesw[tp->t_line].l_rint)(TTY_FE, tp);
        !          1413:                return;
        !          1414:        }
        !          1415: }
        !          1416: #endif

unix.superglobalmegacorp.com

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