Annotation of 41BSD/sys/newdev/tm.c, revision 1.1.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.