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