|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)ut.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: ! 9: #include "tj.h" ! 10: #if NUT > 0 ! 11: /* ! 12: * System Industries Model 9700 Tape Drive ! 13: * emulates a TU45 on the UNIBUS ! 14: * ! 15: * TODO: ! 16: * check out attention processing ! 17: * try reset code and dump code ! 18: */ ! 19: #include "../machine/pte.h" ! 20: ! 21: #include "param.h" ! 22: #include "systm.h" ! 23: #include "buf.h" ! 24: #include "conf.h" ! 25: #include "dir.h" ! 26: #include "file.h" ! 27: #include "user.h" ! 28: #include "map.h" ! 29: #include "ioctl.h" ! 30: #include "mtio.h" ! 31: #include "cmap.h" ! 32: #include "uio.h" ! 33: #include "kernel.h" ! 34: #include "tty.h" ! 35: ! 36: #include "../vax/cpu.h" ! 37: #include "ubareg.h" ! 38: #include "ubavar.h" ! 39: #include "utreg.h" ! 40: ! 41: struct buf rutbuf[NUT]; /* bufs for raw i/o */ ! 42: struct buf cutbuf[NUT]; /* bufs for control operations */ ! 43: struct buf tjutab[NTJ]; /* bufs for slave queue headers */ ! 44: ! 45: struct uba_ctlr *utminfo[NUT]; ! 46: struct uba_device *tjdinfo[NTJ]; ! 47: int utprobe(), utslave(), utattach(), utdgo(), utintr(), uttimer(); ! 48: u_short utstd[] = { 0772440, 0 }; ! 49: struct uba_driver utdriver = ! 50: { utprobe, utslave, utattach, utdgo, utstd, "tj", tjdinfo, "ut", utminfo, 0 }; ! 51: ! 52: #define MASKREG(reg) ((reg)&0xffff) ! 53: ! 54: /* bits in minor device */ ! 55: #define TJUNIT(dev) (minor(dev)&03) ! 56: #define T_NOREWIND 04 ! 57: #define T_1600BPI 010 ! 58: #define T_6250BPI 020 ! 59: short utdens[] = { UT_NRZI, UT_PE, UT_GCR, UT_NRZI }; ! 60: ! 61: /* slave to controller mapping table */ ! 62: short tjtout[NTJ]; ! 63: #define UTUNIT(dev) (tjtout[TJUNIT(dev)]) ! 64: ! 65: #define INF (daddr_t)1000000L /* a block number that wont exist */ ! 66: ! 67: struct tj_softc { ! 68: char sc_openf; /* exclusive open */ ! 69: char sc_lastiow; /* last I/O operation was a write */ ! 70: daddr_t sc_blkno; /* next block to transfer */ ! 71: daddr_t sc_nxrec; /* next record on tape */ ! 72: u_short sc_erreg; /* image of uter */ ! 73: u_short sc_dsreg; /* image of utds */ ! 74: u_short sc_resid; /* residual from transfer */ ! 75: u_short sc_dens; /* sticky selected density */ ! 76: daddr_t sc_timo; /* time until timeout expires */ ! 77: short sc_tact; /* timeout is active flag */ ! 78: struct tty *sc_ttyp; /* record user's tty for errors */ ! 79: } tj_softc[NTJ]; ! 80: ! 81: /* ! 82: * Internal per/slave states found in sc_state ! 83: */ ! 84: #define SSEEK 1 /* seeking */ ! 85: #define SIO 2 /* doing sequential I/O */ ! 86: #define SCOM 3 /* sending a control command */ ! 87: #define SREW 4 /* doing a rewind op */ ! 88: #define SERASE 5 /* erase inter-record gap */ ! 89: #define SERASED 6 /* erased inter-record gap */ ! 90: ! 91: /*ARGSUSED*/ ! 92: utprobe(reg) ! 93: caddr_t reg; ! 94: { ! 95: register int br, cvec; ! 96: #ifdef lint ! 97: br=0; cvec=br; br=cvec; ! 98: utintr(0); ! 99: #endif ! 100: /* ! 101: * The SI documentation says you must set the RDY bit ! 102: * (even though it's read-only) to force an interrupt. ! 103: */ ! 104: ((struct utdevice *) reg)->utcs1 = UT_IE|UT_NOP|UT_RDY; ! 105: DELAY(10000); ! 106: return (sizeof (struct utdevice)); ! 107: } ! 108: ! 109: /*ARGSUSED*/ ! 110: utslave(ui, reg) ! 111: struct uba_device *ui; ! 112: caddr_t reg; ! 113: { ! 114: /* ! 115: * A real TU45 would support the slave present bit ! 116: * int the drive type register, but this thing doesn't, ! 117: * so there's no way to determine if a slave is present or not. ! 118: */ ! 119: return(1); ! 120: } ! 121: ! 122: utattach(ui) ! 123: struct uba_device *ui; ! 124: { ! 125: tjtout[ui->ui_unit] = ui->ui_mi->um_ctlr; ! 126: } ! 127: ! 128: /* ! 129: * Open the device with exclusive access. ! 130: */ ! 131: utopen(dev, flag) ! 132: dev_t dev; ! 133: int flag; ! 134: { ! 135: register int tjunit = TJUNIT(dev); ! 136: register struct uba_device *ui; ! 137: register struct tj_softc *sc; ! 138: int olddens, dens; ! 139: register int s; ! 140: ! 141: if (tjunit >= NTJ || (ui = tjdinfo[tjunit]) == 0 || ui->ui_alive == 0) ! 142: return (ENXIO); ! 143: if ((sc = &tj_softc[tjunit])->sc_openf) ! 144: return (EBUSY); ! 145: olddens = sc->sc_dens; ! 146: dens = sc->sc_dens = ! 147: utdens[(minor(dev)&(T_1600BPI|T_6250BPI))>>3]| ! 148: PDP11FMT|(ui->ui_slave&07); ! 149: get: ! 150: utcommand(dev, UT_SENSE, 1); ! 151: if (sc->sc_dsreg&UTDS_PIP) { ! 152: sleep((caddr_t)&lbolt, PZERO+1); ! 153: goto get; ! 154: } ! 155: sc->sc_dens = olddens; ! 156: if ((sc->sc_dsreg&UTDS_MOL) == 0) { ! 157: uprintf("tj%d: not online\n", tjunit); ! 158: return (EIO); ! 159: } ! 160: if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) { ! 161: uprintf("tj%d: no write ring\n", tjunit); ! 162: return (EIO); ! 163: } ! 164: if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) && ! 165: dens != sc->sc_dens) { ! 166: uprintf("tj%d: can't change density in mid-tape\n", tjunit); ! 167: return (EIO); ! 168: } ! 169: sc->sc_openf = 1; ! 170: sc->sc_blkno = (daddr_t)0; ! 171: sc->sc_nxrec = INF; ! 172: sc->sc_lastiow = 0; ! 173: sc->sc_dens = dens; ! 174: sc->sc_ttyp = u.u_ttyp; ! 175: /* ! 176: * For 6250 bpi take exclusive use of the UNIBUS. ! 177: */ ! 178: ui->ui_driver->ud_xclu = (dens&(T_1600BPI|T_6250BPI)) == T_6250BPI; ! 179: s = splclock(); ! 180: if (sc->sc_tact == 0) { ! 181: sc->sc_timo = INF; ! 182: sc->sc_tact = 1; ! 183: timeout(uttimer, (caddr_t)dev, 5*hz); ! 184: } ! 185: splx(s); ! 186: return (0); ! 187: } ! 188: ! 189: utclose(dev, flag) ! 190: register dev_t dev; ! 191: register flag; ! 192: { ! 193: register struct tj_softc *sc = &tj_softc[TJUNIT(dev)]; ! 194: ! 195: if (flag == FWRITE || ((flag&FWRITE) && sc->sc_lastiow)) { ! 196: utcommand(dev, UT_WEOF, 1); ! 197: utcommand(dev, UT_WEOF, 1); ! 198: utcommand(dev, UT_SREV, 1); ! 199: } ! 200: if ((minor(dev)&T_NOREWIND) == 0) ! 201: utcommand(dev, UT_REW, 0); ! 202: sc->sc_openf = 0; ! 203: } ! 204: ! 205: utcommand(dev, com, count) ! 206: dev_t dev; ! 207: int com, count; ! 208: { ! 209: register struct buf *bp; ! 210: register int s; ! 211: ! 212: bp = &cutbuf[UTUNIT(dev)]; ! 213: s = spl5(); ! 214: while (bp->b_flags&B_BUSY) { ! 215: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) ! 216: break; ! 217: bp->b_flags |= B_WANTED; ! 218: sleep((caddr_t)bp, PRIBIO); ! 219: } ! 220: bp->b_flags = B_BUSY|B_READ; ! 221: splx(s); ! 222: bp->b_dev = dev; ! 223: bp->b_command = com; ! 224: bp->b_repcnt = count; ! 225: bp->b_blkno = 0; ! 226: utstrategy(bp); ! 227: if (count == 0) ! 228: return; ! 229: iowait(bp); ! 230: if (bp->b_flags&B_WANTED) ! 231: wakeup((caddr_t)bp); ! 232: bp->b_flags &= B_ERROR; ! 233: } ! 234: ! 235: /* ! 236: * Queue a tape operation. ! 237: */ ! 238: utstrategy(bp) ! 239: register struct buf *bp; ! 240: { ! 241: int tjunit = TJUNIT(bp->b_dev); ! 242: register struct uba_ctlr *um; ! 243: register struct buf *dp; ! 244: ! 245: /* ! 246: * Put transfer at end of unit queue ! 247: */ ! 248: dp = &tjutab[tjunit]; ! 249: bp->av_forw = NULL; ! 250: um = tjdinfo[tjunit]->ui_mi; ! 251: (void) spl5(); ! 252: if (dp->b_actf == NULL) { ! 253: dp->b_actf = bp; ! 254: /* ! 255: * Transport not active, so... ! 256: * put at end of controller queue ! 257: */ ! 258: dp->b_forw = NULL; ! 259: if (um->um_tab.b_actf == NULL) ! 260: um->um_tab.b_actf = dp; ! 261: else ! 262: um->um_tab.b_actl->b_forw = dp; ! 263: um->um_tab.b_actl = dp; ! 264: } else ! 265: dp->b_actl->av_forw = bp; ! 266: dp->b_actl = bp; ! 267: /* ! 268: * If the controller is not busy, set it going. ! 269: */ ! 270: if (um->um_tab.b_state == 0) ! 271: utstart(um); ! 272: (void) spl0(); ! 273: } ! 274: ! 275: utstart(um) ! 276: register struct uba_ctlr *um; ! 277: { ! 278: register struct utdevice *addr; ! 279: register struct buf *bp, *dp; ! 280: register struct tj_softc *sc; ! 281: struct uba_device *ui; ! 282: int tjunit; ! 283: daddr_t blkno; ! 284: ! 285: loop: ! 286: /* ! 287: * Scan controller queue looking for units with ! 288: * transaction queues to dispatch ! 289: */ ! 290: if ((dp = um->um_tab.b_actf) == NULL) ! 291: return; ! 292: if ((bp = dp->b_actf) == NULL) { ! 293: um->um_tab.b_actf = dp->b_forw; ! 294: goto loop; ! 295: } ! 296: addr = (struct utdevice *)um->um_addr; ! 297: tjunit = TJUNIT(bp->b_dev); ! 298: ui = tjdinfo[tjunit]; ! 299: sc = &tj_softc[tjunit]; ! 300: /* note slave select, density, and format were merged on open */ ! 301: addr->uttc = sc->sc_dens; ! 302: sc->sc_dsreg = addr->utds; ! 303: sc->sc_erreg = addr->uter; ! 304: sc->sc_resid = MASKREG(addr->utfc); ! 305: /* ! 306: * Default is that last command was NOT a write command; ! 307: * if we do a write command we will notice this in utintr(). ! 308: */ ! 309: sc->sc_lastiow = 0; ! 310: if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) { ! 311: /* ! 312: * Have had a hard error on a non-raw tape ! 313: * or the tape unit is now unavailable ! 314: * (e.g. taken off line). ! 315: */ ! 316: bp->b_flags |= B_ERROR; ! 317: goto next; ! 318: } ! 319: if (bp == &cutbuf[UTUNIT(bp->b_dev)]) { ! 320: /* ! 321: * Execute a control operation with the specified ! 322: * count. ! 323: */ ! 324: if (bp->b_command == UT_SENSE) ! 325: goto next; ! 326: if (bp->b_command == UT_SFORW && (addr->utds & UTDS_EOT)) { ! 327: bp->b_resid = bp->b_bcount; ! 328: goto next; ! 329: } ! 330: /* ! 331: * Set next state; handle timeouts ! 332: */ ! 333: if (bp->b_command == UT_REW) { ! 334: um->um_tab.b_state = SREW; ! 335: sc->sc_timo = 5*60; ! 336: } else { ! 337: um->um_tab.b_state = SCOM; ! 338: sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60); ! 339: } ! 340: /* NOTE: this depends on the ut command values */ ! 341: if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF) ! 342: addr->utfc = -bp->b_repcnt; ! 343: goto dobpcmd; ! 344: } ! 345: /* ! 346: * The following checks boundary conditions for operations ! 347: * on non-raw tapes. On raw tapes the initialization of ! 348: * sc->sc_nxrec by utphys causes them to be skipped normally ! 349: * (except in the case of retries). ! 350: */ ! 351: if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { ! 352: /* can't read past end of file */ ! 353: bp->b_flags |= B_ERROR; ! 354: bp->b_error = ENXIO; ! 355: goto next; ! 356: } ! 357: if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && (bp->b_flags&B_READ)) { ! 358: /* read at eof returns 0 count */ ! 359: bp->b_resid = bp->b_bcount; ! 360: clrbuf(bp); ! 361: goto next; ! 362: } ! 363: if ((bp->b_flags&B_READ) == 0) ! 364: sc->sc_nxrec = bdbtofsb(bp->b_blkno)+1; ! 365: /* ! 366: * If the tape is correctly positioned, set up all the ! 367: * registers but the csr, and give control over to the ! 368: * UNIBUS adaptor routines, to wait for resources to ! 369: * start I/O. ! 370: */ ! 371: if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { ! 372: addr->utwc = -(((bp->b_bcount)+1)>>1); ! 373: addr->utfc = -bp->b_bcount; ! 374: if ((bp->b_flags&B_READ) == 0) { ! 375: /* ! 376: * On write error retries erase the ! 377: * inter-record gap before rewriting. ! 378: */ ! 379: if (um->um_tab.b_errcnt) { ! 380: if (um->um_tab.b_state != SERASED) { ! 381: um->um_tab.b_state = SERASE; ! 382: sc->sc_timo = 60; ! 383: addr->utcs1 = UT_ERASE|UT_IE|UT_GO; ! 384: return; ! 385: } ! 386: } ! 387: if (addr->utds & UTDS_EOT) { ! 388: bp->b_resid = bp->b_bcount; ! 389: um->um_tab.b_state = 0; ! 390: goto next; ! 391: } ! 392: um->um_cmd = UT_WCOM; ! 393: } else ! 394: um->um_cmd = UT_RCOM; ! 395: sc->sc_timo = 60; ! 396: um->um_tab.b_state = SIO; ! 397: (void) ubago(ui); ! 398: return; ! 399: } ! 400: /* ! 401: * Tape positioned incorrectly; seek forwards or ! 402: * backwards to the correct spot. This happens for ! 403: * raw tapes only on error retries. ! 404: */ ! 405: um->um_tab.b_state = SSEEK; ! 406: if (blkno < bdbtofsb(bp->b_blkno)) { ! 407: addr->utfc = blkno - bdbtofsb(bp->b_blkno); ! 408: bp->b_command = UT_SFORW; ! 409: } else { ! 410: addr->utfc = bdbtofsb(bp->b_blkno) - blkno; ! 411: bp->b_command = UT_SREV; ! 412: } ! 413: sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60); ! 414: ! 415: dobpcmd: ! 416: /* ! 417: * Perform the command setup in bp. ! 418: */ ! 419: addr->utcs1 = bp->b_command|UT_IE|UT_GO; ! 420: return; ! 421: next: ! 422: /* ! 423: * Advance to the next command in the slave queue, ! 424: * posting notice and releasing resources as needed. ! 425: */ ! 426: if (um->um_ubinfo) ! 427: ubadone(um); ! 428: um->um_tab.b_errcnt = 0; ! 429: dp->b_actf = bp->av_forw; ! 430: iodone(bp); ! 431: goto loop; ! 432: } ! 433: ! 434: /* ! 435: * Start operation on controller -- ! 436: * UNIBUS resources have been allocated. ! 437: */ ! 438: utdgo(um) ! 439: register struct uba_ctlr *um; ! 440: { ! 441: register struct utdevice *addr = (struct utdevice *)um->um_addr; ! 442: ! 443: addr->utba = (u_short) um->um_ubinfo; ! 444: addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300)|UT_IE|UT_GO; ! 445: } ! 446: ! 447: /* ! 448: * Ut interrupt handler ! 449: */ ! 450: /*ARGSUSED*/ ! 451: utintr(ut11) ! 452: int ut11; ! 453: { ! 454: struct buf *dp; ! 455: register struct buf *bp; ! 456: register struct uba_ctlr *um = utminfo[ut11]; ! 457: register struct utdevice *addr; ! 458: register struct tj_softc *sc; ! 459: u_short tjunit, cs2, cs1; ! 460: register state; ! 461: ! 462: if ((dp = um->um_tab.b_actf) == NULL) ! 463: return; ! 464: bp = dp->b_actf; ! 465: tjunit = TJUNIT(bp->b_dev); ! 466: addr = (struct utdevice *)tjdinfo[tjunit]->ui_addr; ! 467: sc = &tj_softc[tjunit]; ! 468: /* ! 469: * Record status... ! 470: */ ! 471: sc->sc_timo = INF; ! 472: sc->sc_dsreg = addr->utds; ! 473: sc->sc_erreg = addr->uter; ! 474: sc->sc_resid = MASKREG(addr->utfc); ! 475: if ((bp->b_flags&B_READ) == 0) ! 476: sc->sc_lastiow = 1; ! 477: state = um->um_tab.b_state; ! 478: um->um_tab.b_state = 0; ! 479: /* ! 480: * Check for errors... ! 481: */ ! 482: if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) { ! 483: /* ! 484: * To clear the ERR bit, we must issue a drive clear ! 485: * command, and to clear the TRE bit we must set the ! 486: * controller clear bit. ! 487: */ ! 488: cs2 = addr->utcs2; ! 489: if ((cs1 = addr->utcs1)&UT_TRE) ! 490: addr->utcs2 |= UTCS2_CLR; ! 491: /* is this dangerous ?? */ ! 492: while ((addr->utcs1&UT_RDY) == 0) ! 493: ; ! 494: addr->utcs1 = UT_CLEAR|UT_GO; ! 495: /* ! 496: * If we were reading at 1600 or 6250 bpi and the error ! 497: * was corrected, then don't consider this an error. ! 498: */ ! 499: if (sc->sc_erreg & UTER_COR && (bp->b_flags & B_READ) && ! 500: (addr->uttc & UTTC_DEN) != UT_NRZI) { ! 501: tprintf(sc->sc_ttyp, ! 502: "ut%d: soft error bn%d cs1=%b er=%b cs2=%b ds=%b\n", ! 503: tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg, ! 504: UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS); ! 505: sc->sc_erreg &= ~UTER_COR; ! 506: } ! 507: /* ! 508: * If we were reading from a raw tape and the only error ! 509: * was that the record was too long, then we don't consider ! 510: * this an error. ! 511: */ ! 512: if (bp == &rutbuf[UTUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && ! 513: (sc->sc_erreg&UTER_FCE)) ! 514: sc->sc_erreg &= ~UTER_FCE; ! 515: if (sc->sc_erreg == 0) ! 516: goto ignoreerr; ! 517: /* ! 518: * Fix up errors which occur due to backspacing ! 519: * "over" the front of the tape. ! 520: */ ! 521: if ((sc->sc_dsreg & UTDS_BOT) && bp->b_command == UT_SREV && ! 522: ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0)) ! 523: goto opdone; ! 524: /* ! 525: * Retry soft errors up to 8 times ! 526: */ ! 527: if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) { ! 528: if (++um->um_tab.b_errcnt < 7) { ! 529: sc->sc_blkno++; ! 530: ubadone(um); ! 531: goto opcont; ! 532: } ! 533: } ! 534: /* ! 535: * Hard or non-I/O errors on non-raw tape ! 536: * cause it to close. ! 537: */ ! 538: if (sc->sc_openf > 0 && bp != &rutbuf[UTUNIT(bp->b_dev)]) ! 539: sc->sc_openf = -1; ! 540: /* ! 541: * Couldn't recover error. ! 542: */ ! 543: tprintf(sc->sc_ttyp, ! 544: "ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n", ! 545: tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg, ! 546: UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS); ! 547: bp->b_flags |= B_ERROR; ! 548: goto opdone; ! 549: } ! 550: ! 551: ignoreerr: ! 552: /* ! 553: * If we hit a tape mark update our position. ! 554: */ ! 555: if (sc->sc_dsreg & UTDS_TM && bp->b_flags & B_READ) { ! 556: /* ! 557: * Set blkno and nxrec ! 558: */ ! 559: if (bp == &cutbuf[UTUNIT(bp->b_dev)]) { ! 560: if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { ! 561: sc->sc_nxrec = ! 562: bdbtofsb(bp->b_blkno) - addr->utfc; ! 563: sc->sc_blkno = sc->sc_nxrec; ! 564: } else { ! 565: sc->sc_blkno = ! 566: bdbtofsb(bp->b_blkno) + addr->utfc; ! 567: sc->sc_nxrec = sc->sc_blkno-1; ! 568: } ! 569: } else ! 570: sc->sc_nxrec = bdbtofsb(bp->b_blkno); ! 571: /* ! 572: * Note: if we get a tape mark on a read, the ! 573: * frame count register will be zero, so b_resid ! 574: * will be calculated correctly below. ! 575: */ ! 576: goto opdone; ! 577: } ! 578: /* ! 579: * Advance tape control FSM. ! 580: */ ! 581: switch (state) { ! 582: ! 583: case SIO: /* read/write increments tape block # */ ! 584: sc->sc_blkno++; ! 585: break; ! 586: ! 587: case SCOM: /* motion commands update current position */ ! 588: if (bp == &cutbuf[UTUNIT(bp->b_dev)]) ! 589: switch ((int)bp->b_command) { ! 590: ! 591: case UT_SFORW: ! 592: sc->sc_blkno -= bp->b_repcnt; ! 593: break; ! 594: ! 595: case UT_SREV: ! 596: sc->sc_blkno += bp->b_repcnt; ! 597: break; ! 598: ! 599: case UT_REWOFFL: ! 600: addr->utcs1 = UT_CLEAR|UT_GO; ! 601: break; ! 602: } ! 603: break; ! 604: ! 605: case SSEEK: ! 606: sc->sc_blkno = bdbtofsb(bp->b_blkno); ! 607: goto opcont; ! 608: ! 609: case SERASE: ! 610: /* ! 611: * Completed erase of the inter-record gap due to a ! 612: * write error; now retry the write operation. ! 613: */ ! 614: um->um_tab.b_state = SERASED; ! 615: goto opcont; ! 616: ! 617: case SREW: /* clear attention bit */ ! 618: addr->utcs1 = UT_CLEAR|UT_GO; ! 619: break; ! 620: ! 621: default: ! 622: printf("bad state %d\n", state); ! 623: panic("utintr"); ! 624: } ! 625: ! 626: opdone: ! 627: /* ! 628: * Reset error count and remove ! 629: * from device queue ! 630: */ ! 631: um->um_tab.b_errcnt = 0; ! 632: dp->b_actf = bp->av_forw; ! 633: /* ! 634: * For read command, frame count register contains ! 635: * actual length of tape record. Otherwise, it ! 636: * holds negative residual count. ! 637: */ ! 638: if (state == SIO && um->um_cmd == UT_RCOM) { ! 639: bp->b_resid = 0; ! 640: if (bp->b_bcount > MASKREG(addr->utfc)) ! 641: bp->b_resid = bp->b_bcount - MASKREG(addr->utfc); ! 642: } else ! 643: bp->b_resid = MASKREG(-addr->utfc); ! 644: ubadone(um); ! 645: iodone(bp); ! 646: /* ! 647: * Circulate slave to end of controller queue ! 648: * to give other slaves a chance ! 649: */ ! 650: um->um_tab.b_actf = dp->b_forw; ! 651: if (dp->b_actf) { ! 652: dp->b_forw = NULL; ! 653: if (um->um_tab.b_actf == NULL) ! 654: um->um_tab.b_actf = dp; ! 655: else ! 656: um->um_tab.b_actl->b_forw = dp; ! 657: um->um_tab.b_actl = dp; ! 658: } ! 659: if (um->um_tab.b_actf == 0) ! 660: return; ! 661: opcont: ! 662: utstart(um); ! 663: } ! 664: ! 665: /* ! 666: * Watchdog timer routine. ! 667: */ ! 668: uttimer(dev) ! 669: int dev; ! 670: { ! 671: register struct tj_softc *sc = &tj_softc[TJUNIT(dev)]; ! 672: register short x; ! 673: ! 674: if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) { ! 675: printf("tj%d: lost interrupt\n", TJUNIT(dev)); ! 676: sc->sc_timo = INF; ! 677: x = spl5(); ! 678: utintr(UTUNIT(dev)); ! 679: (void) splx(x); ! 680: } ! 681: timeout(uttimer, (caddr_t)dev, 5*hz); ! 682: } ! 683: ! 684: /* ! 685: * Raw interface for a read ! 686: */ ! 687: utread(dev, uio) ! 688: dev_t dev; ! 689: struct uio *uio; ! 690: { ! 691: int errno; ! 692: ! 693: errno = utphys(dev, uio); ! 694: if (errno) ! 695: return (errno); ! 696: return (physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_READ, minphys, uio)); ! 697: } ! 698: ! 699: /* ! 700: * Raw interface for a write ! 701: */ ! 702: utwrite(dev, uio) ! 703: dev_t dev; ! 704: struct uio *uio; ! 705: { ! 706: int errno; ! 707: ! 708: errno = utphys(dev, uio); ! 709: if (errno) ! 710: return (errno); ! 711: return (physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_WRITE, minphys, uio)); ! 712: } ! 713: ! 714: /* ! 715: * Check for valid device number dev and update our notion ! 716: * of where we are on the tape ! 717: */ ! 718: utphys(dev, uio) ! 719: dev_t dev; ! 720: struct uio *uio; ! 721: { ! 722: register int tjunit = TJUNIT(dev); ! 723: register struct tj_softc *sc; ! 724: register struct uba_device *ui; ! 725: ! 726: if (tjunit >= NTJ || (ui=tjdinfo[tjunit]) == 0 || ui->ui_alive == 0) ! 727: return (ENXIO); ! 728: sc = &tj_softc[tjunit]; ! 729: sc->sc_blkno = bdbtofsb(uio->uio_offset>>9); ! 730: sc->sc_nxrec = sc->sc_blkno+1; ! 731: return (0); ! 732: } ! 733: ! 734: /*ARGSUSED*/ ! 735: utioctl(dev, cmd, data, flag) ! 736: dev_t dev; ! 737: caddr_t data; ! 738: { ! 739: register struct tj_softc *sc = &tj_softc[TJUNIT(dev)]; ! 740: register struct buf *bp = &cutbuf[UTUNIT(dev)]; ! 741: register callcount; ! 742: int fcount; ! 743: struct mtop *mtop; ! 744: struct mtget *mtget; ! 745: /* we depend of the values and order of the MT codes here */ ! 746: static utops[] = ! 747: {UT_WEOF,UT_SFORWF,UT_SREVF,UT_SFORW,UT_SREV,UT_REW,UT_REWOFFL,UT_SENSE}; ! 748: ! 749: switch (cmd) { ! 750: ! 751: case MTIOCTOP: ! 752: mtop = (struct mtop *)data; ! 753: switch(mtop->mt_op) { ! 754: ! 755: case MTWEOF: ! 756: case MTFSF: case MTBSF: ! 757: case MTFSR: case MTBSR: ! 758: callcount = mtop->mt_count; ! 759: fcount = 1; ! 760: break; ! 761: ! 762: case MTREW: case MTOFFL: case MTNOP: ! 763: callcount = 1; ! 764: fcount = 1; ! 765: break; ! 766: ! 767: default: ! 768: return (ENXIO); ! 769: } ! 770: if (callcount <= 0 || fcount <= 0) ! 771: return (EINVAL); ! 772: while (--callcount >= 0) { ! 773: utcommand(dev, utops[mtop->mt_op], fcount); ! 774: if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT)) ! 775: break; ! 776: } ! 777: return (geterror(bp)); ! 778: ! 779: case MTIOCGET: ! 780: mtget = (struct mtget *)data; ! 781: mtget->mt_dsreg = sc->sc_dsreg; ! 782: mtget->mt_erreg = sc->sc_erreg; ! 783: mtget->mt_resid = sc->sc_resid; ! 784: mtget->mt_type = MT_ISUT; ! 785: break; ! 786: ! 787: default: ! 788: return (ENXIO); ! 789: } ! 790: return (0); ! 791: } ! 792: ! 793: utreset(uban) ! 794: int uban; ! 795: { ! 796: register struct uba_ctlr *um; ! 797: register ut11, tjunit; ! 798: register struct uba_device *ui; ! 799: register struct buf *dp; ! 800: ! 801: for (ut11 = 0; ut11 < NUT; ut11++) { ! 802: if ((um = utminfo[ut11]) == 0 || um->um_alive == 0 || ! 803: um->um_ubanum != uban) ! 804: continue; ! 805: printf(" ut%d", ut11); ! 806: um->um_tab.b_state = 0; ! 807: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 808: if (um->um_ubinfo) { ! 809: printf("<%d>", (um->um_ubinfo>>28)&0xf); ! 810: um->um_ubinfo = 0; ! 811: } ! 812: ((struct utdevice *)(um->um_addr))->utcs1 = UT_CLEAR|UT_GO; ! 813: ((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR; ! 814: for (tjunit = 0; tjunit < NTJ; tjunit++) { ! 815: if ((ui = tjdinfo[tjunit]) == 0 || ui->ui_mi != um || ! 816: ui->ui_alive == 0) ! 817: continue; ! 818: dp = &tjutab[tjunit]; ! 819: dp->b_state = 0; ! 820: dp->b_forw = 0; ! 821: if (um->um_tab.b_actf == NULL) ! 822: um->um_tab.b_actf = dp; ! 823: else ! 824: um->um_tab.b_actl->b_forw = dp; ! 825: um->um_tab.b_actl = dp; ! 826: if (tj_softc[tjunit].sc_openf > 0) ! 827: tj_softc[tjunit].sc_openf = -1; ! 828: } ! 829: utstart(um); ! 830: } ! 831: } ! 832: ! 833: /* ! 834: * Do a stand-alone core dump to tape -- ! 835: * from here down, routines are used only in dump context ! 836: */ ! 837: #define DBSIZE 20 ! 838: ! 839: utdump() ! 840: { ! 841: register struct uba_device *ui; ! 842: register struct uba_regs *up; ! 843: register struct utdevice *addr; ! 844: int blk, num = maxfree; ! 845: int start = 0; ! 846: ! 847: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) ! 848: if (tjdinfo[0] == 0) ! 849: return (ENXIO); ! 850: ui = phys(tjdinfo[0], struct uba_device *); ! 851: up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; ! 852: ubainit(up); ! 853: DELAY(1000000); ! 854: addr = (struct utdevice *)ui->ui_physaddr; ! 855: utwait(addr); ! 856: /* ! 857: * Be sure to set the appropriate density here. We use ! 858: * 6250, but maybe it should be done at 1600 to insure the ! 859: * tape can be read by most any other tape drive available. ! 860: */ ! 861: addr->uttc = UT_GCR|PDP11FMT; /* implicit slave 0 or-ed in */ ! 862: addr->utcs1 = UT_CLEAR|UT_GO; ! 863: while (num > 0) { ! 864: blk = num > DBSIZE ? DBSIZE : num; ! 865: utdwrite(start, blk, addr, up); ! 866: if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) ! 867: return(EIO); ! 868: start += blk; ! 869: num -= blk; ! 870: } ! 871: uteof(addr); ! 872: uteof(addr); ! 873: utwait(addr); ! 874: if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) ! 875: return(EIO); ! 876: addr->utcs1 = UT_REW|UT_GO; ! 877: return (0); ! 878: } ! 879: ! 880: utdwrite(dbuf, num, addr, up) ! 881: register dbuf, num; ! 882: register struct utdevice *addr; ! 883: struct uba_regs *up; ! 884: { ! 885: register struct pte *io; ! 886: register int npf; ! 887: ! 888: utwait(addr); ! 889: io = up->uba_map; ! 890: npf = num + 1; ! 891: while (--npf != 0) ! 892: *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV); ! 893: *(int *)io = 0; ! 894: addr->utwc = -((num*NBPG)>>1); ! 895: addr->utfc = -(num*NBPG); ! 896: addr->utba = 0; ! 897: addr->utcs1 = UT_WCOM|UT_GO; ! 898: } ! 899: ! 900: utwait(addr) ! 901: struct utdevice *addr; ! 902: { ! 903: register s; ! 904: ! 905: do ! 906: s = addr->utds; ! 907: while ((s&UTDS_DRY) == 0); ! 908: } ! 909: ! 910: uteof(addr) ! 911: struct utdevice *addr; ! 912: { ! 913: ! 914: utwait(addr); ! 915: addr->utcs1 = UT_WEOF|UT_GO; ! 916: } ! 917: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.