Annotation of researchv10no/sys/io/te16.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * TM03/TE16 tape driver
        !             3:  *
        !             4:  * TODO:
        !             5:  * multiple drives per formatter might work, but are untested
        !             6:  */
        !             7: #include "sys/param.h"
        !             8: #include "sys/buf.h"
        !             9: #include "sys/conf.h"
        !            10: #include "sys/file.h"
        !            11: #include "sys/user.h"
        !            12: #include "sys/mbaddr.h"
        !            13: #include "sys/mbsts.h"
        !            14: #include "sys/subaddr.h"
        !            15: #include "sys/mtio.h"
        !            16: #include "sys/te16.h"
        !            17: 
        !            18: /*
        !            19:  * hardware stuff
        !            20:  */
        !            21: struct device {
        !            22:        int     htcs1;          /* control status */
        !            23:        int     htds;           /* drive status */
        !            24:        int     hter;           /* error */
        !            25:        int     htmr;           /* maintenance */
        !            26:        int     htas;           /* attention status */
        !            27:        int     htfc;           /* frame count */
        !            28:        int     htdt;           /* drive type */
        !            29:        int     htck;           /* nrzi check (crc) error character */
        !            30:        int     htsn;           /* serial number */
        !            31:        int     httc;           /* tape control */
        !            32: };
        !            33: 
        !            34: /* htcs1 */
        !            35: #define        HT_GO           000001          /* go bit */
        !            36: #define        HT_REWOFFL      000002          /* rewind offline */
        !            37: #define        HT_REW          000006          /* rewind */
        !            38: #define        HT_DCLR         000010          /* drive clear */
        !            39: #define        HT_ERASE        000024          /* erase */
        !            40: #define        HT_WEOF         000026          /* write tape mark */
        !            41: #define        HT_SFORW        000030          /* space forward */
        !            42: #define        HT_SREV         000032          /* space reverse */
        !            43: #define        HT_WCOM         000060          /* write forward */
        !            44: #define        HT_RCOM         000070          /* read forward */
        !            45: 
        !            46: /* htds */
        !            47: #define        HTDS_ATA        0100000         /* attention active */
        !            48: #define        HTDS_ERR        0040000         /* composite error */
        !            49: #define        HTDS_MOL        0010000         /* medium on line */
        !            50: #define        HTDS_WRL        0004000         /* write lock */
        !            51: #define        HTDS_EOT        0002000         /* end of tape */
        !            52: #define        HTDS_DPR        0000400         /* drive present (always 1) */
        !            53: #define        HTDS_DRY        0000200         /* drive ready */
        !            54: #define        HTDS_SSC        0000100         /* slace status changed */
        !            55: #define        HTDS_PES        0000040         /* phase-encoded status */
        !            56: #define        HTDS_TM         0000004         /* tape mark */
        !            57: #define        HTDS_BOT        0000002         /* beginning of tape */
        !            58: #define        HTDS_SLA        0000001         /* slave attention */
        !            59: 
        !            60: /* hter */
        !            61: #define        HTER_CORCRC     0100000         /* correctible data or ecc */
        !            62: #define        HTER_UNS        0040000         /* unsafe */
        !            63: #define        HTER_OPI        0020000         /* operation incomplete */
        !            64: #define        HTER_DTE        0010000         /* drive timing error */
        !            65: #define        HTER_NEF        0004000         /* non-executable function */
        !            66: #define        HTER_CSITM      0002000         /* correctable skew/illegal tape mark */
        !            67: #define        HTER_FCE        0001000         /* frame count error */
        !            68: #define        HTER_NSG        0000400         /* non-standard gap */
        !            69: #define        HTER_PEFLRC     0000200         /* format error or lrc error */
        !            70: #define        HTER_DPAR       0000040         /* data parity error */
        !            71: #define        HTER_FMT        0000020         /* format error */
        !            72: #define        HTER_CPAR       0000010         /* control bus parity error */
        !            73: #define        HTER_RMR        0000004         /* register modification refused */
        !            74: #define        HTER_ILR        0000002         /* illegal register */
        !            75: #define        HTER_ILF        0000001         /* illegal function */
        !            76: #define        HTER_HARD \
        !            77:        (HTER_UNS|HTER_OPI|HTER_NEF|HTER_DPAR|HTER_FMT|HTER_CPAR| \
        !            78:        HTER_RMR|HTER_ILR|HTER_ILF)
        !            79: 
        !            80: /* htdt */
        !            81: #define        HTDT_SPR        0002000         /* slave present */
        !            82: 
        !            83: /* httc */
        !            84: #define        HTTC_800BPI     0001400         /* in bits 8-10, dens=1600 */
        !            85: #define        HTTC_1600BPI    0002000         /* in bits 8-10, dens=800 */
        !            86: #define        HTTC_PDP11      0000300         /* in bits 4-7, pdp11 normal format */
        !            87: 
        !            88: /*
        !            89:  * system stuff
        !            90:  */
        !            91: 
        !            92: int te16open(), te16close(), te16read(), te16write(), te16ioctl(), te16strategy();
        !            93: struct cdevsw te16cdev = cdinit(te16open, te16close, te16read, te16write, te16ioctl);
        !            94: struct bdevsw te16bdev = bdinit(te16open, te16close, te16strategy, B_TAPE);
        !            95: 
        !            96: /*
        !            97:  * per-formatter stuff
        !            98:  */
        !            99: 
        !           100: extern int tm03cnt;
        !           101: extern struct tm03 tm03[];
        !           102: extern struct mbaddr tm03addr[];
        !           103: 
        !           104: #define        T_BUSY  01              /* controller busy */
        !           105: #define        NOUNIT  0377            /* no unit expected */
        !           106: 
        !           107: /*
        !           108:  * per-drive stuff
        !           109:  */
        !           110: 
        !           111: extern int te16cnt;
        !           112: extern struct te16 te16[];
        !           113: extern struct subaddr te16addr[];
        !           114: extern struct buf rte16buf[];
        !           115: extern struct buf cte16buf[];
        !           116: 
        !           117: /*
        !           118:  * bits in minor device
        !           119:  */
        !           120: #define        TEUNIT(dev)     (minor(dev)&03)
        !           121: #define        H_NOREWIND      04
        !           122: #define        H_1600BPI       010
        !           123: 
        !           124: /*
        !           125:  * sc_flags
        !           126:  */
        !           127: #define        H_BUSY  01      /* software drive busy */
        !           128: #define        H_CMD   02      /* hardware command pending */
        !           129: #define        H_WRITTEN 04    /* last operation was a write */
        !           130: #define H_ERASED  010  /* last write retry was an erase gap */
        !           131: #define        H_OPEN  020     /* device open */
        !           132: #define        H_OFFLINE 040   /* device went offline; no io till close */
        !           133: #define        H_WONLY 0100    /* write-only */
        !           134: 
        !           135: /*
        !           136:  * scaling for block magtape blocks
        !           137:  */
        !           138: #define        INF     1000000L /* a block number that won't exist */
        !           139: #define        TBLOCK  2       /* tape blocks per b_blkno block */
        !           140: #define        TBSIZE  1024
        !           141: #define        TBSHIFT 10
        !           142: 
        !           143: /*
        !           144:  * overloads in struct buf; for te16cmd
        !           145:  */
        !           146: #define        b_repcnt  b_bcount
        !           147: #define        b_command b_resid
        !           148: 
        !           149: te16open(dev, flag)
        !           150:        dev_t dev;
        !           151:        int flag;
        !           152: {
        !           153:        register int teunit;
        !           154:        register struct te16 *sc;
        !           155:        register struct subaddr *sa;
        !           156:        register struct device *htaddr;
        !           157:        register int dt;
        !           158: 
        !           159:        teunit = TEUNIT(dev);
        !           160:        if (teunit >= te16cnt || (sc = &te16[teunit])->sc_flags & H_OPEN) {
        !           161:                u.u_error = ENXIO;
        !           162:                return;
        !           163:        }
        !           164:        sc->sc_flags |= H_OPEN;
        !           165:        sa = &te16addr[teunit];
        !           166:        if (tm03init(sa->ctl, sa->unit, teunit) == 0) {
        !           167:                sc->sc_flags &=~ H_OPEN;
        !           168:                u.u_error = ENXIO;
        !           169:                return;
        !           170:        }
        !           171:        sc->sc_ctl = &tm03[sa->ctl];
        !           172:        htaddr = sc->sc_ctl->cc_addr;
        !           173:        sc->sc_dens = ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|HTTC_PDP11|sa->unit;
        !           174:        spl5();
        !           175:        htaddr->httc = sc->sc_dens;
        !           176:        /* delay here? */
        !           177:        dt = htaddr->htdt;
        !           178:        sc->sc_dsreg = htaddr->htds;
        !           179:        spl0();
        !           180:        if ((dt & HTDT_SPR) == 0) {
        !           181:                printf("te16 %d absent\n", teunit);
        !           182:                sc->sc_flags &=~ H_OPEN;
        !           183:                u.u_error = ENODEV;
        !           184:                return;
        !           185:        }
        !           186:        if ((sc->sc_dsreg & HTDS_MOL) == 0) {
        !           187:                sc->sc_flags &=~ H_OPEN;
        !           188:                u.u_error = EIO;
        !           189:                return;
        !           190:        }
        !           191:        if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) {
        !           192:                sc->sc_flags &=~ H_OPEN;
        !           193:                u.u_error = EIO;
        !           194:                return;
        !           195:        }
        !           196:        if ((sc->sc_dsreg & HTDS_BOT) == 0 && flag&FWRITE
        !           197:        &&  ((minor(dev) & H_1600BPI) != 0) != ((sc->sc_dsreg & HTDS_PES) != 0)) {
        !           198:                sc->sc_flags &=~ H_OPEN;
        !           199:                u.u_error = EIO;
        !           200:                return;
        !           201:        }
        !           202:        sc->sc_blkno = 0;
        !           203:        sc->sc_nxrec = INF;
        !           204:        if ((flag & (FREAD|FWRITE)) == FWRITE)
        !           205:                sc->sc_flags |= H_WONLY;        /* stop block dev readahead */
        !           206: }
        !           207: 
        !           208: tm03init(ctl, slave, dev)
        !           209: register int ctl;
        !           210: int slave, dev;
        !           211: {
        !           212:        register struct tm03 *cc;
        !           213:        register int i;
        !           214: 
        !           215:        if (ctl < 0 || slave < 0 || ctl >= tm03cnt || slave >= TM03DRIVES)
        !           216:                return (0);
        !           217:        cc = &tm03[ctl];
        !           218:        cc->cc_drives[slave] = dev;
        !           219:        if (cc->cc_addr)
        !           220:                return (1);
        !           221:        if ((cc->cc_addr = (struct device *)mbaddr(&tm03addr[ctl])) == 0
        !           222:        ||  badaddr(&cc->cc_addr->htcs1, sizeof(long))
        !           223:        ||  (cc->cc_addr->htds & HTDS_DPR) == 0) {
        !           224:                printf("tm03 %d absent\n", ctl);
        !           225:                return (0);
        !           226:        }
        !           227:        cc->cc_mbaddr = &tm03addr[ctl];
        !           228:        for (i = 0; i < TM03DRIVES; i++)
        !           229:                if (i != slave)
        !           230:                        cc->cc_drives[i] = NOUNIT;
        !           231:        /* any reset worth doing? */
        !           232:        return (1);
        !           233: }
        !           234: 
        !           235: te16close(dev)
        !           236:        register dev_t dev;
        !           237: {
        !           238:        register struct te16 *sc = &te16[TEUNIT(dev)];
        !           239: 
        !           240:        if (sc->sc_flags & (H_WONLY|H_WRITTEN)) {
        !           241:                te16cmd(dev, HT_WEOF, 1);
        !           242:                te16cmd(dev, HT_WEOF, 1);
        !           243:                te16cmd(dev, HT_SREV, 1);
        !           244:        }
        !           245:        if ((minor(dev)&H_NOREWIND) == 0)
        !           246:                te16cmd(dev, HT_REW, 0);
        !           247:        sc->sc_flags &= H_CMD|H_BUSY;
        !           248: }
        !           249: 
        !           250: te16cmd(dev, com, count)
        !           251:        dev_t dev;
        !           252:        int com, count;
        !           253: {
        !           254:        register struct buf *bp;
        !           255: 
        !           256:        bp = &cte16buf[TEUNIT(dev)];
        !           257:        (void) spl5();
        !           258:        while (bp->b_flags&B_BUSY) {
        !           259:                if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
        !           260:                        break;
        !           261:                bp->b_flags |= B_WANTED;
        !           262:                sleep((caddr_t)bp, PRIBIO);
        !           263:        }
        !           264:        bp->b_flags = B_BUSY|B_READ;
        !           265:        (void) spl0();
        !           266:        bp->b_dev = dev;
        !           267:        bp->b_command = com;
        !           268:        bp->b_repcnt = count;
        !           269:        bp->b_blkno = 0;
        !           270:        te16strategy(bp);
        !           271:        if (count == 0) {
        !           272:                if (bp->b_flags & B_DONE)
        !           273:                        geterror(bp);
        !           274:                return;
        !           275:        }
        !           276:        iowait(bp);
        !           277:        if (bp->b_flags&B_WANTED)
        !           278:                wakeup((caddr_t)bp);
        !           279:        bp->b_flags &=~ B_BUSY;
        !           280: }
        !           281: 
        !           282: te16strategy(bp)
        !           283:        register struct buf *bp;
        !           284: {
        !           285:        register struct te16 *sc;
        !           286: 
        !           287:        sc = &te16[TEUNIT(bp->b_dev)];
        !           288:        bp->av_forw = NULL;
        !           289:        (void) spl5();
        !           290:        if (sc->sc_actf == NULL)
        !           291:                sc->sc_actf = bp;
        !           292:        else
        !           293:                sc->sc_actl->av_forw = bp;
        !           294:        sc->sc_actl = bp;
        !           295:        if ((sc->sc_flags & H_BUSY) == 0)
        !           296:                te16start(sc);
        !           297:        if (sc->sc_ctl->cc_actf && (sc->sc_ctl->cc_flags & T_BUSY) == 0)
        !           298:                tm03start(sc->sc_ctl);
        !           299:        (void) spl0();
        !           300: }
        !           301: 
        !           302: te16start(sc)
        !           303: register struct te16 *sc;
        !           304: {
        !           305:        register struct buf *bp;
        !           306:        register struct device *htaddr;
        !           307:        register struct tm03 *cc;
        !           308:        register daddr_t bno;
        !           309: 
        !           310:        cc = sc->sc_ctl;
        !           311: loop:
        !           312:        if ((bp = sc->sc_actf) == 0)
        !           313:                return;
        !           314:        htaddr = cc->cc_addr;
        !           315:        htaddr->httc = sc->sc_dens;
        !           316:        if (htaddr->htds & HTDS_SSC)
        !           317:                htaddr->htcs1 = HT_DCLR|HT_GO;
        !           318:        sc->sc_dsreg = htaddr->htds;
        !           319:        sc->sc_erreg = htaddr->hter;
        !           320:        sc->sc_resid = htaddr->htfc;
        !           321:        sc->sc_flags &= ~H_WRITTEN;
        !           322:        if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0)
        !           323:                if (sc->sc_flags & H_OPEN)
        !           324:                        sc->sc_flags |= H_OFFLINE;
        !           325:        if (sc->sc_flags & H_OFFLINE) {
        !           326:                bp->b_flags |= B_ERROR;
        !           327:                goto done;
        !           328:        }
        !           329:        /*
        !           330:         * command, start it
        !           331:         */
        !           332:        if (bp == &cte16buf[TEUNIT(bp->b_dev)]) {
        !           333:                sc->sc_flags |= H_BUSY|H_CMD;
        !           334:                htaddr->htfc = -bp->b_bcount;
        !           335:                htaddr->htcs1 = bp->b_command|HT_GO;
        !           336:                return;
        !           337:        }
        !           338:        /*
        !           339:         * transfer, see if position needed (wretched block magtape)
        !           340:         */
        !           341:        bno = bp->b_blkno/TBLOCK;       
        !           342:        if (bno > sc->sc_nxrec) {
        !           343:                bp->b_error = ENXIO;
        !           344:                bp->b_flags |= B_ERROR;
        !           345:                goto done;
        !           346:        }
        !           347:        if (bp->b_flags & B_READ        /* at EOF, or really just writing? */
        !           348:        &&  (bno == sc->sc_nxrec || sc->sc_flags & H_WONLY)) {
        !           349:                bp->b_resid = bp->b_bcount;
        !           350:                goto done;
        !           351:        }
        !           352:        if ((bp->b_flags&B_READ)==0)
        !           353:                sc->sc_nxrec = bno + 1;
        !           354:        if (sc->sc_blkno != bno) {      /* need position */
        !           355:                sc->sc_flags |= H_BUSY|H_CMD;
        !           356:                if (sc->sc_blkno < bno) {
        !           357:                        htaddr->htfc = sc->sc_blkno - bno;
        !           358:                        htaddr->htcs1 = HT_SFORW|HT_GO;
        !           359:                } else {
        !           360:                        htaddr->htfc = bno - sc->sc_blkno;
        !           361:                        htaddr->htcs1 = HT_SREV|HT_GO;
        !           362:                }
        !           363:                return;
        !           364:        }
        !           365:        /*
        !           366:         * special pleading for `erase gap' write error recovery
        !           367:         * -- is this in the right place?  why bother?
        !           368:         */
        !           369:        if ((bp->b_flags&B_READ) == 0) {
        !           370:                if (cc->cc_errcnt) {
        !           371:                        if ((sc->sc_flags & H_ERASED) == 0) {
        !           372:                                sc->sc_flags |= H_ERASED|H_BUSY|H_CMD;
        !           373:                                htaddr->htcs1 = HT_ERASE|HT_GO;
        !           374:                                return;
        !           375:                        }
        !           376:                        sc->sc_flags &= ~H_ERASED;
        !           377:                }
        !           378:                if (htaddr->htds & HTDS_EOT) {          /* oops */
        !           379:                        bp->b_resid = bp->b_bcount;
        !           380: done:
        !           381:                        sc->sc_actf = bp->av_forw;
        !           382:                        iodone(bp);
        !           383:                        goto loop;
        !           384:                }
        !           385:        }
        !           386:        /*
        !           387:         * time for a transfer
        !           388:         */
        !           389:        cc = sc->sc_ctl;
        !           390:        sc->sc_next = NULL;
        !           391:        if (cc->cc_actf == NULL)
        !           392:                cc->cc_actf = sc;
        !           393:        else
        !           394:                cc->cc_actl->sc_next = sc;
        !           395:        cc->cc_actl = sc;
        !           396:        sc->sc_flags |= H_BUSY;
        !           397: }
        !           398: 
        !           399: tm03start(cc)
        !           400: register struct tm03 *cc;
        !           401: {
        !           402:        register struct te16 *sc;
        !           403:        int tm03xfer();
        !           404: 
        !           405:        if ((sc = cc->cc_actf) == NULL)
        !           406:                return;
        !           407:        if (sc->sc_actf == NULL)
        !           408:                panic("tm03start");
        !           409:        cc->cc_flags |= T_BUSY;
        !           410:        mbstart(cc->cc_mbaddr, sc->sc_actf, tm03xfer);
        !           411: }
        !           412: 
        !           413: tm03xfer(bp)
        !           414: register struct buf *bp;
        !           415: {
        !           416:        register struct te16 *sc;
        !           417:        register struct device *htaddr;
        !           418: 
        !           419:        sc = &te16[TEUNIT(bp->b_dev)];
        !           420:        htaddr = sc->sc_ctl->cc_addr;
        !           421:        htaddr->httc = sc->sc_dens;
        !           422:        htaddr->htfc = -bp->b_bcount;
        !           423:        sc->sc_flags |= H_CMD;
        !           424:        if (bp->b_flags & B_READ)
        !           425:                htaddr->htcs1 = HT_RCOM|HT_GO;
        !           426:        else
        !           427:                htaddr->htcs1 = HT_WCOM|HT_GO;
        !           428: }
        !           429: 
        !           430: /*
        !           431:  * massbus interrupt
        !           432:  * if a transfer was pending, assume it finished;
        !           433:  * if attn set, something else finished too
        !           434:  *
        !           435:  * the loop to see which drives wanted attention is somewhat doubtful
        !           436:  * and has not been tested with multiple drives
        !           437:  */
        !           438: tm030int(ctl, mbsr, mbbc, attn)
        !           439: int ctl, mbsr, mbbc, attn;
        !           440: {
        !           441:        register struct tm03 *cc;
        !           442:        register struct device *htaddr;
        !           443:        register struct te16 *sc;
        !           444:        register int i;
        !           445: 
        !           446:        cc = &tm03[ctl];
        !           447:        if ((htaddr = cc->cc_addr) == NULL) {
        !           448:                printf("tm03 %d: stray intr\n", ctl);
        !           449:                return;
        !           450:        }
        !           451:        htaddr->htas = attn;            /* before we do anything */
        !           452:        if (cc->cc_flags & T_BUSY)
        !           453:                te16dtint(cc, mbsr);
        !           454:        if (attn) {
        !           455:                for (i = 0; i < TM03DRIVES; i++) {
        !           456:                        if (cc->cc_drives[i] == NOUNIT)
        !           457:                                continue;
        !           458:                        sc = &te16[cc->cc_drives[i]];
        !           459:                        htaddr->httc = sc->sc_dens;     /* select drive */
        !           460:                        if ((sc->sc_flags & H_CMD) == 0) {
        !           461:                                sc->sc_dsreg = htaddr->htds;    /* for BOT detection */
        !           462:                                wakeup((caddr_t)sc);
        !           463:                                if (htaddr->htds & HTDS_SSC)
        !           464:                                        htaddr->htcs1 = HT_DCLR|HT_GO;
        !           465:                                continue;
        !           466:                        }
        !           467:                        if ((htaddr->htds & HTDS_DRY) == 0)
        !           468:                                continue;
        !           469:                        te16attn(sc);
        !           470:                }
        !           471:        }
        !           472:        if (cc->cc_actf)
        !           473:                tm03start(cc);
        !           474: }
        !           475: 
        !           476: /*
        !           477:  * error recovery is somewhat doubtful
        !           478:  * particular specialties:
        !           479:  * - short reads show up as frame count errors,
        !           480:  *   so ignore them for the raw device
        !           481:  * - reading at tape mark seems to produce a frame count error too
        !           482:  * - quietly ignore CRC errors the drive corrected
        !           483:  */
        !           484: te16dtint(cc, mbsr)
        !           485: register struct tm03 *cc;
        !           486: int mbsr;
        !           487: {
        !           488:        register struct device *htaddr;
        !           489:        register struct buf *bp;
        !           490:        register struct te16 *sc;
        !           491:        int ds, er, mbs;
        !           492: 
        !           493:        htaddr = cc->cc_addr;
        !           494:        if ((sc = cc->cc_actf) == NULL)
        !           495:                panic("te16dtint");
        !           496:        sc->sc_flags &=~ H_CMD;
        !           497:        bp = sc->sc_actf;
        !           498:        ds = sc->sc_dsreg = htaddr->htds;
        !           499:        er = sc->sc_erreg = htaddr->hter;
        !           500:        sc->sc_resid = htaddr->htfc;
        !           501: #if BABBLE
        !           502: printf("dt: ds%o er%o fc%o mbs%o\n", ds, er, sc->sc_resid, mbsr);
        !           503: printf("bp: bn%d bc%d fl%o\n", bp->b_blkno, bp->b_bcount, bp->b_flags);
        !           504: #endif
        !           505:        mbs = mbsr;
        !           506:        if (er)
        !           507:                htaddr->htcs1 = HT_DCLR|HT_GO;
        !           508:        sc->sc_blkno++;
        !           509:        if((bp->b_flags & B_READ) == 0)
        !           510:                sc->sc_flags |= H_WRITTEN;
        !           511:        if (bp == &rte16buf[TEUNIT(bp->b_dev)] || ds & HTDS_TM) {
        !           512:                if (er & HTER_FCE) {
        !           513:                        er &=~ HTER_FCE;
        !           514:                        mbs &=~ (MBSR_DTABT|MBSR_MBEXC);
        !           515:                }
        !           516:        }
        !           517:        if (er & HTER_HARD || (ds & HTDS_MOL) == 0 || mbs & MBSR_EBITS)
        !           518:                bp->b_flags |= B_ERROR;
        !           519:        else if (er) {                          /* soft error */
        !           520:                if (++cc->cc_errcnt >= 7)
        !           521:                        bp->b_flags |= B_ERROR;
        !           522:                else
        !           523:                        cc->cc_flags &=~ T_BUSY;
        !           524:        }
        !           525:        if (bp->b_flags & B_ERROR)
        !           526:                printf("te16 %d: hard error bn%d mbsr=%o er=%o ds=%o\n",
        !           527:                  TEUNIT(bp->b_dev), bp->b_blkno/TBLOCK, mbsr, sc->sc_erreg, sc->sc_dsreg);
        !           528:        if ((bp->b_flags & B_READ) == 0)
        !           529:                bp->b_resid = -sc->sc_resid;
        !           530:        else {
        !           531:                if (ds & HTDS_TM) {
        !           532:                        bp->b_resid = bp->b_bcount;
        !           533:                        sc->sc_nxrec = bp->b_blkno/TBLOCK;
        !           534:                } else if (sc->sc_resid > bp->b_bcount) {
        !           535:                        bp->b_flags |= B_ERROR;
        !           536:                        bp->b_error = ENOMEM;
        !           537:                } else
        !           538:                        bp->b_resid = bp->b_bcount - sc->sc_resid;
        !           539:        }
        !           540:        if (cc->cc_flags & T_BUSY) {    /* we decided we were finished */
        !           541:                sc->sc_actf = bp->av_forw;
        !           542:                iodone(bp);
        !           543:                cc->cc_actf = sc->sc_next;
        !           544:                cc->cc_errcnt = 0;
        !           545:                cc->cc_flags &=~ T_BUSY;
        !           546:        }
        !           547:        sc->sc_flags &=~ H_BUSY;
        !           548:        if (sc->sc_actf)
        !           549:                te16start(sc);
        !           550: }
        !           551: 
        !           552: te16attn(sc)
        !           553: register struct te16 *sc;
        !           554: {
        !           555:        register struct device *htaddr;
        !           556:        register struct buf *bp;
        !           557:        register struct tm03 *cc;
        !           558:        register int er, ds;
        !           559:        daddr_t bno;
        !           560: 
        !           561:        sc->sc_flags &=~ H_CMD;
        !           562:        cc = sc->sc_ctl;
        !           563:        htaddr = cc->cc_addr;
        !           564:        ds = sc->sc_dsreg = htaddr->htds;
        !           565:        er = sc->sc_erreg = htaddr->hter;
        !           566:        sc->sc_resid = htaddr->htfc;
        !           567:        if (er)
        !           568:                htaddr->htcs1 = HT_DCLR|HT_GO;
        !           569:        wakeup((caddr_t)sc);
        !           570:        if ((bp = sc->sc_actf) == 0)
        !           571:                return;
        !           572: #if BABBLE
        !           573: printf("at: ds%o er%o fc%o\n", sc->sc_dsreg, sc->sc_erreg, sc->sc_resid);
        !           574: printf("bp: bn%d bc%d fl%o cm%o\n", bp->b_blkno, bp->b_bcount, bp->b_flags, bp->b_command);
        !           575: #endif
        !           576:        bno = bp->b_blkno/TBLOCK;
        !           577:        if (bp == &cte16buf[TEUNIT(bp->b_dev)]) {
        !           578:                switch ((int)bp->b_command) {
        !           579:                case HT_REWOFFL:
        !           580:                        /* offline is on purpose; don't do anything special */
        !           581:                        ds |= HTDS_MOL; 
        !           582:                        break;
        !           583:                case HT_SREV:
        !           584:                        /* if backspace file hit bot, its not an error */
        !           585:                        if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT
        !           586:                        &&  bp->b_repcnt == INF)
        !           587:                                er &= ~HTER_NEF;
        !           588:                        break;
        !           589:                }
        !           590:                er &= ~HTER_FCE;
        !           591:                if (er == 0)
        !           592:                        ds &= ~HTDS_ERR;
        !           593:        }
        !           594:        if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) {
        !           595:                if ((ds & HTDS_MOL) == 0 && sc->sc_flags & H_OPEN)
        !           596:                        sc->sc_flags |= H_OFFLINE;
        !           597:                printf("te16 %d: hard error bn%d er%o ds%o\n",
        !           598:                    TEUNIT(bp->b_dev), bno, sc->sc_erreg, sc->sc_dsreg);
        !           599:                bp->b_flags |= B_ERROR;
        !           600:        }
        !           601:        if (bp == &cte16buf[TEUNIT(bp->b_dev)])
        !           602:                bp->b_resid = -sc->sc_resid;
        !           603:        else
        !           604:                sc->sc_flags &=~ H_BUSY;        /* done seeking, now xfer */
        !           605:        if ((ds & HTDS_TM) == 0)
        !           606:                sc->sc_blkno = bno;
        !           607:        else if (sc->sc_blkno > bno) {
        !           608:                sc->sc_nxrec = bno - sc->sc_resid;
        !           609:                sc->sc_blkno = sc->sc_nxrec;
        !           610:        } else {
        !           611:                sc->sc_blkno = bno + sc->sc_resid;
        !           612:                sc->sc_nxrec = sc->sc_blkno - 1;
        !           613:        }
        !           614:        if (sc->sc_flags & H_BUSY) {
        !           615:                sc->sc_actf = bp->av_forw;
        !           616:                iodone(bp);
        !           617:                sc->sc_flags &=~ H_BUSY;
        !           618:        }
        !           619:        if (sc->sc_actf)
        !           620:                te16start(sc);
        !           621: }
        !           622: 
        !           623: te16read(dev)
        !           624: dev_t dev;
        !           625: {
        !           626: 
        !           627:        te16phys(dev);
        !           628:        physio(te16strategy, &rte16buf[TEUNIT(dev)], dev, B_READ, minphys);
        !           629: }
        !           630: 
        !           631: te16write(dev)
        !           632: dev_t dev;
        !           633: {
        !           634: 
        !           635:        te16phys(dev);
        !           636:        physio(te16strategy, &rte16buf[TEUNIT(dev)], dev, B_WRITE, minphys);
        !           637: }
        !           638: 
        !           639: te16phys(dev)
        !           640: dev_t dev;
        !           641: {
        !           642:        register struct te16 *sc;
        !           643: 
        !           644:        sc = &te16[TEUNIT(dev)];
        !           645:        sc->sc_blkno = Lshift(u.u_offset, TBSHIFT);
        !           646:        sc->sc_nxrec = sc->sc_blkno + 1;
        !           647: }
        !           648: 
        !           649: /*ARGSUSED*/
        !           650: te16ioctl(dev, cmd, addr, flag)
        !           651:        dev_t dev;
        !           652:        int cmd;
        !           653:        caddr_t addr;
        !           654:        int flag;
        !           655: {
        !           656:        register struct te16 *sc = &te16[TEUNIT(dev)];
        !           657:        register struct buf *bp = &cte16buf[TEUNIT(dev)];
        !           658:        register callcount;
        !           659:        int fcount, htcmd;
        !           660:        struct mtop mtop;
        !           661: 
        !           662:        switch (cmd) {
        !           663:                case MTIOCTOP:
        !           664:                if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
        !           665:                        u.u_error = EFAULT;
        !           666:                        return;
        !           667:                }
        !           668:                if (mtop.mt_count <= 0) {
        !           669:                        u.u_error = ENXIO;
        !           670:                        return;
        !           671:                }
        !           672:                switch(mtop.mt_op) {
        !           673:                case MTWEOF:
        !           674:                        htcmd = HT_WEOF;
        !           675:                        callcount = mtop.mt_count;
        !           676:                        fcount = 1;
        !           677:                        break;
        !           678:                case MTFSF: case MTBSF:
        !           679:                        htcmd = (mtop.mt_op == MTFSF) ? HT_SFORW : HT_SREV;
        !           680:                        callcount = mtop.mt_count;
        !           681:                        fcount = INF;
        !           682:                        break;
        !           683:                case MTFSR: case MTBSR:
        !           684:                        htcmd = (mtop.mt_op == MTFSF) ? HT_SFORW : HT_SREV;
        !           685:                        callcount = 1;
        !           686:                        fcount = mtop.mt_count;
        !           687:                        break;
        !           688:                case MTREW: case MTOFFL:
        !           689:                        te16cmd(dev, HT_REW, 1);
        !           690:                        if (mtop.mt_op == MTREW)
        !           691:                                return;
        !           692:                        spl5();
        !           693:                        while ((sc->sc_dsreg & HTDS_BOT) == 0)
        !           694:                                sleep((caddr_t)sc, PZERO);
        !           695:                        spl0();
        !           696:                        te16cmd(dev, HT_REWOFFL, 0);
        !           697:                        return;
        !           698:                default:
        !           699:                        u.u_error = ENXIO;
        !           700:                        return;
        !           701:                }
        !           702:                while (--callcount >= 0) {
        !           703:                        te16cmd(dev, htcmd, fcount);
        !           704:                        if (bp->b_resid
        !           705:                        &&  (mtop.mt_op == MTFSR || mtop.mt_op == MTBSR)) {
        !           706:                                u.u_error = EIO;
        !           707:                                break;
        !           708:                        }
        !           709:                        if (u.u_error || sc->sc_dsreg&HTDS_BOT)
        !           710:                                break;
        !           711:                }
        !           712:                return;
        !           713: 
        !           714:        default:
        !           715:                u.u_error = ENXIO;
        !           716:                return;
        !           717:        }
        !           718: }

unix.superglobalmegacorp.com

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