Annotation of 42BSD/sys/vaxuba/uu.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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