Annotation of cci/sys/vba/vcc.c, revision 1.1.1.2

1.1       root        1: #include "vx.h"
                      2: #if NVX > 0
                      3: /*
                      4:  *  VIOC driver
                      5:  */
                      6: #include "../h/param.h"
                      7: #include "../h/file.h"
                      8: #include "../h/ioctl.h"
                      9: #include "../h/tty.h"
                     10: #include "../h/errno.h"
                     11: #include "../h/time.h"
                     12: #include "../h/kernel.h"
                     13: #include "../vba/vioc.h"
                     14: #ifdef VXPERF
                     15: #include "../vba/scope.h"
                     16: #endif VXPERF
                     17: 
                     18: #define CMDquals 0
                     19: #define RSPquals 1
                     20: #define UNSquals 2
                     21: 
1.1.1.2 ! root       22: extern struct vcx      vcx[];
        !            23: extern struct tty      vx_tty[];
        !            24: struct vcmds           v_cmds[NVIOCX];
1.1       root       25: 
                     26: extern char vxtype[];
                     27: extern char vxbbno;
                     28: extern char vxbopno[];
                     29: 
                     30: #if defined(NVSNA) | defined(NSD)
                     31: extern vbrall();
                     32: #else
                     33: vbrall() {};
                     34: #endif
                     35: 
                     36: /*
                     37:  *  Write a command out to the VIOC
                     38:  */
                     39: vcmd(n, cmdad)
1.1.1.2 ! root       40: register int n;
        !            41: register caddr_t cmdad;                /* command address */
1.1       root       42: {
1.1.1.2 ! root       43:        register struct vcmds *cp;
1.1       root       44:        register struct vcx *xp;
1.1.1.2 ! root       45:        int s;
1.1       root       46: 
1.1.1.2 ! root       47:        s = spl8();
        !            48:        cp = &v_cmds[n];
1.1       root       49:        xp = &vcx[n];
1.1.1.2 ! root       50: 
1.1       root       51:        if (xp->v_state&V_RESETTING && cmdad != NULL) {
                     52:                /*
                     53:                 * When the vioc is resetting, don't process
                     54:                 * anything other than LIDENT commands.
                     55:                 */
                     56:                register struct vxcmd *cp = (struct vxcmd *)
                     57:                                ((char *)cmdad - sizeof(cp->c_fwd));
                     58:                if (cp->cmd != LIDENT) {
                     59:                        vrelease(xp, cp);
                     60:                        return(0);
                     61:                }
                     62:        }
                     63:        if (cmdad != (caddr_t) 0) {
1.1.1.2 ! root       64:                cp->cmdbuf[cp->v_fill] = cmdad;
        !            65:                if (++cp->v_fill >= VC_CMDBUFL)
        !            66:                        cp->v_fill = 0;
        !            67:                if (cp->v_fill == cp->v_empty) {
        !            68:                        vpanic("vc: CMD Q OVFLO");
1.1       root       69:                        vxstreset(n);
                     70:                        splx(s);
                     71:                        return(0);
                     72:                }
                     73:                cp->v_cmdsem++;
                     74:        }
1.1.1.2 ! root       75:        if (cp->v_cmdsem && cp->v_curcnt < vcx[n].v_maxcmd) {
1.1       root       76:                cp->v_cmdsem--;
                     77:                cp->v_curcnt++;
1.1.1.2 ! root       78:                vinthandl(n, ((V_BSY | CMDquals) << 8) | V_INTR);
1.1       root       79:        }
1.1.1.2 ! root       80:        splx(s);
        !            81:        return(1);
1.1       root       82: }
                     83: 
                     84: /*
                     85:  * VIOC acknowledge interrupt.  The VIOC has received the new
                     86:  * command.  If no errors, the new command becomes one of 16 (max)
                     87:  * current commands being executed.
                     88:  */
                     89: vackint(n)
1.1.1.2 ! root       90: register int n;                /* VIOC number */
1.1       root       91: {
1.1.1.2 ! root       92:        register struct vblok   *vp;
        !            93:        register struct vcmds   *cp;
        !            94:        register int s;
1.1       root       95: 
                     96: #ifdef VXPERF
                     97:        scope_out(5);
                     98: #endif VXPERF
1.1.1.2 ! root       99: 
        !           100:        if (vxtype[n]) {        /* It is a BOP */
        !           101:                vbrall(n);      /* Int. from BOP, port 0 */
1.1       root      102:                return;
                    103:        }
1.1.1.2 ! root      104: 
1.1       root      105:        s = spl8();
1.1.1.2 ! root      106:        vp = VBAS(n);
        !           107:        cp = &v_cmds[n];
        !           108:        if (vp->v_vcid&V_ERR) {
1.1       root      109:                register char *resp;
                    110:                register i;
1.1.1.2 ! root      111:                printf("INTR ERR type = %x VIOC = %x\n", vp->v_vcid&07, n);
        !           112:                resp = (char *)vp + (vp->v_rspoff&0x7FFF);
        !           113:                for (i = 0; i < 16; i++)
1.1       root      114:                        printf("%x ", resp[i]&0xff);
1.1.1.2 ! root      115:                vpanic("\nvcc: vackint");
1.1       root      116:                vxstreset(n);
1.1.1.2 ! root      117:                splx(s);
        !           118:                return;
1.1       root      119:        }
1.1.1.2 ! root      120:        if ((vp->v_hdwre&017) == CMDquals)  {
        !           121:                cp->v_curcmd[vp->v_vcid&VCMDLEN-1] = cp->cmdbuf[cp->v_empty];
        !           122:                if (++cp->v_empty >= VC_CMDBUFL)
        !           123:                        cp->v_empty = 0;
        !           124:        }
        !           125:        if (++cp->v_itrempt >= VC_IQLEN)
        !           126:                cp->v_itrempt = 0;
        !           127:        vintempt(n);
1.1       root      128:        splx(s);
                    129:        vcmd(n, 0);     /* queue next cmd, if any */
                    130: }
                    131: 
                    132: /*
                    133:  *  Command Response interrupt.  The Vioc has completed
                    134:  *  a command.  The command may now be returned to
                    135:  *  the appropriate device driver .
                    136:  */
                    137: vcmdrsp(n)
1.1.1.2 ! root      138: register int n;
1.1       root      139: {
1.1.1.2 ! root      140:        register struct vblok *vp;
        !           141:        register struct vcmds *cp;
        !           142:        register caddr_t cmd;
        !           143:        register char *resp;
        !           144:        register int k, s;
1.1       root      145: 
                    146: #ifdef VXPERF
                    147:        scope_out(6);
                    148: #endif VXPERF
1.1.1.2 ! root      149: 
1.1       root      150:        if (vxtype[n]) {        /* Its a BOP */
1.1.1.2 ! root      151:                printf("vcmdrsp: stray interrupt from BOP at VIOC%d...\n", n);
1.1       root      152:                return;
                    153:        }
                    154:        s = spl8();
1.1.1.2 ! root      155:        vp = VBAS(n);
        !           156: 
        !           157:        cp = &v_cmds[n];
1.1       root      158:        resp = (char *)vp;
1.1.1.2 ! root      159:        resp += vp->v_rspoff&0x7FFF;
1.1       root      160: 
                    161:        if (
                    162: #if VX_TESTING
1.1.1.2 ! root      163:           (vx_test&VX_CMDRESP_DEBUG) == 0 &&
1.1       root      164: #endif
1.1.1.2 ! root      165:           (k=resp[1])&V_UNBSY)  {
1.1       root      166:                k &= VCMDLEN-1;
                    167:                cmd = cp->v_curcmd[k];
                    168:                cp->v_curcmd[k] = (caddr_t)0;
                    169:                cp->v_curcnt--;
                    170:                k = *((short *)&resp[4]);       /* cmd operation code */
1.1.1.2 ! root      171:                if ((k&0xFF00) == LIDENT) {     /* want hiport number */
        !           172:                        for (k = 0; k < VRESPLEN; k++)
1.1       root      173:                                cmd[k] = resp[k+4];
                    174:                }
                    175:                resp[1] = 0;
1.1.1.2 ! root      176:                vxxint(n, cmd);
1.1       root      177:        }
                    178:        else {
1.1.1.2 ! root      179:                vpanic("vc, cmdresp debug");
1.1       root      180:                vxstreset(n);
1.1.1.2 ! root      181:                splx(s);
1.1       root      182:                return;
                    183:        }
                    184: 
1.1.1.2 ! root      185:        vinthandl(n, ((V_BSY | RSPquals) << 8) | V_INTR);
1.1       root      186:        splx(s);
                    187: 
                    188: }
                    189: 
                    190: /*
                    191:  * Unsolicited interrupt.
                    192:  */
                    193: vunsol(n)
1.1.1.2 ! root      194: register int n;
1.1       root      195: {
1.1.1.2 ! root      196:        register struct vblok *vp;
        !           197:        register int s;
1.1       root      198: 
                    199: #ifdef VXPERF
                    200:        scope_out(1);
                    201: #endif VXPERF
1.1.1.2 ! root      202: 
1.1       root      203:        if (vxtype[n]) {        /* Its a BOP */
1.1.1.2 ! root      204:                printf("vunsol: stray interrupt from BOP at VIOC%d...\n", n);
1.1       root      205:                return;
                    206:        }
                    207:        s = spl8();
1.1.1.2 ! root      208:        vp = VBAS(n);
        !           209:        if (vp == 0) {
        !           210:                printf("vunsol: stray interrupt from VIOC%d...\n", n);
        !           211:                splx(s);
        !           212:                return;
        !           213:        }
        !           214: 
1.1       root      215:        if (
                    216: #if VX_TESTING
                    217:            (vx_test&VX_UNSOL_INT_DEBUG) == 0 &&
                    218: #endif
1.1.1.2 ! root      219:            vp->v_uqual&V_UNBSY) {
1.1       root      220:                if (vxrint(n))
1.1.1.2 ! root      221:                        vinthandl(n, ((V_BSY | UNSquals) << 8) | V_INTR);
1.1       root      222:                splx(s);
                    223:        }
                    224:        else {
1.1.1.2 ! root      225:                vpanic("vc: UNSOL INT ERR");
1.1       root      226:                vxstreset(n);
1.1.1.2 ! root      227:                splx(s);
1.1       root      228:        }
                    229: }
                    230: 
                    231: /*
                    232:  * Enqueue an interrupt
                    233:  */
                    234: vinthandl(n, item)
1.1.1.2 ! root      235: register int n, item;
1.1       root      236: {
1.1.1.2 ! root      237:        register struct vcmds *cp;
        !           238:        register int empflag = 0;
1.1       root      239: 
1.1.1.2 ! root      240:        cp = &v_cmds[n];
        !           241:        if (cp->v_itrfill == cp->v_itrempt)
        !           242:                empflag++;
        !           243:        cp->v_itrqueu[cp->v_itrfill] = item;
        !           244:        if (++cp->v_itrfill >= VC_IQLEN)
        !           245:                cp->v_itrfill = 0;
        !           246:        if (cp->v_itrfill == cp->v_itrempt) {
        !           247:                vpanic("vc: INT Q OVFLO");
1.1       root      248:                vxstreset(n);
1.1.1.2 ! root      249:        } else if (empflag)
        !           250:                vintempt(n);
1.1       root      251: }
                    252: 
                    253: vintempt(n)
1.1.1.2 ! root      254: register int n;
1.1       root      255: {
1.1.1.2 ! root      256:        register struct vcmds *cp;
        !           257:        register struct vblok *vp;
        !           258:        register short item, *intr;
1.1       root      259: 
1.1.1.2 ! root      260:        vp = VBAS(n);
        !           261:        if (vp->v_vioc&V_BSY)
        !           262:                return;
        !           263:        cp = &v_cmds[n];
        !           264:        if (cp->v_itrempt == cp->v_itrfill)
        !           265:                return;
        !           266:        item = cp->v_itrqueu[cp->v_itrempt];
        !           267:        intr = (short *)&vp->v_vioc;
        !           268:        switch ((item >> 8)&03) {
1.1       root      269:        case CMDquals:          /* command */
                    270:                {
                    271:                int phys;
                    272: 
1.1.1.2 ! root      273:                if (cp->v_empty == cp->v_fill || vp->v_vcbsy&V_BSY)
1.1       root      274:                        break;
1.1.1.2 ! root      275:                phys = vtoph(0, cp->cmdbuf[cp->v_empty]); /* should be a sys address */
1.1       root      276:                vp->v_vcp[0] = ((short *)&phys)[0];
                    277:                vp->v_vcp[1] = ((short *)&phys)[1];
1.1.1.2 ! root      278:                vp->v_vcbsy = V_BSY;
        !           279:                *intr = item;
1.1       root      280:                }
                    281: #ifdef VXPERF
                    282:        scope_out(4);
                    283: #endif VXPERF
1.1.1.2 ! root      284:                break;
1.1       root      285: 
                    286:        case RSPquals:          /* command response */
1.1.1.2 ! root      287:                *intr = item;
1.1       root      288: #ifdef VXPERF
                    289:        scope_out(7);
                    290: #endif VXPERF
1.1.1.2 ! root      291:                break;
1.1       root      292: 
                    293:        case UNSquals:          /* unsolicited interrupt */
1.1.1.2 ! root      294:                vp->v_uqual = 0;
        !           295:                *intr = item;
1.1       root      296: #ifdef VXPERF
                    297:        scope_out(2);
                    298: #endif VXPERF
1.1.1.2 ! root      299:                break;
1.1       root      300:        }
                    301: }
                    302: 
1.1.1.2 ! root      303: struct viocdump viocdump;      /* contents of VIOC memory prior to reset */
1.1       root      304: 
                    305: /* start a reset on a vioc after error (hopefully) */
                    306: vxstreset(n)
1.1.1.2 ! root      307: register int n;
1.1       root      308: {
                    309:        register struct vcx *xp;
1.1.1.2 ! root      310:        register struct vblok *vp;
1.1       root      311:        register struct vxcmd *cp;
1.1.1.2 ! root      312:        register short *src, *dst, *end;
1.1       root      313:        register int j;
                    314:        extern int vxinreset();
1.1.1.2 ! root      315:        int s;
1.1       root      316: 
1.1.1.2 ! root      317:        s = spl8();
1.1       root      318:        vp = VBAS(n);
                    319:        xp = &vcx[n];
                    320: 
                    321: #if VX_TESTING
                    322:        vx_test = 0;
                    323: #endif
1.1.1.2 ! root      324:        if (xp->v_state&V_RESETTING) {
1.1       root      325:                /*
                    326:                 * Avoid infinite recursion.
                    327:                 */
1.1.1.2 ! root      328:                splx(s);
1.1       root      329:                return;
1.1.1.2 ! root      330:        }
        !           331: 
        !           332:        /*
        !           333:         * Dump the VIOC memory -- important we do it as shorts.
        !           334:         */
        !           335:        src = (short *)vp;
        !           336:        dst = (short *)viocdump.vxcore;
        !           337:        end = (short *)((char *)viocdump.vxcore + sizeof(viocdump.vxcore));
        !           338:        while (dst < end)
        !           339:                *dst++ = *src++;
        !           340: 
        !           341:        /*
        !           342:         * Note the time so we may correlate console messages
        !           343:         * with the vioc dump.
        !           344:         */
        !           345:        viocdump.vxtime = time.tv_sec;
        !           346:        viocdump.vxn = n;
        !           347:        viocdump.vxmagic = VIOCDMAGIC;
1.1       root      348: 
                    349:        /*
                    350:         * Zero out the vioc structures, mark the vioc as being
                    351:         * reset, reinitialize the free command list, reset the vioc
                    352:         * and start a timer to check on the progress of the reset.
                    353:         */
                    354:        bzero(&v_cmds[n], sizeof(struct vcmds));
                    355:        bzero(xp, sizeof(struct vcx));
                    356: 
                    357:        /*
                    358:         * Setting V_RESETTING prevents others from issuing
                    359:         * commands while allowing currently queued commands to
                    360:         * be passed to the VIOC.
                    361:         */
                    362:        xp->v_state |= V_RESETTING;
1.1.1.2 ! root      363:        for (j = 0; j < NVCXBUFS; j++) {/* init all cmd buffers */
1.1       root      364:                cp = &xp->vx_lst[j];    /* index a buffer */
                    365:                cp->c_fwd = &xp->vx_lst[j+1];   /* point to next buf */
                    366:        }
                    367:        xp->vx_avail = &xp->vx_lst[0];  /* set idx to 1st free buf */
                    368:        cp->c_fwd = (struct vxcmd *)0;  /* mark last buf in free list */
                    369: 
1.1.1.2 ! root      370:        printf("resetting VIOC %x at %x .. ", n, viocdump.vxtime);
1.1       root      371: 
1.1.1.2 ! root      372:        vp->v_fault = 0;
        !           373:        vp->v_vioc = V_BSY;
        !           374:        vp->v_hdwre = V_RESET;          /* reset interrupt */
1.1       root      375: 
                    376:        timeout(vxinreset, (caddr_t)n, hz*5);
                    377:        splx(s);
                    378:        return;
                    379: }
                    380: 
                    381: /* continue processing a reset on a vioc after an error (hopefully) */
                    382: vxinreset(vioc)
                    383: caddr_t vioc;
                    384: {
                    385:        register struct vcx *xp;
1.1.1.2 ! root      386:        register struct vblok *vp;
1.1       root      387:        register int n = (int)vioc;
                    388:        int s = spl8();
                    389: 
                    390:        vp = VBAS(n);
                    391:        xp = &vcx[n];
                    392: 
                    393:        /*
                    394:         * See if the vioc has reset.
                    395:         */
                    396:        if (vp->v_fault != VREADY) {
                    397:                printf("failed\n");
                    398:                splx(s);
                    399:                return;
                    400:        }
                    401: 
                    402:        /*
                    403:         * Send a LIDENT to the vioc and mess with carrier flags
                    404:         * on parallel printer ports.
                    405:         */
                    406:        vxinit(n, 0);
                    407:        splx(s);
                    408: }
                    409: 
                    410: /*
                    411:  * Restore modem control, parameters and restart output.
                    412:  */
                    413: /* finish the reset on the vioc after an error (hopefully) */
                    414: vxfnreset(n, cp)
                    415: register int n;
                    416: register struct vxcmd *cp;
                    417: {
                    418:        register struct vcx *xp;
1.1.1.2 ! root      419:        register struct vblok *vp;
        !           420:        register struct tty *tp, *tp0;
1.1       root      421:        register int i;
                    422:        register int on;
                    423:        int s = spl8();
                    424: 
                    425:        vp = VBAS(n);
                    426:        xp = &vcx[n];
                    427: 
                    428:        xp->v_loport = cp->par[5];      /* save low port number */
1.1.1.2 ! root      429:        xp->v_hiport = cp->par[7];      /* VIOC knows high port numbr */
        !           430:        vrelease(xp, cp);               /* done with this control block */
        !           431:        xp->v_nbr = n;                  /* assign VIOC-X board number */
1.1       root      432: 
                    433:        xp->v_state &= ~V_RESETTING;
                    434:        vp->v_vcid = 0;
                    435: 
                    436:        /*
1.1.1.2 ! root      437:         * Wakeup up anyone waiting for the reset (LIDENT) to complete.
        !           438:         */
        !           439:        wakeup((caddr_t)&xp->v_state);
        !           440: 
        !           441:        /*
1.1       root      442:         * Restore modem information and control.
                    443:         */
1.1.1.2 ! root      444:        tp0 = &vx_tty[n<<4];
        !           445:        for (i = xp->v_loport; i <= xp->v_hiport; i++) {
        !           446:                tp = tp0 + i;
        !           447:                if ((tp->t_state&(TS_ISOPEN|TS_WOPEN)) == 0)
        !           448:                        /*
        !           449:                         * Nobody cares about this line.
        !           450:                         */
        !           451:                        continue;
        !           452:                /*
        !           453:                 * Reset modem signals and set parameters
        !           454:                 */
        !           455:                tp->t_state &= ~TS_CARR_ON;
        !           456:                vcmodem(tp->t_dev, VMOD_ON);
        !           457:                vxcparam(tp->t_dev, 0);
        !           458: 
1.1       root      459:                /*
                    460:                 * If carrier has changed while we were resetting,
                    461:                 * take appropriate action.
                    462:                 */
1.1.1.2 ! root      463:                on = vp->v_dcd&1<<i;
        !           464:                if (on && (tp->t_state&TS_CARR_ON) == 0)  {
        !           465:                        /*
        !           466:                         * Carrier has come on.
        !           467:                         */
        !           468:                        tp->t_state |= TS_CARR_ON;
        !           469:                        wakeup((caddr_t)&tp->t_canq);
1.1       root      470:                } else if (!on && tp->t_state&TS_CARR_ON) {
1.1.1.2 ! root      471:                        /*
        !           472:                         * Carrier has gone off.
        !           473:                         */
        !           474:                        tp->t_state &= ~TS_CARR_ON;
        !           475:                        if (tp->t_state&TS_ISOPEN) {
1.1       root      476:                                ttyflush(tp, FREAD|FWRITE);
1.1.1.2 ! root      477:                                if (tp->t_state&TS_FLUSH)
        !           478:                                        wakeup((caddr_t)&tp->t_state);
        !           479:                                if ((tp->t_flags&NOHANG)==0) {
        !           480:                                        gsignal(tp->t_pgrp, SIGHUP);
1.1       root      481:                                        gsignal(tp->t_pgrp, SIGCONT);
                    482:                                }
                    483:                        }
                    484:                }
                    485: 
1.1.1.2 ! root      486:                /*
        !           487:                 * If anyone is awaiting a transmission interrupt,
        !           488:                 * wake them up.
        !           489:                 */
        !           490:                if (tp->t_state&TS_ASLEEP) {
        !           491:                        tp->t_state &= ~TS_ASLEEP;
        !           492:                        wakeup((caddr_t)&tp->t_outq);
1.1       root      493:                }
                    494: 
1.1.1.2 ! root      495:                /*
        !           496:                 * Restart pending output.
        !           497:                 */
        !           498:                tp->t_state &= ~(TS_BUSY|TS_TIMEOUT);
        !           499:                if (tp->t_state&(TS_ISOPEN|TS_WOPEN))
        !           500:                        vxstart(tp);
        !           501:        }
        !           502:        printf("done\n");
1.1       root      503:        splx(s);
                    504: }
                    505: 
                    506: vxreset(dev)
                    507: dev_t dev;
                    508: {
                    509:        vxstreset(minor(dev)>>4);       /* completes asynchronously */
                    510: }
                    511: 
                    512: vxfreset(n)
                    513: register int n;
                    514: {
                    515:        register struct vblok *vp;
                    516: 
                    517:        if (n < 0 || n > NVX || VBAS(n) == NULL)
                    518:                return(ENODEV);
                    519:        vcx[n].v_state &= ~V_RESETTING;
                    520:        vxstreset(n);
                    521:        return(0);              /* completes asynchronously */
                    522: }
                    523: #endif

unix.superglobalmegacorp.com

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