|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.