|
|
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: * @(#)ht.c 7.6 (Berkeley) 5/6/88 ! 7: */ ! 8: ! 9: #include "tu.h" ! 10: #if NHT > 0 ! 11: /* ! 12: * TM03/TU?? tape driver ! 13: * ! 14: * TODO: ! 15: * cleanup messages on errors ! 16: * test ioctl's ! 17: * see how many rewind interrups we get if we kick when not at BOT ! 18: * fixup rle error on block tape code ! 19: */ ! 20: #include "param.h" ! 21: #include "systm.h" ! 22: #include "buf.h" ! 23: #include "conf.h" ! 24: #include "dir.h" ! 25: #include "file.h" ! 26: #include "user.h" ! 27: #include "map.h" ! 28: #include "ioctl.h" ! 29: #include "mtio.h" ! 30: #include "cmap.h" ! 31: #include "uio.h" ! 32: #include "tty.h" ! 33: #include "syslog.h" ! 34: ! 35: #include "../machine/pte.h" ! 36: #include "../vax/cpu.h" ! 37: #include "mbareg.h" ! 38: #include "mbavar.h" ! 39: #include "htreg.h" ! 40: ! 41: struct buf chtbuf[NHT]; ! 42: ! 43: short httypes[] = ! 44: { MBDT_TM03, MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; ! 45: struct mba_device *htinfo[NHT]; ! 46: struct mba_slave *tuinfo[NTU]; ! 47: int htattach(), htslave(), htustart(), htndtint(), htdtint(); ! 48: struct mba_driver htdriver = ! 49: { htattach, htslave, htustart, 0, htdtint, htndtint, ! 50: httypes, "ht", "tu", htinfo }; ! 51: ! 52: #define MASKREG(r) ((r) & 0xffff) ! 53: ! 54: /* bits in minor device */ ! 55: #define TUUNIT(dev) (minor(dev)&03) ! 56: #define H_NOREWIND 04 ! 57: #define H_DENS(dev) ((minor(dev) >> 3) & 03) ! 58: ! 59: #define HTUNIT(dev) (tuinfo[TUUNIT(dev)]->ms_ctlr) ! 60: ! 61: #define INF (daddr_t)1000000L /* a block number that wont exist */ ! 62: ! 63: struct tu_softc { ! 64: char sc_openf; ! 65: char sc_flags; ! 66: daddr_t sc_blkno; ! 67: daddr_t sc_nxrec; ! 68: u_short sc_erreg; ! 69: u_short sc_dsreg; ! 70: short sc_resid; ! 71: short sc_dens; ! 72: struct tty *sc_ttyp; /* record user's tty for errors */ ! 73: int sc_blks; /* number of I/O operations since open */ ! 74: int sc_softerrs; /* number of soft I/O errors since open */ ! 75: } tu_softc[NTU]; ! 76: ! 77: /* ! 78: * Bits for sc_flags. ! 79: */ ! 80: #define H_WRITTEN 1 /* last operation was a write */ ! 81: #define H_ERASED 2 /* last write retry was an erase gap */ ! 82: #define H_REWIND 4 /* last unit start was a rewind */ ! 83: ! 84: char hter_bits[] = HTER_BITS; ! 85: char htds_bits[] = HTDS_BITS; ! 86: ! 87: /*ARGSUSED*/ ! 88: htattach(mi) ! 89: struct mba_device *mi; ! 90: { ! 91: ! 92: } ! 93: ! 94: htslave(mi, ms, sn) ! 95: struct mba_device *mi; ! 96: struct mba_slave *ms; ! 97: int sn; ! 98: { ! 99: register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; ! 100: ! 101: htaddr->httc = sn; ! 102: if (htaddr->htdt & HTDT_SPR) { ! 103: tuinfo[ms->ms_unit] = ms; ! 104: return (1); ! 105: } else ! 106: return (0); ! 107: } ! 108: ! 109: int htdens[4] = { HTTC_800BPI, HTTC_1600BPI, HTTC_6250BPI, HTTC_800BPI }; ! 110: ! 111: htopen(dev, flag) ! 112: dev_t dev; ! 113: int flag; ! 114: { ! 115: register int tuunit; ! 116: register struct tu_softc *sc; ! 117: register struct mba_slave *ms; ! 118: int olddens, dens; ! 119: ! 120: tuunit = TUUNIT(dev); ! 121: if (tuunit >= NTU || (ms = tuinfo[tuunit]) == NULL || ! 122: ms->ms_alive == 0 || htinfo[ms->ms_ctlr]->mi_alive == 0) ! 123: return (ENXIO); ! 124: if ((sc = &tu_softc[tuunit])->sc_openf) ! 125: return (EBUSY); ! 126: sc->sc_openf = 1; ! 127: olddens = sc->sc_dens; ! 128: dens = sc->sc_dens = htdens[H_DENS(dev)] | HTTC_PDP11 | ms->ms_slave; ! 129: htcommand(dev, HT_SENSE, 1); ! 130: sc->sc_dens = olddens; ! 131: if ((sc->sc_dsreg & HTDS_MOL) == 0) { ! 132: sc->sc_openf = 0; ! 133: uprintf("tu%d: not online\n", tuunit); ! 134: return (EIO); ! 135: } ! 136: if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { ! 137: sc->sc_openf = 0; ! 138: uprintf("tu%d: no write ring\n", tuunit); ! 139: return (EIO); ! 140: } ! 141: if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && ! 142: dens != sc->sc_dens) { ! 143: sc->sc_openf = 0; ! 144: uprintf("tu%d: can't change density in mid-tape\n", tuunit); ! 145: return (EIO); ! 146: } ! 147: sc->sc_blkno = (daddr_t)0; ! 148: sc->sc_nxrec = INF; ! 149: sc->sc_flags = 0; ! 150: sc->sc_dens = dens; ! 151: sc->sc_blks = 0; ! 152: sc->sc_softerrs = 0; ! 153: sc->sc_ttyp = u.u_ttyp; ! 154: return (0); ! 155: } ! 156: ! 157: htclose(dev, flag) ! 158: register dev_t dev; ! 159: register flag; ! 160: { ! 161: register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; ! 162: ! 163: if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { ! 164: htcommand(dev, HT_WEOF, 1); ! 165: htcommand(dev, HT_WEOF, 1); ! 166: htcommand(dev, HT_SREV, 1); ! 167: } ! 168: if ((minor(dev)&H_NOREWIND) == 0) ! 169: htcommand(dev, HT_REW, 0); ! 170: if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100) ! 171: log(LOG_INFO, "tu%d: %d soft errors in %d blocks\n", ! 172: TUUNIT(dev), sc->sc_softerrs, sc->sc_blks); ! 173: sc->sc_openf = 0; ! 174: } ! 175: ! 176: htcommand(dev, com, count) ! 177: dev_t dev; ! 178: int com, count; ! 179: { ! 180: register struct buf *bp; ! 181: register int s; ! 182: ! 183: bp = &chtbuf[HTUNIT(dev)]; ! 184: s = spl5(); ! 185: while (bp->b_flags&B_BUSY) { ! 186: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) ! 187: break; ! 188: bp->b_flags |= B_WANTED; ! 189: sleep((caddr_t)bp, PRIBIO); ! 190: } ! 191: bp->b_flags = B_BUSY|B_READ; ! 192: splx(s); ! 193: bp->b_dev = dev; ! 194: bp->b_command = com; ! 195: bp->b_repcnt = count; ! 196: bp->b_blkno = 0; ! 197: htstrategy(bp); ! 198: if (count == 0) ! 199: return; ! 200: iowait(bp); ! 201: if (bp->b_flags&B_WANTED) ! 202: wakeup((caddr_t)bp); ! 203: bp->b_flags &= B_ERROR; ! 204: } ! 205: ! 206: htstrategy(bp) ! 207: register struct buf *bp; ! 208: { ! 209: register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; ! 210: register struct buf *dp; ! 211: register int s; ! 212: ! 213: bp->av_forw = NULL; ! 214: dp = &mi->mi_tab; ! 215: s = spl5(); ! 216: if (dp->b_actf == NULL) ! 217: dp->b_actf = bp; ! 218: else ! 219: dp->b_actl->av_forw = bp; ! 220: dp->b_actl = bp; ! 221: if (dp->b_active == 0) ! 222: mbustart(mi); ! 223: splx(s); ! 224: } ! 225: ! 226: htustart(mi) ! 227: register struct mba_device *mi; ! 228: { ! 229: register struct htdevice *htaddr = ! 230: (struct htdevice *)mi->mi_drv; ! 231: register struct buf *bp = mi->mi_tab.b_actf; ! 232: register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; ! 233: daddr_t blkno; ! 234: ! 235: htaddr->httc = sc->sc_dens; ! 236: #ifdef notdef ! 237: /* unneeded, may hang controller */ ! 238: if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { ! 239: htaddr->htcs1 = HT_SENSE|HT_GO; ! 240: mbclrattn(mi); ! 241: } ! 242: #endif ! 243: sc->sc_dsreg = htaddr->htds; ! 244: sc->sc_erreg = htaddr->hter; ! 245: sc->sc_resid = htaddr->htfc; ! 246: sc->sc_flags &= ~(H_WRITTEN|H_REWIND); ! 247: if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) ! 248: if (sc->sc_openf > 0) ! 249: sc->sc_openf = -1; ! 250: if (sc->sc_openf < 0) { ! 251: bp->b_flags |= B_ERROR; ! 252: return (MBU_NEXT); ! 253: } ! 254: if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { ! 255: /* transfer: check positioning */ ! 256: if (bp->b_flags & B_RAW) { ! 257: /* raw transfer: record position for retry */ ! 258: if (mi->mi_tab.b_errcnt == 0) { ! 259: sc->sc_blkno = bdbtofsb(bp->b_blkno); ! 260: sc->sc_nxrec = sc->sc_blkno + 1; ! 261: } ! 262: } else { ! 263: if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { ! 264: bp->b_flags |= B_ERROR; ! 265: bp->b_error = ENXIO; ! 266: return (MBU_NEXT); ! 267: } ! 268: if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && ! 269: bp->b_flags&B_READ) { ! 270: bp->b_resid = bp->b_bcount; ! 271: clrbuf(bp); ! 272: return (MBU_NEXT); ! 273: } ! 274: if ((bp->b_flags&B_READ)==0) ! 275: sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; ! 276: } ! 277: } else { ! 278: if (bp->b_command == HT_SENSE) ! 279: return (MBU_NEXT); ! 280: if (bp->b_command == HT_REW) ! 281: sc->sc_flags |= H_REWIND; ! 282: else ! 283: htaddr->htfc = -bp->b_bcount; ! 284: htaddr->htcs1 = bp->b_command|HT_GO; ! 285: return (MBU_STARTED); ! 286: } ! 287: if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { ! 288: htaddr->htfc = -bp->b_bcount; ! 289: if ((bp->b_flags&B_READ) == 0) { ! 290: if (mi->mi_tab.b_errcnt) { ! 291: if ((sc->sc_flags & H_ERASED) == 0) { ! 292: sc->sc_flags |= H_ERASED; ! 293: htaddr->htcs1 = HT_ERASE | HT_GO; ! 294: return (MBU_STARTED); ! 295: } ! 296: sc->sc_flags &= ~H_ERASED; ! 297: } ! 298: if (htaddr->htds & HTDS_EOT) { ! 299: bp->b_resid = bp->b_bcount; ! 300: bp->b_flags |= B_ERROR; ! 301: return (MBU_NEXT); ! 302: } ! 303: } ! 304: return (MBU_DODATA); ! 305: } ! 306: if (blkno < bdbtofsb(bp->b_blkno)) { ! 307: htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); ! 308: htaddr->htcs1 = HT_SFORW|HT_GO; ! 309: } else { ! 310: htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; ! 311: htaddr->htcs1 = HT_SREV|HT_GO; ! 312: } ! 313: return (MBU_STARTED); ! 314: } ! 315: ! 316: htdtint(mi, mbsr) ! 317: register struct mba_device *mi; ! 318: int mbsr; ! 319: { ! 320: register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; ! 321: register struct buf *bp = mi->mi_tab.b_actf; ! 322: register struct tu_softc *sc; ! 323: int ds, er, mbs; ! 324: ! 325: sc = &tu_softc[TUUNIT(bp->b_dev)]; ! 326: ds = sc->sc_dsreg = MASKREG(htaddr->htds); ! 327: er = sc->sc_erreg = MASKREG(htaddr->hter); ! 328: sc->sc_resid = MASKREG(htaddr->htfc); ! 329: mbs = mbsr; ! 330: sc->sc_blkno++; ! 331: if((bp->b_flags & B_READ) == 0) ! 332: sc->sc_flags |= H_WRITTEN; ! 333: if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { ! 334: htaddr->htcs1 = HT_DCLR|HT_GO; ! 335: mbclrattn(mi); ! 336: if (bp->b_flags & B_RAW) { ! 337: er &= ~HTER_FCE; ! 338: mbs &= ~(MBSR_DTABT|MBSR_MBEXC); ! 339: } ! 340: if (bp->b_flags & B_READ && ds & HTDS_PES) ! 341: er &= ~(HTER_CSITM|HTER_CORCRC); ! 342: if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || ! 343: er && ++mi->mi_tab.b_errcnt >= 7) { ! 344: if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) ! 345: sc->sc_openf = -1; ! 346: if ((er&HTER_HARD) == HTER_FCE && ! 347: (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && ! 348: (ds&HTDS_MOL)) ! 349: goto noprint; ! 350: tprintf(sc->sc_ttyp, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", ! 351: TUUNIT(bp->b_dev), bp->b_blkno, ! 352: mbsr, mbsr_bits, ! 353: sc->sc_erreg, hter_bits, ! 354: sc->sc_dsreg, htds_bits); ! 355: noprint: ! 356: bp->b_flags |= B_ERROR; ! 357: return (MBD_DONE); ! 358: } ! 359: if (er) ! 360: return (MBD_RETRY); ! 361: } ! 362: bp->b_resid = 0; ! 363: sc->sc_blks++; ! 364: if (mi->mi_tab.b_errcnt) ! 365: sc->sc_softerrs++; ! 366: if (bp->b_flags & B_READ) ! 367: if (ds&HTDS_TM) { /* must be a read, right? */ ! 368: bp->b_resid = bp->b_bcount; ! 369: sc->sc_nxrec = bdbtofsb(bp->b_blkno); ! 370: } else if(bp->b_bcount > MASKREG(htaddr->htfc)) ! 371: bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); ! 372: return (MBD_DONE); ! 373: } ! 374: ! 375: htndtint(mi) ! 376: register struct mba_device *mi; ! 377: { ! 378: register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; ! 379: register struct buf *bp = mi->mi_tab.b_actf; ! 380: register struct tu_softc *sc; ! 381: int er, ds, fc; ! 382: ! 383: ds = MASKREG(htaddr->htds); ! 384: er = MASKREG(htaddr->hter); ! 385: fc = MASKREG(htaddr->htfc); ! 386: if (er) { ! 387: htaddr->htcs1 = HT_DCLR|HT_GO; ! 388: mbclrattn(mi); ! 389: } ! 390: if (bp == 0) ! 391: return (MBN_SKIP); ! 392: sc = &tu_softc[TUUNIT(bp->b_dev)]; ! 393: sc->sc_dsreg = ds; ! 394: sc->sc_erreg = er; ! 395: sc->sc_resid = fc; ! 396: if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { ! 397: switch ((int)bp->b_command) { ! 398: case HT_REWOFFL: ! 399: /* offline is on purpose; don't do anything special */ ! 400: ds |= HTDS_MOL; ! 401: break; ! 402: case HT_SREV: ! 403: /* if backspace file hit bot, its not an error */ ! 404: if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && ! 405: bp->b_repcnt == INF) ! 406: er &= ~HTER_NEF; ! 407: break; ! 408: } ! 409: er &= ~HTER_FCE; ! 410: if (er == 0) ! 411: ds &= ~HTDS_ERR; ! 412: } ! 413: if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { ! 414: if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) ! 415: sc->sc_openf = -1; ! 416: tprintf(sc->sc_ttyp, "tu%d: hard error bn%d er=%b ds=%b\n", ! 417: TUUNIT(bp->b_dev), bp->b_blkno, ! 418: sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); ! 419: bp->b_flags |= B_ERROR; ! 420: return (MBN_DONE); ! 421: } ! 422: if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { ! 423: if (sc->sc_flags & H_REWIND) ! 424: return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); ! 425: bp->b_resid = -sc->sc_resid; ! 426: return (MBN_DONE); ! 427: } ! 428: if (ds & HTDS_TM) ! 429: if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { ! 430: sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; ! 431: sc->sc_blkno = sc->sc_nxrec; ! 432: } else { ! 433: sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; ! 434: sc->sc_nxrec = sc->sc_blkno - 1; ! 435: } ! 436: else ! 437: sc->sc_blkno = bdbtofsb(bp->b_blkno); ! 438: return (MBN_RETRY); ! 439: } ! 440: ! 441: /*ARGSUSED*/ ! 442: htioctl(dev, cmd, data, flag) ! 443: dev_t dev; ! 444: int cmd; ! 445: caddr_t data; ! 446: int flag; ! 447: { ! 448: register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; ! 449: register struct buf *bp = &chtbuf[HTUNIT(dev)]; ! 450: register callcount; ! 451: int fcount; ! 452: struct mtop *mtop; ! 453: struct mtget *mtget; ! 454: /* we depend of the values and order of the MT codes here */ ! 455: static htops[] = ! 456: {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; ! 457: ! 458: switch (cmd) { ! 459: ! 460: case MTIOCTOP: /* tape operation */ ! 461: mtop = (struct mtop *)data; ! 462: switch (mtop->mt_op) { ! 463: ! 464: case MTWEOF: ! 465: callcount = mtop->mt_count; ! 466: fcount = 1; ! 467: break; ! 468: ! 469: case MTFSF: case MTBSF: ! 470: callcount = mtop->mt_count; ! 471: fcount = INF; ! 472: break; ! 473: ! 474: case MTFSR: case MTBSR: ! 475: callcount = 1; ! 476: fcount = mtop->mt_count; ! 477: break; ! 478: ! 479: case MTREW: case MTOFFL: ! 480: callcount = 1; ! 481: fcount = 1; ! 482: break; ! 483: ! 484: default: ! 485: return (ENXIO); ! 486: } ! 487: if (callcount <= 0 || fcount <= 0) ! 488: return (EINVAL); ! 489: while (--callcount >= 0) { ! 490: htcommand(dev, htops[mtop->mt_op], fcount); ! 491: if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && ! 492: bp->b_resid) ! 493: return (EIO); ! 494: if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) ! 495: break; ! 496: } ! 497: return (geterror(bp)); ! 498: ! 499: case MTIOCGET: ! 500: mtget = (struct mtget *)data; ! 501: mtget->mt_dsreg = sc->sc_dsreg; ! 502: mtget->mt_erreg = sc->sc_erreg; ! 503: mtget->mt_resid = sc->sc_resid; ! 504: mtget->mt_type = MT_ISHT; ! 505: break; ! 506: ! 507: default: ! 508: return (ENXIO); ! 509: } ! 510: return (0); ! 511: } ! 512: ! 513: #define DBSIZE 20 ! 514: ! 515: htdump() ! 516: { ! 517: register struct mba_device *mi; ! 518: register struct mba_regs *mp; ! 519: register struct htdevice *htaddr; ! 520: int blk, num; ! 521: int start; ! 522: ! 523: start = 0; ! 524: num = maxfree; ! 525: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) ! 526: if (htinfo[0] == 0) ! 527: return (ENXIO); ! 528: mi = phys(htinfo[0], struct mba_device *); ! 529: mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; ! 530: mp->mba_cr = MBCR_IE; ! 531: htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; ! 532: htaddr->httc = HTTC_PDP11|HTTC_1600BPI; ! 533: htaddr->htcs1 = HT_DCLR|HT_GO; ! 534: while (num > 0) { ! 535: blk = num > DBSIZE ? DBSIZE : num; ! 536: htdwrite(start, blk, htaddr, mp); ! 537: start += blk; ! 538: num -= blk; ! 539: } ! 540: hteof(htaddr); ! 541: hteof(htaddr); ! 542: htwait(htaddr); ! 543: if (htaddr->htds&HTDS_ERR) ! 544: return (EIO); ! 545: htaddr->htcs1 = HT_REW|HT_GO; ! 546: return (0); ! 547: } ! 548: ! 549: htdwrite(dbuf, num, htaddr, mp) ! 550: register dbuf, num; ! 551: register struct htdevice *htaddr; ! 552: struct mba_regs *mp; ! 553: { ! 554: register struct pte *io; ! 555: register int i; ! 556: ! 557: htwait(htaddr); ! 558: io = mp->mba_map; ! 559: for (i = 0; i < num; i++) ! 560: *(int *)io++ = dbuf++ | PG_V; ! 561: htaddr->htfc = -(num*NBPG); ! 562: mp->mba_sr = -1; ! 563: mp->mba_bcr = -(num*NBPG); ! 564: mp->mba_var = 0; ! 565: htaddr->htcs1 = HT_WCOM|HT_GO; ! 566: } ! 567: ! 568: htwait(htaddr) ! 569: struct htdevice *htaddr; ! 570: { ! 571: register s; ! 572: ! 573: do ! 574: s = htaddr->htds; ! 575: while ((s & HTDS_DRY) == 0); ! 576: } ! 577: ! 578: hteof(htaddr) ! 579: struct htdevice *htaddr; ! 580: { ! 581: ! 582: htwait(htaddr); ! 583: htaddr->htcs1 = HT_WEOF|HT_GO; ! 584: } ! 585: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.