Annotation of researchv10dc/sys/io/tu78.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * TM78/TU78 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/tu78.h"
        !            17: 
        !            18: /*
        !            19:  * hardware stuff
        !            20:  */
        !            21: 
        !            22: struct device {
        !            23:        int     mtcs;           /* control/status */
        !            24:        int     mter;           /* error */
        !            25:        int     mtca;           /* command address, rec cnt, skp cnt */
        !            26:        int     mtmr1;          /* maint */
        !            27:        int     mtas;           /* attention summary */
        !            28:        int     mtbc;           /* byte count */
        !            29:        int     mtdt;           /* drive type */
        !            30:        int     mtds;           /* drive status */
        !            31:        int     mtsn;           /* serial number */
        !            32:        int     mtmr2;          /* maint */
        !            33:        int     mtmr3;          /* maint */
        !            34:        int     mtner;          /* non-data transfer error */
        !            35:        int     mtncs[TM78DRIVES];      /* non-data transfer command */
        !            36:        int     mtia;           /* internal address */
        !            37:        int     mtid;           /* internal data */
        !            38: };
        !            39: 
        !            40: /* mtcs */
        !            41: #define        MT_GO           000001          /* go bit */
        !            42: #define        MT_GCR          000002          /* make generic ops GCR ops */
        !            43: #define        MT_UNLOAD       000004          /* unload tape */
        !            44: #define        MT_REW          000006          /* rewind */
        !            45: #define        MT_SENSE        000010          /* sense */
        !            46: #define        MT_WTM          000014          /* generic write tape mark */
        !            47: #define        MT_SFORW        000020          /* space forward record */
        !            48: #define        MT_SREV         000022          /* space reverse record */
        !            49: #define        MT_SFORWF       000024          /* space forward file */
        !            50: #define        MT_SREVF        000026          /* space reverse file */
        !            51: #define        MT_CLS          000040          /* generic close file */
        !            52: #define        MT_WRITE        000060          /* generic write */
        !            53: #define        MT_READ         000070          /* read forward */
        !            54: #define        MT_READREV      000076          /* read reverse */
        !            55: 
        !            56: /* mtds */
        !            57: #define        MTDS_PRES       0040000         /* tape unit has power */
        !            58: #define        MTDS_ONL        0020000         /* online */
        !            59: #define        MTDS_PE         0004000         /* tape set for phase encoded */
        !            60: #define        MTDS_BOT        0002000         /* tape at BOT */
        !            61: #define        MTDS_FPT        0000400         /* write protected */
        !            62: #define        MTDS_AVAIL      0000200         /* unit available */
        !            63: 
        !            64: /* mtncs */
        !            65: #define        MT_COFF         8               /* bits to shift count */
        !            66: #define        MTNCS_COUNT(c)  (((c)>>MT_COFF)&0377)   /* repeat count */
        !            67: #define        MAXCOUNT        0377
        !            68: 
        !            69: /* mter */
        !            70: #define        MTER_INTCODE(e) ((int)(e)&0377) /* interrupt code */
        !            71: #define        MTER_DPR        0400            /* drive (formatter) present */
        !            72: #define        MTER_UNIT(e)    (((e)>>8)&03)   /* interrupting unit in mtner */
        !            73: 
        !            74: /* interrupt codes */
        !            75: #define        MTER_DONE       001             /* operation complete */
        !            76: #define        MTER_TM         002             /* unexpected tape mark */
        !            77: #define        MTER_BOT        003             /* unexpected BOT detected */
        !            78: #define        MTER_EOT        004             /* tape positioned beyond EOT */
        !            79: #define        MTER_LEOT       005             /* unexpected LEOT detected */
        !            80: #define        MTER_NOOP       006             /* no-op completed */
        !            81: #define        MTER_RWDING     007             /* rewinding */
        !            82: #define        MTER_FPT        010             /* write protect error */
        !            83: #define        MTER_NOTRDY     011             /* not ready */
        !            84: #define        MTER_NOTAVL     012             /* not available */
        !            85: #define        MTER_OFFLINE    013             /* offline */
        !            86: #define        MTER_NONEX      014             /* unit does not exist */
        !            87: #define        MTER_NOTCAP     015             /* not capable */
        !            88: #define        MTER_ONLINE     017             /* tape came online */
        !            89: #define        MTER_LONGREC    020             /* long tape record */
        !            90: #define        MTER_SHRTREC    021             /* short tape record */
        !            91: #define        MTER_RETRY      022             /* retry */
        !            92: #define        MTER_RDOPP      023             /* read opposite */
        !            93: #define        MTER_UNREAD     024             /* unreadable */
        !            94: #define        MTER_ERROR      025             /* error */
        !            95: #define        MTER_EOTERR     026             /* EOT error */
        !            96: #define        MTER_BADTAPE    027             /* tape position lost */
        !            97: #define        MTER_TMFLTA     030             /* TM fault A */
        !            98: #define        MTER_TUFLTA     031             /* TU fault A */
        !            99: #define        MTER_TMFLTB     032             /* TM fault B */
        !           100: #define        MTER_MBFLT      034             /* Massbus fault */
        !           101: #define        MTER_KEYFAIL    077             /* keypad entry error */
        !           102: 
        !           103: /* mtid */
        !           104: #define        MTID_RDY        0100000         /* controller ready */
        !           105: #define        MTID_CLR        0040000         /* controller clear */
        !           106: 
        !           107: #define MTTIMEOUT      10000           /* loop limit for controller test */
        !           108: 
        !           109: /*
        !           110:  * system stuff
        !           111:  */
        !           112: 
        !           113: int tu78open(), tu78close(), tu78read(), tu78write(), tu78ioctl(), tu78strategy();
        !           114: struct cdevsw tu78cdev = cdinit(tu78open, tu78close, tu78read, tu78write, tu78ioctl);
        !           115: struct bdevsw tu78bdev = bdinit(tu78open, tu78close, tu78strategy, B_TAPE);
        !           116: 
        !           117: /*
        !           118:  * per-formatter stuff
        !           119:  */
        !           120: 
        !           121: extern int tm78cnt;
        !           122: extern struct tm78 tm78[];
        !           123: extern struct mbaddr tm78addr[];
        !           124: 
        !           125: #define        T_BUSY  01              /* controller busy */
        !           126: #define        NOUNIT  0377            /* no slave expected */
        !           127: 
        !           128: /*
        !           129:  * per-drive stuff
        !           130:  */
        !           131: 
        !           132: extern int tu78cnt;
        !           133: extern struct tu78 tu78[];
        !           134: extern struct subaddr tu78addr[];
        !           135: extern struct buf rtu78buf[];
        !           136: extern struct buf ctu78buf[];
        !           137: 
        !           138: /*
        !           139:  * bits in minor device
        !           140:  */
        !           141: #define        TUUNIT(dev)     (minor(dev)&03)
        !           142: #define        H_NOREWIND      04
        !           143: #define        H_6250BPI       010
        !           144: 
        !           145: /*
        !           146:  * sc_flags
        !           147:  */
        !           148: #define        H_BUSY  01      /* software drive busy */
        !           149: #define        H_EOT   02      /* saw physical end-of-tape */
        !           150: #define        H_WRITTEN 04    /* last operation was a write */
        !           151: #define H_ERASED  010  /* last write retry was an erase gap */
        !           152: #define        H_OPEN  020     /* device open */
        !           153: #define        H_OFFLINE 040   /* device went offline; no io till close */
        !           154: #define        H_WONLY 0100    /* write-only */
        !           155: 
        !           156: /*
        !           157:  * scaling for block magtape blocks
        !           158:  */
        !           159: #define        INF     1000000L /* a block number that won't exist */
        !           160: #define        TBLOCK  2       /* tape blocks per b_blkno block */
        !           161: #define        TBSIZE  1024
        !           162: #define        TBSHIFT 10
        !           163: 
        !           164: /*
        !           165:  * overloads in struct buf; for tu78cmd
        !           166:  */
        !           167: #define        b_repcnt  b_bcount
        !           168: #define        b_command b_resid
        !           169: 
        !           170: tu78open(dev, flag)
        !           171:        dev_t dev;
        !           172:        int flag;
        !           173: {
        !           174:        register int tuunit;
        !           175:        register struct tu78 *sc;
        !           176:        register struct subaddr *sa;
        !           177:        int dens;
        !           178: 
        !           179:        tuunit = TUUNIT(dev);
        !           180:        if (tuunit >= tu78cnt || (sc = &tu78[tuunit])->sc_flags & H_OPEN) {
        !           181:                u.u_error = ENXIO;
        !           182:                return;
        !           183:        }
        !           184:        sc->sc_flags |= H_OPEN;
        !           185:        sa = &tu78addr[tuunit];
        !           186:        if (tm78init(sa->ctl, sa->unit, tuunit) == 0) {
        !           187:                sc->sc_flags &=~ H_OPEN;
        !           188:                u.u_error = ENXIO;
        !           189:                return;
        !           190:        }
        !           191:        sc->sc_ctl = &tm78[sa->ctl];
        !           192:        sc->sc_dens = minor(dev) & H_6250BPI ? MT_GCR : 0;
        !           193:        sc->sc_slave = sa->unit;
        !           194:        sc->sc_flags &=~ H_OFFLINE;     /* so we can sense */
        !           195:        tu78cmd(dev, MT_SENSE, 1L);
        !           196:        if ((sc->sc_dsreg & MTDS_PRES) == 0) {  /* what's the right test? */
        !           197:                printf("tu78 %d absent\n", tuunit);
        !           198:                sc->sc_flags &=~ H_OPEN;
        !           199:                u.u_error = ENODEV;
        !           200:                return;
        !           201:        }
        !           202:        if ((sc->sc_dsreg & MTDS_ONL) == 0) {
        !           203:                sc->sc_flags &=~ H_OPEN;
        !           204:                u.u_error = EIO;
        !           205:                return;
        !           206:        }
        !           207:        if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) {
        !           208:                sc->sc_flags &=~ H_OPEN;
        !           209:                u.u_error = EIO;
        !           210:                return;
        !           211:        }
        !           212:        if ((sc->sc_dsreg & MTDS_BOT) == 0 && flag&FWRITE) {
        !           213:                dens = sc->sc_dsreg & MTDS_PE ? 0 : MT_GCR;
        !           214:                if (sc->sc_dens != dens) {
        !           215:                        sc->sc_flags &=~ H_OPEN;
        !           216:                        u.u_error = EIO;
        !           217:                        return;
        !           218:                }
        !           219:        }
        !           220:        sc->sc_blkno = 0;
        !           221:        sc->sc_nxrec = INF;
        !           222:        if ((flag & (FREAD|FWRITE)) == FWRITE)
        !           223:                sc->sc_flags |= H_WONLY;        /* stop block dev readahead */
        !           224: }
        !           225: 
        !           226: tm78init(ctl, slave, dev)
        !           227: register int ctl;
        !           228: int slave, dev;
        !           229: {
        !           230:        register struct tm78 *cc;
        !           231:        register int i;
        !           232: 
        !           233:        if (ctl < 0 || slave < 0 || ctl >= tm78cnt || slave >= TM78DRIVES)
        !           234:                return (0);
        !           235:        cc = &tm78[ctl];
        !           236:        cc->cc_drives[slave] = dev;
        !           237:        if (cc->cc_mbaddr)
        !           238:                return (1);
        !           239:        if ((cc->cc_addr = (struct device *)mbaddr(&tm78addr[ctl])) == 0
        !           240:        ||  badaddr(&cc->cc_addr->mtcs, sizeof(long))
        !           241:        ||  (cc->cc_addr->mter & MTER_DPR) == 0) {
        !           242:                printf("tm78 %d absent\n", ctl);
        !           243:                return (0);
        !           244:        }
        !           245:        for (i = 0; i < TM78DRIVES; i++)
        !           246:                if (i != slave)
        !           247:                        cc->cc_drives[i] = NOUNIT;
        !           248:        if (tm78reset(ctl) == 0)
        !           249:                return (0);
        !           250:        cc->cc_mbaddr = &tm78addr[ctl];
        !           251:        return (1);
        !           252: }
        !           253: 
        !           254: /*
        !           255:  * reset the formatter
        !           256:  * initially or after some awful error
        !           257:  */
        !           258: tm78reset(ctl)
        !           259: int ctl;
        !           260: {
        !           261:        register struct tm78 *cc;
        !           262:        register struct device *tmaddr;
        !           263:        register struct tu78 *sc;
        !           264:        register struct buf *bp;
        !           265:        register int i;
        !           266: 
        !           267:        cc = &tm78[ctl];
        !           268:        tmaddr = cc->cc_addr;
        !           269:        tmaddr->mtid = MTID_CLR;
        !           270:        while ((sc = cc->cc_actf) != NULL) {
        !           271:                cc->cc_actf = sc->sc_next;
        !           272:                while ((bp = sc->sc_actf) != NULL) {
        !           273:                        sc->sc_actf = bp->av_forw;
        !           274:                        bp->b_flags |= B_ERROR;
        !           275:                        iodone(bp);
        !           276:                }
        !           277:                sc->sc_flags &=~ H_BUSY;
        !           278:        }
        !           279:        cc->cc_flags &=~ T_BUSY;
        !           280:        DELAY(200);
        !           281:        for (i = 0; i < MTTIMEOUT; i++) {
        !           282:                if (tmaddr->mtid & MTID_RDY)
        !           283:                        return (1);             /* done */
        !           284:                DELAY(50);              /* wait a bit more */
        !           285:        }
        !           286:        printf("tm78 %d: never ready\n", ctl);
        !           287:        return (0);
        !           288: }
        !           289: 
        !           290: tu78close(dev)
        !           291:        register dev_t dev;
        !           292: {
        !           293:        register struct tu78 *sc = &tu78[TUUNIT(dev)];
        !           294: 
        !           295:        if (sc->sc_flags & (H_WONLY|H_WRITTEN))
        !           296:                tu78cmd(dev, MT_CLS|sc->sc_dens, 1L);
        !           297:        if ((minor(dev)&H_NOREWIND) == 0)
        !           298:                tu78cmd(dev, MT_REW, 0L);
        !           299:        sc->sc_flags &= H_BUSY;
        !           300: }
        !           301: 
        !           302: tu78cmd(dev, com, count)
        !           303: dev_t dev;
        !           304: int com;
        !           305: register daddr_t count;
        !           306: {
        !           307:        register struct buf *bp;
        !           308:        register int some;
        !           309: 
        !           310:        bp = &ctu78buf[TUUNIT(dev)];
        !           311:        (void) spl5();
        !           312:        while (bp->b_flags&B_BUSY) {
        !           313:                if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
        !           314:                        break;
        !           315:                bp->b_flags |= B_WANTED;
        !           316:                sleep((caddr_t)bp, PRIBIO);
        !           317:        }
        !           318:        bp->b_flags = B_BUSY|B_READ;
        !           319:        (void) spl0();
        !           320:        bp->b_dev = dev;
        !           321:        bp->b_command = com;
        !           322:        bp->b_blkno = 0;
        !           323:        do {
        !           324:                if (count <= MAXCOUNT)
        !           325:                        some = count;
        !           326:                else
        !           327:                        some = MAXCOUNT;
        !           328:                bp->b_repcnt = some;
        !           329:                tu78strategy(bp);
        !           330:                if (count == 0) {
        !           331:                        if (bp->b_flags & B_DONE)
        !           332:                                geterror(bp);
        !           333:                        return;         /* sic */
        !           334:                }
        !           335:                iowait(bp);
        !           336:        } while (u.u_error == 0 && (count -= some) > 0);
        !           337:        if (bp->b_flags&B_WANTED)
        !           338:                wakeup((caddr_t)bp);
        !           339:        bp->b_flags &=~ B_BUSY;
        !           340: }
        !           341: 
        !           342: tu78strategy(bp)
        !           343:        register struct buf *bp;
        !           344: {
        !           345:        register struct tu78 *sc;
        !           346: 
        !           347:        sc = &tu78[TUUNIT(bp->b_dev)];
        !           348:        bp->av_forw = NULL;
        !           349:        (void) spl5();
        !           350:        if (sc->sc_actf == NULL)
        !           351:                sc->sc_actf = bp;
        !           352:        else
        !           353:                sc->sc_actl->av_forw = bp;
        !           354:        sc->sc_actl = bp;
        !           355:        if ((sc->sc_flags & H_BUSY) == 0)
        !           356:                tu78start(sc);
        !           357:        if (sc->sc_ctl->cc_actf && (sc->sc_ctl->cc_flags & T_BUSY) == 0)
        !           358:                tm78start(sc->sc_ctl);
        !           359:        (void) spl0();
        !           360: }
        !           361: 
        !           362: tu78start(sc)
        !           363: register struct tu78 *sc;
        !           364: {
        !           365:        register struct buf *bp;
        !           366:        register struct device *tmaddr;
        !           367:        register struct tm78 *cc;
        !           368:        register daddr_t bno;
        !           369:        register int cmd, dist;
        !           370: 
        !           371:        cc = sc->sc_ctl;
        !           372: loop:
        !           373:        if ((bp = sc->sc_actf) == 0)
        !           374:                return;
        !           375:        tmaddr = cc->cc_addr;
        !           376:        sc->sc_flags &= ~H_WRITTEN;
        !           377:        if (sc->sc_flags & H_OFFLINE) {
        !           378:                bp->b_flags |= B_ERROR;
        !           379:                goto done;
        !           380:        }
        !           381:        /*
        !           382:         * command, start it
        !           383:         */
        !           384:        if (bp == &ctu78buf[TUUNIT(bp->b_dev)]) {
        !           385:                sc->sc_flags |= H_BUSY;
        !           386:                cmd = bp->b_command|MT_GO;
        !           387:                cmd |= bp->b_repcnt << MT_COFF;
        !           388: #if BABBLE
        !           389: printf("cmd %o\n", cmd);
        !           390: #endif
        !           391:                tmaddr->mtncs[sc->sc_slave] = cmd;
        !           392:                return;
        !           393:        }
        !           394:        /*
        !           395:         * transfer, see if position needed (wretched block magtape)
        !           396:         */
        !           397:        bno = bp->b_blkno/TBLOCK;       
        !           398:        if (bno > sc->sc_nxrec) {
        !           399:                bp->b_error = ENXIO;
        !           400:                bp->b_flags |= B_ERROR;
        !           401:                goto done;
        !           402:        }
        !           403:        if (bp->b_flags & B_READ        /* at EOF, or really just writing? */
        !           404:        &&  (bno == sc->sc_nxrec || sc->sc_flags & H_WONLY)) {
        !           405:                bp->b_resid = bp->b_bcount;
        !           406:                goto done;
        !           407:        }
        !           408:        if ((bp->b_flags&B_READ)==0)
        !           409:                sc->sc_nxrec = bno + 1;
        !           410:        if (sc->sc_blkno != bno) {      /* need position */
        !           411:                sc->sc_flags |= H_BUSY;
        !           412:                if (sc->sc_blkno < bno) {
        !           413:                        sc->sc_flags &=~ H_EOT;
        !           414:                        dist = bno - sc->sc_blkno;
        !           415:                        cmd = MT_SREV;
        !           416:                } else {
        !           417:                        dist = sc->sc_blkno - bno;
        !           418:                        cmd = MT_SFORW;
        !           419:                }
        !           420:                if (dist > MAXCOUNT)
        !           421:                        dist = MAXCOUNT;
        !           422:                tmaddr->mtncs[sc->sc_slave] = (dist<<MT_COFF)|cmd|MT_GO;
        !           423:                return;
        !           424:        }
        !           425:        /*
        !           426:         * time for a transfer
        !           427:         */
        !           428:        if ((bp->b_flags&B_READ) == 0 && sc->sc_flags & H_EOT) {
        !           429:                bp->b_resid = bp->b_bcount;
        !           430: done:
        !           431:                sc->sc_actf = bp->av_forw;
        !           432:                iodone(bp);
        !           433:                goto loop;
        !           434:        }
        !           435:        cc = sc->sc_ctl;
        !           436:        sc->sc_next = NULL;
        !           437:        if (cc->cc_actf == NULL)
        !           438:                cc->cc_actf = sc;
        !           439:        else
        !           440:                cc->cc_actl->sc_next = sc;
        !           441:        cc->cc_actl = sc;
        !           442:        sc->sc_flags |= H_BUSY;
        !           443: }
        !           444: 
        !           445: tm78start(cc)
        !           446: register struct tm78 *cc;
        !           447: {
        !           448:        register struct tu78 *sc;
        !           449:        int tm78xfer();
        !           450: 
        !           451:        if ((sc = cc->cc_actf) == NULL)
        !           452:                return;
        !           453:        if (sc->sc_actf == NULL)
        !           454:                panic("tm78start");
        !           455:        cc->cc_flags |= T_BUSY;
        !           456:        mbstart(cc->cc_mbaddr, sc->sc_actf, tm78xfer);
        !           457: }
        !           458: 
        !           459: tm78xfer(bp)
        !           460: register struct buf *bp;
        !           461: {
        !           462:        register struct tu78 *sc;
        !           463:        register struct device *tmaddr;
        !           464: 
        !           465:        sc = &tu78[TUUNIT(bp->b_dev)];
        !           466:        tmaddr = sc->sc_ctl->cc_addr;
        !           467:        tmaddr->mtca = sc->sc_slave;
        !           468:        tmaddr->mtbc = bp->b_bcount;
        !           469: #if BABBLE
        !           470: printf("xfer go\n");
        !           471: #endif
        !           472:        if (bp->b_flags & B_READ)
        !           473:                tmaddr->mtcs = MT_READ|MT_GO;
        !           474:        else
        !           475:                tmaddr->mtcs = MT_WRITE|sc->sc_dens|MT_GO;
        !           476: }
        !           477: 
        !           478: /*
        !           479:  * massbus interrupt
        !           480:  * if a transfer was pending, assume it finished;
        !           481:  * if attn set, something else finished too
        !           482:  */
        !           483: tm780int(ctl, mbsr, mbbc, attn)
        !           484: int ctl, mbsr, mbbc, attn;
        !           485: {
        !           486:        register struct tm78 *cc;
        !           487: 
        !           488:        cc = &tm78[ctl];
        !           489:        if (cc->cc_addr == NULL) {
        !           490:                printf("tm78 %d: stray intr\n", ctl);
        !           491:                return;
        !           492:        }
        !           493:        if (attn)
        !           494:                tu78attn(ctl, mbsr, attn);
        !           495:        if (cc->cc_flags & T_BUSY)
        !           496:                tu78dtint(ctl, mbsr);
        !           497:        if (cc->cc_actf)
        !           498:                tm78start(cc);
        !           499: }
        !           500: 
        !           501: /*
        !           502:  * here with an attention:
        !           503:  * a boring interrupt, a disaster, or a command finished
        !           504:  * don't clear the attn until we've read the registers
        !           505:  */
        !           506: 
        !           507: tu78attn(ctl, mbsr, attn)
        !           508: int ctl, mbsr, attn;
        !           509: {
        !           510:        register struct tm78 *cc;
        !           511:        register struct tu78 *sc;
        !           512:        register struct buf *bp;
        !           513:        register struct device *tmaddr;
        !           514:        register int unit;
        !           515:        daddr_t bno;
        !           516:        register int i;
        !           517:        register long rt;       /* register temp to avoid compiler botches */
        !           518: 
        !           519:        cc = &tm78[ctl];
        !           520:        tmaddr = cc->cc_addr;
        !           521:        rt = tmaddr->mtner;
        !           522:        i = MTER_UNIT(rt);
        !           523: #if BABBLE
        !           524: printf("attn er%o ds%o cs%o\n", tmaddr->mtner&0xffff, tmaddr->mtds&0xffff, tmaddr->mtncs[i]&0xffff);
        !           525: #endif
        !           526:        switch (MTER_INTCODE(rt)) {
        !           527:        case MTER_ONLINE:
        !           528:        case MTER_RWDING:
        !           529:                tmaddr->mtas = attn;
        !           530:                return;                 /* boring */
        !           531: 
        !           532:        case MTER_MBFLT:
        !           533:        case MTER_TMFLTB:
        !           534:                printf("tm78 %d fault er%o mbsr%o\n", ctl, tmaddr->mtner, mbsr);
        !           535:                tm78reset(ctl);
        !           536:                tmaddr->mtas = attn;
        !           537:                return;
        !           538:        }
        !           539:        if ((unit = cc->cc_drives[i]) == NOUNIT) {
        !           540:                printf("tm78 %d unit %d stray intr er%o\n", ctl, i, tmaddr->mtner);
        !           541:                tmaddr->mtas = attn;
        !           542:                return;
        !           543:        }
        !           544:        sc = &tu78[unit];
        !           545:        rt = tmaddr->mtds; sc->sc_dsreg = rt;
        !           546:        rt = tmaddr->mtner; sc->sc_erreg = rt;
        !           547:        rt = tmaddr->mtncs[i]; sc->sc_resid = MTNCS_COUNT(rt);
        !           548:        tmaddr->mtas = attn;
        !           549:        if ((bp = sc->sc_actf) == NULL) {
        !           550:                printf("tu78 %d: odd intr er%o\n", unit, sc->sc_erreg);
        !           551:                return;
        !           552:        }
        !           553:        switch (MTER_INTCODE(sc->sc_erreg)) {
        !           554:        case MTER_EOT:
        !           555:                sc->sc_flags |= H_EOT;
        !           556:                /* fall through */
        !           557:        case MTER_TM:
        !           558:        case MTER_LEOT:
        !           559:        case MTER_BOT:
        !           560:        case MTER_NOOP:
        !           561:        case MTER_DONE:
        !           562:                /*
        !           563:                 * this was a block magtape seek,
        !           564:                 * or we're closing (so sc_blkno is boring),
        !           565:                 * or it's raw magtape (ditto)
        !           566:                 */
        !           567:                bno = bp->b_blkno / TBLOCK;
        !           568:                if (sc->sc_blkno > bno)
        !           569:                        sc->sc_blkno += sc->sc_resid;
        !           570:                else
        !           571:                        sc->sc_blkno -= sc->sc_resid;
        !           572:                if (sc->sc_flags & H_EOT)
        !           573:                        sc->sc_nxrec = sc->sc_blkno;
        !           574:                if (bp != &ctu78buf[unit])
        !           575:                        sc->sc_flags &=~ H_BUSY;        /* done with seek */
        !           576:                break;
        !           577: 
        !           578:        case MTER_NOTAVL:
        !           579:        case MTER_OFFLINE:
        !           580:        case MTER_NONEX:
        !           581:                if (sc->sc_flags & H_OPEN)
        !           582:                        sc->sc_flags |= H_OFFLINE;
        !           583:                bp->b_error = ENXIO;
        !           584:                bp->b_flags |= B_ERROR;
        !           585:                break;
        !           586: 
        !           587:        default:
        !           588:                printf("tu78 %d: hard error bn%d er%o mbsr%o\n",
        !           589:                        unit, bp->b_blkno, sc->sc_erreg, mbsr);
        !           590:                bp->b_flags |= B_ERROR;
        !           591:                break;
        !           592:        }
        !           593:        if (sc->sc_flags & H_BUSY) {
        !           594:                sc->sc_actf = bp->av_forw;
        !           595:                iodone(bp);
        !           596:                sc->sc_flags &=~ H_BUSY;
        !           597:        }
        !           598:        if (sc->sc_actf)
        !           599:                tu78start(sc);
        !           600: }
        !           601: 
        !           602: tu78dtint(ctl, mbsr)
        !           603: int ctl, mbsr;
        !           604: {
        !           605:        register struct tm78 *cc;
        !           606:        register struct tu78 *sc;
        !           607:        register struct buf *bp;
        !           608:        register struct device *tmaddr;
        !           609:        register int rt;        /* reg temp to avoid compiler botches */
        !           610: 
        !           611:        cc = &tm78[ctl];
        !           612:        tmaddr = cc->cc_addr;
        !           613:        if ((sc = cc->cc_actf) == NULL
        !           614:        ||  (bp = sc->sc_actf) == NULL)
        !           615:                panic("tu78dtint");
        !           616:        rt = tmaddr->mtbc; sc->sc_resid = rt;
        !           617:        rt = tmaddr->mter; sc->sc_erreg = rt;
        !           618: #if BABBLE
        !           619: printf("dtint er%o bc%o mbs%o\n", sc->sc_erreg, sc->sc_resid, mbsr);
        !           620: #endif
        !           621:        if (mbsr & MBSR_HARD) {
        !           622:                printf("tu78 %d: mb error er%o mbsr%o\n",
        !           623:                        TUUNIT(bp->b_dev), sc->sc_erreg, mbsr);
        !           624:                bp->b_flags |= B_ERROR;
        !           625:        } else switch (MTER_INTCODE(sc->sc_erreg)) {
        !           626:        case MTER_MBFLT:
        !           627:        case MTER_TMFLTB:
        !           628:                printf("tm78 %d fault er%o mbsr%o\n", ctl, sc->sc_erreg, mbsr);
        !           629:                tm78reset(ctl);
        !           630:                return;
        !           631: 
        !           632:        case MTER_EOT:
        !           633:                sc->sc_flags |= H_EOT;
        !           634:                /* fall through */
        !           635:        case MTER_LEOT:
        !           636:        case MTER_TM:
        !           637:                bp->b_resid = bp->b_bcount;
        !           638:                sc->sc_nxrec = sc->sc_blkno;
        !           639:                break;
        !           640: 
        !           641:        case MTER_LONGREC:
        !           642:                sc->sc_blkno++;
        !           643:                bp->b_error = ENOMEM;
        !           644:                bp->b_flags |= B_ERROR;
        !           645:                break;
        !           646: 
        !           647:        case MTER_SHRTREC:
        !           648:                if (bp != &rtu78buf[TUUNIT(bp->b_dev)]) /* block tape */
        !           649:                        bp->b_flags |= B_ERROR;
        !           650:                /* fall in */
        !           651:        case MTER_DONE:
        !           652:                bp->b_resid = bp->b_bcount - sc->sc_resid;
        !           653:                sc->sc_blkno++;
        !           654:                break;
        !           655: 
        !           656:        case MTER_RETRY:
        !           657:                cc->cc_flags &=~ T_BUSY;
        !           658:                break;
        !           659: 
        !           660:        case MTER_NOTAVL:
        !           661:        case MTER_OFFLINE:
        !           662:        case MTER_NONEX:
        !           663:                if (sc->sc_flags & H_OPEN)
        !           664:                        sc->sc_flags |= H_OFFLINE;
        !           665:                bp->b_error = ENXIO;
        !           666:                bp->b_flags |= B_ERROR;
        !           667:                break;
        !           668: 
        !           669:        case MTER_NOTCAP:
        !           670:        case MTER_BADTAPE:
        !           671:                if (sc->sc_flags & H_OPEN)
        !           672:                        sc->sc_flags |= H_OFFLINE;      /* really position lost */
        !           673:                /* fall through */
        !           674:        default:
        !           675:                printf("tu78 %d: hard error bn%d er%o mbsr%o\n",
        !           676:                        TUUNIT(bp->b_dev), bp->b_blkno, sc->sc_erreg, mbsr);
        !           677:                sc->sc_blkno++;
        !           678:                bp->b_flags |= B_ERROR;
        !           679:                break;
        !           680:        }
        !           681:        if (cc->cc_flags & T_BUSY) {
        !           682:                cc->cc_actf = sc->sc_next;
        !           683:                sc->sc_actf = bp->av_forw;
        !           684:                iodone(bp);
        !           685:                sc->sc_flags &=~ H_BUSY;
        !           686:                if (sc->sc_actf)
        !           687:                        tu78start(sc);
        !           688:                cc->cc_flags &=~ T_BUSY;
        !           689:        }
        !           690: }
        !           691: 
        !           692: tu78read(dev)
        !           693: dev_t dev;
        !           694: {
        !           695: 
        !           696:        tu78phys(dev);
        !           697:        physio(tu78strategy, &rtu78buf[TUUNIT(dev)], dev, B_READ, minphys);
        !           698: }
        !           699: 
        !           700: tu78write(dev)
        !           701: dev_t dev;
        !           702: {
        !           703: 
        !           704:        tu78phys(dev);
        !           705:        physio(tu78strategy, &rtu78buf[TUUNIT(dev)], dev, B_WRITE, minphys);
        !           706: }
        !           707: 
        !           708: tu78phys(dev)
        !           709: dev_t dev;
        !           710: {
        !           711:        register struct tu78 *sc;
        !           712: 
        !           713:        sc = &tu78[TUUNIT(dev)];
        !           714:        sc->sc_blkno = Lshift(u.u_offset, TBSHIFT);
        !           715:        sc->sc_nxrec = sc->sc_blkno + 1;
        !           716: }
        !           717: 
        !           718: tu78ioctl(dev, cmd, addr, flag)
        !           719: dev_t dev;
        !           720: int cmd;
        !           721: caddr_t addr;
        !           722: int flag;
        !           723: {
        !           724:        struct mtop mtop;
        !           725: 
        !           726:        switch (cmd) {
        !           727:        case MTIOCTOP:          /* tape operation */
        !           728:                if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
        !           729:                        u.u_error = EFAULT;
        !           730:                        return;
        !           731:                }
        !           732:                if (mtop.mt_count == 0)
        !           733:                        mtop.mt_count = 1;
        !           734:                switch(mtop.mt_op) {
        !           735:                case MTWEOF:
        !           736:                        tu78cmd(dev, MT_WTM|tu78[TUUNIT(dev)].sc_dens, mtop.mt_count);
        !           737:                        break;
        !           738: 
        !           739:                case MTFSF:
        !           740:                        tu78cmd(dev, MT_SFORWF, mtop.mt_count);
        !           741:                        break;
        !           742: 
        !           743:                case MTBSF:
        !           744:                        tu78cmd(dev, MT_SREVF, mtop.mt_count);
        !           745:                        break;
        !           746: 
        !           747:                case MTFSR:
        !           748:                        tu78cmd(dev, MT_SFORW, mtop.mt_count);
        !           749:                        break;
        !           750: 
        !           751:                case MTBSR:
        !           752:                        tu78cmd(dev, MT_SREV, mtop.mt_count);
        !           753:                        break;
        !           754: 
        !           755:                case MTREW:
        !           756:                        tu78cmd(dev, MT_REW, 1L);
        !           757:                        break;
        !           758: 
        !           759:                case MTOFFL:
        !           760:                        tu78cmd(dev, MT_UNLOAD, 1L);
        !           761:                        break;
        !           762: 
        !           763:                default:
        !           764:                        u.u_error = ENXIO;
        !           765:                        break;
        !           766:                }
        !           767:                return;
        !           768: 
        !           769:        default:
        !           770:                u.u_error = ENXIO;
        !           771:                return;
        !           772:        }
        !           773: }

unix.superglobalmegacorp.com

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