Annotation of 43BSD/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.1 (Berkeley) 6/5/86
                      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;
                    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:        sleep((caddr_t)uuc, PZERO+1);
                    171:        uitab[ctlr].b_active = NULL;
                    172:        if (uuc->tu_state != TUS_IDLE) {
                    173:                uuc->tu_state = TUS_INIT1;
                    174:                uuc->tu_dopen[unit&UMASK] = 0;
                    175:                uuc->tu_rcnt = uuc->tu_wcnt = 0;
                    176:                uuaddr->rcs = 0;
                    177:                uuaddr->tcs = 0;
                    178:                splx(s);
                    179:                return (EIO);
                    180:        }
                    181: ok:
                    182:        splx(s);
                    183:        return (0);
                    184: }
                    185: 
                    186: /*
                    187:  * Wait for all outstanding IO on this drive
                    188:  * complete, before closing. If both drives on
                    189:  * this controller are idle, mark the controller
                    190:  * `inactive'.
                    191:  */
                    192: 
                    193: uuclose(dev, flag)
                    194:        dev_t dev;
                    195:        int flag;
                    196: {
                    197:        int s, unit = UNIT(dev);
                    198:        register struct uu_softc *uuc = &uu_softc[unit/NDPC];
                    199:        struct buf *bp, *last = NULL;
                    200:        struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr;
                    201: 
                    202:        s = splx(UUIPL);
                    203:        while (uu_pcnt[unit])
                    204:                sleep(&uu_pcnt[unit], PRIBIO);
                    205:        /*
                    206:         * No more writes are pending, scan the 
                    207:         * buffer queue for oustanding reads from
                    208:         * this unit.
                    209:         */
                    210:        for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) {
                    211:                if (bp->b_dev == dev)
                    212:                        last = bp;
                    213:        }
                    214:        if (last) {
                    215:                last->b_flags |= B_CALL;
                    216:                last->b_iodone = uuwake;
                    217:                sleep((caddr_t)last, PRIBIO);
                    218:        }
                    219:        uuc->tu_dopen[unit&UMASK] = 0;
                    220:        if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) {
                    221:                uuc->tu_flag = 0;
                    222:                uuaddr->rcs = 0;
                    223:        }
                    224:        splx(s);
                    225: }
                    226: 
                    227: uuwake(bp)
                    228:        struct buf *bp;
                    229: {
                    230:        wakeup(bp);
                    231: }
                    232: 
                    233: uureset(ctlr)
                    234:        int ctlr;
                    235: {
                    236:        register struct uu_softc *uuc = &uu_softc[ctlr];
                    237:        register struct packet *cmd = &uucmd[ctlr];
                    238:        struct uba_device *ui = uudinfo[ctlr];
                    239:        register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
                    240: 
                    241:        uitab[ctlr].b_active++;
                    242:        uuc->tu_state = TUS_INIT1;
                    243:        uuc->tu_wbptr = uunull;
                    244:        uuc->tu_wcnt = sizeof (uunull);
                    245:        uuc->tu_rcnt = 0;
                    246:        cmd->pk_flag = TUF_CMD;
                    247:        cmd->pk_mcount = sizeof (*cmd) - 4;
                    248:        cmd->pk_mod = 0;
                    249:        cmd->pk_seq = 0;
                    250:        cmd->pk_sw = 0;
                    251:        uuaddr->rcs = 0;
                    252:        uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
                    253:        uuxintr(ctlr);                          /* start output */
                    254: }
                    255: 
                    256: /*
                    257:  * Strategy routine for block I/O
                    258:  */
                    259: uustrategy(bp)
                    260:        register struct buf *bp;
                    261: {
                    262:        register struct buf *uutab;
                    263:        struct uba_device *ui;
                    264:        int s, unit = UNIT(bp->b_dev);
                    265: 
                    266:        if ((unit > NUX) || (bp->b_blkno >= NTUBLK))
                    267:                goto bad;
                    268:        ui = uudinfo[unit/NDPC];
                    269:        if (ui == 0 || ui->ui_alive == 0)
                    270:                goto bad;
                    271:        uutab = &uitab[unit/NDPC];      /* one request queue per controller */
                    272:        s = splx(UUIPL);
                    273:        if ((bp->b_flags&B_READ) == 0)
                    274:                tu_pee(&uu_pcnt[unit]);
                    275:        bp->b_actf = NULL;
                    276:        if (uutab->b_actf == NULL)
                    277:                uutab->b_actf = bp;
                    278:        else
                    279:                uutab->b_actl->b_actf = bp;
                    280:        uutab->b_actl = bp;
                    281:        if (uutab->b_active == 0)
                    282:                uustart(ui);
                    283:        splx(s);
                    284:        return;
                    285: 
                    286: bad:
                    287:        bp->b_flags |= B_ERROR;
                    288:        bp->b_error = ENXIO;
                    289:        iodone(bp);
                    290:        return;
                    291: }
                    292: 
                    293: /*
                    294:  * Start the transfer
                    295:  */
                    296: uustart(ui)
                    297:        register struct uba_device *ui;
                    298: {
                    299:        register struct buf *bp;
                    300:        register struct uu_softc *uuc;
                    301:        struct packet *cmd;
                    302:        int ctlr = ui->ui_unit, s;
                    303: 
                    304:        if ((bp = uitab[ctlr].b_actf) == NULL)
                    305:                return;
                    306:        s = splx(UUIPL);
                    307:        uuc = &uu_softc[ctlr];
                    308:        if (uuc->tu_state != TUS_IDLE) {
                    309:                uureset(ctlr);
                    310:                splx(s);
                    311:                return;
                    312:        }
                    313:        cmd = &uucmd[ctlr];
                    314:        uitab[ctlr].b_active++;
                    315:        uitab[ctlr].b_errcnt = 0;
                    316:        uuc->tu_addr = bp->b_un.b_addr;
                    317:        uuc->tu_count = cmd->pk_count = bp->b_bcount;
                    318:        cmd->pk_block = bp->b_blkno;
                    319:        if (bp->b_flags&B_READ) {
                    320:                cmd->pk_op = TUOP_READ;
                    321:                cmd->pk_mod = 0;
                    322:                uuc->tu_state = TUS_SENDR;
                    323:        } else {
                    324:                cmd->pk_op = TUOP_WRITE;
                    325:                cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
                    326:                uuc->tu_state = TUS_SENDW;
                    327:        }
                    328:        cmd->pk_unit = UNIT(bp->b_dev)&UMASK;
                    329:        cmd->pk_sw = 0;
                    330:        cmd->pk_chksum =
                    331:            tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
                    332:        uuc->tu_wbptr = (u_char *)cmd;
                    333:        uuc->tu_wcnt = sizeof (*cmd);
                    334:        uuxintr(ctlr);
                    335:        splx(s);
                    336: }
                    337: 
                    338: /*
                    339:  * TU58 receiver interrupt, handles whatever condition the
                    340:  * pseudo DMA routine in locore is unable to handle, 
                    341:  * or, if UUDMA is undefined, handle all receiver interrupt
                    342:  * processing.
                    343:  */
                    344: uurintr(ctlr)
                    345:        int ctlr;
                    346: {
                    347:        struct uba_device *ui = uudinfo[ctlr];
                    348:        register struct uu_softc *uuc = &uu_softc[ctlr];
                    349:        register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
                    350:        register struct buf *uutab = &uitab[ctlr];
                    351:        struct packet *data, *cmd;
                    352:        struct buf *bp;
                    353:        int c, unit;
                    354: 
                    355:        c = uuaddr->rdb;
                    356:        data = &uudata[ctlr];
                    357:        cmd = &uucmd[ctlr];
                    358: #if !defined(UUDMA)
                    359:        if (c & UURDB_ERROR)
                    360:                uuc->tu_state = TUS_RCVERR;
                    361:        else {
                    362:                if (uuc->tu_rcnt) {
                    363:                        *uuc->tu_rbptr++ = c;
                    364:                        if (--uuc->tu_rcnt)
                    365:                                return;
                    366:                }
                    367:        }
                    368: #endif
                    369: 
                    370:        /*
                    371:         * Switch on the tu_state of the transfer.
                    372:         */
                    373:        switch(uuc->tu_state) {
                    374: 
                    375:        /*
                    376:         * A data error occured in uudma
                    377:         * (either overrun or break)
                    378:         */
                    379:        case TUS_RCVERR:
                    380:                if ((c & UURDB_ORUN) == 0)
                    381:                        printf("uu%d: break received, transfer restarted\n",
                    382:                            data->pk_unit);
                    383: #ifdef UUDEBUG
                    384:                else
                    385:                        printf("uu%d: data overrun, recovered\n", 
                    386:                            data->pk_unit);
                    387: #endif
                    388:                uuc->tu_serrs++;
                    389:                uu_restart(ctlr, ui);   
                    390:                break;
                    391: 
                    392:        /*
                    393:         * If we get an unexpected "continue",
                    394:         * start all over again...
                    395:         */
                    396:        case TUS_INIT2:
                    397:                uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
                    398:                uuc->tu_flag = 0;
                    399:                wakeup((caddr_t)uuc);
                    400:                uustart(ui);
                    401:                break;
                    402: 
                    403:        /*
                    404:         * Only transition from this state
                    405:         * is on a "continue", so if we don't
                    406:         * get it, reset the world.
                    407:         */
                    408:        case TUS_WAIT:                  /* waiting for continue */
                    409:                switch(c) {
                    410:                case TUF_CONT:  /* got the expected continue */
                    411:                        uuc->tu_flag = 0;
                    412:                        data->pk_flag = TUF_DATA;
                    413:                        data->pk_mcount = MIN(128, uuc->tu_count);
                    414:                        data->pk_chksum =
                    415:                            tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
                    416:                                (int)data->pk_mcount);
                    417:                        uuc->tu_state = TUS_SENDH;
                    418:                        uuc->tu_wbptr = (u_char *)data;
                    419:                        uuc->tu_wcnt = 2;
                    420:                        uuxintr(ctlr);
                    421:                        break;
                    422: 
                    423:                case TUF_CMD:   /* sending us an END packet...error */
                    424:                        uuc->tu_state = TUS_GET;
                    425:                        uuc->tu_rbptr = (u_char *)data;
                    426:                        uuc->tu_rcnt = sizeof (*data) - 1;
                    427:                        uuc->tu_flag = 1;
                    428:                        uuaddr->tcs = 0;
                    429:                        *uuc->tu_rbptr++ = c & UUDB_DMASK;
                    430:                        break;
                    431: 
                    432:                case TUF_INITF:
                    433:                        uureset(ctlr);
                    434:                        break;
                    435: 
                    436:                default:        /* something random...bad news */
                    437:                        uuc->tu_state = TUS_INIT1;
                    438:                        break;
                    439:                }
                    440:                break;
                    441: 
                    442:        case TUS_SENDW:
                    443:                if (c != TUF_CONT && c != TUF_INITF)
                    444:                        goto bad;
                    445:                uu_restart(ctlr, ui);
                    446:                break;
                    447: 
                    448:        /*
                    449:         * Got header, now get data; amount to
                    450:         * fetch is included in packet.
                    451:         * (data packets are handled entirely
                    452:         * in uudma)
                    453:         */
                    454:        case TUS_GETH:
                    455: #ifndef UUDMA
                    456:                if (data->pk_flag == TUF_DATA)
                    457:                        uuc->tu_rbptr = (u_char *)uuc->tu_addr;
                    458: #endif
                    459:                uuc->tu_rcnt = data->pk_mcount;
                    460:                uuc->tu_state = TUS_GETD;
                    461:                break;
                    462: 
                    463:        /*
                    464:         * Got the data, now fetch the checksum.
                    465:         */
                    466:        case TUS_GETD:
                    467:                uuc->tu_rbptr = (u_char *)&data->pk_chksum;
                    468:                uuc->tu_rcnt = sizeof (data->pk_chksum);
                    469:                uuc->tu_state = TUS_GETC;
                    470:                break;
                    471: 
                    472:        case TUS_GETC:
                    473:                /* got entire packet */
                    474:                if (data->pk_chksum !=
                    475:                    tuchk(*((short *)data), (u_short *)
                    476:                     (data->pk_flag == TUF_DATA ?
                    477:                     (u_short *) uuc->tu_addr : (u_short *)&data->pk_op),
                    478:                     (int)data->pk_mcount))
                    479:        case TUS_CHKERR:
                    480:                        uuc->tu_cerrs++;
                    481:        case TUS_GET:
                    482:                if (data->pk_flag == TUF_DATA) {
                    483:                        /* data packet, advance to next */
                    484:                        uuc->tu_addr += data->pk_mcount;
                    485:                        uuc->tu_count -= data->pk_mcount;
                    486:                        uuc->tu_state = TUS_GETH;
                    487:                        uuc->tu_rbptr = (u_char *)data; /* next packet */
                    488:                        uuc->tu_rcnt = 2;
                    489:                } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
                    490:                        /* end packet, idle and reenable transmitter */
                    491:                        uuc->tu_state = TUS_IDLE;
                    492:                        uuc->tu_flag = 0;
                    493:                        uuaddr->tcs = UUCS_INTR;
                    494:                        if ((bp = uutab->b_actf) == NULL) {
                    495:                                printf("uu%d: no bp, active %d\n", 
                    496:                                    data->pk_unit, uitab[ctlr].b_active);
                    497:                                uustart(ui);
                    498:                                return;
                    499:                        }
                    500:                        unit = UNIT(bp->b_dev);
                    501:                        if (data->pk_mod > 1) {        /* hard error */
                    502:                                printf("uu%d: hard error bn%d,", unit, 
                    503:                                    bp->b_blkno);
                    504:                                printf(" pk_mod 0%o\n", data->pk_mod&0xff);
                    505:                                bp->b_flags |= B_ERROR;
                    506:                                uuc->tu_herrs++;
                    507:                        } else if (data->pk_mod)        /* soft error */
                    508:                                uuc->tu_serrs++;
                    509:                        uutab->b_active = NULL;
                    510:                        uutab->b_actf = bp->b_actf;
                    511:                        bp->b_resid = uuc->tu_count;
                    512:                        if ((bp->b_flags&B_READ) == 0)
                    513:                                tu_vee(&uu_pcnt[unit]);
                    514:                        iodone(bp);
                    515:                        uustart(ui);
                    516:                } else {
                    517:                        /*
                    518:                         * Neither data nor end: data was lost
                    519:                         * somehow, flush and restart the transfer.
                    520:                         */
                    521:                        uuaddr->rcs = 0;
                    522:                        uu_restart(ctlr, ui);
                    523:                        uuc->tu_serrs++;
                    524:                }
                    525:                break;
                    526: 
                    527:        case TUS_IDLE:
                    528:        case TUS_INIT1:
                    529:                break;
                    530: 
                    531:        default:
                    532: bad:
                    533:                if (c == TUF_INITF) {
                    534:                        printf("uu%d protocol error, state=", data->pk_unit);
                    535:                        printstate(uuc->tu_state);
                    536:                        printf(", op=%x, cnt=%d, block=%d\n",
                    537:                            cmd->pk_op, cmd->pk_count, cmd->pk_block);
                    538:                        uutab->b_active = NULL;
                    539:                        if (bp = uutab->b_actf) {
                    540:                                bp->b_flags |= B_ERROR;
                    541:                                uutab->b_actf = bp->b_actf;
                    542:                                if ((bp->b_flags&B_READ) == 0)
                    543:                                        tu_vee(&uu_pcnt[unit]);
                    544:                                iodone(bp);
                    545:                        }
                    546:                        uuc->tu_state = TUS_INIT1;
                    547:                } else {
                    548:                        printf("uu%d receive state error, state=", 
                    549:                                data->pk_unit);
                    550:                        printstate(uuc->tu_state);
                    551:                        printf(", byte=%x\n", c & 0xff);
                    552: #ifdef notdef
                    553:                        uuc->tu_state = TUS_INIT1;
                    554: #endif
                    555:                        wakeup((caddr_t)uuc);
                    556:                }
                    557:        }
                    558: }
                    559: 
                    560: 
                    561: /*
                    562:  * TU58 transmitter interrupt
                    563:  */
                    564: uuxintr(ctlr)
                    565:        int ctlr;
                    566: {
                    567:        register struct uu_softc *uuc = &uu_softc[ctlr];
                    568:        register struct uudevice *uuaddr;
                    569:        register struct packet *data;
                    570:        struct uba_device *ui = uudinfo[ctlr];
                    571:        int c;
                    572: 
                    573:        data = &uudata[ctlr];
                    574:        uuaddr = (struct uudevice *) ui->ui_addr;
                    575: top:
                    576:        if (uuc->tu_wcnt > 0) {
                    577:                /* still stuff to send, send one byte */
                    578:                while ((uuaddr->tcs & UUCS_READY) == 0)
                    579:                        ;
                    580:                uuaddr->tdb = *uuc->tu_wbptr++;
                    581:                uuc->tu_wcnt--;
                    582:                return;
                    583:        }
                    584: 
                    585:        /*
                    586:         * Last message byte was sent out.
                    587:         * Switch on tu_state of transfer.
                    588:         */
                    589:        switch(uuc->tu_state) {
                    590: 
                    591:        /*
                    592:         * Two nulls have been sent, remove break, and send inits
                    593:         */
                    594:        case TUS_INIT1: 
                    595:                uuc->tu_flag = 0;
                    596:                uuaddr->tcs = UUCS_INTR;
                    597:                uuc->tu_state = TUS_INIT2;
                    598:                uuc->tu_wbptr = uuinit;
                    599:                uuc->tu_wcnt = sizeof (uuinit);
                    600:                goto top;
                    601: 
                    602:        /*
                    603:         * Inits have been sent, wait for a continue msg.
                    604:         */
                    605:        case TUS_INIT2: 
                    606:                c = uuaddr->rdb;        /* prevent overrun error */
                    607:                uuaddr->rcs = UUCS_INTR;
                    608:                uuc->tu_flag = 1;
                    609:                break;
                    610: 
                    611:        /*
                    612:         * Read cmd packet sent, get ready for data
                    613:         */
                    614:        case TUS_SENDR:
                    615:                uuc->tu_state = TUS_GETH;
                    616:                uuc->tu_rbptr = (u_char *)data;
                    617:                uuc->tu_rcnt = 2;
                    618:                uuc->tu_flag = 1;
                    619:                uuaddr->tcs = 0;
                    620:                uuaddr->rcs = UUCS_INTR;
                    621:                break;
                    622: 
                    623:        /*
                    624:         * Write cmd packet sent, wait for continue
                    625:         */
                    626:        case TUS_SENDW: 
                    627:                uuc->tu_state = TUS_WAIT;
                    628:                uuc->tu_flag = 1;
                    629:                if ((uuaddr->rcs&UUCS_INTR) == 0) {
                    630:                        printf("NO IE\n");
                    631:                        uuaddr->rcs = UUCS_INTR;
                    632:                }
                    633:                break;
                    634: 
                    635:        /*
                    636:         * Header sent, send data.
                    637:         */
                    638:        case TUS_SENDH:
                    639:                uuc->tu_state = TUS_SENDD;
                    640:                uuc->tu_wbptr = (u_char *)uuc->tu_addr;
                    641:                uuc->tu_wcnt = data->pk_mcount;
                    642:                goto top;
                    643: 
                    644:        /*
                    645:         * Data sent, follow with checksum.
                    646:         */
                    647:        case TUS_SENDD: 
                    648:                uuc->tu_state = TUS_SENDC;
                    649:                uuc->tu_wbptr = (u_char *)&data->pk_chksum;
                    650:                uuc->tu_wcnt = 2;
                    651:                goto top;
                    652: 
                    653:        /* 
                    654:         * Checksum sent, wait for continue.
                    655:         */
                    656:        case TUS_SENDC:
                    657:                /*
                    658:                 * Update buffer address and count.
                    659:                 */
                    660:                uuc->tu_addr += data->pk_mcount;
                    661:                uuc->tu_count -= data->pk_mcount;
                    662:                if (uuc->tu_count > 0) {
                    663:                        uuc->tu_state = TUS_WAIT;
                    664:                        uuc->tu_flag = 1;
                    665:                        break;
                    666:                }
                    667: 
                    668:                /*
                    669:                 * End of transmission, get ready for end packet.
                    670:                 */
                    671:                uuc->tu_state = TUS_GET;
                    672:                uuc->tu_rbptr = (u_char *)data;
                    673:                uuc->tu_rcnt = sizeof (*data);
                    674:                uuc->tu_flag = 1;
                    675:                uuaddr->tcs = 0;
                    676:                break;
                    677: 
                    678:        /*
                    679:         * Random interrupt
                    680:         */
                    681:        case TUS_IDLE:          /* stray interrupt? */
                    682: 
                    683:        default:
                    684:                break;
                    685:        }
                    686: }
                    687: 
                    688: uuwatch()
                    689: {
                    690:        register struct uu_softc *uuc;
                    691:        register struct uudevice *uuaddr;
                    692:        struct uba_device *ui;
                    693:        struct buf *bp, *uutab;
                    694:        int s, ctlr, active = 0;
                    695: 
                    696:        for (ctlr=0; ctlr<NUU; ctlr++) {
                    697:                int i;
                    698: 
                    699:                uuc = &uu_softc[ctlr];
                    700: 
                    701:                if (uuc->tu_dopen[0] || uuc->tu_dopen[1])
                    702:                        active++;
                    703:                if (uuc->tu_flag == 0)
                    704:                        /*
                    705:                         * If no read is in progress
                    706:                         * just skip
                    707:                         */
                    708:                        continue;
                    709: 
                    710:                ui = uudinfo[ctlr];
                    711:                uuaddr = (struct uudevice *)ui->ui_addr;
                    712:                uutab = &uitab[ctlr];
                    713:                if (uuc->tu_flag++ < 40)
                    714:                        continue;
                    715:                printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);
                    716: #ifdef UUDEBUG
                    717:                printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
                    718:                       uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr,
                    719:                       uuc->tu_count);
                    720: #endif
                    721:                s = splx(UUIPL);
                    722:                uuc->tu_flag = 0;
                    723:                i = uuaddr->rdb;                /* dummy */
                    724:                uuaddr->rcs = UUCS_INTR;        /* in case we were flushing */
                    725:                uuaddr->tcs = UUCS_INTR;
                    726:                uuc->tu_state = TUS_IDLE;
                    727:                if (!uutab->b_active) {
                    728:                        wakeup((caddr_t)uuc);
                    729:                        goto retry;
                    730:                }
                    731:                if (++uutab->b_errcnt <= 1) {
                    732:                        uustart(ui);
                    733:                        goto retry;
                    734:                }
                    735:                if (bp = uutab->b_actf) {
                    736:                        bp->b_flags |= B_ERROR;
                    737:                        if ((bp->b_flags&B_READ) == 0)
                    738:                                tu_vee(&uu_pcnt[UNIT(bp->b_dev)]);
                    739:                        iodone(bp);
                    740:                }
                    741: retry:
                    742:                (void) splx(s);
                    743:        }
                    744:        if (active)
                    745:                timeout(uuwatch, (caddr_t)0, hz);
                    746:        else
                    747:                uuwstart = 0;
                    748:        return;
                    749: }
                    750: 
                    751: #if !defined(VAX750) && !defined(VAX730)
                    752: /*
                    753:  * Compute checksum TU58 fashion
                    754:  */
                    755: #ifdef lint
                    756: tuchk(word, cp, n)
                    757:        register word;
                    758:        register unsigned short *cp;
                    759:        int n;
                    760: {
                    761:        register int c = n >> 1;
                    762:        register long temp;
                    763: 
                    764:        do {
                    765:                temp = *cp++;   /* temp, only because vax cc won't *r++ */
                    766:                word += temp;
                    767:        } while (--c > 0);
                    768:        if (n & 1)
                    769:                word += *(unsigned char *)cp;
                    770:        while (word & 0xffff0000)
                    771:                word = (word & 0xffff) + ((word >> 16) & 0xffff);
                    772:        return (word);
                    773: }
                    774: #else
                    775: tuchk(word0, wp, n)
                    776:        register int word0;                     /* r11 */
                    777:        register char *wp;                      /* r10 */
                    778:        register int n;                         /* r9 */
                    779: {
                    780:        asm("loop:");
                    781:        asm("   addw2   (r10)+,r11");           /* add a word to sum */
                    782:        asm("   adwc    $0,r11");               /* add in carry, end-around */
                    783:        asm("   acbl    $2,$-2,r9,loop");       /* done yet? */
                    784:        asm("   blbc    r9,ok");                /* odd byte count? */
                    785:        asm("   movzbw  (r10),r10");            /* yes, get last byte */
                    786:        asm("   addw2   r10,r11");              /* add it in */
                    787:        asm("   adwc    $0,r11");               /* and the carry */
                    788:        asm("ok:");
                    789:        asm("   movl    r11,r0");               /* return sum */
                    790: }
                    791: #endif
                    792: 
                    793: /*
                    794:  * Make sure this incredibly slow device
                    795:  * doesn't eat up all the buffers in the
                    796:  * system by putting the requesting process
                    797:  * (remember: this device is 'single-user')
                    798:  * to sleep if the write-behind queue grows
                    799:  * larger than NUUQ.
                    800:  */
                    801: tu_pee(cp)
                    802:        char *cp;
                    803: {
                    804:        register int s;
                    805: 
                    806:        s = splx(UUIPL);
                    807:        if (++(*cp) > NUUQ) 
                    808:                sleep(cp, PRIBIO);
                    809:        splx(s);
                    810: }
                    811: 
                    812: tu_vee(cp)
                    813:        char *cp;
                    814: {
                    815:        register int s;
                    816: 
                    817:        s = splx(UUIPL);
                    818:        if (--(*cp) <= NUUQ) 
                    819:                wakeup(cp);
                    820:        splx(s);
                    821: }
                    822: #endif
                    823: 
                    824: uuioctl(dev, cmd, data, flag)
                    825:        dev_t dev;
                    826:        caddr_t data;
                    827: {
                    828:        /*
                    829:         * add code to wind/rewind cassette here
                    830:         */
                    831:        return (ENXIO);
                    832: }
                    833: 
                    834: uu_restart(ctlr, ui)
                    835:        int ctlr;
                    836:        struct uba_device *ui;
                    837: {
                    838:        uureset(ctlr);
                    839:        timeout(uustart, (caddr_t)ui, hz * 3);
                    840: }
                    841: 
                    842: #endif

unix.superglobalmegacorp.com

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