|
|
1.1 ! root 1: /* ! 2: * TM78/TU78 tape driver ! 3: * ! 4: * TODO: ! 5: * multiple drives per formatter might work, but are untested ! 6: */ ! 7: #include "sys/param.h" ! 8: #include "sys/buf.h" ! 9: #include "sys/conf.h" ! 10: #include "sys/file.h" ! 11: #include "sys/user.h" ! 12: #include "sys/mbaddr.h" ! 13: #include "sys/mbsts.h" ! 14: #include "sys/subaddr.h" ! 15: #include "sys/mtio.h" ! 16: #include "sys/tu78.h" ! 17: ! 18: /* ! 19: * hardware stuff ! 20: */ ! 21: ! 22: struct device { ! 23: int mtcs; /* control/status */ ! 24: int mter; /* error */ ! 25: int mtca; /* command address, rec cnt, skp cnt */ ! 26: int mtmr1; /* maint */ ! 27: int mtas; /* attention summary */ ! 28: int mtbc; /* byte count */ ! 29: int mtdt; /* drive type */ ! 30: int mtds; /* drive status */ ! 31: int mtsn; /* serial number */ ! 32: int mtmr2; /* maint */ ! 33: int mtmr3; /* maint */ ! 34: int mtner; /* non-data transfer error */ ! 35: int mtncs[TM78DRIVES]; /* non-data transfer command */ ! 36: int mtia; /* internal address */ ! 37: int mtid; /* internal data */ ! 38: }; ! 39: ! 40: /* mtcs */ ! 41: #define MT_GO 000001 /* go bit */ ! 42: #define MT_GCR 000002 /* make generic ops GCR ops */ ! 43: #define MT_UNLOAD 000004 /* unload tape */ ! 44: #define MT_REW 000006 /* rewind */ ! 45: #define MT_SENSE 000010 /* sense */ ! 46: #define MT_WTM 000014 /* generic write tape mark */ ! 47: #define MT_SFORW 000020 /* space forward record */ ! 48: #define MT_SREV 000022 /* space reverse record */ ! 49: #define MT_SFORWF 000024 /* space forward file */ ! 50: #define MT_SREVF 000026 /* space reverse file */ ! 51: #define MT_CLS 000040 /* generic close file */ ! 52: #define MT_WRITE 000060 /* generic write */ ! 53: #define MT_READ 000070 /* read forward */ ! 54: #define MT_READREV 000076 /* read reverse */ ! 55: ! 56: /* mtds */ ! 57: #define MTDS_PRES 0040000 /* tape unit has power */ ! 58: #define MTDS_ONL 0020000 /* online */ ! 59: #define MTDS_PE 0004000 /* tape set for phase encoded */ ! 60: #define MTDS_BOT 0002000 /* tape at BOT */ ! 61: #define MTDS_FPT 0000400 /* write protected */ ! 62: #define MTDS_AVAIL 0000200 /* unit available */ ! 63: ! 64: /* mtncs */ ! 65: #define MT_COFF 8 /* bits to shift count */ ! 66: #define MTNCS_COUNT(c) (((c)>>MT_COFF)&0377) /* repeat count */ ! 67: #define MAXCOUNT 0377 ! 68: ! 69: /* mter */ ! 70: #define MTER_INTCODE(e) ((int)(e)&0377) /* interrupt code */ ! 71: #define MTER_DPR 0400 /* drive (formatter) present */ ! 72: #define MTER_UNIT(e) (((e)>>8)&03) /* interrupting unit in mtner */ ! 73: ! 74: /* interrupt codes */ ! 75: #define MTER_DONE 001 /* operation complete */ ! 76: #define MTER_TM 002 /* unexpected tape mark */ ! 77: #define MTER_BOT 003 /* unexpected BOT detected */ ! 78: #define MTER_EOT 004 /* tape positioned beyond EOT */ ! 79: #define MTER_LEOT 005 /* unexpected LEOT detected */ ! 80: #define MTER_NOOP 006 /* no-op completed */ ! 81: #define MTER_RWDING 007 /* rewinding */ ! 82: #define MTER_FPT 010 /* write protect error */ ! 83: #define MTER_NOTRDY 011 /* not ready */ ! 84: #define MTER_NOTAVL 012 /* not available */ ! 85: #define MTER_OFFLINE 013 /* offline */ ! 86: #define MTER_NONEX 014 /* unit does not exist */ ! 87: #define MTER_NOTCAP 015 /* not capable */ ! 88: #define MTER_ONLINE 017 /* tape came online */ ! 89: #define MTER_LONGREC 020 /* long tape record */ ! 90: #define MTER_SHRTREC 021 /* short tape record */ ! 91: #define MTER_RETRY 022 /* retry */ ! 92: #define MTER_RDOPP 023 /* read opposite */ ! 93: #define MTER_UNREAD 024 /* unreadable */ ! 94: #define MTER_ERROR 025 /* error */ ! 95: #define MTER_EOTERR 026 /* EOT error */ ! 96: #define MTER_BADTAPE 027 /* tape position lost */ ! 97: #define MTER_TMFLTA 030 /* TM fault A */ ! 98: #define MTER_TUFLTA 031 /* TU fault A */ ! 99: #define MTER_TMFLTB 032 /* TM fault B */ ! 100: #define MTER_MBFLT 034 /* Massbus fault */ ! 101: #define MTER_KEYFAIL 077 /* keypad entry error */ ! 102: ! 103: /* mtid */ ! 104: #define MTID_RDY 0100000 /* controller ready */ ! 105: #define MTID_CLR 0040000 /* controller clear */ ! 106: ! 107: #define MTTIMEOUT 10000 /* loop limit for controller test */ ! 108: ! 109: /* ! 110: * system stuff ! 111: */ ! 112: ! 113: int tu78open(), tu78close(), tu78read(), tu78write(), tu78ioctl(), tu78strategy(); ! 114: struct cdevsw tu78cdev = cdinit(tu78open, tu78close, tu78read, tu78write, tu78ioctl); ! 115: struct bdevsw tu78bdev = bdinit(tu78open, tu78close, tu78strategy, B_TAPE); ! 116: ! 117: /* ! 118: * per-formatter stuff ! 119: */ ! 120: ! 121: extern int tm78cnt; ! 122: extern struct tm78 tm78[]; ! 123: extern struct mbaddr tm78addr[]; ! 124: ! 125: #define T_BUSY 01 /* controller busy */ ! 126: #define NOUNIT 0377 /* no slave expected */ ! 127: ! 128: /* ! 129: * per-drive stuff ! 130: */ ! 131: ! 132: extern int tu78cnt; ! 133: extern struct tu78 tu78[]; ! 134: extern struct subaddr tu78addr[]; ! 135: extern struct buf rtu78buf[]; ! 136: extern struct buf ctu78buf[]; ! 137: ! 138: /* ! 139: * bits in minor device ! 140: */ ! 141: #define TUUNIT(dev) (minor(dev)&03) ! 142: #define H_NOREWIND 04 ! 143: #define H_6250BPI 010 ! 144: ! 145: /* ! 146: * sc_flags ! 147: */ ! 148: #define H_BUSY 01 /* software drive busy */ ! 149: #define H_EOT 02 /* saw physical end-of-tape */ ! 150: #define H_WRITTEN 04 /* last operation was a write */ ! 151: #define H_ERASED 010 /* last write retry was an erase gap */ ! 152: #define H_OPEN 020 /* device open */ ! 153: #define H_OFFLINE 040 /* device went offline; no io till close */ ! 154: #define H_WONLY 0100 /* write-only */ ! 155: ! 156: /* ! 157: * scaling for block magtape blocks ! 158: */ ! 159: #define INF 1000000L /* a block number that won't exist */ ! 160: #define TBLOCK 2 /* tape blocks per b_blkno block */ ! 161: #define TBSIZE 1024 ! 162: #define TBSHIFT 10 ! 163: ! 164: /* ! 165: * overloads in struct buf; for tu78cmd ! 166: */ ! 167: #define b_repcnt b_bcount ! 168: #define b_command b_resid ! 169: ! 170: tu78open(dev, flag) ! 171: dev_t dev; ! 172: int flag; ! 173: { ! 174: register int tuunit; ! 175: register struct tu78 *sc; ! 176: register struct subaddr *sa; ! 177: int dens; ! 178: ! 179: tuunit = TUUNIT(dev); ! 180: if (tuunit >= tu78cnt || (sc = &tu78[tuunit])->sc_flags & H_OPEN) { ! 181: u.u_error = ENXIO; ! 182: return; ! 183: } ! 184: sc->sc_flags |= H_OPEN; ! 185: sa = &tu78addr[tuunit]; ! 186: if (tm78init(sa->ctl, sa->unit, tuunit) == 0) { ! 187: sc->sc_flags &=~ H_OPEN; ! 188: u.u_error = ENXIO; ! 189: return; ! 190: } ! 191: sc->sc_ctl = &tm78[sa->ctl]; ! 192: sc->sc_dens = minor(dev) & H_6250BPI ? MT_GCR : 0; ! 193: sc->sc_slave = sa->unit; ! 194: sc->sc_flags &=~ H_OFFLINE; /* so we can sense */ ! 195: tu78cmd(dev, MT_SENSE, 1L); ! 196: if ((sc->sc_dsreg & MTDS_PRES) == 0) { /* what's the right test? */ ! 197: printf("tu78 %d absent\n", tuunit); ! 198: sc->sc_flags &=~ H_OPEN; ! 199: u.u_error = ENODEV; ! 200: return; ! 201: } ! 202: if ((sc->sc_dsreg & MTDS_ONL) == 0) { ! 203: sc->sc_flags &=~ H_OPEN; ! 204: u.u_error = EIO; ! 205: return; ! 206: } ! 207: if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) { ! 208: sc->sc_flags &=~ H_OPEN; ! 209: u.u_error = EIO; ! 210: return; ! 211: } ! 212: if ((sc->sc_dsreg & MTDS_BOT) == 0 && flag&FWRITE) { ! 213: dens = sc->sc_dsreg & MTDS_PE ? 0 : MT_GCR; ! 214: if (sc->sc_dens != dens) { ! 215: sc->sc_flags &=~ H_OPEN; ! 216: u.u_error = EIO; ! 217: return; ! 218: } ! 219: } ! 220: sc->sc_blkno = 0; ! 221: sc->sc_nxrec = INF; ! 222: if ((flag & (FREAD|FWRITE)) == FWRITE) ! 223: sc->sc_flags |= H_WONLY; /* stop block dev readahead */ ! 224: } ! 225: ! 226: tm78init(ctl, slave, dev) ! 227: register int ctl; ! 228: int slave, dev; ! 229: { ! 230: register struct tm78 *cc; ! 231: register int i; ! 232: ! 233: if (ctl < 0 || slave < 0 || ctl >= tm78cnt || slave >= TM78DRIVES) ! 234: return (0); ! 235: cc = &tm78[ctl]; ! 236: cc->cc_drives[slave] = dev; ! 237: if (cc->cc_mbaddr) ! 238: return (1); ! 239: if ((cc->cc_addr = (struct device *)mbaddr(&tm78addr[ctl])) == 0 ! 240: || badaddr(&cc->cc_addr->mtcs, sizeof(long)) ! 241: || (cc->cc_addr->mter & MTER_DPR) == 0) { ! 242: printf("tm78 %d absent\n", ctl); ! 243: return (0); ! 244: } ! 245: for (i = 0; i < TM78DRIVES; i++) ! 246: if (i != slave) ! 247: cc->cc_drives[i] = NOUNIT; ! 248: if (tm78reset(ctl) == 0) ! 249: return (0); ! 250: cc->cc_mbaddr = &tm78addr[ctl]; ! 251: return (1); ! 252: } ! 253: ! 254: /* ! 255: * reset the formatter ! 256: * initially or after some awful error ! 257: */ ! 258: tm78reset(ctl) ! 259: int ctl; ! 260: { ! 261: register struct tm78 *cc; ! 262: register struct device *tmaddr; ! 263: register struct tu78 *sc; ! 264: register struct buf *bp; ! 265: register int i; ! 266: ! 267: cc = &tm78[ctl]; ! 268: tmaddr = cc->cc_addr; ! 269: tmaddr->mtid = MTID_CLR; ! 270: while ((sc = cc->cc_actf) != NULL) { ! 271: cc->cc_actf = sc->sc_next; ! 272: while ((bp = sc->sc_actf) != NULL) { ! 273: sc->sc_actf = bp->av_forw; ! 274: bp->b_flags |= B_ERROR; ! 275: iodone(bp); ! 276: } ! 277: sc->sc_flags &=~ H_BUSY; ! 278: } ! 279: cc->cc_flags &=~ T_BUSY; ! 280: DELAY(200); ! 281: for (i = 0; i < MTTIMEOUT; i++) { ! 282: if (tmaddr->mtid & MTID_RDY) ! 283: return (1); /* done */ ! 284: DELAY(50); /* wait a bit more */ ! 285: } ! 286: printf("tm78 %d: never ready\n", ctl); ! 287: return (0); ! 288: } ! 289: ! 290: tu78close(dev) ! 291: register dev_t dev; ! 292: { ! 293: register struct tu78 *sc = &tu78[TUUNIT(dev)]; ! 294: ! 295: if (sc->sc_flags & (H_WONLY|H_WRITTEN)) ! 296: tu78cmd(dev, MT_CLS|sc->sc_dens, 1L); ! 297: if ((minor(dev)&H_NOREWIND) == 0) ! 298: tu78cmd(dev, MT_REW, 0L); ! 299: sc->sc_flags &= H_BUSY; ! 300: } ! 301: ! 302: tu78cmd(dev, com, count) ! 303: dev_t dev; ! 304: int com; ! 305: register daddr_t count; ! 306: { ! 307: register struct buf *bp; ! 308: register int some; ! 309: ! 310: bp = &ctu78buf[TUUNIT(dev)]; ! 311: (void) spl5(); ! 312: while (bp->b_flags&B_BUSY) { ! 313: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) ! 314: break; ! 315: bp->b_flags |= B_WANTED; ! 316: sleep((caddr_t)bp, PRIBIO); ! 317: } ! 318: bp->b_flags = B_BUSY|B_READ; ! 319: (void) spl0(); ! 320: bp->b_dev = dev; ! 321: bp->b_command = com; ! 322: bp->b_blkno = 0; ! 323: do { ! 324: if (count <= MAXCOUNT) ! 325: some = count; ! 326: else ! 327: some = MAXCOUNT; ! 328: bp->b_repcnt = some; ! 329: tu78strategy(bp); ! 330: if (count == 0) { ! 331: if (bp->b_flags & B_DONE) ! 332: geterror(bp); ! 333: return; /* sic */ ! 334: } ! 335: iowait(bp); ! 336: } while (u.u_error == 0 && (count -= some) > 0); ! 337: if (bp->b_flags&B_WANTED) ! 338: wakeup((caddr_t)bp); ! 339: bp->b_flags &=~ B_BUSY; ! 340: } ! 341: ! 342: tu78strategy(bp) ! 343: register struct buf *bp; ! 344: { ! 345: register struct tu78 *sc; ! 346: ! 347: sc = &tu78[TUUNIT(bp->b_dev)]; ! 348: bp->av_forw = NULL; ! 349: (void) spl5(); ! 350: if (sc->sc_actf == NULL) ! 351: sc->sc_actf = bp; ! 352: else ! 353: sc->sc_actl->av_forw = bp; ! 354: sc->sc_actl = bp; ! 355: if ((sc->sc_flags & H_BUSY) == 0) ! 356: tu78start(sc); ! 357: if (sc->sc_ctl->cc_actf && (sc->sc_ctl->cc_flags & T_BUSY) == 0) ! 358: tm78start(sc->sc_ctl); ! 359: (void) spl0(); ! 360: } ! 361: ! 362: tu78start(sc) ! 363: register struct tu78 *sc; ! 364: { ! 365: register struct buf *bp; ! 366: register struct device *tmaddr; ! 367: register struct tm78 *cc; ! 368: register daddr_t bno; ! 369: register int cmd, dist; ! 370: ! 371: cc = sc->sc_ctl; ! 372: loop: ! 373: if ((bp = sc->sc_actf) == 0) ! 374: return; ! 375: tmaddr = cc->cc_addr; ! 376: sc->sc_flags &= ~H_WRITTEN; ! 377: if (sc->sc_flags & H_OFFLINE) { ! 378: bp->b_flags |= B_ERROR; ! 379: goto done; ! 380: } ! 381: /* ! 382: * command, start it ! 383: */ ! 384: if (bp == &ctu78buf[TUUNIT(bp->b_dev)]) { ! 385: sc->sc_flags |= H_BUSY; ! 386: cmd = bp->b_command|MT_GO; ! 387: cmd |= bp->b_repcnt << MT_COFF; ! 388: #if BABBLE ! 389: printf("cmd %o\n", cmd); ! 390: #endif ! 391: tmaddr->mtncs[sc->sc_slave] = cmd; ! 392: return; ! 393: } ! 394: /* ! 395: * transfer, see if position needed (wretched block magtape) ! 396: */ ! 397: bno = bp->b_blkno/TBLOCK; ! 398: if (bno > sc->sc_nxrec) { ! 399: bp->b_error = ENXIO; ! 400: bp->b_flags |= B_ERROR; ! 401: goto done; ! 402: } ! 403: if (bp->b_flags & B_READ /* at EOF, or really just writing? */ ! 404: && (bno == sc->sc_nxrec || sc->sc_flags & H_WONLY)) { ! 405: bp->b_resid = bp->b_bcount; ! 406: goto done; ! 407: } ! 408: if ((bp->b_flags&B_READ)==0) ! 409: sc->sc_nxrec = bno + 1; ! 410: if (sc->sc_blkno != bno) { /* need position */ ! 411: sc->sc_flags |= H_BUSY; ! 412: if (sc->sc_blkno < bno) { ! 413: sc->sc_flags &=~ H_EOT; ! 414: dist = bno - sc->sc_blkno; ! 415: cmd = MT_SREV; ! 416: } else { ! 417: dist = sc->sc_blkno - bno; ! 418: cmd = MT_SFORW; ! 419: } ! 420: if (dist > MAXCOUNT) ! 421: dist = MAXCOUNT; ! 422: tmaddr->mtncs[sc->sc_slave] = (dist<<MT_COFF)|cmd|MT_GO; ! 423: return; ! 424: } ! 425: /* ! 426: * time for a transfer ! 427: */ ! 428: if ((bp->b_flags&B_READ) == 0 && sc->sc_flags & H_EOT) { ! 429: bp->b_resid = bp->b_bcount; ! 430: done: ! 431: sc->sc_actf = bp->av_forw; ! 432: iodone(bp); ! 433: goto loop; ! 434: } ! 435: cc = sc->sc_ctl; ! 436: sc->sc_next = NULL; ! 437: if (cc->cc_actf == NULL) ! 438: cc->cc_actf = sc; ! 439: else ! 440: cc->cc_actl->sc_next = sc; ! 441: cc->cc_actl = sc; ! 442: sc->sc_flags |= H_BUSY; ! 443: } ! 444: ! 445: tm78start(cc) ! 446: register struct tm78 *cc; ! 447: { ! 448: register struct tu78 *sc; ! 449: int tm78xfer(); ! 450: ! 451: if ((sc = cc->cc_actf) == NULL) ! 452: return; ! 453: if (sc->sc_actf == NULL) ! 454: panic("tm78start"); ! 455: cc->cc_flags |= T_BUSY; ! 456: mbstart(cc->cc_mbaddr, sc->sc_actf, tm78xfer); ! 457: } ! 458: ! 459: tm78xfer(bp) ! 460: register struct buf *bp; ! 461: { ! 462: register struct tu78 *sc; ! 463: register struct device *tmaddr; ! 464: ! 465: sc = &tu78[TUUNIT(bp->b_dev)]; ! 466: tmaddr = sc->sc_ctl->cc_addr; ! 467: tmaddr->mtca = sc->sc_slave; ! 468: tmaddr->mtbc = bp->b_bcount; ! 469: #if BABBLE ! 470: printf("xfer go\n"); ! 471: #endif ! 472: if (bp->b_flags & B_READ) ! 473: tmaddr->mtcs = MT_READ|MT_GO; ! 474: else ! 475: tmaddr->mtcs = MT_WRITE|sc->sc_dens|MT_GO; ! 476: } ! 477: ! 478: /* ! 479: * massbus interrupt ! 480: * if a transfer was pending, assume it finished; ! 481: * if attn set, something else finished too ! 482: */ ! 483: tm780int(ctl, mbsr, mbbc, attn) ! 484: int ctl, mbsr, mbbc, attn; ! 485: { ! 486: register struct tm78 *cc; ! 487: ! 488: cc = &tm78[ctl]; ! 489: if (cc->cc_addr == NULL) { ! 490: printf("tm78 %d: stray intr\n", ctl); ! 491: return; ! 492: } ! 493: if (attn) ! 494: tu78attn(ctl, mbsr, attn); ! 495: if (cc->cc_flags & T_BUSY) ! 496: tu78dtint(ctl, mbsr); ! 497: if (cc->cc_actf) ! 498: tm78start(cc); ! 499: } ! 500: ! 501: /* ! 502: * here with an attention: ! 503: * a boring interrupt, a disaster, or a command finished ! 504: * don't clear the attn until we've read the registers ! 505: */ ! 506: ! 507: tu78attn(ctl, mbsr, attn) ! 508: int ctl, mbsr, attn; ! 509: { ! 510: register struct tm78 *cc; ! 511: register struct tu78 *sc; ! 512: register struct buf *bp; ! 513: register struct device *tmaddr; ! 514: register int unit; ! 515: daddr_t bno; ! 516: register int i; ! 517: register long rt; /* register temp to avoid compiler botches */ ! 518: ! 519: cc = &tm78[ctl]; ! 520: tmaddr = cc->cc_addr; ! 521: rt = tmaddr->mtner; ! 522: i = MTER_UNIT(rt); ! 523: #if BABBLE ! 524: printf("attn er%o ds%o cs%o\n", tmaddr->mtner&0xffff, tmaddr->mtds&0xffff, tmaddr->mtncs[i]&0xffff); ! 525: #endif ! 526: switch (MTER_INTCODE(rt)) { ! 527: case MTER_ONLINE: ! 528: case MTER_RWDING: ! 529: tmaddr->mtas = attn; ! 530: return; /* boring */ ! 531: ! 532: case MTER_MBFLT: ! 533: case MTER_TMFLTB: ! 534: printf("tm78 %d fault er%o mbsr%o\n", ctl, tmaddr->mtner, mbsr); ! 535: tm78reset(ctl); ! 536: tmaddr->mtas = attn; ! 537: return; ! 538: } ! 539: if ((unit = cc->cc_drives[i]) == NOUNIT) { ! 540: printf("tm78 %d unit %d stray intr er%o\n", ctl, i, tmaddr->mtner); ! 541: tmaddr->mtas = attn; ! 542: return; ! 543: } ! 544: sc = &tu78[unit]; ! 545: rt = tmaddr->mtds; sc->sc_dsreg = rt; ! 546: rt = tmaddr->mtner; sc->sc_erreg = rt; ! 547: rt = tmaddr->mtncs[i]; sc->sc_resid = MTNCS_COUNT(rt); ! 548: tmaddr->mtas = attn; ! 549: if ((bp = sc->sc_actf) == NULL) { ! 550: printf("tu78 %d: odd intr er%o\n", unit, sc->sc_erreg); ! 551: return; ! 552: } ! 553: switch (MTER_INTCODE(sc->sc_erreg)) { ! 554: case MTER_EOT: ! 555: sc->sc_flags |= H_EOT; ! 556: /* fall through */ ! 557: case MTER_TM: ! 558: case MTER_LEOT: ! 559: case MTER_BOT: ! 560: case MTER_NOOP: ! 561: case MTER_DONE: ! 562: /* ! 563: * this was a block magtape seek, ! 564: * or we're closing (so sc_blkno is boring), ! 565: * or it's raw magtape (ditto) ! 566: */ ! 567: bno = bp->b_blkno / TBLOCK; ! 568: if (sc->sc_blkno > bno) ! 569: sc->sc_blkno += sc->sc_resid; ! 570: else ! 571: sc->sc_blkno -= sc->sc_resid; ! 572: if (sc->sc_flags & H_EOT) ! 573: sc->sc_nxrec = sc->sc_blkno; ! 574: if (bp != &ctu78buf[unit]) ! 575: sc->sc_flags &=~ H_BUSY; /* done with seek */ ! 576: break; ! 577: ! 578: case MTER_NOTAVL: ! 579: case MTER_OFFLINE: ! 580: case MTER_NONEX: ! 581: if (sc->sc_flags & H_OPEN) ! 582: sc->sc_flags |= H_OFFLINE; ! 583: bp->b_error = ENXIO; ! 584: bp->b_flags |= B_ERROR; ! 585: break; ! 586: ! 587: default: ! 588: printf("tu78 %d: hard error bn%d er%o mbsr%o\n", ! 589: unit, bp->b_blkno, sc->sc_erreg, mbsr); ! 590: bp->b_flags |= B_ERROR; ! 591: break; ! 592: } ! 593: if (sc->sc_flags & H_BUSY) { ! 594: sc->sc_actf = bp->av_forw; ! 595: iodone(bp); ! 596: sc->sc_flags &=~ H_BUSY; ! 597: } ! 598: if (sc->sc_actf) ! 599: tu78start(sc); ! 600: } ! 601: ! 602: tu78dtint(ctl, mbsr) ! 603: int ctl, mbsr; ! 604: { ! 605: register struct tm78 *cc; ! 606: register struct tu78 *sc; ! 607: register struct buf *bp; ! 608: register struct device *tmaddr; ! 609: register int rt; /* reg temp to avoid compiler botches */ ! 610: ! 611: cc = &tm78[ctl]; ! 612: tmaddr = cc->cc_addr; ! 613: if ((sc = cc->cc_actf) == NULL ! 614: || (bp = sc->sc_actf) == NULL) ! 615: panic("tu78dtint"); ! 616: rt = tmaddr->mtbc; sc->sc_resid = rt; ! 617: rt = tmaddr->mter; sc->sc_erreg = rt; ! 618: #if BABBLE ! 619: printf("dtint er%o bc%o mbs%o\n", sc->sc_erreg, sc->sc_resid, mbsr); ! 620: #endif ! 621: if (mbsr & MBSR_HARD) { ! 622: printf("tu78 %d: mb error er%o mbsr%o\n", ! 623: TUUNIT(bp->b_dev), sc->sc_erreg, mbsr); ! 624: bp->b_flags |= B_ERROR; ! 625: } else switch (MTER_INTCODE(sc->sc_erreg)) { ! 626: case MTER_MBFLT: ! 627: case MTER_TMFLTB: ! 628: printf("tm78 %d fault er%o mbsr%o\n", ctl, sc->sc_erreg, mbsr); ! 629: tm78reset(ctl); ! 630: return; ! 631: ! 632: case MTER_EOT: ! 633: sc->sc_flags |= H_EOT; ! 634: /* fall through */ ! 635: case MTER_LEOT: ! 636: case MTER_TM: ! 637: bp->b_resid = bp->b_bcount; ! 638: sc->sc_nxrec = sc->sc_blkno; ! 639: break; ! 640: ! 641: case MTER_LONGREC: ! 642: sc->sc_blkno++; ! 643: bp->b_error = ENOMEM; ! 644: bp->b_flags |= B_ERROR; ! 645: break; ! 646: ! 647: case MTER_SHRTREC: ! 648: if (bp != &rtu78buf[TUUNIT(bp->b_dev)]) /* block tape */ ! 649: bp->b_flags |= B_ERROR; ! 650: /* fall in */ ! 651: case MTER_DONE: ! 652: bp->b_resid = bp->b_bcount - sc->sc_resid; ! 653: sc->sc_blkno++; ! 654: break; ! 655: ! 656: case MTER_RETRY: ! 657: cc->cc_flags &=~ T_BUSY; ! 658: break; ! 659: ! 660: case MTER_NOTAVL: ! 661: case MTER_OFFLINE: ! 662: case MTER_NONEX: ! 663: if (sc->sc_flags & H_OPEN) ! 664: sc->sc_flags |= H_OFFLINE; ! 665: bp->b_error = ENXIO; ! 666: bp->b_flags |= B_ERROR; ! 667: break; ! 668: ! 669: case MTER_NOTCAP: ! 670: case MTER_BADTAPE: ! 671: if (sc->sc_flags & H_OPEN) ! 672: sc->sc_flags |= H_OFFLINE; /* really position lost */ ! 673: /* fall through */ ! 674: default: ! 675: printf("tu78 %d: hard error bn%d er%o mbsr%o\n", ! 676: TUUNIT(bp->b_dev), bp->b_blkno, sc->sc_erreg, mbsr); ! 677: sc->sc_blkno++; ! 678: bp->b_flags |= B_ERROR; ! 679: break; ! 680: } ! 681: if (cc->cc_flags & T_BUSY) { ! 682: cc->cc_actf = sc->sc_next; ! 683: sc->sc_actf = bp->av_forw; ! 684: iodone(bp); ! 685: sc->sc_flags &=~ H_BUSY; ! 686: if (sc->sc_actf) ! 687: tu78start(sc); ! 688: cc->cc_flags &=~ T_BUSY; ! 689: } ! 690: } ! 691: ! 692: tu78read(dev) ! 693: dev_t dev; ! 694: { ! 695: ! 696: tu78phys(dev); ! 697: physio(tu78strategy, &rtu78buf[TUUNIT(dev)], dev, B_READ, minphys); ! 698: } ! 699: ! 700: tu78write(dev) ! 701: dev_t dev; ! 702: { ! 703: ! 704: tu78phys(dev); ! 705: physio(tu78strategy, &rtu78buf[TUUNIT(dev)], dev, B_WRITE, minphys); ! 706: } ! 707: ! 708: tu78phys(dev) ! 709: dev_t dev; ! 710: { ! 711: register struct tu78 *sc; ! 712: ! 713: sc = &tu78[TUUNIT(dev)]; ! 714: sc->sc_blkno = Lshift(u.u_offset, TBSHIFT); ! 715: sc->sc_nxrec = sc->sc_blkno + 1; ! 716: } ! 717: ! 718: tu78ioctl(dev, cmd, addr, flag) ! 719: dev_t dev; ! 720: int cmd; ! 721: caddr_t addr; ! 722: int flag; ! 723: { ! 724: struct mtop mtop; ! 725: ! 726: switch (cmd) { ! 727: case MTIOCTOP: /* tape operation */ ! 728: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { ! 729: u.u_error = EFAULT; ! 730: return; ! 731: } ! 732: if (mtop.mt_count == 0) ! 733: mtop.mt_count = 1; ! 734: switch(mtop.mt_op) { ! 735: case MTWEOF: ! 736: tu78cmd(dev, MT_WTM|tu78[TUUNIT(dev)].sc_dens, mtop.mt_count); ! 737: break; ! 738: ! 739: case MTFSF: ! 740: tu78cmd(dev, MT_SFORWF, mtop.mt_count); ! 741: break; ! 742: ! 743: case MTBSF: ! 744: tu78cmd(dev, MT_SREVF, mtop.mt_count); ! 745: break; ! 746: ! 747: case MTFSR: ! 748: tu78cmd(dev, MT_SFORW, mtop.mt_count); ! 749: break; ! 750: ! 751: case MTBSR: ! 752: tu78cmd(dev, MT_SREV, mtop.mt_count); ! 753: break; ! 754: ! 755: case MTREW: ! 756: tu78cmd(dev, MT_REW, 1L); ! 757: break; ! 758: ! 759: case MTOFFL: ! 760: tu78cmd(dev, MT_UNLOAD, 1L); ! 761: break; ! 762: ! 763: default: ! 764: u.u_error = ENXIO; ! 765: break; ! 766: } ! 767: return; ! 768: ! 769: default: ! 770: u.u_error = ENXIO; ! 771: return; ! 772: } ! 773: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.