Annotation of 43BSDTahoe/sys/tahoevba/vx.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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