Annotation of 40BSD/sys/newdev/tm.c, revision 1.1

1.1     ! root        1: /*     %M%     %I%     %G%     */
        !             2: 
        !             3: /*
        !             4:  * TM tape driver
        !             5:  */
        !             6: #include "../h/param.h"
        !             7: #include "../h/buf.h"
        !             8: #include "../h/dir.h"
        !             9: #include "../h/conf.h"
        !            10: #include "../h/user.h"
        !            11: #include "../h/file.h"
        !            12: #include "../h/map.h"
        !            13: #include "../h/pte.h"
        !            14: #include "../h/uba.h"
        !            15: 
        !            16: extern struct device *tmaddr;
        !            17: extern int ntm;
        !            18: extern char tm_flags[];                /* used for T_WRITTEN flag */
        !            19: extern char tm_openf[];                /* open flag for device */
        !            20: extern daddr_t tm_blkno[];             /* pointer to current block on tape */
        !            21: extern daddr_t tm_nxrec[];             /* pointer to end of file on tape */
        !            22: 
        !            23: struct device {
        !            24:        short   tmer;           /* status register*/
        !            25:        short   tmcs;           /* command register */
        !            26:        short   tmbc;           /* byte (read/write) record (space) counter */
        !            27:        unsigned short  tmba;   /* current memory address counter */
        !            28:        short   tmdb;           /* data buffer register */
        !            29:        short   tmrd;           /* tu10 read lines */
        !            30: };
        !            31: 
        !            32: #define        b_repcnt  b_bcount      /* Command repetition counter */
        !            33: #define        b_command b_resid       /* Command to do */
        !            34: #define        b_status  b_resid       /* Status after a tcommand */
        !            35: 
        !            36: struct buf     tmtab;          /* block device list header */
        !            37: struct buf     ctmbuf;         /* control semaphore*/
        !            38: struct buf     rtmbuf;         /* raw i/o device list header */
        !            39: 
        !            40: #define        U_REWD    04            /* Rewind on close */
        !            41: #define        U_DUALD   08            /* Dual density */
        !            42: 
        !            43: /* CONTROL FLAGS */
        !            44: #define        GO      01              /* initiate command and reset CU RDY */
        !            45: #define        RCOM    02              /* read */
        !            46: #define        WCOM    04              /* write */
        !            47: #define        WEOF    06              /* write eof mark */
        !            48: #define        SFORW   010             /* space forward */
        !            49: #define        SREV    012             /* space reverse */
        !            50: #define        WIRG    014             /* write with extended irg; for write errors */
        !            51: #define        REW     016             /* rewind */
        !            52: #define        NOP     0100            /* nop = interrupt enable */
        !            53: #define        IENABLE 0100            /* enable interrupts */
        !            54: #define        DCLR    010000          /* Drive clear -- reset any hard error bits */
        !            55: #define        D800    060000          /* 9-channel, 800 bpi density */
        !            56: #define D1600   0117777                /* 9-channel, 1600 bpi density*/
        !            57: 
        !            58: /* STATUS FLAGS */
        !            59: #define        TUR     1               /* tape unit ready */
        !            60: #define RWS    02              /* rewind in progress--set on first rewind int*/
        !            61: #define        WL      04              /* write lock bit -- read ring off tape */
        !            62: #define GAPSD  010             /* gap settle down bit */
        !            63: #define RLE    0100            /* record length error on read */
        !            64: #define        CRDY    0200            /* control unit ready */
        !            65: #define        EOF     040000          /* end of file */
        !            66: #define HARD    0100000         /* ILC (could be more if we trusted the UBA) */
        !            67: 
        !            68: /* DRIVER MODES */
        !            69: #define        SSEEK   1               /* seek mode */
        !            70: #define        SIO     2               /* sequential i/o mode */
        !            71: #define        SCOM    3               /* command mode */
        !            72: 
        !            73: #define T_WRITTEN 1            /* device flag for eof writes */
        !            74: #define T_WANTED  02           /* wait for rewind flag*/
        !            75: 
        !            76: tmopen(dev, flag)
        !            77: dev_t dev;
        !            78: int flag;
        !            79: {
        !            80:        register unit, ds;
        !            81: 
        !            82:        unit = minor(dev) & 03;
        !            83:        if (tm_openf[unit])
        !            84:        {
        !            85:                u.u_error = ENXIO;
        !            86:                return;
        !            87:        }
        !            88:        tm_blkno[unit] = 0;
        !            89:        tm_flags[unit] = 0;
        !            90:        tm_nxrec[unit] = 65535;
        !            91: 
        !            92:        tmtab.b_flags |= B_TAPE;
        !            93: 
        !            94:        ds = tcommand(dev, NOP, 1);
        !            95: 
        !            96:        if ((ds & TUR) == 0) {
        !            97:                while (ds = tcommand(dev, NOP, 1) & RWS) {
        !            98:                        /* sleep during rewind initiated during prior IO */
        !            99:                        tm_flags[ntm11] |= T_WANTED;
        !           100:                        sleep((caddr_t)&tm_flags[ntm11],PRIBIO);
        !           101:                }
        !           102:        }
        !           103: 
        !           104:        while ((ds = tcommand(dev, NOP, 1)) & GAPSD)
        !           105:                continue;
        !           106: 
        !           107:        if ((ds&TUR)==0 || (flag && ds&WL)) {
        !           108:                /* Offline or needs a write ring */
        !           109:                tmaddr->tmcs = DCLR|GO;
        !           110:                u.u_error = EIO;
        !           111:        }
        !           112:        /* tm_openf may have value -1 if certain hardware conditions came up */
        !           113:        tm_openf[unit] = (u.u_error == 0);
        !           114: }
        !           115: 
        !           116: tmclose(dev, flag)
        !           117: register dev_t dev;
        !           118: register flag;
        !           119: {
        !           120:        register unit;
        !           121: 
        !           122:        unit = minor(dev)&03;
        !           123:        tm_openf[unit]++;
        !           124:        if (flag == FWRITE ||
        !           125:            ((flag&FWRITE) && (tm_flags[minor(dev)&03] & T_WRITTEN))) {
        !           126:                (void) tcommand(dev, WEOF, 2);
        !           127:                (void) tcommand(dev, SREV, 1);
        !           128:        }
        !           129:        if ((minor(dev)&U_REWD) == 0)
        !           130:                /* rewind if bit 2 is set in minor */
        !           131:                (void) tcommand(dev, REW, 1);
        !           132:        tm_openf[minor(dev)&03] = 0;
        !           133: }
        !           134: 
        !           135: tcommand(dev, com, cnt)
        !           136: register dev_t dev;
        !           137: register com, cnt;
        !           138: {
        !           139:        register struct buf *bp;
        !           140: 
        !           141:        bp = &ctmbuf;
        !           142:        (void) spl5();
        !           143:        while (bp->b_flags&B_BUSY) 
        !           144:        {
        !           145:                bp->b_flags |= B_WANTED;
        !           146:                sleep((caddr_t)bp, PRIBIO);
        !           147:        }
        !           148:        bp->b_flags = B_BUSY|B_READ;
        !           149:        (void) spl0();
        !           150: 
        !           151:        bp->b_dev = dev;
        !           152:        bp->b_repcnt = -cnt;
        !           153:        bp->b_command = com;
        !           154:        bp->b_blkno = 0;
        !           155: 
        !           156:        tmstrategy(bp);
        !           157: 
        !           158:        iowait(bp);
        !           159:        if (bp->b_flags&B_WANTED)
        !           160:                wakeup((caddr_t)bp);
        !           161:        bp->b_flags = 0;
        !           162:        return(bp->b_status);
        !           163: }
        !           164: 
        !           165: tmstrategy(bp)
        !           166: register struct buf *bp;
        !           167: {
        !           168:        register daddr_t *p;
        !           169: 
        !           170:        if (bp != &ctmbuf) {
        !           171:                p = &tm_nxrec[minor(bp->b_dev)&03];
        !           172:                if (*p <= dbtofsb(bp->b_blkno)) {
        !           173:                        if (*p < dbtofsb(bp->b_blkno)) {
        !           174:                                /* Blkno past EOF */
        !           175:                                bp->b_flags |= B_ERROR;
        !           176:                                iodone(bp);
        !           177:                                return;
        !           178:                        }
        !           179:                        if (bp->b_flags&B_READ) {
        !           180:                                /* Reading at EOF */
        !           181:                                clrbuf(bp);
        !           182:                                bp->b_resid = bp->b_bcount;
        !           183:                                iodone(bp);
        !           184:                                return;
        !           185:                        }
        !           186:                }
        !           187:                if ((bp->b_flags&B_READ) == 0) {
        !           188:                        tm_flags[minor(bp->b_dev)&03] |= T_WRITTEN;
        !           189:                        /* Change software location of EOF */
        !           190:                        *p = dbtofsb(bp->b_blkno) + 1;
        !           191:                }
        !           192:        }
        !           193: 
        !           194:        bp->av_forw = 0;
        !           195: 
        !           196:        (void) spl5();
        !           197:        if (tmtab.b_actf == NULL)
        !           198:                tmtab.b_actf = bp;
        !           199:        else
        !           200:                tmtab.b_actl->av_forw = bp;
        !           201:        tmtab.b_actl = bp;
        !           202:        if (tmtab.b_active == NULL)
        !           203:                tmstart();
        !           204:        (void) spl0();
        !           205: }
        !           206: 
        !           207: tmstart()
        !           208: {
        !           209:        register struct buf *bp;
        !           210:        register com;
        !           211:        register unit;
        !           212:        register daddr_t blkno;
        !           213: 
        !           214: loop:
        !           215:        if ((bp = tmtab.b_actf) == 0)
        !           216:                return;
        !           217:        unit = minor(bp->b_dev)&03;
        !           218:        blkno = tm_blkno[unit];
        !           219:        if (tm_openf[unit] < 0 || (tmaddr->tmcs & CRDY) == NULL) {
        !           220:                bp->b_flags |= B_ERROR;
        !           221:                goto next;
        !           222:        }
        !           223:        com = IENABLE | (unit << 8) | GO;
        !           224: 
        !           225:        if (minor(bp->b_dev) & U_DUALD)
        !           226:                com &= D1600;
        !           227:        else
        !           228:                com |= D800;
        !           229: 
        !           230:        if (bp == &ctmbuf) {
        !           231:                if (bp->b_command == NOP) {
        !           232:                        /* return device status */
        !           233:                        bp->b_status = tmaddr->tmer;
        !           234:                        goto next;
        !           235:                }
        !           236:                com |= bp->b_command;
        !           237:                tmtab.b_active = SCOM;
        !           238:                if(bp->b_command == SFORW || bp->b_command == SREV)
        !           239:                        tmaddr->tmbc = bp->b_repcnt;
        !           240:                tmaddr->tmcs = com;
        !           241:                return;
        !           242:        }
        !           243:        if (blkno != dbtofsb(bp->b_blkno)) {
        !           244:                /* Block mode, seek to correct block */
        !           245:                tmtab.b_active = SSEEK;
        !           246:                if (blkno < dbtofsb(bp->b_blkno)) {
        !           247:                        com |= SFORW;
        !           248:                        tmaddr->tmbc = blkno - dbtofsb(bp->b_blkno);
        !           249:                } else {
        !           250:                        com |= SREV;
        !           251:                        tmaddr->tmbc = dbtofsb(bp->b_blkno) - blkno;
        !           252:                }
        !           253:                tmaddr->tmcs = com;
        !           254:                return;
        !           255:        }
        !           256:        if (tmtab.b_un.b_addr == 0)
        !           257:                tmtab.b_un.b_addr = (caddr_t)ubasetup(bp,1);
        !           258: 
        !           259:        /* Set high 2 bits of UNIBUS address */
        !           260:        com |= (((long)tmtab.b_un.b_addr >> (16-4)) & 060); 
        !           261: 
        !           262:        tmtab.b_active = SIO;
        !           263:        com |= ((bp->b_flags & B_READ) ? RCOM : ((tmtab.b_errcnt) ? WIRG : WCOM ));
        !           264:        tmaddr->tmbc = -bp->b_bcount;
        !           265:        tmaddr->tmba = ((int)tmtab.b_un.b_addr & 0xffff);
        !           266:        tmaddr->tmcs = com; 
        !           267:        return;
        !           268: 
        !           269: next:
        !           270:        if (tmtab.b_un.b_addr != 0) {
        !           271:                ubafree(tmtab.b_un.b_addr);
        !           272:                tmtab.b_un.b_addr = 0;
        !           273:        }
        !           274:        tmtab.b_actf = bp->av_forw;
        !           275:        iodone(bp);
        !           276:        goto loop;
        !           277: }
        !           278: 
        !           279: tmintr()
        !           280: {
        !           281:        register struct buf *bp;
        !           282:        register state, unit;
        !           283: 
        !           284:        if (tm_flags[ntm11] & T_WANTED)  {
        !           285:                /* wake up any rewind sleepers*/
        !           286:                tm_flags[NUNIT] &= ~T_WANTED;
        !           287:                wakeup((caddr_t)&tm_flags[NUNIT]);
        !           288:        }
        !           289:        if ((bp = tmtab.b_actf) == NULL)
        !           290:                return;
        !           291: 
        !           292:        unit = minor(bp->b_dev)&03;
        !           293:        state = tmtab.b_active;
        !           294:        tmtab.b_active = NULL;
        !           295:        if (tmaddr->tmcs < 0) {
        !           296:                /*
        !           297:                 * On error, first wait for gap shutdown 
        !           298:                 */
        !           299:                while(tmaddr->tmer & GAPSD)
        !           300:                        ;
        !           301:                if (tmaddr->tmer&EOF) {
        !           302:                        /* EOF, set nxrec to sought block */
        !           303:                        tm_nxrec[unit] = dbtofsb(bp->b_blkno);
        !           304:                        state = SCOM;
        !           305:                        tmaddr->tmbc = -bp->b_bcount;
        !           306:                        goto out;
        !           307:                }
        !           308:                if ((bp->b_flags&B_READ) && (tmaddr->tmer&(HARD|RLE)) == RLE)
        !           309:                        goto out;
        !           310:                if ((tmaddr->tmer&(HARD|EOF)) == NULL && state==SIO) {
        !           311:                        /* if not a hard error or eof and in sequential mode */
        !           312:                        if (++tmtab.b_errcnt < 3) {
        !           313:                                if((tmaddr->tmer&~RLE) != 0xC0)
        !           314:                                        tm_blkno[unit]++;
        !           315:                                else
        !           316:                                        printf("TM UBA late error\n");
        !           317:                                if(tmtab.b_un.b_addr) {
        !           318:                                        ubafree(tmtab.b_un.b_addr);
        !           319:                                        tmtab.b_un.b_addr = 0;
        !           320:                                }
        !           321:                                /* retry: skip reverse one and do IO again */
        !           322:                                tmstart();
        !           323:                                return;
        !           324:                        }
        !           325:                } else if (tm_openf[unit]>0 && bp!=&rtmbuf &&
        !           326:                    (tmaddr->tmer&EOF)==0)
        !           327:                        tm_openf[unit] = -1;
        !           328:                deverror(bp, tmaddr->tmer&0xffff, tmaddr->tmcs&0xffff);
        !           329:                bp->b_flags |= B_ERROR;
        !           330:                state = SIO;
        !           331:        }
        !           332: out:
        !           333:        switch (state) {
        !           334:        
        !           335:        case SIO:
        !           336:                tm_blkno[unit]++;
        !           337:                /* fall into ... */
        !           338:        case SCOM:
        !           339:                if (bp == &ctmbuf)
        !           340:                        if (bp->b_command == SFORW || bp->b_command == SREV) {
        !           341:                                if (bp->b_command == SREV)
        !           342:                                        tm_blkno[unit] -= -bp->b_repcnt;
        !           343:                                else
        !           344:                                        tm_blkno[unit] += -bp->b_repcnt;
        !           345:                        } else if (++bp->b_repcnt)
        !           346:                                break;
        !           347:                tmtab.b_errcnt = 0;
        !           348:                tmtab.b_actf = bp->av_forw;
        !           349:                bp->b_resid = -tmaddr->tmbc;
        !           350:                if(tmtab.b_un.b_addr != 0) {
        !           351:                        ubafree(tmtab.b_un.b_addr);
        !           352:                        tmtab.b_un.b_addr = 0;
        !           353:                }
        !           354:                iodone(bp);
        !           355:                break;
        !           356:        case SSEEK:
        !           357:                tm_blkno[unit] = dbtofsb(bp->b_blkno);
        !           358:                break;
        !           359:        default:
        !           360:                return;
        !           361:        }
        !           362:        tmstart();
        !           363: }
        !           364: 
        !           365: tmread(dev)
        !           366: {
        !           367: 
        !           368:        tmphys(dev);
        !           369:        physio(tmstrategy, &rtmbuf, dev, B_READ, minphys);
        !           370: }
        !           371: 
        !           372: tmwrite(dev)
        !           373: {
        !           374: 
        !           375:        tmphys(dev);
        !           376:        physio(tmstrategy, &rtmbuf, dev, B_WRITE, minphys);
        !           377: }
        !           378: 
        !           379: tmphys(dev)
        !           380: {
        !           381:        register unit;
        !           382:        register daddr_t a;
        !           383: 
        !           384:        unit = minor(dev) & 03;
        !           385:        a = dbtofsb(u.u_offset >> 9);
        !           386:        tm_blkno[unit] = a;
        !           387:        tm_nxrec[unit] = a + 1;
        !           388: }
        !           389: 
        !           390: #define        NTMIOCTRL       (sizeof tmiolist)
        !           391: 
        !           392: char   tmiolist[] =
        !           393: {
        !           394:        SFORW,          /* 0 = skip forward */
        !           395:        SREV,           /* 1 = skip reverse */
        !           396:        WEOF,           /* 2 = Write EOF */
        !           397:        REW,            /* 3 = rewind */
        !           398:        0,              /* 4 = skip forward file */
        !           399:        0               /* 5 = skip reverse file */
        !           400: };
        !           401: 
        !           402: tmioctrl(dev, cmd, arg, flag)
        !           403: register dev_t dev;
        !           404: register int cmd, flag, arg;
        !           405: {
        !           406:        register ioctr;
        !           407: 
        !           408:        if((unsigned)cmd >= NTMIOCTRL || arg <= 0)
        !           409:                u.u_error = ENXIO;
        !           410:        else {
        !           411:                if(cmd > 3) {
        !           412:                        /* Skip forward/reverse file(s) */
        !           413:                        cmd -= 3;
        !           414:                        ioctr = arg;
        !           415:                        arg = -1;
        !           416:                } else
        !           417:                        ioctr = 1;
        !           418:                do
        !           419:                        (void) tcommand(dev, tmiolist[cmd], arg);
        !           420:                while (--ioctr);
        !           421:        }
        !           422: }

unix.superglobalmegacorp.com

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