Annotation of researchv10no/sys/io/tu78.c, revision 1.1.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.