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) 05/06/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 586