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

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

unix.superglobalmegacorp.com

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