|
|
1.1 ! root 1: /* ! 2: * TM03/TE16 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/te16.h" ! 17: ! 18: /* ! 19: * hardware stuff ! 20: */ ! 21: struct device { ! 22: int htcs1; /* control status */ ! 23: int htds; /* drive status */ ! 24: int hter; /* error */ ! 25: int htmr; /* maintenance */ ! 26: int htas; /* attention status */ ! 27: int htfc; /* frame count */ ! 28: int htdt; /* drive type */ ! 29: int htck; /* nrzi check (crc) error character */ ! 30: int htsn; /* serial number */ ! 31: int httc; /* tape control */ ! 32: }; ! 33: ! 34: /* htcs1 */ ! 35: #define HT_GO 000001 /* go bit */ ! 36: #define HT_REWOFFL 000002 /* rewind offline */ ! 37: #define HT_REW 000006 /* rewind */ ! 38: #define HT_DCLR 000010 /* drive clear */ ! 39: #define HT_ERASE 000024 /* erase */ ! 40: #define HT_WEOF 000026 /* write tape mark */ ! 41: #define HT_SFORW 000030 /* space forward */ ! 42: #define HT_SREV 000032 /* space reverse */ ! 43: #define HT_WCOM 000060 /* write forward */ ! 44: #define HT_RCOM 000070 /* read forward */ ! 45: ! 46: /* htds */ ! 47: #define HTDS_ATA 0100000 /* attention active */ ! 48: #define HTDS_ERR 0040000 /* composite error */ ! 49: #define HTDS_MOL 0010000 /* medium on line */ ! 50: #define HTDS_WRL 0004000 /* write lock */ ! 51: #define HTDS_EOT 0002000 /* end of tape */ ! 52: #define HTDS_DPR 0000400 /* drive present (always 1) */ ! 53: #define HTDS_DRY 0000200 /* drive ready */ ! 54: #define HTDS_SSC 0000100 /* slace status changed */ ! 55: #define HTDS_PES 0000040 /* phase-encoded status */ ! 56: #define HTDS_TM 0000004 /* tape mark */ ! 57: #define HTDS_BOT 0000002 /* beginning of tape */ ! 58: #define HTDS_SLA 0000001 /* slave attention */ ! 59: ! 60: /* hter */ ! 61: #define HTER_CORCRC 0100000 /* correctible data or ecc */ ! 62: #define HTER_UNS 0040000 /* unsafe */ ! 63: #define HTER_OPI 0020000 /* operation incomplete */ ! 64: #define HTER_DTE 0010000 /* drive timing error */ ! 65: #define HTER_NEF 0004000 /* non-executable function */ ! 66: #define HTER_CSITM 0002000 /* correctable skew/illegal tape mark */ ! 67: #define HTER_FCE 0001000 /* frame count error */ ! 68: #define HTER_NSG 0000400 /* non-standard gap */ ! 69: #define HTER_PEFLRC 0000200 /* format error or lrc error */ ! 70: #define HTER_DPAR 0000040 /* data parity error */ ! 71: #define HTER_FMT 0000020 /* format error */ ! 72: #define HTER_CPAR 0000010 /* control bus parity error */ ! 73: #define HTER_RMR 0000004 /* register modification refused */ ! 74: #define HTER_ILR 0000002 /* illegal register */ ! 75: #define HTER_ILF 0000001 /* illegal function */ ! 76: #define HTER_HARD \ ! 77: (HTER_UNS|HTER_OPI|HTER_NEF|HTER_DPAR|HTER_FMT|HTER_CPAR| \ ! 78: HTER_RMR|HTER_ILR|HTER_ILF) ! 79: ! 80: /* htdt */ ! 81: #define HTDT_SPR 0002000 /* slave present */ ! 82: ! 83: /* httc */ ! 84: #define HTTC_800BPI 0001400 /* in bits 8-10, dens=1600 */ ! 85: #define HTTC_1600BPI 0002000 /* in bits 8-10, dens=800 */ ! 86: #define HTTC_PDP11 0000300 /* in bits 4-7, pdp11 normal format */ ! 87: ! 88: /* ! 89: * system stuff ! 90: */ ! 91: ! 92: int te16open(), te16close(), te16read(), te16write(), te16ioctl(), te16strategy(); ! 93: struct cdevsw te16cdev = cdinit(te16open, te16close, te16read, te16write, te16ioctl); ! 94: struct bdevsw te16bdev = bdinit(te16open, te16close, te16strategy, B_TAPE); ! 95: ! 96: /* ! 97: * per-formatter stuff ! 98: */ ! 99: ! 100: extern int tm03cnt; ! 101: extern struct tm03 tm03[]; ! 102: extern struct mbaddr tm03addr[]; ! 103: ! 104: #define T_BUSY 01 /* controller busy */ ! 105: #define NOUNIT 0377 /* no unit expected */ ! 106: ! 107: /* ! 108: * per-drive stuff ! 109: */ ! 110: ! 111: extern int te16cnt; ! 112: extern struct te16 te16[]; ! 113: extern struct subaddr te16addr[]; ! 114: extern struct buf rte16buf[]; ! 115: extern struct buf cte16buf[]; ! 116: ! 117: /* ! 118: * bits in minor device ! 119: */ ! 120: #define TEUNIT(dev) (minor(dev)&03) ! 121: #define H_NOREWIND 04 ! 122: #define H_1600BPI 010 ! 123: ! 124: /* ! 125: * sc_flags ! 126: */ ! 127: #define H_BUSY 01 /* software drive busy */ ! 128: #define H_CMD 02 /* hardware command pending */ ! 129: #define H_WRITTEN 04 /* last operation was a write */ ! 130: #define H_ERASED 010 /* last write retry was an erase gap */ ! 131: #define H_OPEN 020 /* device open */ ! 132: #define H_OFFLINE 040 /* device went offline; no io till close */ ! 133: #define H_WONLY 0100 /* write-only */ ! 134: ! 135: /* ! 136: * scaling for block magtape blocks ! 137: */ ! 138: #define INF 1000000L /* a block number that won't exist */ ! 139: #define TBLOCK 2 /* tape blocks per b_blkno block */ ! 140: #define TBSIZE 1024 ! 141: #define TBSHIFT 10 ! 142: ! 143: /* ! 144: * overloads in struct buf; for te16cmd ! 145: */ ! 146: #define b_repcnt b_bcount ! 147: #define b_command b_resid ! 148: ! 149: te16open(dev, flag) ! 150: dev_t dev; ! 151: int flag; ! 152: { ! 153: register int teunit; ! 154: register struct te16 *sc; ! 155: register struct subaddr *sa; ! 156: register struct device *htaddr; ! 157: register int dt; ! 158: ! 159: teunit = TEUNIT(dev); ! 160: if (teunit >= te16cnt || (sc = &te16[teunit])->sc_flags & H_OPEN) { ! 161: u.u_error = ENXIO; ! 162: return; ! 163: } ! 164: sc->sc_flags |= H_OPEN; ! 165: sa = &te16addr[teunit]; ! 166: if (tm03init(sa->ctl, sa->unit, teunit) == 0) { ! 167: sc->sc_flags &=~ H_OPEN; ! 168: u.u_error = ENXIO; ! 169: return; ! 170: } ! 171: sc->sc_ctl = &tm03[sa->ctl]; ! 172: htaddr = sc->sc_ctl->cc_addr; ! 173: sc->sc_dens = ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|HTTC_PDP11|sa->unit; ! 174: spl5(); ! 175: htaddr->httc = sc->sc_dens; ! 176: /* delay here? */ ! 177: dt = htaddr->htdt; ! 178: sc->sc_dsreg = htaddr->htds; ! 179: spl0(); ! 180: if ((dt & HTDT_SPR) == 0) { ! 181: printf("te16 %d absent\n", teunit); ! 182: sc->sc_flags &=~ H_OPEN; ! 183: u.u_error = ENODEV; ! 184: return; ! 185: } ! 186: if ((sc->sc_dsreg & HTDS_MOL) == 0) { ! 187: sc->sc_flags &=~ H_OPEN; ! 188: u.u_error = EIO; ! 189: return; ! 190: } ! 191: if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { ! 192: sc->sc_flags &=~ H_OPEN; ! 193: u.u_error = EIO; ! 194: return; ! 195: } ! 196: if ((sc->sc_dsreg & HTDS_BOT) == 0 && flag&FWRITE ! 197: && ((minor(dev) & H_1600BPI) != 0) != ((sc->sc_dsreg & HTDS_PES) != 0)) { ! 198: sc->sc_flags &=~ H_OPEN; ! 199: u.u_error = EIO; ! 200: return; ! 201: } ! 202: sc->sc_blkno = 0; ! 203: sc->sc_nxrec = INF; ! 204: if ((flag & (FREAD|FWRITE)) == FWRITE) ! 205: sc->sc_flags |= H_WONLY; /* stop block dev readahead */ ! 206: } ! 207: ! 208: tm03init(ctl, slave, dev) ! 209: register int ctl; ! 210: int slave, dev; ! 211: { ! 212: register struct tm03 *cc; ! 213: register int i; ! 214: ! 215: if (ctl < 0 || slave < 0 || ctl >= tm03cnt || slave >= TM03DRIVES) ! 216: return (0); ! 217: cc = &tm03[ctl]; ! 218: cc->cc_drives[slave] = dev; ! 219: if (cc->cc_addr) ! 220: return (1); ! 221: if ((cc->cc_addr = (struct device *)mbaddr(&tm03addr[ctl])) == 0 ! 222: || badaddr(&cc->cc_addr->htcs1, sizeof(long)) ! 223: || (cc->cc_addr->htds & HTDS_DPR) == 0) { ! 224: printf("tm03 %d absent\n", ctl); ! 225: return (0); ! 226: } ! 227: cc->cc_mbaddr = &tm03addr[ctl]; ! 228: for (i = 0; i < TM03DRIVES; i++) ! 229: if (i != slave) ! 230: cc->cc_drives[i] = NOUNIT; ! 231: /* any reset worth doing? */ ! 232: return (1); ! 233: } ! 234: ! 235: te16close(dev) ! 236: register dev_t dev; ! 237: { ! 238: register struct te16 *sc = &te16[TEUNIT(dev)]; ! 239: ! 240: if (sc->sc_flags & (H_WONLY|H_WRITTEN)) { ! 241: te16cmd(dev, HT_WEOF, 1); ! 242: te16cmd(dev, HT_WEOF, 1); ! 243: te16cmd(dev, HT_SREV, 1); ! 244: } ! 245: if ((minor(dev)&H_NOREWIND) == 0) ! 246: te16cmd(dev, HT_REW, 0); ! 247: sc->sc_flags &= H_CMD|H_BUSY; ! 248: } ! 249: ! 250: te16cmd(dev, com, count) ! 251: dev_t dev; ! 252: int com, count; ! 253: { ! 254: register struct buf *bp; ! 255: ! 256: bp = &cte16buf[TEUNIT(dev)]; ! 257: (void) spl5(); ! 258: while (bp->b_flags&B_BUSY) { ! 259: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) ! 260: break; ! 261: bp->b_flags |= B_WANTED; ! 262: sleep((caddr_t)bp, PRIBIO); ! 263: } ! 264: bp->b_flags = B_BUSY|B_READ; ! 265: (void) spl0(); ! 266: bp->b_dev = dev; ! 267: bp->b_command = com; ! 268: bp->b_repcnt = count; ! 269: bp->b_blkno = 0; ! 270: te16strategy(bp); ! 271: if (count == 0) { ! 272: if (bp->b_flags & B_DONE) ! 273: geterror(bp); ! 274: return; ! 275: } ! 276: iowait(bp); ! 277: if (bp->b_flags&B_WANTED) ! 278: wakeup((caddr_t)bp); ! 279: bp->b_flags &=~ B_BUSY; ! 280: } ! 281: ! 282: te16strategy(bp) ! 283: register struct buf *bp; ! 284: { ! 285: register struct te16 *sc; ! 286: ! 287: sc = &te16[TEUNIT(bp->b_dev)]; ! 288: bp->av_forw = NULL; ! 289: (void) spl5(); ! 290: if (sc->sc_actf == NULL) ! 291: sc->sc_actf = bp; ! 292: else ! 293: sc->sc_actl->av_forw = bp; ! 294: sc->sc_actl = bp; ! 295: if ((sc->sc_flags & H_BUSY) == 0) ! 296: te16start(sc); ! 297: if (sc->sc_ctl->cc_actf && (sc->sc_ctl->cc_flags & T_BUSY) == 0) ! 298: tm03start(sc->sc_ctl); ! 299: (void) spl0(); ! 300: } ! 301: ! 302: te16start(sc) ! 303: register struct te16 *sc; ! 304: { ! 305: register struct buf *bp; ! 306: register struct device *htaddr; ! 307: register struct tm03 *cc; ! 308: register daddr_t bno; ! 309: ! 310: cc = sc->sc_ctl; ! 311: loop: ! 312: if ((bp = sc->sc_actf) == 0) ! 313: return; ! 314: htaddr = cc->cc_addr; ! 315: htaddr->httc = sc->sc_dens; ! 316: if (htaddr->htds & HTDS_SSC) ! 317: htaddr->htcs1 = HT_DCLR|HT_GO; ! 318: sc->sc_dsreg = htaddr->htds; ! 319: sc->sc_erreg = htaddr->hter; ! 320: sc->sc_resid = htaddr->htfc; ! 321: sc->sc_flags &= ~H_WRITTEN; ! 322: if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) ! 323: if (sc->sc_flags & H_OPEN) ! 324: sc->sc_flags |= H_OFFLINE; ! 325: if (sc->sc_flags & H_OFFLINE) { ! 326: bp->b_flags |= B_ERROR; ! 327: goto done; ! 328: } ! 329: /* ! 330: * command, start it ! 331: */ ! 332: if (bp == &cte16buf[TEUNIT(bp->b_dev)]) { ! 333: sc->sc_flags |= H_BUSY|H_CMD; ! 334: htaddr->htfc = -bp->b_bcount; ! 335: htaddr->htcs1 = bp->b_command|HT_GO; ! 336: return; ! 337: } ! 338: /* ! 339: * transfer, see if position needed (wretched block magtape) ! 340: */ ! 341: bno = bp->b_blkno/TBLOCK; ! 342: if (bno > sc->sc_nxrec) { ! 343: bp->b_error = ENXIO; ! 344: bp->b_flags |= B_ERROR; ! 345: goto done; ! 346: } ! 347: if (bp->b_flags & B_READ /* at EOF, or really just writing? */ ! 348: && (bno == sc->sc_nxrec || sc->sc_flags & H_WONLY)) { ! 349: bp->b_resid = bp->b_bcount; ! 350: goto done; ! 351: } ! 352: if ((bp->b_flags&B_READ)==0) ! 353: sc->sc_nxrec = bno + 1; ! 354: if (sc->sc_blkno != bno) { /* need position */ ! 355: sc->sc_flags |= H_BUSY|H_CMD; ! 356: if (sc->sc_blkno < bno) { ! 357: htaddr->htfc = sc->sc_blkno - bno; ! 358: htaddr->htcs1 = HT_SFORW|HT_GO; ! 359: } else { ! 360: htaddr->htfc = bno - sc->sc_blkno; ! 361: htaddr->htcs1 = HT_SREV|HT_GO; ! 362: } ! 363: return; ! 364: } ! 365: /* ! 366: * special pleading for `erase gap' write error recovery ! 367: * -- is this in the right place? why bother? ! 368: */ ! 369: if ((bp->b_flags&B_READ) == 0) { ! 370: if (cc->cc_errcnt) { ! 371: if ((sc->sc_flags & H_ERASED) == 0) { ! 372: sc->sc_flags |= H_ERASED|H_BUSY|H_CMD; ! 373: htaddr->htcs1 = HT_ERASE|HT_GO; ! 374: return; ! 375: } ! 376: sc->sc_flags &= ~H_ERASED; ! 377: } ! 378: if (htaddr->htds & HTDS_EOT) { /* oops */ ! 379: bp->b_resid = bp->b_bcount; ! 380: done: ! 381: sc->sc_actf = bp->av_forw; ! 382: iodone(bp); ! 383: goto loop; ! 384: } ! 385: } ! 386: /* ! 387: * time for a transfer ! 388: */ ! 389: cc = sc->sc_ctl; ! 390: sc->sc_next = NULL; ! 391: if (cc->cc_actf == NULL) ! 392: cc->cc_actf = sc; ! 393: else ! 394: cc->cc_actl->sc_next = sc; ! 395: cc->cc_actl = sc; ! 396: sc->sc_flags |= H_BUSY; ! 397: } ! 398: ! 399: tm03start(cc) ! 400: register struct tm03 *cc; ! 401: { ! 402: register struct te16 *sc; ! 403: int tm03xfer(); ! 404: ! 405: if ((sc = cc->cc_actf) == NULL) ! 406: return; ! 407: if (sc->sc_actf == NULL) ! 408: panic("tm03start"); ! 409: cc->cc_flags |= T_BUSY; ! 410: mbstart(cc->cc_mbaddr, sc->sc_actf, tm03xfer); ! 411: } ! 412: ! 413: tm03xfer(bp) ! 414: register struct buf *bp; ! 415: { ! 416: register struct te16 *sc; ! 417: register struct device *htaddr; ! 418: ! 419: sc = &te16[TEUNIT(bp->b_dev)]; ! 420: htaddr = sc->sc_ctl->cc_addr; ! 421: htaddr->httc = sc->sc_dens; ! 422: htaddr->htfc = -bp->b_bcount; ! 423: sc->sc_flags |= H_CMD; ! 424: if (bp->b_flags & B_READ) ! 425: htaddr->htcs1 = HT_RCOM|HT_GO; ! 426: else ! 427: htaddr->htcs1 = HT_WCOM|HT_GO; ! 428: } ! 429: ! 430: /* ! 431: * massbus interrupt ! 432: * if a transfer was pending, assume it finished; ! 433: * if attn set, something else finished too ! 434: * ! 435: * the loop to see which drives wanted attention is somewhat doubtful ! 436: * and has not been tested with multiple drives ! 437: */ ! 438: tm030int(ctl, mbsr, mbbc, attn) ! 439: int ctl, mbsr, mbbc, attn; ! 440: { ! 441: register struct tm03 *cc; ! 442: register struct device *htaddr; ! 443: register struct te16 *sc; ! 444: register int i; ! 445: ! 446: cc = &tm03[ctl]; ! 447: if ((htaddr = cc->cc_addr) == NULL) { ! 448: printf("tm03 %d: stray intr\n", ctl); ! 449: return; ! 450: } ! 451: htaddr->htas = attn; /* before we do anything */ ! 452: if (cc->cc_flags & T_BUSY) ! 453: te16dtint(cc, mbsr); ! 454: if (attn) { ! 455: for (i = 0; i < TM03DRIVES; i++) { ! 456: if (cc->cc_drives[i] == NOUNIT) ! 457: continue; ! 458: sc = &te16[cc->cc_drives[i]]; ! 459: htaddr->httc = sc->sc_dens; /* select drive */ ! 460: if ((sc->sc_flags & H_CMD) == 0) { ! 461: sc->sc_dsreg = htaddr->htds; /* for BOT detection */ ! 462: wakeup((caddr_t)sc); ! 463: if (htaddr->htds & HTDS_SSC) ! 464: htaddr->htcs1 = HT_DCLR|HT_GO; ! 465: continue; ! 466: } ! 467: if ((htaddr->htds & HTDS_DRY) == 0) ! 468: continue; ! 469: te16attn(sc); ! 470: } ! 471: } ! 472: if (cc->cc_actf) ! 473: tm03start(cc); ! 474: } ! 475: ! 476: /* ! 477: * error recovery is somewhat doubtful ! 478: * particular specialties: ! 479: * - short reads show up as frame count errors, ! 480: * so ignore them for the raw device ! 481: * - reading at tape mark seems to produce a frame count error too ! 482: * - quietly ignore CRC errors the drive corrected ! 483: */ ! 484: te16dtint(cc, mbsr) ! 485: register struct tm03 *cc; ! 486: int mbsr; ! 487: { ! 488: register struct device *htaddr; ! 489: register struct buf *bp; ! 490: register struct te16 *sc; ! 491: int ds, er, mbs; ! 492: ! 493: htaddr = cc->cc_addr; ! 494: if ((sc = cc->cc_actf) == NULL) ! 495: panic("te16dtint"); ! 496: sc->sc_flags &=~ H_CMD; ! 497: bp = sc->sc_actf; ! 498: ds = sc->sc_dsreg = htaddr->htds; ! 499: er = sc->sc_erreg = htaddr->hter; ! 500: sc->sc_resid = htaddr->htfc; ! 501: #if BABBLE ! 502: printf("dt: ds%o er%o fc%o mbs%o\n", ds, er, sc->sc_resid, mbsr); ! 503: printf("bp: bn%d bc%d fl%o\n", bp->b_blkno, bp->b_bcount, bp->b_flags); ! 504: #endif ! 505: mbs = mbsr; ! 506: if (er) ! 507: htaddr->htcs1 = HT_DCLR|HT_GO; ! 508: sc->sc_blkno++; ! 509: if((bp->b_flags & B_READ) == 0) ! 510: sc->sc_flags |= H_WRITTEN; ! 511: if (bp == &rte16buf[TEUNIT(bp->b_dev)] || ds & HTDS_TM) { ! 512: if (er & HTER_FCE) { ! 513: er &=~ HTER_FCE; ! 514: mbs &=~ (MBSR_DTABT|MBSR_MBEXC); ! 515: } ! 516: } ! 517: if (er & HTER_HARD || (ds & HTDS_MOL) == 0 || mbs & MBSR_EBITS) ! 518: bp->b_flags |= B_ERROR; ! 519: else if (er) { /* soft error */ ! 520: if (++cc->cc_errcnt >= 7) ! 521: bp->b_flags |= B_ERROR; ! 522: else ! 523: cc->cc_flags &=~ T_BUSY; ! 524: } ! 525: if (bp->b_flags & B_ERROR) ! 526: printf("te16 %d: hard error bn%d mbsr=%o er=%o ds=%o\n", ! 527: TEUNIT(bp->b_dev), bp->b_blkno/TBLOCK, mbsr, sc->sc_erreg, sc->sc_dsreg); ! 528: if ((bp->b_flags & B_READ) == 0) ! 529: bp->b_resid = -sc->sc_resid; ! 530: else { ! 531: if (ds & HTDS_TM) { ! 532: bp->b_resid = bp->b_bcount; ! 533: sc->sc_nxrec = bp->b_blkno/TBLOCK; ! 534: } else if (sc->sc_resid > bp->b_bcount) { ! 535: bp->b_flags |= B_ERROR; ! 536: bp->b_error = ENOMEM; ! 537: } else ! 538: bp->b_resid = bp->b_bcount - sc->sc_resid; ! 539: } ! 540: if (cc->cc_flags & T_BUSY) { /* we decided we were finished */ ! 541: sc->sc_actf = bp->av_forw; ! 542: iodone(bp); ! 543: cc->cc_actf = sc->sc_next; ! 544: cc->cc_errcnt = 0; ! 545: cc->cc_flags &=~ T_BUSY; ! 546: } ! 547: sc->sc_flags &=~ H_BUSY; ! 548: if (sc->sc_actf) ! 549: te16start(sc); ! 550: } ! 551: ! 552: te16attn(sc) ! 553: register struct te16 *sc; ! 554: { ! 555: register struct device *htaddr; ! 556: register struct buf *bp; ! 557: register struct tm03 *cc; ! 558: register int er, ds; ! 559: daddr_t bno; ! 560: ! 561: sc->sc_flags &=~ H_CMD; ! 562: cc = sc->sc_ctl; ! 563: htaddr = cc->cc_addr; ! 564: ds = sc->sc_dsreg = htaddr->htds; ! 565: er = sc->sc_erreg = htaddr->hter; ! 566: sc->sc_resid = htaddr->htfc; ! 567: if (er) ! 568: htaddr->htcs1 = HT_DCLR|HT_GO; ! 569: wakeup((caddr_t)sc); ! 570: if ((bp = sc->sc_actf) == 0) ! 571: return; ! 572: #if BABBLE ! 573: printf("at: ds%o er%o fc%o\n", sc->sc_dsreg, sc->sc_erreg, sc->sc_resid); ! 574: printf("bp: bn%d bc%d fl%o cm%o\n", bp->b_blkno, bp->b_bcount, bp->b_flags, bp->b_command); ! 575: #endif ! 576: bno = bp->b_blkno/TBLOCK; ! 577: if (bp == &cte16buf[TEUNIT(bp->b_dev)]) { ! 578: switch ((int)bp->b_command) { ! 579: case HT_REWOFFL: ! 580: /* offline is on purpose; don't do anything special */ ! 581: ds |= HTDS_MOL; ! 582: break; ! 583: case HT_SREV: ! 584: /* if backspace file hit bot, its not an error */ ! 585: if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT ! 586: && bp->b_repcnt == INF) ! 587: er &= ~HTER_NEF; ! 588: break; ! 589: } ! 590: er &= ~HTER_FCE; ! 591: if (er == 0) ! 592: ds &= ~HTDS_ERR; ! 593: } ! 594: if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { ! 595: if ((ds & HTDS_MOL) == 0 && sc->sc_flags & H_OPEN) ! 596: sc->sc_flags |= H_OFFLINE; ! 597: printf("te16 %d: hard error bn%d er%o ds%o\n", ! 598: TEUNIT(bp->b_dev), bno, sc->sc_erreg, sc->sc_dsreg); ! 599: bp->b_flags |= B_ERROR; ! 600: } ! 601: if (bp == &cte16buf[TEUNIT(bp->b_dev)]) ! 602: bp->b_resid = -sc->sc_resid; ! 603: else ! 604: sc->sc_flags &=~ H_BUSY; /* done seeking, now xfer */ ! 605: if ((ds & HTDS_TM) == 0) ! 606: sc->sc_blkno = bno; ! 607: else if (sc->sc_blkno > bno) { ! 608: sc->sc_nxrec = bno - sc->sc_resid; ! 609: sc->sc_blkno = sc->sc_nxrec; ! 610: } else { ! 611: sc->sc_blkno = bno + sc->sc_resid; ! 612: sc->sc_nxrec = sc->sc_blkno - 1; ! 613: } ! 614: if (sc->sc_flags & H_BUSY) { ! 615: sc->sc_actf = bp->av_forw; ! 616: iodone(bp); ! 617: sc->sc_flags &=~ H_BUSY; ! 618: } ! 619: if (sc->sc_actf) ! 620: te16start(sc); ! 621: } ! 622: ! 623: te16read(dev) ! 624: dev_t dev; ! 625: { ! 626: ! 627: te16phys(dev); ! 628: physio(te16strategy, &rte16buf[TEUNIT(dev)], dev, B_READ, minphys); ! 629: } ! 630: ! 631: te16write(dev) ! 632: dev_t dev; ! 633: { ! 634: ! 635: te16phys(dev); ! 636: physio(te16strategy, &rte16buf[TEUNIT(dev)], dev, B_WRITE, minphys); ! 637: } ! 638: ! 639: te16phys(dev) ! 640: dev_t dev; ! 641: { ! 642: register struct te16 *sc; ! 643: ! 644: sc = &te16[TEUNIT(dev)]; ! 645: sc->sc_blkno = Lshift(u.u_offset, TBSHIFT); ! 646: sc->sc_nxrec = sc->sc_blkno + 1; ! 647: } ! 648: ! 649: /*ARGSUSED*/ ! 650: te16ioctl(dev, cmd, addr, flag) ! 651: dev_t dev; ! 652: int cmd; ! 653: caddr_t addr; ! 654: int flag; ! 655: { ! 656: register struct te16 *sc = &te16[TEUNIT(dev)]; ! 657: register struct buf *bp = &cte16buf[TEUNIT(dev)]; ! 658: register callcount; ! 659: int fcount, htcmd; ! 660: struct mtop mtop; ! 661: ! 662: switch (cmd) { ! 663: case MTIOCTOP: ! 664: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { ! 665: u.u_error = EFAULT; ! 666: return; ! 667: } ! 668: if (mtop.mt_count <= 0) { ! 669: u.u_error = ENXIO; ! 670: return; ! 671: } ! 672: switch(mtop.mt_op) { ! 673: case MTWEOF: ! 674: htcmd = HT_WEOF; ! 675: callcount = mtop.mt_count; ! 676: fcount = 1; ! 677: break; ! 678: case MTFSF: case MTBSF: ! 679: htcmd = (mtop.mt_op == MTFSF) ? HT_SFORW : HT_SREV; ! 680: callcount = mtop.mt_count; ! 681: fcount = INF; ! 682: break; ! 683: case MTFSR: case MTBSR: ! 684: htcmd = (mtop.mt_op == MTFSF) ? HT_SFORW : HT_SREV; ! 685: callcount = 1; ! 686: fcount = mtop.mt_count; ! 687: break; ! 688: case MTREW: case MTOFFL: ! 689: te16cmd(dev, HT_REW, 1); ! 690: if (mtop.mt_op == MTREW) ! 691: return; ! 692: spl5(); ! 693: while ((sc->sc_dsreg & HTDS_BOT) == 0) ! 694: sleep((caddr_t)sc, PZERO); ! 695: spl0(); ! 696: te16cmd(dev, HT_REWOFFL, 0); ! 697: return; ! 698: default: ! 699: u.u_error = ENXIO; ! 700: return; ! 701: } ! 702: while (--callcount >= 0) { ! 703: te16cmd(dev, htcmd, fcount); ! 704: if (bp->b_resid ! 705: && (mtop.mt_op == MTFSR || mtop.mt_op == MTBSR)) { ! 706: u.u_error = EIO; ! 707: break; ! 708: } ! 709: if (u.u_error || sc->sc_dsreg&HTDS_BOT) ! 710: break; ! 711: } ! 712: return; ! 713: ! 714: default: ! 715: u.u_error = ENXIO; ! 716: return; ! 717: } ! 718: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.