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