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

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

unix.superglobalmegacorp.com

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