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.13 (Berkeley) 12/16/90 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 "sys/param.h" 21 #include "sys/systm.h" 22 #include "sys/buf.h" 23 #include "sys/conf.h" 24 #include "sys/file.h" 25 #include "sys/user.h" 26 #include "sys/proc.h" 27 #include "sys/map.h" 28 #include "sys/ioctl.h" 29 #include "sys/mtio.h" 30 #include "sys/cmap.h" 31 #include "sys/tty.h" 32 #include "sys/syslog.h" 33 #include "sys/tprintf.h" 34 35 #include "../include/pte.h" 36 #include "../include/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 tpr_t sc_tpr; /* tprintf handle for errors to user */ 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_tpr = tprintf_open(); 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 tprintf_close(sc->sc_tpr); 174 sc->sc_openf = 0; 175 return (0); 176 } 177 178 htcommand(dev, com, count) 179 dev_t dev; 180 int com, count; 181 { 182 register struct buf *bp; 183 register int s; 184 185 bp = &chtbuf[HTUNIT(dev)]; 186 s = spl5(); 187 while (bp->b_flags&B_BUSY) { 188 if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 189 break; 190 bp->b_flags |= B_WANTED; 191 sleep((caddr_t)bp, PRIBIO); 192 } 193 bp->b_flags = B_BUSY|B_READ; 194 splx(s); 195 bp->b_dev = dev; 196 bp->b_command = com; 197 bp->b_repcnt = count; 198 bp->b_blkno = 0; 199 htstrategy(bp); 200 if (count == 0) 201 return; 202 iowait(bp); 203 if (bp->b_flags&B_WANTED) 204 wakeup((caddr_t)bp); 205 bp->b_flags &= B_ERROR; 206 } 207 208 htstrategy(bp) 209 register struct buf *bp; 210 { 211 register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 212 register struct buf *dp; 213 register int s; 214 215 bp->av_forw = NULL; 216 dp = &mi->mi_tab; 217 s = spl5(); 218 if (dp->b_actf == NULL) 219 dp->b_actf = bp; 220 else 221 dp->b_actl->av_forw = bp; 222 dp->b_actl = bp; 223 if (dp->b_active == 0) 224 mbustart(mi); 225 splx(s); 226 } 227 228 htustart(mi) 229 register struct mba_device *mi; 230 { 231 register struct htdevice *htaddr = 232 (struct htdevice *)mi->mi_drv; 233 register struct buf *bp = mi->mi_tab.b_actf; 234 register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 235 daddr_t blkno; 236 237 htaddr->httc = sc->sc_dens; 238 #ifdef notdef 239 /* unneeded, may hang controller */ 240 if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 241 htaddr->htcs1 = HT_SENSE|HT_GO; 242 mbclrattn(mi); 243 } 244 #endif 245 sc->sc_dsreg = htaddr->htds; 246 sc->sc_erreg = htaddr->hter; 247 sc->sc_resid = htaddr->htfc; 248 sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 249 if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 250 if (sc->sc_openf > 0) 251 sc->sc_openf = -1; 252 if (sc->sc_openf < 0) { 253 bp->b_flags |= B_ERROR; 254 return (MBU_NEXT); 255 } 256 if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 257 /* transfer: check positioning */ 258 if (bp->b_flags & B_RAW) { 259 /* raw transfer: record position for retry */ 260 if (mi->mi_tab.b_errcnt == 0) { 261 sc->sc_blkno = bdbtofsb(bp->b_blkno); 262 sc->sc_nxrec = sc->sc_blkno + 1; 263 } 264 } else { 265 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 266 bp->b_flags |= B_ERROR; 267 bp->b_error = ENXIO; 268 return (MBU_NEXT); 269 } 270 if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 271 bp->b_flags&B_READ) { 272 bp->b_resid = bp->b_bcount; 273 clrbuf(bp); 274 return (MBU_NEXT); 275 } 276 if ((bp->b_flags&B_READ)==0) 277 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 278 } 279 } else { 280 if (bp->b_command == HT_SENSE) 281 return (MBU_NEXT); 282 if (bp->b_command == HT_REW) 283 sc->sc_flags |= H_REWIND; 284 else 285 htaddr->htfc = -bp->b_bcount; 286 htaddr->htcs1 = bp->b_command|HT_GO; 287 return (MBU_STARTED); 288 } 289 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 290 htaddr->htfc = -bp->b_bcount; 291 if ((bp->b_flags&B_READ) == 0) { 292 if (mi->mi_tab.b_errcnt) { 293 if ((sc->sc_flags & H_ERASED) == 0) { 294 sc->sc_flags |= H_ERASED; 295 htaddr->htcs1 = HT_ERASE | HT_GO; 296 return (MBU_STARTED); 297 } 298 sc->sc_flags &= ~H_ERASED; 299 } 300 if (htaddr->htds & HTDS_EOT) { 301 bp->b_resid = bp->b_bcount; 302 bp->b_flags |= B_ERROR; 303 return (MBU_NEXT); 304 } 305 } 306 return (MBU_DODATA); 307 } 308 if (blkno < bdbtofsb(bp->b_blkno)) { 309 htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 310 htaddr->htcs1 = HT_SFORW|HT_GO; 311 } else { 312 htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 313 htaddr->htcs1 = HT_SREV|HT_GO; 314 } 315 return (MBU_STARTED); 316 } 317 318 htdtint(mi, mbsr) 319 register struct mba_device *mi; 320 int mbsr; 321 { 322 register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 323 register struct buf *bp = mi->mi_tab.b_actf; 324 register struct tu_softc *sc; 325 int ds, er, mbs; 326 327 sc = &tu_softc[TUUNIT(bp->b_dev)]; 328 ds = sc->sc_dsreg = MASKREG(htaddr->htds); 329 er = sc->sc_erreg = MASKREG(htaddr->hter); 330 sc->sc_resid = MASKREG(htaddr->htfc); 331 mbs = mbsr; 332 sc->sc_blkno++; 333 if((bp->b_flags & B_READ) == 0) 334 sc->sc_flags |= H_WRITTEN; 335 if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 336 htaddr->htcs1 = HT_DCLR|HT_GO; 337 mbclrattn(mi); 338 if (bp->b_flags & B_RAW) { 339 er &= ~HTER_FCE; 340 mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 341 } 342 if (bp->b_flags & B_READ && ds & HTDS_PES) 343 er &= ~(HTER_CSITM|HTER_CORCRC); 344 if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 345 er && ++mi->mi_tab.b_errcnt >= 7) { 346 if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 347 sc->sc_openf = -1; 348 if ((er&HTER_HARD) == HTER_FCE && 349 (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 350 (ds&HTDS_MOL)) 351 goto noprint; 352 tprintf(sc->sc_tpr, 353 "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 354 TUUNIT(bp->b_dev), bp->b_blkno, 355 mbsr, mbsr_bits, 356 sc->sc_erreg, hter_bits, 357 sc->sc_dsreg, htds_bits); 358 noprint: 359 bp->b_flags |= B_ERROR; 360 return (MBD_DONE); 361 } 362 if (er) 363 return (MBD_RETRY); 364 } 365 bp->b_resid = 0; 366 sc->sc_blks++; 367 if (mi->mi_tab.b_errcnt) 368 sc->sc_softerrs++; 369 if (bp->b_flags & B_READ) 370 if (ds&HTDS_TM) { /* must be a read, right? */ 371 bp->b_resid = bp->b_bcount; 372 sc->sc_nxrec = bdbtofsb(bp->b_blkno); 373 } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 374 bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 375 return (MBD_DONE); 376 } 377 378 htndtint(mi) 379 register struct mba_device *mi; 380 { 381 register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 382 register struct buf *bp = mi->mi_tab.b_actf; 383 register struct tu_softc *sc; 384 int er, ds, fc; 385 386 ds = MASKREG(htaddr->htds); 387 er = MASKREG(htaddr->hter); 388 fc = MASKREG(htaddr->htfc); 389 if (er) { 390 htaddr->htcs1 = HT_DCLR|HT_GO; 391 mbclrattn(mi); 392 } 393 if (bp == 0) 394 return (MBN_SKIP); 395 sc = &tu_softc[TUUNIT(bp->b_dev)]; 396 sc->sc_dsreg = ds; 397 sc->sc_erreg = er; 398 sc->sc_resid = fc; 399 if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 400 switch ((int)bp->b_command) { 401 case HT_REWOFFL: 402 /* offline is on purpose; don't do anything special */ 403 ds |= HTDS_MOL; 404 break; 405 case HT_SREV: 406 /* if backspace file hit bot, its not an error */ 407 if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 408 bp->b_repcnt == INF) 409 er &= ~HTER_NEF; 410 break; 411 } 412 er &= ~HTER_FCE; 413 if (er == 0) 414 ds &= ~HTDS_ERR; 415 } 416 if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 417 if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 418 sc->sc_openf = -1; 419 tprintf(sc->sc_tpr, "tu%d: hard error bn%d er=%b ds=%b\n", 420 TUUNIT(bp->b_dev), bp->b_blkno, 421 sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 422 bp->b_flags |= B_ERROR; 423 return (MBN_DONE); 424 } 425 if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 426 if (sc->sc_flags & H_REWIND) 427 return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 428 bp->b_resid = -sc->sc_resid; 429 return (MBN_DONE); 430 } 431 if (ds & HTDS_TM) 432 if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 433 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 434 sc->sc_blkno = sc->sc_nxrec; 435 } else { 436 sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 437 sc->sc_nxrec = sc->sc_blkno - 1; 438 } 439 else 440 sc->sc_blkno = bdbtofsb(bp->b_blkno); 441 return (MBN_RETRY); 442 } 443 444 /*ARGSUSED*/ 445 htioctl(dev, cmd, data, flag) 446 dev_t dev; 447 int cmd; 448 caddr_t data; 449 int flag; 450 { 451 register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 452 register struct buf *bp = &chtbuf[HTUNIT(dev)]; 453 register callcount; 454 int fcount; 455 struct mtop *mtop; 456 struct mtget *mtget; 457 /* we depend of the values and order of the MT codes here */ 458 static htops[] = 459 {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 460 461 switch (cmd) { 462 463 case MTIOCTOP: /* tape operation */ 464 mtop = (struct mtop *)data; 465 switch (mtop->mt_op) { 466 467 case MTWEOF: 468 callcount = mtop->mt_count; 469 fcount = 1; 470 break; 471 472 case MTFSF: case MTBSF: 473 callcount = mtop->mt_count; 474 fcount = INF; 475 break; 476 477 case MTFSR: case MTBSR: 478 callcount = 1; 479 fcount = mtop->mt_count; 480 break; 481 482 case MTREW: case MTOFFL: 483 callcount = 1; 484 fcount = 1; 485 break; 486 487 default: 488 return (ENXIO); 489 } 490 if (callcount <= 0 || fcount <= 0) 491 return (EINVAL); 492 while (--callcount >= 0) { 493 htcommand(dev, htops[mtop->mt_op], fcount); 494 if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 495 bp->b_resid) 496 return (EIO); 497 if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 498 break; 499 } 500 if (bp->b_flags&B_ERROR) 501 return (bp->b_error ? bp->b_error : EIO); 502 return (0); 503 504 case MTIOCGET: 505 mtget = (struct mtget *)data; 506 mtget->mt_dsreg = sc->sc_dsreg; 507 mtget->mt_erreg = sc->sc_erreg; 508 mtget->mt_resid = sc->sc_resid; 509 mtget->mt_type = MT_ISHT; 510 break; 511 512 default: 513 return (ENXIO); 514 } 515 return (0); 516 } 517 518 #define DBSIZE 20 519 520 htdump() 521 { 522 register struct mba_device *mi; 523 register struct mba_regs *mp; 524 register struct htdevice *htaddr; 525 int blk, num; 526 int start; 527 528 start = 0; 529 num = maxfree; 530 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 531 if (htinfo[0] == 0) 532 return (ENXIO); 533 mi = phys(htinfo[0], struct mba_device *); 534 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 535 mp->mba_cr = MBCR_IE; 536 htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 537 htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 538 htaddr->htcs1 = HT_DCLR|HT_GO; 539 while (num > 0) { 540 blk = num > DBSIZE ? DBSIZE : num; 541 htdwrite(start, blk, htaddr, mp); 542 start += blk; 543 num -= blk; 544 } 545 hteof(htaddr); 546 hteof(htaddr); 547 htwait(htaddr); 548 if (htaddr->htds&HTDS_ERR) 549 return (EIO); 550 htaddr->htcs1 = HT_REW|HT_GO; 551 return (0); 552 } 553 554 htdwrite(dbuf, num, htaddr, mp) 555 register dbuf, num; 556 register struct htdevice *htaddr; 557 struct mba_regs *mp; 558 { 559 register struct pte *io; 560 register int i; 561 562 htwait(htaddr); 563 io = mp->mba_map; 564 for (i = 0; i < num; i++) 565 *(int *)io++ = dbuf++ | PG_V; 566 htaddr->htfc = -(num*NBPG); 567 mp->mba_sr = -1; 568 mp->mba_bcr = -(num*NBPG); 569 mp->mba_var = 0; 570 htaddr->htcs1 = HT_WCOM|HT_GO; 571 } 572 573 htwait(htaddr) 574 struct htdevice *htaddr; 575 { 576 register s; 577 578 do 579 s = htaddr->htds; 580 while ((s & HTDS_DRY) == 0); 581 } 582 583 hteof(htaddr) 584 struct htdevice *htaddr; 585 { 586 587 htwait(htaddr); 588 htaddr->htcs1 = HT_WEOF|HT_GO; 589 } 590 #endif 591