Annotation of 43BSDReno/sys/vaxuba/uu.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)uu.c        7.4 (Berkeley) 4/3/90
                      7:  */
                      8: 
                      9: #include "uu.h"
                     10: #if NUU > 0
                     11: /*
                     12:  * TU58 DECtape II/DL11 device driver
                     13:  *
                     14:  * The TU58 is treated as a block device (only).  Error detection and
                     15:  * recovery is not very extensive, but sufficient to handle the most
                     16:  * common errors. It is assumed that the TU58 will follow the RSP 
                     17:  * protocol exactly, very few protocol errors are checked for.  
                     18:  *
                     19:  * To reduce interrupt latency, `options UUDMA' should be specified 
                     20:  * in the config file to make sure the `pseudo-DMA' code in locore.s
                     21:  * will be compiled into the system. Otherwise overrun errors will 
                     22:  * occur frequently (these errors are not reported).
                     23:  *
                     24:  * TODO:
                     25:  *
                     26:  * - Add ioctl code to wind/rewind cassette
                     27:  *
                     28:  */
                     29: 
                     30: #include "machine/pte.h"
                     31: 
                     32: #include "param.h"
                     33: #include "systm.h"
                     34: #include "buf.h"
                     35: #include "conf.h"
                     36: #include "time.h"
                     37: #include "kernel.h"
                     38: #include "errno.h"
                     39: #include "file.h"
                     40: 
                     41: #include "../vax/cpu.h"
                     42: #include "../vax/nexus.h"
                     43: #include "../vax/rsp.h"
                     44: 
                     45: #include "ubavar.h"
                     46: #include "ubareg.h"
                     47: #include "uureg.h"
                     48: 
                     49: #define        NTUBLK  512             /* number of blocks on a TU58 cassette */
                     50: #define        WRV     01              /* bit in minor dev => write w. read verify */
                     51: #define        NDPC    02              /* drives per controller */
                     52: #define        NUX     NDPC * NUU      /* number of drives */
                     53: #define        NUUQ    02              /* # of block which can be queued up */
                     54: #define        UMASK   01              /* unit number mask */
                     55: #define UUIPL  0x14            /* ipl level to use */
                     56: 
                     57: struct packet uucmd[NUU];      /* a command sent to the TU58 */
                     58: struct packet uudata[NUU];     /* a command or data returned from TU58 */
                     59: struct buf uitab[NUU];         /* buffer queue headers */
                     60: 
                     61: /*
                     62:  * Driver soft carrier structure
                     63:  */
                     64: struct uu_softc {
                     65:        u_char  *tu_rbptr;      /* pointer to buffer for read */
                     66:        int     tu_rcnt;        /* how much to read */
                     67:        u_char  *tu_wbptr;      /* pointer to buffer for write */
                     68:        int     tu_wcnt;        /* how much to write */
                     69:        int     tu_state;       /* current state of tansfer operation */
                     70:        int     tu_flag;        /* read in progress flag */
                     71:        char    *tu_addr;       /* real buffer data address */
                     72:        int     tu_count;       /* real requested count */
                     73:        int     tu_serrs;       /* count of soft errors */
                     74:        int     tu_cerrs;       /* count of checksum errors */
                     75:        int     tu_herrs;       /* count of hard errors */
                     76:        char    tu_dopen[2];    /* drive is open */
                     77: } uu_softc[NUU];
                     78: 
                     79: #if defined(VAX750) || defined(VAX730)
                     80: extern char *tustates[];
                     81: #else
                     82: char *tustates[TUS_NSTATES] = {
                     83:        "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
                     84:        "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR"
                     85: };
                     86: #endif
                     87: 
                     88: #define        UNIT(dev)       (minor(dev)>>1)
                     89: 
                     90: u_char uunull[2] = { 0, 0 };           /* nulls to send for initialization */
                     91: u_char uuinit[2] = { TUF_INITF, TUF_INITF };   /* inits to send */
                     92: 
                     93: struct uba_device      *uudinfo[NUU];
                     94: 
                     95: int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch();
                     96: u_short uustd[] = { 0176500, 0 };
                     97: struct uba_driver uudriver =
                     98:     { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo };
                     99: 
                    100: int    uuwstart;
                    101: int    uuwake();
                    102: static char uu_pcnt[NUX];              /* pee/vee counters, one per drive */
                    103: 
                    104: /*ARGSUSED*/
                    105: uuprobe(reg)
                    106:        caddr_t reg;
                    107: {
                    108:        register int br, cvec;                  /* value result */
                    109:        struct uudevice *uuaddr = (struct uudevice *)reg;
                    110: 
                    111: #ifdef lint
                    112:        br = 0; cvec = br; br = cvec;
                    113:        uurintr(0); uuxintr(0);
                    114: #endif
                    115:        uuaddr->tcs = UUCS_INTR;
                    116:        DELAY(1000);
                    117:        uuaddr->tcs = 0;
                    118:        cvec -= 4;              /* since we are using the xmitter intrpt */
                    119:        return(sizeof (*uuaddr));
                    120: }
                    121: 
                    122: uuattach(ui)
                    123:        register struct uba_device *ui;
                    124: {
                    125: }
                    126: 
                    127: /*ARGSUSED1*/
                    128: uuopen(dev, flag)
                    129:        dev_t dev;
                    130:        int flag;       
                    131: {
                    132:        register struct uba_device *ui;
                    133:        register struct uu_softc *uuc;
                    134:        register struct uudevice *uuaddr;
                    135:        int ctlr, unit = UNIT(dev), s, error;
                    136: 
                    137:        ctlr = unit / NDPC;
                    138:        if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0)
                    139:                return (ENXIO);
                    140:        uuc = &uu_softc[ctlr];
                    141:        if (uuc->tu_dopen[unit&UMASK])
                    142:                return (EBUSY);
                    143:        if (uuwstart++ == 0)
                    144:                timeout(uuwatch, (caddr_t)0, hz);
                    145: 
                    146:        uuc->tu_dopen[unit&UMASK]++;
                    147:        uuaddr = (struct uudevice *)ui->ui_addr;
                    148:        s = splx(UUIPL);
                    149:        /*
                    150:         * If the other device on this controller
                    151:         * is already active, no need to initialize
                    152:         */
                    153:        if (uuc->tu_dopen[0] && uuc->tu_dopen[1])
                    154:                goto ok;
                    155: 
                    156:        /*
                    157:         * If the unit already initialized,
                    158:         * just enable interrupts and return.
                    159:         */
                    160:        if (uuc->tu_state == TUS_IDLE) {
                    161:                uuaddr->rcs = UUCS_INTR;
                    162:                goto ok;
                    163:        }
                    164: 
                    165:        /* 
                    166:         * Must initialize, reset the cassette
                    167:         * and wait for things to settle down.
                    168:         */
                    169:        uureset(ctlr);
                    170:        if (error = tsleep((caddr_t)uuc, (PZERO+1) | PCATCH, devopn, 0)) {
                    171:                splx(s);
                    172:                return (error);
                    173:        }
                    174:        uitab[ctlr].b_active = NULL;
                    175:        if (uuc->tu_state != TUS_IDLE) {
                    176:                uuc->tu_state = TUS_INIT1;
                    177:                uuc->tu_dopen[unit&UMASK] = 0;
                    178:                uuc->tu_rcnt = uuc->tu_wcnt = 0;
                    179:                uuaddr->rcs = 0;
                    180:                uuaddr->tcs = 0;
                    181:                splx(s);
                    182:                return (EIO);
                    183:        }
                    184: ok:
                    185:        splx(s);
                    186:        return (0);
                    187: }
                    188: 
                    189: /*
                    190:  * Wait for all outstanding IO on this drive
                    191:  * complete, before closing. If both drives on
                    192:  * this controller are idle, mark the controller
                    193:  * `inactive'.
                    194:  */
                    195: 
                    196: uuclose(dev, flag)
                    197:        dev_t dev;
                    198:        int flag;
                    199: {
                    200:        int s, unit = UNIT(dev);
                    201:        register struct uu_softc *uuc = &uu_softc[unit/NDPC];
                    202:        struct buf *bp, *last = NULL;
                    203:        struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr;
                    204: 
                    205:        s = splx(UUIPL);
                    206:        while (uu_pcnt[unit])
                    207:                sleep(&uu_pcnt[unit], PRIBIO);
                    208:        /*
                    209:         * No more writes are pending, scan the 
                    210:         * buffer queue for oustanding reads from
                    211:         * this unit.
                    212:         */
                    213:        for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) {
                    214:                if (bp->b_dev == dev)
                    215:                        last = bp;
                    216:        }
                    217:        if (last) {
                    218:                last->b_flags |= B_CALL;
                    219:                last->b_iodone = uuwake;
                    220:                sleep((caddr_t)last, PRIBIO);
                    221:        }
                    222:        uuc->tu_dopen[unit&UMASK] = 0;
                    223:        if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) {
                    224:                uuc->tu_flag = 0;
                    225:                uuaddr->rcs = 0;
                    226:        }
                    227:        splx(s);
                    228:        return (0);
                    229: }
                    230: 
                    231: uuwake(bp)
                    232:        struct buf *bp;
                    233: {
                    234:        wakeup(bp);
                    235: }
                    236: 
                    237: uureset(ctlr)
                    238:        int ctlr;
                    239: {
                    240:        register struct uu_softc *uuc = &uu_softc[ctlr];
                    241:        register struct packet *cmd = &uucmd[ctlr];
                    242:        struct uba_device *ui = uudinfo[ctlr];
                    243:        register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
                    244: 
                    245:        uitab[ctlr].b_active++;
                    246:        uuc->tu_state = TUS_INIT1;
                    247:        uuc->tu_wbptr = uunull;
                    248:        uuc->tu_wcnt = sizeof (uunull);
                    249:        uuc->tu_rcnt = 0;
                    250:        cmd->pk_flag = TUF_CMD;
                    251:        cmd->pk_mcount = sizeof (*cmd) - 4;
                    252:        cmd->pk_mod = 0;
                    253:        cmd->pk_seq = 0;
                    254:        cmd->pk_sw = 0;
                    255:        uuaddr->rcs = 0;
                    256:        uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
                    257:        uuxintr(ctlr);                          /* start output */
                    258: }
                    259: 
                    260: /*
                    261:  * Strategy routine for block I/O
                    262:  */
                    263: uustrategy(bp)
                    264:        register struct buf *bp;
                    265: {
                    266:        register struct buf *uutab;
                    267:        struct uba_device *ui;
                    268:        int s, unit = UNIT(bp->b_dev);
                    269: 
                    270:        if ((unit > NUX) || (bp->b_blkno >= NTUBLK))
                    271:                goto bad;
                    272:        ui = uudinfo[unit/NDPC];
                    273:        if (ui == 0 || ui->ui_alive == 0)
                    274:                goto bad;
                    275:        uutab = &uitab[unit/NDPC];      /* one request queue per controller */
                    276:        s = splx(UUIPL);
                    277:        if ((bp->b_flags&B_READ) == 0)
                    278:                tu_pee(&uu_pcnt[unit]);
                    279:        bp->b_actf = NULL;
                    280:        if (uutab->b_actf == NULL)
                    281:                uutab->b_actf = bp;
                    282:        else
                    283:                uutab->b_actl->b_actf = bp;
                    284:        uutab->b_actl = bp;
                    285:        if (uutab->b_active == 0)
                    286:                uustart(ui);
                    287:        splx(s);
                    288:        return;
                    289: 
                    290: bad:
                    291:        bp->b_flags |= B_ERROR;
                    292:        bp->b_error = ENXIO;
                    293:        iodone(bp);
                    294:        return;
                    295: }
                    296: 
                    297: /*
                    298:  * Start the transfer
                    299:  */
                    300: uustart(ui)
                    301:        register struct uba_device *ui;
                    302: {
                    303:        register struct buf *bp;
                    304:        register struct uu_softc *uuc;
                    305:        struct packet *cmd;
                    306:        int ctlr = ui->ui_unit, s;
                    307: 
                    308:        if ((bp = uitab[ctlr].b_actf) == NULL)
                    309:                return;
                    310:        s = splx(UUIPL);
                    311:        uuc = &uu_softc[ctlr];
                    312:        if (uuc->tu_state != TUS_IDLE) {
                    313:                uureset(ctlr);
                    314:                splx(s);
                    315:                return;
                    316:        }
                    317:        cmd = &uucmd[ctlr];
                    318:        uitab[ctlr].b_active++;
                    319:        uitab[ctlr].b_errcnt = 0;
                    320:        uuc->tu_addr = bp->b_un.b_addr;
                    321:        uuc->tu_count = cmd->pk_count = bp->b_bcount;
                    322:        cmd->pk_block = bp->b_blkno;
                    323:        if (bp->b_flags&B_READ) {
                    324:                cmd->pk_op = TUOP_READ;
                    325:                cmd->pk_mod = 0;
                    326:                uuc->tu_state = TUS_SENDR;
                    327:        } else {
                    328:                cmd->pk_op = TUOP_WRITE;
                    329:                cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
                    330:                uuc->tu_state = TUS_SENDW;
                    331:        }
                    332:        cmd->pk_unit = UNIT(bp->b_dev)&UMASK;
                    333:        cmd->pk_sw = 0;
                    334:        cmd->pk_chksum =
                    335:            tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
                    336:        uuc->tu_wbptr = (u_char *)cmd;
                    337:        uuc->tu_wcnt = sizeof (*cmd);
                    338:        uuxintr(ctlr);
                    339:        splx(s);
                    340: }
                    341: 
                    342: /*
                    343:  * TU58 receiver interrupt, handles whatever condition the
                    344:  * pseudo DMA routine in locore is unable to handle, 
                    345:  * or, if UUDMA is undefined, handle all receiver interrupt
                    346:  * processing.
                    347:  */
                    348: uurintr(ctlr)
                    349:        int ctlr;
                    350: {
                    351:        struct uba_device *ui = uudinfo[ctlr];
                    352:        register struct uu_softc *uuc = &uu_softc[ctlr];
                    353:        register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
                    354:        register struct buf *uutab = &uitab[ctlr];
                    355:        struct packet *data, *cmd;
                    356:        struct buf *bp;
                    357:        int c, unit;
                    358: 
                    359:        c = uuaddr->rdb;
                    360:        data = &uudata[ctlr];
                    361:        cmd = &uucmd[ctlr];
                    362: #if !defined(UUDMA)
                    363:        if (c & UURDB_ERROR)
                    364:                uuc->tu_state = TUS_RCVERR;
                    365:        else {
                    366:                if (uuc->tu_rcnt) {
                    367:                        *uuc->tu_rbptr++ = c;
                    368:                        if (--uuc->tu_rcnt)
                    369:                                return;
                    370:                }
                    371:        }
                    372: #endif
                    373: 
                    374:        /*
                    375:         * Switch on the tu_state of the transfer.
                    376:         */
                    377:        switch(uuc->tu_state) {
                    378: 
                    379:        /*
                    380:         * A data error occured in uudma
                    381:         * (either overrun or break)
                    382:         */
                    383:        case TUS_RCVERR:
                    384:                if ((c & UURDB_ORUN) == 0)
                    385:                        printf("uu%d: break received, transfer restarted\n",
                    386:                            data->pk_unit);
                    387: #ifdef UUDEBUG
                    388:                else
                    389:                        printf("uu%d: data overrun, recovered\n", 
                    390:                            data->pk_unit);
                    391: #endif
                    392:                uuc->tu_serrs++;
                    393:                uu_restart(ctlr, ui);   
                    394:                break;
                    395: 
                    396:        /*
                    397:         * If we get an unexpected "continue",
                    398:         * start all over again...
                    399:         */
                    400:        case TUS_INIT2:
                    401:                uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
                    402:                uuc->tu_flag = 0;
                    403:                wakeup((caddr_t)uuc);
                    404:                uustart(ui);
                    405:                break;
                    406: 
                    407:        /*
                    408:         * Only transition from this state
                    409:         * is on a "continue", so if we don't
                    410:         * get it, reset the world.
                    411:         */
                    412:        case TUS_WAIT:                  /* waiting for continue */
                    413:                switch(c) {
                    414:                case TUF_CONT:  /* got the expected continue */
                    415:                        uuc->tu_flag = 0;
                    416:                        data->pk_flag = TUF_DATA;
                    417:                        data->pk_mcount = MIN(128, uuc->tu_count);
                    418:                        data->pk_chksum =
                    419:                            tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
                    420:                                (int)data->pk_mcount);
                    421:                        uuc->tu_state = TUS_SENDH;
                    422:                        uuc->tu_wbptr = (u_char *)data;
                    423:                        uuc->tu_wcnt = 2;
                    424:                        uuxintr(ctlr);
                    425:                        break;
                    426: 
                    427:                case TUF_CMD:   /* sending us an END packet...error */
                    428:                        uuc->tu_state = TUS_GET;
                    429:                        uuc->tu_rbptr = (u_char *)data;
                    430:                        uuc->tu_rcnt = sizeof (*data) - 1;
                    431:                        uuc->tu_flag = 1;
                    432:                        uuaddr->tcs = 0;
                    433:                        *uuc->tu_rbptr++ = c & UUDB_DMASK;
                    434:                        break;
                    435: 
                    436:                case TUF_INITF:
                    437:                        uureset(ctlr);
                    438:                        break;
                    439: 
                    440:                default:        /* something random...bad news */
                    441:                        uuc->tu_state = TUS_INIT1;
                    442:                        break;
                    443:                }
                    444:                break;
                    445: 
                    446:        case TUS_SENDW:
                    447:                if (c != TUF_CONT && c != TUF_INITF)
                    448:                        goto bad;
                    449:                uu_restart(ctlr, ui);
                    450:                break;
                    451: 
                    452:        /*
                    453:         * Got header, now get data; amount to
                    454:         * fetch is included in packet.
                    455:         * (data packets are handled entirely
                    456:         * in uudma)
                    457:         */
                    458:        case TUS_GETH:
                    459: #ifndef UUDMA
                    460:                if (data->pk_flag == TUF_DATA)
                    461:                        uuc->tu_rbptr = (u_char *)uuc->tu_addr;
                    462: #endif
                    463:                uuc->tu_rcnt = data->pk_mcount;
                    464:                uuc->tu_state = TUS_GETD;
                    465:                break;
                    466: 
                    467:        /*
                    468:         * Got the data, now fetch the checksum.
                    469:         */
                    470:        case TUS_GETD:
                    471:                uuc->tu_rbptr = (u_char *)&data->pk_chksum;
                    472:                uuc->tu_rcnt = sizeof (data->pk_chksum);
                    473:                uuc->tu_state = TUS_GETC;
                    474:                break;
                    475: 
                    476:        case TUS_GETC:
                    477:                /* got entire packet */
                    478:                if (data->pk_chksum !=
                    479:                    tuchk(*((short *)data), (u_short *)
                    480:                     (data->pk_flag == TUF_DATA ?
                    481:                     (u_short *) uuc->tu_addr : (u_short *)&data->pk_op),
                    482:                     (int)data->pk_mcount))
                    483:        case TUS_CHKERR:
                    484:                        uuc->tu_cerrs++;
                    485:        case TUS_GET:
                    486:                if (data->pk_flag == TUF_DATA) {
                    487:                        /* data packet, advance to next */
                    488:                        uuc->tu_addr += data->pk_mcount;
                    489:                        uuc->tu_count -= data->pk_mcount;
                    490:                        uuc->tu_state = TUS_GETH;
                    491:                        uuc->tu_rbptr = (u_char *)data; /* next packet */
                    492:                        uuc->tu_rcnt = 2;
                    493:                } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
                    494:                        /* end packet, idle and reenable transmitter */
                    495:                        uuc->tu_state = TUS_IDLE;
                    496:                        uuc->tu_flag = 0;
                    497:                        uuaddr->tcs = UUCS_INTR;
                    498:                        if ((bp = uutab->b_actf) == NULL) {
                    499:                                printf("uu%d: no bp, active %d\n", 
                    500:                                    data->pk_unit, uitab[ctlr].b_active);
                    501:                                uustart(ui);
                    502:                                return;
                    503:                        }
                    504:                        unit = UNIT(bp->b_dev);
                    505:                        if (data->pk_mod > 1) {        /* hard error */
                    506:                                printf("uu%d: hard error bn%d,", unit, 
                    507:                                    bp->b_blkno);
                    508:                                printf(" pk_mod 0%o\n", data->pk_mod&0xff);
                    509:                                bp->b_flags |= B_ERROR;
                    510:                                uuc->tu_herrs++;
                    511:                        } else if (data->pk_mod)        /* soft error */
                    512:                                uuc->tu_serrs++;
                    513:                        uutab->b_active = NULL;
                    514:                        uutab->b_actf = bp->b_actf;
                    515:                        bp->b_resid = uuc->tu_count;
                    516:                        if ((bp->b_flags&B_READ) == 0)
                    517:                                tu_vee(&uu_pcnt[unit]);
                    518:                        iodone(bp);
                    519:                        uustart(ui);
                    520:                } else {
                    521:                        /*
                    522:                         * Neither data nor end: data was lost
                    523:                         * somehow, flush and restart the transfer.
                    524:                         */
                    525:                        uuaddr->rcs = 0;
                    526:                        uu_restart(ctlr, ui);
                    527:                        uuc->tu_serrs++;
                    528:                }
                    529:                break;
                    530: 
                    531:        case TUS_IDLE:
                    532:        case TUS_INIT1:
                    533:                break;
                    534: 
                    535:        default:
                    536: bad:
                    537:                if (c == TUF_INITF) {
                    538:                        printf("uu%d protocol error, state=", data->pk_unit);
                    539:                        printstate(uuc->tu_state);
                    540:                        printf(", op=%x, cnt=%d, block=%d\n",
                    541:                            cmd->pk_op, cmd->pk_count, cmd->pk_block);
                    542:                        uutab->b_active = NULL;
                    543:                        if (bp = uutab->b_actf) {
                    544:                                bp->b_flags |= B_ERROR;
                    545:                                uutab->b_actf = bp->b_actf;
                    546:                                if ((bp->b_flags&B_READ) == 0)
                    547:                                        tu_vee(&uu_pcnt[unit]);
                    548:                                iodone(bp);
                    549:                        }
                    550:                        uuc->tu_state = TUS_INIT1;
                    551:                } else {
                    552:                        printf("uu%d receive state error, state=", 
                    553:                                data->pk_unit);
                    554:                        printstate(uuc->tu_state);
                    555:                        printf(", byte=%x\n", c & 0xff);
                    556: #ifdef notdef
                    557:                        uuc->tu_state = TUS_INIT1;
                    558: #endif
                    559:                        wakeup((caddr_t)uuc);
                    560:                }
                    561:        }
                    562: }
                    563: 
                    564: 
                    565: /*
                    566:  * TU58 transmitter interrupt
                    567:  */
                    568: uuxintr(ctlr)
                    569:        int ctlr;
                    570: {
                    571:        register struct uu_softc *uuc = &uu_softc[ctlr];
                    572:        register struct uudevice *uuaddr;
                    573:        register struct packet *data;
                    574:        struct uba_device *ui = uudinfo[ctlr];
                    575:        int c;
                    576: 
                    577:        data = &uudata[ctlr];
                    578:        uuaddr = (struct uudevice *) ui->ui_addr;
                    579: top:
                    580:        if (uuc->tu_wcnt > 0) {
                    581:                /* still stuff to send, send one byte */
                    582:                while ((uuaddr->tcs & UUCS_READY) == 0)
                    583:                        ;
                    584:                uuaddr->tdb = *uuc->tu_wbptr++;
                    585:                uuc->tu_wcnt--;
                    586:                return;
                    587:        }
                    588: 
                    589:        /*
                    590:         * Last message byte was sent out.
                    591:         * Switch on tu_state of transfer.
                    592:         */
                    593:        switch(uuc->tu_state) {
                    594: 
                    595:        /*
                    596:         * Two nulls have been sent, remove break, and send inits
                    597:         */
                    598:        case TUS_INIT1: 
                    599:                uuc->tu_flag = 0;
                    600:                uuaddr->tcs = UUCS_INTR;
                    601:                uuc->tu_state = TUS_INIT2;
                    602:                uuc->tu_wbptr = uuinit;
                    603:                uuc->tu_wcnt = sizeof (uuinit);
                    604:                goto top;
                    605: 
                    606:        /*
                    607:         * Inits have been sent, wait for a continue msg.
                    608:         */
                    609:        case TUS_INIT2: 
                    610:                c = uuaddr->rdb;        /* prevent overrun error */
                    611:                uuaddr->rcs = UUCS_INTR;
                    612:                uuc->tu_flag = 1;
                    613:                break;
                    614: 
                    615:        /*
                    616:         * Read cmd packet sent, get ready for data
                    617:         */
                    618:        case TUS_SENDR:
                    619:                uuc->tu_state = TUS_GETH;
                    620:                uuc->tu_rbptr = (u_char *)data;
                    621:                uuc->tu_rcnt = 2;
                    622:                uuc->tu_flag = 1;
                    623:                uuaddr->tcs = 0;
                    624:                uuaddr->rcs = UUCS_INTR;
                    625:                break;
                    626: 
                    627:        /*
                    628:         * Write cmd packet sent, wait for continue
                    629:         */
                    630:        case TUS_SENDW: 
                    631:                uuc->tu_state = TUS_WAIT;
                    632:                uuc->tu_flag = 1;
                    633:                if ((uuaddr->rcs&UUCS_INTR) == 0) {
                    634:                        printf("NO IE\n");
                    635:                        uuaddr->rcs = UUCS_INTR;
                    636:                }
                    637:                break;
                    638: 
                    639:        /*
                    640:         * Header sent, send data.
                    641:         */
                    642:        case TUS_SENDH:
                    643:                uuc->tu_state = TUS_SENDD;
                    644:                uuc->tu_wbptr = (u_char *)uuc->tu_addr;
                    645:                uuc->tu_wcnt = data->pk_mcount;
                    646:                goto top;
                    647: 
                    648:        /*
                    649:         * Data sent, follow with checksum.
                    650:         */
                    651:        case TUS_SENDD: 
                    652:                uuc->tu_state = TUS_SENDC;
                    653:                uuc->tu_wbptr = (u_char *)&data->pk_chksum;
                    654:                uuc->tu_wcnt = 2;
                    655:                goto top;
                    656: 
                    657:        /* 
                    658:         * Checksum sent, wait for continue.
                    659:         */
                    660:        case TUS_SENDC:
                    661:                /*
                    662:                 * Update buffer address and count.
                    663:                 */
                    664:                uuc->tu_addr += data->pk_mcount;
                    665:                uuc->tu_count -= data->pk_mcount;
                    666:                if (uuc->tu_count > 0) {
                    667:                        uuc->tu_state = TUS_WAIT;
                    668:                        uuc->tu_flag = 1;
                    669:                        break;
                    670:                }
                    671: 
                    672:                /*
                    673:                 * End of transmission, get ready for end packet.
                    674:                 */
                    675:                uuc->tu_state = TUS_GET;
                    676:                uuc->tu_rbptr = (u_char *)data;
                    677:                uuc->tu_rcnt = sizeof (*data);
                    678:                uuc->tu_flag = 1;
                    679:                uuaddr->tcs = 0;
                    680:                break;
                    681: 
                    682:        /*
                    683:         * Random interrupt
                    684:         */
                    685:        case TUS_IDLE:          /* stray interrupt? */
                    686: 
                    687:        default:
                    688:                break;
                    689:        }
                    690: }
                    691: 
                    692: uuwatch()
                    693: {
                    694:        register struct uu_softc *uuc;
                    695:        register struct uudevice *uuaddr;
                    696:        struct uba_device *ui;
                    697:        struct buf *bp, *uutab;
                    698:        int s, ctlr, active = 0;
                    699: 
                    700:        for (ctlr=0; ctlr<NUU; ctlr++) {
                    701:                int i;
                    702: 
                    703:                uuc = &uu_softc[ctlr];
                    704: 
                    705:                if (uuc->tu_dopen[0] || uuc->tu_dopen[1])
                    706:                        active++;
                    707:                if (uuc->tu_flag == 0)
                    708:                        /*
                    709:                         * If no read is in progress
                    710:                         * just skip
                    711:                         */
                    712:                        continue;
                    713: 
                    714:                ui = uudinfo[ctlr];
                    715:                uuaddr = (struct uudevice *)ui->ui_addr;
                    716:                uutab = &uitab[ctlr];
                    717:                if (uuc->tu_flag++ < 40)
                    718:                        continue;
                    719:                printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);
                    720: #ifdef UUDEBUG
                    721:                printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
                    722:                       uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr,
                    723:                       uuc->tu_count);
                    724: #endif
                    725:                s = splx(UUIPL);
                    726:                uuc->tu_flag = 0;
                    727:                i = uuaddr->rdb;                /* dummy */
                    728:                uuaddr->rcs = UUCS_INTR;        /* in case we were flushing */
                    729:                uuaddr->tcs = UUCS_INTR;
                    730:                uuc->tu_state = TUS_IDLE;
                    731:                if (!uutab->b_active) {
                    732:                        wakeup((caddr_t)uuc);
                    733:                        goto retry;
                    734:                }
                    735:                if (++uutab->b_errcnt <= 1) {
                    736:                        uustart(ui);
                    737:                        goto retry;
                    738:                }
                    739:                if (bp = uutab->b_actf) {
                    740:                        bp->b_flags |= B_ERROR;
                    741:                        if ((bp->b_flags&B_READ) == 0)
                    742:                                tu_vee(&uu_pcnt[UNIT(bp->b_dev)]);
                    743:                        iodone(bp);
                    744:                }
                    745: retry:
                    746:                (void) splx(s);
                    747:        }
                    748:        if (active)
                    749:                timeout(uuwatch, (caddr_t)0, hz);
                    750:        else
                    751:                uuwstart = 0;
                    752:        return;
                    753: }
                    754: 
                    755: #if !defined(VAX750) && !defined(VAX730)
                    756: /*
                    757:  * Compute checksum TU58 fashion
                    758:  */
                    759: #ifdef lint
                    760: tuchk(word, cp, n)
                    761:        register word;
                    762:        register unsigned short *cp;
                    763:        int n;
                    764: {
                    765:        register int c = n >> 1;
                    766:        register long temp;
                    767: 
                    768:        do {
                    769:                temp = *cp++;   /* temp, only because vax cc won't *r++ */
                    770:                word += temp;
                    771:        } while (--c > 0);
                    772:        if (n & 1)
                    773:                word += *(unsigned char *)cp;
                    774:        while (word & 0xffff0000)
                    775:                word = (word & 0xffff) + ((word >> 16) & 0xffff);
                    776:        return (word);
                    777: }
                    778: #else
                    779: tuchk(word0, wp, n)
                    780:        register int word0;                     /* r11 */
                    781:        register char *wp;                      /* r10 */
                    782:        register int n;                         /* r9 */
                    783: {
                    784:        asm("loop:");
                    785:        asm("   addw2   (r10)+,r11");           /* add a word to sum */
                    786:        asm("   adwc    $0,r11");               /* add in carry, end-around */
                    787:        asm("   acbl    $2,$-2,r9,loop");       /* done yet? */
                    788:        asm("   blbc    r9,ok");                /* odd byte count? */
                    789:        asm("   movzbw  (r10),r10");            /* yes, get last byte */
                    790:        asm("   addw2   r10,r11");              /* add it in */
                    791:        asm("   adwc    $0,r11");               /* and the carry */
                    792:        asm("ok:");
                    793:        asm("   movl    r11,r0");               /* return sum */
                    794: }
                    795: #endif
                    796: 
                    797: /*
                    798:  * Make sure this incredibly slow device
                    799:  * doesn't eat up all the buffers in the
                    800:  * system by putting the requesting process
                    801:  * (remember: this device is 'single-user')
                    802:  * to sleep if the write-behind queue grows
                    803:  * larger than NUUQ.
                    804:  */
                    805: tu_pee(cp)
                    806:        char *cp;
                    807: {
                    808:        register int s;
                    809: 
                    810:        s = splx(UUIPL);
                    811:        if (++(*cp) > NUUQ) 
                    812:                sleep(cp, PRIBIO);
                    813:        splx(s);
                    814: }
                    815: 
                    816: tu_vee(cp)
                    817:        char *cp;
                    818: {
                    819:        register int s;
                    820: 
                    821:        s = splx(UUIPL);
                    822:        if (--(*cp) <= NUUQ) 
                    823:                wakeup(cp);
                    824:        splx(s);
                    825: }
                    826: #endif
                    827: 
                    828: uuioctl(dev, cmd, data, flag)
                    829:        dev_t dev;
                    830:        caddr_t data;
                    831: {
                    832:        /*
                    833:         * add code to wind/rewind cassette here
                    834:         */
                    835:        return (ENXIO);
                    836: }
                    837: 
                    838: uu_restart(ctlr, ui)
                    839:        int ctlr;
                    840:        struct uba_device *ui;
                    841: {
                    842:        uureset(ctlr);
                    843:        timeout(uustart, (caddr_t)ui, hz * 3);
                    844: }
                    845: 
                    846: #endif

unix.superglobalmegacorp.com

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