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

unix.superglobalmegacorp.com

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