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