Annotation of 43BSDReno/sys/vaxuba/ut.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:  *     @(#)ut.c        7.11 (Berkeley) 7/1/90
                      7:  */
                      8: 
                      9: #include "tj.h"
                     10: #if NUT > 0
                     11: /*
                     12:  * System Industries Model 9700 Tape Drive
                     13:  *   emulates a TU45 on the UNIBUS
                     14:  *
                     15:  * TODO:
                     16:  *     check out attention processing
                     17:  *     try reset code and dump code
                     18:  */
                     19: #include "param.h"
                     20: #include "systm.h"
                     21: #include "buf.h"
                     22: #include "conf.h"
                     23: #include "errno.h"
                     24: #include "file.h"
                     25: #include "map.h"
                     26: #include "ioctl.h"
                     27: #include "mtio.h"
                     28: #include "cmap.h"
                     29: #include "time.h"
                     30: #include "uio.h"
                     31: #include "kernel.h"
                     32: #include "syslog.h"
                     33: #include "tprintf.h"
                     34: 
                     35: #include "machine/pte.h"
                     36: #include "../vax/cpu.h"
                     37: #include "ubareg.h"
                     38: #include "ubavar.h"
                     39: #include "utreg.h"
                     40: 
                     41: struct buf     cutbuf[NUT];    /* bufs for control operations */
                     42: struct buf     tjutab[NTJ];    /* bufs for slave queue headers */
                     43: 
                     44: struct uba_ctlr *utminfo[NUT];
                     45: struct uba_device *tjdinfo[NTJ];
                     46: int utprobe(), utslave(), utattach(), utdgo(), utintr(), uttimer();
                     47: u_short utstd[] = { 0772440, 0 };
                     48: struct uba_driver utdriver =
                     49:   { utprobe, utslave, utattach, utdgo, utstd, "tj", tjdinfo, "ut", utminfo, 0 };
                     50: 
                     51: #define        MASKREG(reg)    ((reg)&0xffff)
                     52: 
                     53: /* bits in minor device */
                     54: #define        TJUNIT(dev)     (minor(dev)&03)
                     55: #define        T_NOREWIND      04
                     56: #define        T_1600BPI       010
                     57: #define        T_6250BPI       020
                     58: short  utdens[] = { UT_NRZI, UT_PE, UT_GCR, UT_NRZI };
                     59: 
                     60: /* slave to controller mapping table */
                     61: short  tjtout[NTJ];
                     62: #define UTUNIT(dev)    (tjtout[TJUNIT(dev)])
                     63: 
                     64: #define        INF     (daddr_t)1000000L       /* a block number that wont exist */
                     65: 
                     66: struct tj_softc {
                     67:        char    sc_openf;       /* exclusive open */
                     68:        char    sc_lastiow;     /* last I/O operation was a write */
                     69:        daddr_t sc_blkno;       /* next block to transfer */
                     70:        daddr_t sc_nxrec;       /* next record on tape */
                     71:        u_short sc_erreg;       /* image of uter */
                     72:        u_short sc_dsreg;       /* image of utds */
                     73:        u_short sc_resid;       /* residual from transfer */
                     74:        u_short sc_dens;        /* sticky selected density */
                     75:        daddr_t sc_timo;        /* time until timeout expires */
                     76:        short   sc_tact;        /* timeout is active flag */
                     77:        tpr_t   sc_tpr;         /* tprintf handle */
                     78:        int     sc_blks;        /* number of I/O operations since open */
                     79:        int     sc_softerrs;    /* number of soft I/O errors since open */
                     80: } tj_softc[NTJ];
                     81: 
                     82: /*
                     83:  * Internal per/slave states found in sc_state
                     84:  */
                     85: #define        SSEEK           1       /* seeking */
                     86: #define        SIO             2       /* doing sequential I/O */
                     87: #define        SCOM            3       /* sending a control command */
                     88: #define        SREW            4       /* doing a rewind op */
                     89: #define        SERASE          5       /* erase inter-record gap */
                     90: #define        SERASED         6       /* erased inter-record gap */
                     91: 
                     92: /*ARGSUSED*/
                     93: utprobe(reg)
                     94:        caddr_t reg;
                     95: {
                     96:        register int br, cvec;
                     97: #ifdef lint
                     98:        br=0; cvec=br; br=cvec;
                     99:        utintr(0);
                    100: #endif
                    101:        /*
                    102:         * The SI documentation says you must set the RDY bit
                    103:         * (even though it's read-only) to force an interrupt.
                    104:         */
                    105:        ((struct utdevice *) reg)->utcs1 = UT_IE|UT_NOP|UT_RDY;
                    106:        DELAY(10000);
                    107:        return (sizeof (struct utdevice));
                    108: }
                    109: 
                    110: /*ARGSUSED*/
                    111: utslave(ui, reg)
                    112:        struct uba_device *ui;
                    113:        caddr_t reg;
                    114: {
                    115:        /*
                    116:         * A real TU45 would support the slave present bit
                    117:         * int the drive type register, but this thing doesn't,
                    118:         * so there's no way to determine if a slave is present or not.
                    119:         */
                    120:         return(1);
                    121: }
                    122: 
                    123: utattach(ui)
                    124:        struct uba_device *ui;
                    125: {
                    126:        tjtout[ui->ui_unit] = ui->ui_mi->um_ctlr;
                    127: }
                    128: 
                    129: /*
                    130:  * Open the device with exclusive access.
                    131:  */
                    132: utopen(dev, flag)
                    133:        dev_t dev;
                    134:        int flag;
                    135: {
                    136:        register int tjunit = TJUNIT(dev);
                    137:        register struct uba_device *ui;
                    138:        register struct tj_softc *sc;
                    139:        int olddens, dens, error;
                    140:        register int s;
                    141: 
                    142:        if (tjunit >= NTJ || (ui = tjdinfo[tjunit]) == 0 || ui->ui_alive == 0)
                    143:                return (ENXIO);
                    144:        if ((sc = &tj_softc[tjunit])->sc_openf)
                    145:                return (EBUSY);
                    146:        sc->sc_openf = 1;
                    147:        olddens = sc->sc_dens;
                    148:        dens = sc->sc_dens =
                    149:            utdens[(minor(dev)&(T_1600BPI|T_6250BPI))>>3]|
                    150:              PDP11FMT|(ui->ui_slave&07);
                    151: get:
                    152:        utcommand(dev, UT_SENSE, 1);
                    153:        if (sc->sc_dsreg&UTDS_PIP) {
                    154:                if (error = tsleep((caddr_t)&lbolt, (PZERO+1) | PCATCH,
                    155:                    devopn, 0))
                    156:                        return (error);
                    157:                goto get;
                    158:        }
                    159:        sc->sc_dens = olddens;
                    160:        if ((sc->sc_dsreg&UTDS_MOL) == 0) {
                    161:                sc->sc_openf = 0;
                    162:                uprintf("tj%d: not online\n", tjunit);
                    163:                return (EIO);
                    164:        }
                    165:        if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) {
                    166:                sc->sc_openf = 0;
                    167:                uprintf("tj%d: no write ring\n", tjunit);
                    168:                return (EIO);
                    169:        }
                    170:        if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) &&
                    171:            dens != sc->sc_dens) {
                    172:                sc->sc_openf = 0;
                    173:                uprintf("tj%d: can't change density in mid-tape\n", tjunit);
                    174:                return (EIO);
                    175:        }
                    176:        sc->sc_blkno = (daddr_t)0;
                    177:        sc->sc_nxrec = INF;
                    178:        sc->sc_lastiow = 0;
                    179:        sc->sc_blks = 0;
                    180:        sc->sc_softerrs = 0;
                    181:        sc->sc_dens = dens;
                    182:        sc->sc_tpr = tprintf_open();
                    183:        /*
                    184:         * For 6250 bpi take exclusive use of the UNIBUS.
                    185:         */
                    186:        ui->ui_driver->ud_xclu = (dens&(T_1600BPI|T_6250BPI)) == T_6250BPI;
                    187:        s = splclock();
                    188:        if (sc->sc_tact == 0) {
                    189:                sc->sc_timo = INF;
                    190:                sc->sc_tact = 1;
                    191:                timeout(uttimer, (caddr_t)dev, 5*hz);
                    192:        }
                    193:        splx(s);
                    194:        return (0);
                    195: }
                    196: 
                    197: utclose(dev, flag)
                    198:        register dev_t dev;
                    199:        register flag;
                    200: {
                    201:        register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
                    202: 
                    203:        if (flag == FWRITE || ((flag&FWRITE) && sc->sc_lastiow)) {
                    204:                utcommand(dev, UT_WEOF, 1);
                    205:                utcommand(dev, UT_WEOF, 1);
                    206:                utcommand(dev, UT_SREV, 1);
                    207:        }
                    208:        if ((minor(dev)&T_NOREWIND) == 0)
                    209:                utcommand(dev, UT_REW, 0);
                    210:        if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100)
                    211:                log(LOG_INFO, "tj%d: %d soft errors in %d blocks\n",
                    212:                    TJUNIT(dev), sc->sc_softerrs, sc->sc_blks);
                    213:        tprintf_close(sc->sc_tpr);
                    214:        sc->sc_openf = 0;
                    215:        return (0);
                    216: }
                    217: 
                    218: utcommand(dev, com, count)
                    219:        dev_t dev;
                    220:        int com, count;
                    221: {
                    222:        register struct buf *bp;
                    223:        register int s;
                    224: 
                    225:        bp = &cutbuf[UTUNIT(dev)];
                    226:        s = spl5();
                    227:        while (bp->b_flags&B_BUSY) {
                    228:                if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
                    229:                        break;
                    230:                bp->b_flags |= B_WANTED;
                    231:                sleep((caddr_t)bp, PRIBIO);
                    232:        }
                    233:        bp->b_flags = B_BUSY|B_READ;
                    234:        splx(s);
                    235:        bp->b_dev = dev;
                    236:        bp->b_command = com;
                    237:        bp->b_repcnt = count;
                    238:        bp->b_blkno = 0;
                    239:        utstrategy(bp);
                    240:        if (count == 0)
                    241:                return;
                    242:        iowait(bp);
                    243:        if (bp->b_flags&B_WANTED)
                    244:                wakeup((caddr_t)bp);
                    245:        bp->b_flags &= B_ERROR;
                    246: }
                    247: 
                    248: /*
                    249:  * Queue a tape operation.
                    250:  */
                    251: utstrategy(bp)
                    252:        register struct buf *bp;
                    253: {
                    254:        int tjunit = TJUNIT(bp->b_dev);
                    255:        register struct uba_ctlr *um;
                    256:        register struct buf *dp;
                    257:        int s;
                    258: 
                    259:        /*
                    260:         * Put transfer at end of unit queue
                    261:         */
                    262:        dp = &tjutab[tjunit];
                    263:        bp->av_forw = NULL;
                    264:        um = tjdinfo[tjunit]->ui_mi;
                    265:        s = spl5();
                    266:        if (dp->b_actf == NULL) {
                    267:                dp->b_actf = bp;
                    268:                /*
                    269:                 * Transport not active, so...
                    270:                 * put at end of controller queue
                    271:                 */
                    272:                dp->b_forw = NULL;
                    273:                if (um->um_tab.b_actf == NULL)
                    274:                        um->um_tab.b_actf = dp;
                    275:                else
                    276:                        um->um_tab.b_actl->b_forw = dp;
                    277:                um->um_tab.b_actl = dp;
                    278:        } else
                    279:                dp->b_actl->av_forw = bp;
                    280:        dp->b_actl = bp;
                    281:        /*
                    282:         * If the controller is not busy, set it going.
                    283:         */
                    284:        if (um->um_tab.b_state == 0)
                    285:                utstart(um);
                    286:        splx(s);
                    287: }
                    288: 
                    289: utstart(um)
                    290:        register struct uba_ctlr *um;
                    291: {
                    292:        register struct utdevice *addr;
                    293:        register struct buf *bp, *dp;
                    294:        register struct tj_softc *sc;
                    295:        struct uba_device *ui;
                    296:        int tjunit;
                    297:        daddr_t blkno;
                    298: 
                    299: loop:
                    300:        /*
                    301:         * Scan controller queue looking for units with
                    302:         * transaction queues to dispatch
                    303:         */
                    304:        if ((dp = um->um_tab.b_actf) == NULL)
                    305:                return;
                    306:        if ((bp = dp->b_actf) == NULL) {
                    307:                um->um_tab.b_actf = dp->b_forw;
                    308:                goto loop;
                    309:        }
                    310:        addr = (struct utdevice *)um->um_addr;
                    311:        tjunit = TJUNIT(bp->b_dev);
                    312:        ui = tjdinfo[tjunit];
                    313:        sc = &tj_softc[tjunit];
                    314:        /* note slave select, density, and format were merged on open */
                    315:        addr->uttc = sc->sc_dens;
                    316:        sc->sc_dsreg = addr->utds;
                    317:        sc->sc_erreg = addr->uter;
                    318:        sc->sc_resid = MASKREG(addr->utfc);
                    319:        /*
                    320:         * Default is that last command was NOT a write command;
                    321:         * if we do a write command we will notice this in utintr().
                    322:         */
                    323:        sc->sc_lastiow = 0;
                    324:        if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {
                    325:                /*
                    326:                 * Have had a hard error on a non-raw tape
                    327:                 * or the tape unit is now unavailable
                    328:                 * (e.g. taken off line).
                    329:                 */
                    330:                bp->b_flags |= B_ERROR;
                    331:                goto next;
                    332:        }
                    333:        if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
                    334:                /*
                    335:                 * Execute a control operation with the specified
                    336:                 * count.
                    337:                 */
                    338:                if (bp->b_command == UT_SENSE)
                    339:                        goto next;
                    340:                if (bp->b_command == UT_SFORW && (addr->utds & UTDS_EOT)) {
                    341:                        bp->b_resid = bp->b_bcount;
                    342:                        goto next;
                    343:                }
                    344:                /*
                    345:                 * Set next state; handle timeouts
                    346:                 */
                    347:                if (bp->b_command == UT_REW) {
                    348:                        um->um_tab.b_state = SREW;
                    349:                        sc->sc_timo = 5*60;
                    350:                } else {
                    351:                        um->um_tab.b_state = SCOM;
                    352:                        sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60);
                    353:                }
                    354:                /* NOTE: this depends on the ut command values */
                    355:                if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF)
                    356:                        addr->utfc = -bp->b_repcnt;
                    357:                goto dobpcmd;
                    358:        }
                    359:        /*
                    360:         * For raw I/O, save the current block
                    361:         * number in case we have to retry.
                    362:         */
                    363:        if (bp->b_flags & B_RAW) {
                    364:                if (um->um_tab.b_errcnt == 0) {
                    365:                        sc->sc_blkno = bdbtofsb(bp->b_blkno);
                    366:                        sc->sc_nxrec = sc->sc_blkno + 1;
                    367:                }
                    368:        }
                    369:        else {
                    370:                /*
                    371:                 * Handle boundary cases for operation
                    372:                 * on non-raw tapes.
                    373:                 */
                    374:                if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
                    375:                        /* can't read past end of file */
                    376:                        bp->b_flags |= B_ERROR;
                    377:                        bp->b_error = ENXIO;
                    378:                        goto next;
                    379:                }
                    380:                if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec &&
                    381:                    (bp->b_flags&B_READ)) {
                    382:                        /*
                    383:                         * Reading at end of file returns 0 bytes.
                    384:                         */
                    385:                        bp->b_resid = bp->b_bcount;
                    386:                        clrbuf(bp);
                    387:                        goto next;
                    388:                }
                    389:                if ((bp->b_flags&B_READ) == 0)
                    390:                        sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
                    391:        }
                    392:        /*
                    393:         * If the tape is correctly positioned, set up all the
                    394:         * registers but the csr, and give control over to the
                    395:         * UNIBUS adaptor routines, to wait for resources to
                    396:         * start I/O.
                    397:         */
                    398:        if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {
                    399:                addr->utwc = -(((bp->b_bcount)+1)>>1);
                    400:                addr->utfc = -bp->b_bcount;
                    401:                if ((bp->b_flags&B_READ) == 0) {
                    402:                        /*
                    403:                         * On write error retries erase the
                    404:                         * inter-record gap before rewriting.
                    405:                         */
                    406:                        if (um->um_tab.b_errcnt) {
                    407:                                if (um->um_tab.b_state != SERASED) {
                    408:                                        um->um_tab.b_state = SERASE;
                    409:                                        sc->sc_timo = 60;
                    410:                                        addr->utcs1 = UT_ERASE|UT_IE|UT_GO;
                    411:                                        return;
                    412:                                }
                    413:                        }
                    414:                        if (addr->utds & UTDS_EOT) {
                    415:                                bp->b_resid = bp->b_bcount;
                    416:                                um->um_tab.b_state = 0;
                    417:                                goto next;
                    418:                        }
                    419:                        um->um_cmd = UT_WCOM;
                    420:                } else
                    421:                        um->um_cmd = UT_RCOM;
                    422:                sc->sc_timo = 60;
                    423:                um->um_tab.b_state = SIO;
                    424:                (void) ubago(ui);
                    425:                return;
                    426:        }
                    427:        /*
                    428:         * Tape positioned incorrectly; seek forwards or
                    429:         * backwards to the correct spot.  This happens for
                    430:         * raw tapes only on error retries.
                    431:         */
                    432:        um->um_tab.b_state = SSEEK;
                    433:        if (blkno < bdbtofsb(bp->b_blkno)) {
                    434:                addr->utfc = blkno - bdbtofsb(bp->b_blkno);
                    435:                bp->b_command = UT_SFORW;
                    436:        } else {
                    437:                addr->utfc = bdbtofsb(bp->b_blkno) - blkno;
                    438:                bp->b_command = UT_SREV;
                    439:        }
                    440:        sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);
                    441: 
                    442: dobpcmd:
                    443:        /*
                    444:         * Perform the command setup in bp.
                    445:         */
                    446:        addr->utcs1 = bp->b_command|UT_IE|UT_GO;
                    447:        return;
                    448: next:
                    449:        /*
                    450:         * Advance to the next command in the slave queue,
                    451:         * posting notice and releasing resources as needed.
                    452:         */
                    453:        if (um->um_ubinfo)
                    454:                ubadone(um);
                    455:        um->um_tab.b_errcnt = 0;
                    456:        dp->b_actf = bp->av_forw;
                    457:        iodone(bp);
                    458:        goto loop;
                    459: }
                    460: 
                    461: /*
                    462:  * Start operation on controller --
                    463:  * UNIBUS resources have been allocated.
                    464:  */
                    465: utdgo(um)
                    466:        register struct uba_ctlr *um;
                    467: {
                    468:        register struct utdevice *addr = (struct utdevice *)um->um_addr;
                    469: 
                    470:        addr->utba = (u_short) um->um_ubinfo;
                    471:        addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300)|UT_IE|UT_GO;
                    472: }
                    473: 
                    474: /*
                    475:  * Ut interrupt handler
                    476:  */
                    477: /*ARGSUSED*/
                    478: utintr(ut11)
                    479:        int ut11;
                    480: {
                    481:        struct buf *dp;
                    482:        register struct buf *bp;
                    483:        register struct uba_ctlr *um = utminfo[ut11];
                    484:        register struct utdevice *addr;
                    485:        register struct tj_softc *sc;
                    486:        u_short tjunit, cs2, cs1;
                    487:        register state;
                    488: 
                    489:        if ((dp = um->um_tab.b_actf) == NULL)
                    490:                return;
                    491:        bp = dp->b_actf;
                    492:        tjunit = TJUNIT(bp->b_dev);
                    493:        addr = (struct utdevice *)tjdinfo[tjunit]->ui_addr;
                    494:        sc = &tj_softc[tjunit];
                    495:        /*
                    496:         * Record status...
                    497:         */
                    498:        sc->sc_timo = INF;
                    499:        sc->sc_dsreg = addr->utds;
                    500:        sc->sc_erreg = addr->uter;
                    501:        sc->sc_resid = MASKREG(addr->utfc);
                    502:        if ((bp->b_flags&B_READ) == 0)
                    503:                sc->sc_lastiow = 1;
                    504:        state = um->um_tab.b_state;
                    505:        um->um_tab.b_state = 0;
                    506:        /*
                    507:         * Check for errors...
                    508:         */
                    509:        if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
                    510:                /*
                    511:                 * To clear the ERR bit, we must issue a drive clear
                    512:                 * command, and to clear the TRE bit we must set the
                    513:                 * controller clear bit.
                    514:                 */
                    515:                cs2 = addr->utcs2;
                    516:                if ((cs1 = addr->utcs1)&UT_TRE)
                    517:                        addr->utcs2 |= UTCS2_CLR;
                    518:                /* is this dangerous ?? */
                    519:                while ((addr->utcs1&UT_RDY) == 0)
                    520:                        ;
                    521:                addr->utcs1 = UT_CLEAR|UT_GO;
                    522:                /*
                    523:                 * If we were reading at 1600 or 6250 bpi and the error
                    524:                 * was corrected, then don't consider this an error.
                    525:                 */
                    526:                if (sc->sc_erreg & UTER_COR && (bp->b_flags & B_READ) &&
                    527:                    (addr->uttc & UTTC_DEN) != UT_NRZI) {
                    528:                        tprintf(sc->sc_tpr,
                    529:                          "ut%d: soft error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
                    530:                          tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
                    531:                          UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
                    532:                        sc->sc_erreg &= ~UTER_COR;
                    533:                }
                    534:                /*
                    535:                 * If we were reading from a raw tape and the only error
                    536:                 * was that the record was too long, then we don't consider
                    537:                 * this an error.
                    538:                 */
                    539:                if ((bp->b_flags & (B_READ|B_RAW)) == (B_READ|B_RAW) &&
                    540:                    (sc->sc_erreg&UTER_FCE))
                    541:                        sc->sc_erreg &= ~UTER_FCE;
                    542:                if (sc->sc_erreg == 0)
                    543:                        goto ignoreerr;
                    544:                /*
                    545:                 * Fix up errors which occur due to backspacing
                    546:                 * "over" the front of the tape.
                    547:                 */
                    548:                if ((sc->sc_dsreg & UTDS_BOT) && bp->b_command == UT_SREV &&
                    549:                    ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0))
                    550:                        goto opdone;
                    551:                /*
                    552:                 * Retry soft errors up to 8 times
                    553:                 */
                    554:                if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) {
                    555:                        if (++um->um_tab.b_errcnt < 7) {
                    556:                                sc->sc_blkno++;
                    557:                                ubadone(um);
                    558:                                goto opcont;
                    559:                        }
                    560:                }
                    561:                /*
                    562:                 * Hard or non-I/O errors on non-raw tape
                    563:                 * cause it to close.
                    564:                 */
                    565:                if ((bp->b_flags&B_RAW) == 0 && sc->sc_openf > 0)
                    566:                        sc->sc_openf = -1;
                    567:                /*
                    568:                 * Couldn't recover error.
                    569:                 */
                    570:                tprintf(sc->sc_tpr,
                    571:                        "ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
                    572:                        tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
                    573:                        UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
                    574:                bp->b_flags |= B_ERROR;
                    575:                goto opdone;
                    576:        }
                    577: 
                    578: ignoreerr:
                    579:        /*
                    580:         * If we hit a tape mark update our position.
                    581:         */
                    582:        if (sc->sc_dsreg & UTDS_TM && bp->b_flags & B_READ) {
                    583:                /*
                    584:                 * Set blkno and nxrec
                    585:                 */
                    586:                if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
                    587:                        if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
                    588:                                sc->sc_nxrec =
                    589:                                     bdbtofsb(bp->b_blkno) - addr->utfc;
                    590:                                sc->sc_blkno = sc->sc_nxrec;
                    591:                        } else {
                    592:                                sc->sc_blkno =
                    593:                                     bdbtofsb(bp->b_blkno) + addr->utfc;
                    594:                                sc->sc_nxrec = sc->sc_blkno-1;
                    595:                        }
                    596:                } else
                    597:                        sc->sc_nxrec = bdbtofsb(bp->b_blkno);
                    598:                /*
                    599:                 * Note: if we get a tape mark on a read, the
                    600:                 * frame count register will be zero, so b_resid
                    601:                 * will be calculated correctly below.
                    602:                 */
                    603:                goto opdone;
                    604:        }
                    605:        /*
                    606:         * Advance tape control FSM.
                    607:         */
                    608:        switch (state) {
                    609: 
                    610:        case SIO:               /* read/write increments tape block # */
                    611:                sc->sc_blkno++;
                    612:                sc->sc_blks++;
                    613:                if (um->um_tab.b_errcnt)
                    614:                        sc->sc_softerrs++;
                    615:                break;
                    616: 
                    617:        case SCOM:              /* motion commands update current position */
                    618:                if (bp == &cutbuf[UTUNIT(bp->b_dev)])
                    619:                switch ((int)bp->b_command) {
                    620: 
                    621:                case UT_SFORW:
                    622:                        sc->sc_blkno -= bp->b_repcnt;
                    623:                        break;
                    624: 
                    625:                case UT_SREV:
                    626:                        sc->sc_blkno += bp->b_repcnt;
                    627:                        break;
                    628: 
                    629:                case UT_REWOFFL:
                    630:                        addr->utcs1 = UT_CLEAR|UT_GO;
                    631:                        break;
                    632:                }
                    633:                break;
                    634: 
                    635:        case SSEEK:
                    636:                sc->sc_blkno = bdbtofsb(bp->b_blkno);
                    637:                goto opcont;
                    638: 
                    639:        case SERASE:
                    640:                /*
                    641:                 * Completed erase of the inter-record gap due to a
                    642:                 * write error; now retry the write operation.
                    643:                 */
                    644:                um->um_tab.b_state = SERASED;
                    645:                goto opcont;
                    646: 
                    647:        case SREW:                      /* clear attention bit */
                    648:                addr->utcs1 = UT_CLEAR|UT_GO;
                    649:                break;
                    650: 
                    651:        default:
                    652:                printf("bad state %d\n", state);
                    653:                panic("utintr");
                    654:        }
                    655: 
                    656: opdone:
                    657:        /*
                    658:         * Reset error count and remove
                    659:         * from device queue
                    660:         */
                    661:        um->um_tab.b_errcnt = 0;
                    662:        dp->b_actf = bp->av_forw;
                    663:        /*
                    664:         * For read command, frame count register contains
                    665:         * actual length of tape record.  Otherwise, it
                    666:         * holds negative residual count.
                    667:         */
                    668:        if (state == SIO && um->um_cmd == UT_RCOM) {
                    669:                bp->b_resid = 0;
                    670:                if (bp->b_bcount > MASKREG(addr->utfc))
                    671:                        bp->b_resid = bp->b_bcount - MASKREG(addr->utfc);
                    672:        } else
                    673:                bp->b_resid = MASKREG(-addr->utfc);
                    674:        ubadone(um);
                    675:        iodone(bp);
                    676:        /*
                    677:         * Circulate slave to end of controller queue
                    678:         * to give other slaves a chance
                    679:         */
                    680:        um->um_tab.b_actf = dp->b_forw;
                    681:        if (dp->b_actf) {
                    682:                dp->b_forw = NULL;
                    683:                if (um->um_tab.b_actf == NULL)
                    684:                        um->um_tab.b_actf = dp;
                    685:                else
                    686:                        um->um_tab.b_actl->b_forw = dp;
                    687:                um->um_tab.b_actl = dp;
                    688:        }
                    689:        if (um->um_tab.b_actf == 0)
                    690:                return;
                    691: opcont:
                    692:        utstart(um);
                    693: }
                    694: 
                    695: /*
                    696:  * Watchdog timer routine.
                    697:  */
                    698: uttimer(dev)
                    699:        int dev;
                    700: {
                    701:        register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
                    702:        register short x;
                    703: 
                    704:        if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
                    705:                printf("tj%d: lost interrupt\n", TJUNIT(dev));
                    706:                sc->sc_timo = INF;
                    707:                x = spl5();
                    708:                utintr(UTUNIT(dev));
                    709:                (void) splx(x);
                    710:        }
                    711:        timeout(uttimer, (caddr_t)dev, 5*hz);
                    712: }
                    713: 
                    714: /*ARGSUSED*/
                    715: utioctl(dev, cmd, data, flag)
                    716:        dev_t dev;
                    717:        caddr_t data;
                    718: {
                    719:        register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
                    720:        register struct buf *bp = &cutbuf[UTUNIT(dev)];
                    721:        register callcount;
                    722:        int fcount, error = 0;
                    723:        struct mtop *mtop;
                    724:        struct mtget *mtget;
                    725:        /* we depend of the values and order of the MT codes here */
                    726:        static utops[] =
                    727:       {UT_WEOF,UT_SFORWF,UT_SREVF,UT_SFORW,UT_SREV,UT_REW,UT_REWOFFL,UT_SENSE};
                    728: 
                    729:        switch (cmd) {
                    730: 
                    731:        case MTIOCTOP:
                    732:                mtop = (struct mtop *)data;
                    733:                switch(mtop->mt_op) {
                    734: 
                    735:                case MTWEOF:
                    736:                case MTFSF: case MTBSF:
                    737:                case MTFSR: case MTBSR:
                    738:                        callcount = mtop->mt_count;
                    739:                        fcount = 1;
                    740:                        break;
                    741: 
                    742:                case MTREW: case MTOFFL: case MTNOP:
                    743:                        callcount = 1;
                    744:                        fcount = 1;
                    745:                        break;
                    746: 
                    747:                default:
                    748:                        return (ENXIO);
                    749:                }
                    750:                if (callcount <= 0 || fcount <= 0)
                    751:                        return (EINVAL);
                    752:                while (--callcount >= 0) {
                    753:                        utcommand(dev, utops[mtop->mt_op], fcount);
                    754:                        if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT))
                    755:                                break;
                    756:                }
                    757:                if (bp->b_flags&B_ERROR)
                    758:                        if ((error = bp->b_error)==0)
                    759:                                return (EIO);
                    760:                return (error);
                    761: 
                    762:        case MTIOCGET:
                    763:                mtget = (struct mtget *)data;
                    764:                mtget->mt_dsreg = sc->sc_dsreg;
                    765:                mtget->mt_erreg = sc->sc_erreg;
                    766:                mtget->mt_resid = sc->sc_resid;
                    767:                mtget->mt_type = MT_ISUT;
                    768:                break;
                    769: 
                    770:        default:
                    771:                return (ENXIO);
                    772:        }
                    773:        return (0);
                    774: }
                    775: 
                    776: utreset(uban)
                    777:        int uban;
                    778: {
                    779:        register struct uba_ctlr *um;
                    780:        register ut11, tjunit;
                    781:        register struct uba_device *ui;
                    782:        register struct buf *dp;
                    783: 
                    784:        for (ut11 = 0; ut11 < NUT; ut11++) {
                    785:                if ((um = utminfo[ut11]) == 0 || um->um_alive == 0 ||
                    786:                   um->um_ubanum != uban)
                    787:                        continue;
                    788:                printf(" ut%d", ut11);
                    789:                um->um_tab.b_state = 0;
                    790:                um->um_tab.b_actf = um->um_tab.b_actl = 0;
                    791:                if (um->um_ubinfo) {
                    792:                        printf("<%d>", (um->um_ubinfo>>28)&0xf);
                    793:                        um->um_ubinfo = 0;
                    794:                }
                    795:                ((struct utdevice *)(um->um_addr))->utcs1 = UT_CLEAR|UT_GO;
                    796:                ((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR;
                    797:                for (tjunit = 0; tjunit < NTJ; tjunit++) {
                    798:                        if ((ui = tjdinfo[tjunit]) == 0 || ui->ui_mi != um ||
                    799:                            ui->ui_alive == 0)
                    800:                                continue;
                    801:                        dp = &tjutab[tjunit];
                    802:                        dp->b_state = 0;
                    803:                        dp->b_forw = 0;
                    804:                        if (um->um_tab.b_actf == NULL)
                    805:                                um->um_tab.b_actf = dp;
                    806:                        else
                    807:                                um->um_tab.b_actl->b_forw = dp;
                    808:                        um->um_tab.b_actl = dp;
                    809:                        if (tj_softc[tjunit].sc_openf > 0)
                    810:                                tj_softc[tjunit].sc_openf = -1;
                    811:                }
                    812:                utstart(um);
                    813:        }
                    814: }
                    815: 
                    816: /*
                    817:  * Do a stand-alone core dump to tape --
                    818:  * from here down, routines are used only in dump context
                    819:  */
                    820: #define        DBSIZE  20
                    821: 
                    822: utdump()
                    823: {
                    824:        register struct uba_device *ui;
                    825:        register struct uba_regs *up;
                    826:        register struct utdevice *addr;
                    827:        int blk, num = maxfree;
                    828:        int start = 0;
                    829: 
                    830: #define        phys(a,b)               ((b)((int)(a)&0x7fffffff))
                    831:        if (tjdinfo[0] == 0)
                    832:                return (ENXIO);
                    833:        ui = phys(tjdinfo[0], struct uba_device *);
                    834:        up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
                    835:        ubainit(up);
                    836:        DELAY(1000000);
                    837:        addr = (struct utdevice *)ui->ui_physaddr;
                    838:        utwait(addr);
                    839:        /*
                    840:         * Be sure to set the appropriate density here.  We use
                    841:         * 6250, but maybe it should be done at 1600 to insure the
                    842:         * tape can be read by most any other tape drive available.
                    843:         */
                    844:        addr->uttc = UT_GCR|PDP11FMT;   /* implicit slave 0 or-ed in */
                    845:        addr->utcs1 = UT_CLEAR|UT_GO;
                    846:        while (num > 0) {
                    847:                blk = num > DBSIZE ? DBSIZE : num;
                    848:                utdwrite(start, blk, addr, up);
                    849:                if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
                    850:                        return(EIO);
                    851:                start += blk;
                    852:                num -= blk;
                    853:        }
                    854:        uteof(addr);
                    855:        uteof(addr);
                    856:        utwait(addr);
                    857:        if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
                    858:                return(EIO);
                    859:        addr->utcs1 = UT_REW|UT_GO;
                    860:        return (0);
                    861: }
                    862: 
                    863: utdwrite(dbuf, num, addr, up)
                    864:        register dbuf, num;
                    865:        register struct utdevice *addr;
                    866:        struct uba_regs *up;
                    867: {
                    868:        register struct pte *io;
                    869:        register int npf;
                    870: 
                    871:        utwait(addr);
                    872:        io = up->uba_map;
                    873:        npf = num + 1;
                    874:        while (--npf != 0)
                    875:                *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV);
                    876:        *(int *)io = 0;
                    877:        addr->utwc = -((num*NBPG)>>1);
                    878:        addr->utfc = -(num*NBPG);
                    879:        addr->utba = 0;
                    880:        addr->utcs1 = UT_WCOM|UT_GO;
                    881: }
                    882: 
                    883: utwait(addr)
                    884:        struct utdevice *addr;
                    885: {
                    886:        register s;
                    887: 
                    888:        do
                    889:                s = addr->utds;
                    890:        while ((s&UTDS_DRY) == 0);
                    891: }
                    892: 
                    893: uteof(addr)
                    894:        struct utdevice *addr;
                    895: {
                    896: 
                    897:        utwait(addr);
                    898:        addr->utcs1 = UT_WEOF|UT_GO;
                    899: }
                    900: #endif

unix.superglobalmegacorp.com

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