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 * @(#)mt.c 7.4 (Berkeley) 01/14/89 7 */ 8 9 #include "mu.h" 10 #if NMT > 0 11 /* 12 * TM78/TU78 tape driver 13 * 14 * Original author - ? 15 * Most error recovery bug fixes - ggs (ulysses!ggs) 16 * `read reverse' error recovery - ggs (ulysses!ggs) 17 * 18 * OPTIONS: 19 * MTLERRM - Long error message text - twd, Brown University 20 * 21 * TODO: 22 * Add odd byte count kludge from VMS driver (?) 23 * Write dump routine 24 */ 25 26 #include "param.h" 27 #include "systm.h" 28 #include "buf.h" 29 #include "conf.h" 30 #include "dir.h" 31 #include "file.h" 32 #include "user.h" 33 #include "map.h" 34 #include "ioctl.h" 35 #include "mtio.h" 36 #include "cmap.h" 37 #include "uio.h" 38 #include "tty.h" 39 #include "syslog.h" 40 41 #include "../vax/pte.h" 42 #include "../vax/cpu.h" 43 #include "mbareg.h" 44 #include "mbavar.h" 45 #include "mtreg.h" 46 47 #define MTTIMEOUT 10000 /* loop limit for controller test */ 48 #define INF 1000000L /* a block number that won't exist */ 49 #define MASKREG(r) ((r) & 0xffff) /* the control registers have 16 bits */ 50 51 /* Bits for sc_flags */ 52 53 #define H_WRITTEN 01 /* last operation was a write */ 54 #define H_EOT 02 /* end of tape encountered */ 55 #define H_IEOT 04 /* ignore EOT condition */ 56 57 int mt_do_readrev = 1; 58 59 /* Per unit status information */ 60 61 struct mu_softc { 62 char sc_openf; /* unit is open if != 0 */ 63 char sc_flags; /* state flags */ 64 daddr_t sc_blkno; /* current physical block number */ 65 daddr_t sc_nxrec; /* firewall input block number */ 66 u_short sc_erreg; /* copy of mter or mtner */ 67 u_short sc_dsreg; /* copy of mtds */ 68 short sc_resid; /* residual function count for ioctl */ 69 short sc_dens; /* density code - MT_GCR or zero */ 70 int sc_i_mtas; /* mtas at slave attach time */ 71 int sc_i_mtner; /* mtner at slave attach time */ 72 int sc_i_mtds; /* mtds at slave attach time */ 73 struct tty *sc_ttyp; /* record user's tty for errors */ 74 int sc_blks; /* number of I/O operations since open */ 75 int sc_softerrs; /* number of soft I/O errors since open */ 76 } mu_softc[NMU]; 77 78 struct buf cmtbuf[NMT]; /* tape command buffer structures */ 79 80 struct mba_device *mtinfo[NMT]; /* unit to ctlr structures */ 81 struct mba_slave *muinfo[NMU]; /* unit to slave structures */ 82 83 char mtds_bits[] = MTDS_BITS; /* mtds bit names for error messages */ 84 short mttypes[] = { MBDT_TU78, 0 }; 85 86 int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint(); 87 struct mba_driver mtdriver = 88 { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint, 89 mttypes, "mt", "mu", mtinfo }; 90 91 /* Bits in minor device */ 92 #define MUUNIT(dev) (minor(dev)&03) 93 #define H_NOREWIND 04 94 #define H_6250BPI 010 95 96 #define MTUNIT(dev) (muinfo[MUUNIT(dev)]->ms_ctlr) 97 98 void mtcreset(); 99 100 /*ARGSUSED*/ 101 mtattach(mi) 102 struct mba_device *mi; 103 { 104 105 /* void */ 106 } 107 108 mtslave(mi, ms, sn) 109 struct mba_device *mi; 110 struct mba_slave *ms; 111 int sn; 112 { 113 register struct mu_softc *sc = &mu_softc[ms->ms_unit]; 114 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 115 int s = spl5(), rtn = 0, i; 116 117 /* 118 * Just in case the controller is ill, reset it. Then issue 119 * a sense operation and wait about a second for it to respond. 120 */ 121 mtcreset(mtaddr); 122 mtaddr->mtas = -1; 123 mtaddr->mtncs[sn] = MT_SENSE|MT_GO; 124 for (i = MTTIMEOUT; i > 0; i--) { 125 DELAY(50); 126 if (MASKREG(mtaddr->mtas) != 0) 127 break; 128 } 129 sc->sc_i_mtas = mtaddr->mtas; 130 sc->sc_i_mtner = mtaddr->mtner; 131 sc->sc_i_mtds = mtaddr->mtds; 132 133 /* 134 * If no response, whimper. If wrong response, call it an 135 * unsolicited interrupt and use mtndtint to log and correct. 136 * Otherwise, note whether this slave exists. 137 */ 138 if (i <= 0) 139 printf("mt: controller hung\n"); 140 else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) 141 (void) mtndtint(mi); 142 else if (mtaddr->mtds & MTDS_PRES) { 143 muinfo[ms->ms_unit] = ms; 144 rtn = 1; 145 } 146 147 /* cancel the interrupt, then wait a little while for it to go away */ 148 mtaddr->mtas = mtaddr->mtas; 149 DELAY(10); 150 splx(s); 151 return (rtn); 152 } 153 154 mtopen(dev, flag) 155 dev_t dev; 156 int flag; 157 { 158 register int muunit; 159 register struct mu_softc *sc; 160 register struct mba_slave *ms; 161 162 muunit = MUUNIT(dev); 163 if (muunit >= NMU || (ms = muinfo[muunit]) == NULL || 164 ms->ms_alive == 0 || mtinfo[ms->ms_ctlr]->mi_alive == 0) 165 return (ENXIO); 166 if ((sc = &mu_softc[muunit])->sc_openf) 167 return (EBUSY); 168 sc->sc_openf = 1; 169 sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0; 170 mtcommand(dev, MT_SENSE, 1); 171 if ((sc->sc_dsreg & MTDS_ONL) == 0) { 172 uprintf("mu%d: not online\n", muunit); 173 sc->sc_openf = 0; 174 return (EIO); 175 } 176 if ((sc->sc_dsreg & MTDS_AVAIL) == 0) { 177 uprintf("mu%d: not online (port selector)\n", muunit); 178 sc->sc_openf = 0; 179 return (EIO); 180 } 181 if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) { 182 uprintf("mu%d: no write ring\n", muunit); 183 sc->sc_openf = 0; 184 return (EIO); 185 } 186 if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag & FWRITE) && 187 (sc->sc_dens == MT_GCR) != ((sc->sc_dsreg & MTDS_PE) == 0)) { 188 uprintf("mu%d: can't change density in mid-tape\n", muunit); 189 sc->sc_openf = 0; 190 return (EIO); 191 } 192 sc->sc_blkno = (daddr_t)0; 193 194 /* 195 * Since cooked I/O may do a read-ahead before a write, trash 196 * on a tape can make the first write fail. Suppress the first 197 * read-ahead unless definitely doing read-write. 198 */ 199 sc->sc_nxrec = ((flag & (FTRUNC | FWRITE)) == (FTRUNC | FWRITE)) ? 200 (daddr_t)0 : (daddr_t)INF; 201 sc->sc_flags = 0; 202 sc->sc_blks = 0; 203 sc->sc_softerrs = 0; 204 sc->sc_ttyp = u.u_ttyp; 205 return (0); 206 } 207 208 mtclose(dev, flag) 209 register dev_t dev; 210 register int flag; 211 { 212 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 213 214 if ((flag & (FREAD | FWRITE)) == FWRITE || 215 ((flag & FWRITE) && (sc->sc_flags & H_WRITTEN))) 216 mtcommand(dev, MT_CLS|sc->sc_dens, 1); 217 if ((minor(dev) & H_NOREWIND) == 0) 218 mtcommand(dev, MT_REW, 0); 219 if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100) 220 log(LOG_INFO, "mu%d: %d soft errors in %d blocks\n", 221 MUUNIT(dev), sc->sc_softerrs, sc->sc_blks); 222 sc->sc_openf = 0; 223 } 224 225 mtcommand(dev, com, count) 226 dev_t dev; 227 int com, count; 228 { 229 register struct buf *bp; 230 int s; 231 232 bp = &cmtbuf[MTUNIT(dev)]; 233 s = spl5(); 234 while (bp->b_flags & B_BUSY) { 235 if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) 236 break; 237 bp->b_flags |= B_WANTED; 238 sleep((caddr_t)bp, PRIBIO); 239 } 240 bp->b_flags = B_BUSY|B_READ; 241 splx(s); 242 bp->b_dev = dev; 243 bp->b_command = com; 244 bp->b_repcnt = count; 245 bp->b_blkno = 0; 246 bp->b_error = 0; 247 mtstrategy(bp); 248 if (count == 0) 249 return; 250 biowait(bp); 251 if (bp->b_flags & B_WANTED) 252 wakeup((caddr_t)bp); 253 bp->b_flags &= B_ERROR; 254 } 255 256 mtstrategy(bp) 257 register struct buf *bp; 258 { 259 register struct buf *dp; 260 struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)]; 261 int s; 262 263 /* 264 * If this is a data transfer operation, set the resid to a 265 * default value (EOF) to simplify getting it right during 266 * error recovery or bail out. 267 */ 268 if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) 269 bp->b_resid = bp->b_bcount; 270 271 /* 272 * Link this request onto the end of the queue for this 273 * controller, then start I/O if not already active. 274 */ 275 bp->av_forw = NULL; 276 dp = &mi->mi_tab; 277 s = spl5(); 278 if (dp->b_actf == NULL) 279 dp->b_actf = bp; 280 else 281 dp->b_actl->av_forw = bp; 282 dp->b_actl = bp; 283 if (dp->b_active == 0) 284 mbustart(mi); 285 splx(s); 286 } 287 288 mtustart(mi) 289 register struct mba_device *mi; 290 { 291 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 292 register struct buf *bp = mi->mi_tab.b_actf; 293 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 294 daddr_t blkno; 295 int count; 296 297 if (sc->sc_openf < 0) { 298 bp->b_flags |= B_ERROR; 299 return (MBU_NEXT); 300 } 301 if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) { 302 /* 303 * Data transfer. If write at end of tape, 304 * signal "no space" unless suppressed 305 * by MTIOCIEOT. 306 */ 307 if ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT && 308 (bp->b_flags & B_READ) == 0) { 309 bp->b_flags |= B_ERROR; 310 bp->b_error = ENOSPC; 311 return (MBU_NEXT); 312 } 313 314 if (bp->b_flags & B_RAW) { 315 /* raw transfer; never seek */ 316 sc->sc_blkno = bdbtofsb(bp->b_blkno); 317 sc->sc_nxrec = sc->sc_blkno + 1; 318 } else { 319 /* seek beyond end of file */ 320 if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 321 bp->b_flags |= B_ERROR; 322 bp->b_error = ENXIO; 323 return (MBU_NEXT); 324 } 325 326 /* 327 * This should be end of file, but the buffer 328 * system wants a one-block look-ahead. Humor it. 329 */ 330 if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 331 bp->b_flags & B_READ) { 332 bp->b_resid = bp->b_bcount; 333 clrbuf(bp); 334 return (MBU_NEXT); 335 } 336 337 /* If writing, mark the next block invalid. */ 338 if ((bp->b_flags & B_READ) == 0) 339 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 340 } 341 } else { 342 /* It's a command, do it now. */ 343 mtaddr->mtncs[MUUNIT(bp->b_dev)] = 344 (bp->b_repcnt<<8)|bp->b_command|MT_GO; 345 return (MBU_STARTED); 346 } 347 348 /* 349 * If raw I/O, or if the tape is positioned correctly for 350 * cooked I/O, set the byte count, unit number and repeat count 351 * then tell the MASSBUS to proceed. Note that a negative 352 * bcount tells mbstart to map the buffer for "read backwards". 353 */ 354 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 355 if (mi->mi_tab.b_errcnt == 2) { 356 mtaddr->mtbc = -bp->b_bcount; 357 mtaddr->mtca = MUUNIT(bp->b_dev); 358 } else { 359 mtaddr->mtbc = bp->b_bcount; 360 mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); 361 } 362 return (MBU_DODATA); 363 } 364 365 /* Issue skip operations to position the next block for cooked I/O. */ 366 367 if (blkno < bdbtofsb(bp->b_blkno)) 368 count = bdbtofsb(bp->b_blkno) - blkno; 369 else 370 count = blkno - bdbtofsb(bp->b_blkno); 371 if ((unsigned)count > 0377) 372 count = 0377; 373 mtaddr->mtncs[MUUNIT(bp->b_dev)] = count | MT_SFORW|MT_GO; 374 return (MBU_STARTED); 375 } 376 377 mtstart(mi) 378 register struct mba_device *mi; 379 { 380 register struct buf *bp = mi->mi_tab.b_actf; 381 register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; 382 383 if (bp->b_flags & B_READ) 384 if (mi->mi_tab.b_errcnt == 2) 385 return (MT_READREV|MT_GO); 386 else 387 return (MT_READ|MT_GO); 388 else 389 return (MT_WRITE|sc->sc_dens|MT_GO); 390 } 391 392 mtdtint(mi, mbsr) 393 register struct mba_device *mi; 394 int mbsr; 395 { 396 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 397 register struct buf *bp = mi->mi_tab.b_actf; 398 register struct mu_softc *sc; 399 register int er; 400 401 /* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ 402 if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) { 403 printf("mt: wrong unit!\n"); 404 mtaddr->mtca = MUUNIT(bp->b_dev); 405 } 406 407 er = MASKREG(mtaddr->mter); 408 sc = &mu_softc[MUUNIT(bp->b_dev)]; 409 sc->sc_erreg = er; 410 if (bp->b_flags & B_READ) 411 sc->sc_flags &= ~H_WRITTEN; 412 else 413 sc->sc_flags |= H_WRITTEN; 414 switch (er & MTER_INTCODE) { 415 416 case MTER_EOT: 417 sc->sc_flags |= H_EOT; 418 /* fall into MTER_DONE */ 419 420 case MTER_DONE: 421 sc->sc_blkno++; 422 if (mi->mi_tab.b_errcnt == 2) { 423 bp->b_bcount = bp->b_resid; 424 bp->b_resid -= MASKREG(mtaddr->mtbc); 425 if (bp->b_resid > 0 && (bp->b_flags & B_RAW) == 0) 426 bp->b_flags |= B_ERROR; 427 } else 428 bp->b_resid = 0; 429 break; 430 431 case MTER_SHRTREC: 432 sc->sc_blkno++; 433 bp->b_bcount = bp->b_resid; 434 bp->b_resid -= MASKREG(mtaddr->mtbc); 435 if ((bp->b_flags & B_RAW) == 0) 436 bp->b_flags |= B_ERROR; 437 break; 438 439 case MTER_RETRY: 440 /* 441 * Simple re-try. Since resid is always a copy of the 442 * original byte count, use it to restore the count. 443 */ 444 mi->mi_tab.b_errcnt = 1; 445 bp->b_bcount = bp->b_resid; 446 return (MBD_RETRY); 447 448 case MTER_RDOPP: 449 /* 450 * The controller just decided to read it backwards. 451 * If the controller returns a byte count of zero, 452 * change it to 1, since zero encodes 65536, which 453 * isn't quite what we had in mind. The byte count 454 * may be larger than the size of the input buffer, so 455 * limit the count to the buffer size. After 456 * making the byte count reasonable, set bcount to the 457 * negative of the controller's version of the byte 458 * count so that the start address for the transfer is 459 * set up correctly. 460 */ 461 if (mt_do_readrev) { 462 mi->mi_tab.b_errcnt = 2; 463 if ((bp->b_bcount = MASKREG(mtaddr->mtbc)) == 0) 464 bp->b_bcount = 1; 465 if (bp->b_bcount > bp->b_resid) 466 bp->b_bcount = bp->b_resid; 467 bp->b_bcount = -(bp->b_bcount); 468 return(MBD_RETRY); 469 } else if (MASKREG(mtaddr->mtbc) <= bp->b_resid) { 470 sc->sc_blkno++; 471 bp->b_bcount = bp->b_resid; 472 bp->b_resid -= MASKREG(mtaddr->mtbc); 473 bp->b_flags |= B_ERROR; 474 break; 475 } 476 bp->b_flags |= B_ERROR; 477 /* fall into MTER_LONGREC */ 478 479 case MTER_LONGREC: 480 sc->sc_blkno++; 481 bp->b_bcount = bp->b_resid; 482 bp->b_resid = 0; 483 bp->b_error = ENOMEM; 484 bp->b_flags |= B_ERROR; 485 break; 486 487 case MTER_NOTCAP: 488 printf("mu%d: blank tape\n", MUUNIT(bp->b_dev)); 489 goto err; 490 491 case MTER_TM: 492 /* 493 * End of file. Since the default byte count has 494 * already been set, just count the block and proceed. 495 */ 496 sc->sc_blkno++; 497 err: 498 sc->sc_nxrec = bdbtofsb(bp->b_blkno); 499 break; 500 501 case MTER_OFFLINE: 502 if (sc->sc_openf > 0) { 503 sc->sc_openf = -1; 504 tprintf(sc->sc_ttyp, "mu%d: offline\n", 505 MUUNIT(bp->b_dev)); 506 } 507 bp->b_flags |= B_ERROR; 508 break; 509 510 case MTER_NOTAVL: 511 if (sc->sc_openf > 0) { 512 sc->sc_openf = -1; 513 tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", 514 MUUNIT(bp->b_dev)); 515 } 516 bp->b_flags |= B_ERROR; 517 break; 518 519 case MTER_FPT: 520 tprintf(sc->sc_ttyp, "mu%d: no write ring\n", 521 MUUNIT(bp->b_dev)); 522 bp->b_flags |= B_ERROR; 523 break; 524 525 case MTER_UNREAD: 526 sc->sc_blkno++; 527 bp->b_bcount = bp->b_resid; 528 bp->b_resid -= MIN(MASKREG(mtaddr->mtbc), bp->b_bcount); 529 530 /* code 010 means a garbage record, nothing serious. */ 531 if ((er & MTER_FAILCODE) == (010 << MTER_FSHIFT)) { 532 tprintf(sc->sc_ttyp, 533 "mu%d: rn=%d bn=%d unreadable record\n", 534 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno); 535 bp->b_flags |= B_ERROR; 536 break; 537 } 538 539 /* 540 * Anything else might be a hardware problem, 541 * fall into the error report. 542 */ 543 544 default: 545 /* 546 * The bits in sc->sc_dsreg are from the last sense 547 * command. To get the most recent copy, you have to 548 * do a sense at interrupt level, which requires nested 549 * error processing. This is a bit messy, so leave 550 * well enough alone. 551 */ 552 tprintf(sc->sc_ttyp, "\ 553 mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=0%o ds=%b\n", 554 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno, 555 mbsr, mbsr_bits, er, 556 MASKREG(sc->sc_dsreg), mtds_bits); 557 #ifdef MTLERRM 558 mtintfail(er); 559 #endif 560 bp->b_flags |= B_ERROR; 561 562 /* 563 * The TM78 manual says to reset the controller after 564 * TM fault B or MASSBUS fault. 565 */ 566 if ((er & MTER_INTCODE) == MTER_TMFLTB || 567 (er & MTER_INTCODE) == MTER_MBFLT) 568 mtcreset(mtaddr); 569 } 570 571 /* 572 * Just in case some strange error slipped through (drive off 573 * line during read-reverse error recovery comes to mind), make 574 * sure the byte count is reasonable. 575 */ 576 if (bp->b_bcount < 0) 577 bp->b_bcount = bp->b_resid; 578 579 if ((bp->b_flags & B_ERROR) == 0) { 580 /* this counts reverse reads as soft errors */ 581 sc->sc_blks++; 582 if (mi->mi_tab.b_errcnt) /* alternatively, if == 1 */ 583 sc->sc_softerrs++; 584 } 585 return (MBD_DONE); 586 } 587 588 mtndtint(mi) 589 register struct mba_device *mi; 590 { 591 register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv; 592 register struct buf *bp = mi->mi_tab.b_actf; 593 register struct mu_softc *sc; 594 register int er, fc; 595 int unit; 596 597 unit = (mtaddr->mtner >> 8) & 3; 598 er = MASKREG(mtaddr->mtner); 599 sc = &mu_softc[unit]; 600 sc->sc_erreg = er; 601 602 /* Check for unsolicited interrupts. */ 603 if (bp == NULL || unit != MUUNIT(bp->b_dev)) { 604 if ((er & MTER_INTCODE) == MTER_ONLINE) 605 return (MBN_SKIP); 606 607 printf("mu%d: stray intr (non data transfer) er=0%o ds=%b\n", 608 unit, er, MASKREG(sc->sc_dsreg), mtds_bits); 609 #ifdef MTLERRM 610 mtintfail(er); 611 #endif 612 if ((er & MTER_INTCODE) == MTER_TMFLTB || 613 (er & MTER_INTCODE) == MTER_MBFLT) { 614 /* 615 * Reset the controller, then set error status 616 * if there was anything active when the fault 617 * occurred. This may shoot an innocent 618 * bystander, but it's better than letting 619 * an error slip through. 620 */ 621 mtcreset(mtaddr); 622 if (bp != NULL) { 623 bp->b_flags |= B_ERROR; 624 return (MBN_DONE); 625 } 626 } 627 return (MBN_SKIP); 628 } 629 630 fc = (mtaddr->mtncs[unit] >> 8) & 0xff; 631 sc->sc_resid = fc; 632 633 /* 634 * Clear the "written" flag after any operation that changes 635 * the position of the tape. 636 */ 637 if (bp != &cmtbuf[MTUNIT(bp->b_dev)] || bp->b_command != MT_SENSE) 638 sc->sc_flags &= ~H_WRITTEN; 639 640 switch (er & MTER_INTCODE) { 641 642 case MTER_EOT: 643 sc->sc_flags |= H_EOT; 644 /* fall into MTER_DONE */ 645 646 case MTER_DONE: 647 /* If this is a command buffer, just update the status. */ 648 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { 649 done: 650 if (bp->b_command == MT_SENSE) 651 sc->sc_dsreg = MASKREG(mtaddr->mtds); 652 return (MBN_DONE); 653 } 654 655 /* 656 * It's not a command buffer, must be a cooked I/O 657 * skip operation (perhaps a shaky assumption, but it 658 * wasn't my idea). 659 */ 660 if ((fc = bdbtofsb(bp->b_blkno) - sc->sc_blkno) < 0) 661 sc->sc_blkno -= MIN(0377, -fc); 662 else 663 sc->sc_blkno += MIN(0377, fc); 664 return (MBN_RETRY); 665 666 case MTER_ONLINE: /* ddj -- shouldn't happen but did */ 667 case MTER_RWDING: 668 return (MBN_SKIP); /* ignore "rewind started" interrupt */ 669 670 case MTER_NOTCAP: 671 tprintf(sc->sc_ttyp, "mu%d: blank tape\n", MUUNIT(bp->b_dev)); 672 bp->b_flags |= B_ERROR; 673 return (MBN_DONE); 674 675 case MTER_TM: 676 case MTER_LEOT: 677 /* 678 * For an ioctl skip operation, count a tape mark as 679 * a record. If there's anything left to do, update 680 * the repeat count and re-start the command. 681 */ 682 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) { 683 if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0) 684 return (MBN_DONE); 685 else 686 return (MBN_RETRY); 687 } else { 688 /* 689 * Cooked I/O again. Just update the books and 690 * wait for someone else to return end of file or 691 * complain about a bad seek. 692 */ 693 if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 694 sc->sc_nxrec = bdbtofsb(bp->b_blkno) + fc - 1; 695 sc->sc_blkno = sc->sc_nxrec; 696 } else { 697 sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 698 sc->sc_blkno = sc->sc_nxrec + 1; 699 } 700 } 701 return (MBN_RETRY); 702 703 case MTER_FPT: 704 tprintf(sc->sc_ttyp, "mu%d: no write ring\n", 705 MUUNIT(bp->b_dev)); 706 bp->b_flags |= B_ERROR; 707 return (MBN_DONE); 708 709 case MTER_OFFLINE: 710 /* If `off line' was intentional, don't complain. */ 711 if (bp == &cmtbuf[MTUNIT(bp->b_dev)] && 712 bp->b_command == MT_UNLOAD) 713 return(MBN_DONE); 714 if (sc->sc_openf > 0) { 715 sc->sc_openf = -1; 716 tprintf(sc->sc_ttyp, "mu%d: offline\n", 717 MUUNIT(bp->b_dev)); 718 } 719 bp->b_flags |= B_ERROR; 720 return (MBN_DONE); 721 722 case MTER_NOTAVL: 723 if (sc->sc_openf > 0) { 724 sc->sc_openf = -1; 725 tprintf(sc->sc_ttyp, "mu%d: offline (port selector)\n", 726 MUUNIT(bp->b_dev)); 727 } 728 bp->b_flags |= B_ERROR; 729 return (MBN_DONE); 730 731 case MTER_BOT: 732 if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) 733 goto done; 734 /* fall through */ 735 736 default: 737 tprintf(sc->sc_ttyp, "\ 738 mu%d: hard error (non data transfer) rn=%d bn=%d er=0%o ds=%b\n", 739 MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno, 740 er, MASKREG(sc->sc_dsreg), mtds_bits); 741 #ifdef MTLERRM 742 mtintfail(er); 743 #endif 744 if ((er & MTER_INTCODE) == MTER_TMFLTB || 745 (er & MTER_INTCODE) == MTER_MBFLT) 746 mtcreset(mtaddr); /* reset the controller */ 747 bp->b_flags |= B_ERROR; 748 return (MBN_DONE); 749 } 750 /* NOTREACHED */ 751 } 752 753 void 754 mtcreset(mtaddr) 755 register struct mtdevice *mtaddr; 756 { 757 register int i; 758 759 mtaddr->mtid = MTID_CLR; /* reset the TM78 */ 760 DELAY(200); 761 for (i = MTTIMEOUT; i > 0; i--) { 762 DELAY(50); /* don't nag */ 763 if ((mtaddr->mtid & MTID_RDY) != 0) 764 return; /* exit when ready */ 765 } 766 printf("mt: controller hung\n"); 767 } 768 769 /*ARGSUSED*/ 770 mtioctl(dev, cmd, data, flag) 771 dev_t dev; 772 int cmd; 773 caddr_t data; 774 int flag; 775 { 776 register struct mu_softc *sc = &mu_softc[MUUNIT(dev)]; 777 register struct buf *bp = &cmtbuf[MTUNIT(dev)]; 778 register struct mtop *mtop; 779 register struct mtget *mtget; 780 int callcount, fcount; 781 int op; 782 783 /* We depend on the values and order of the MT codes here. */ 784 785 static mtops[] = 786 {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE}; 787 788 switch (cmd) { 789 790 /* tape operation */ 791 792 case MTIOCTOP: 793 mtop = (struct mtop *)data; 794 switch (mtop->mt_op) { 795 796 case MTWEOF: 797 callcount = mtop->mt_count; 798 fcount = 1; 799 break; 800 801 case MTFSF: case MTBSF: 802 callcount = mtop->mt_count; 803 fcount = 1; 804 break; 805 806 case MTFSR: case MTBSR: 807 callcount = 1; 808 fcount = mtop->mt_count; 809 break; 810 811 case MTREW: case MTOFFL: 812 callcount = 1; 813 fcount = 1; 814 break; 815 816 default: 817 return (ENXIO); 818 } 819 if (callcount <= 0 || fcount <= 0) 820 return (EINVAL); 821 op = mtops[mtop->mt_op]; 822 if (op == MT_WTM) 823 op |= sc->sc_dens; 824 while (--callcount >= 0) { 825 register int n, fc = fcount; 826 827 do { 828 n = MIN(fc, 0xff); 829 mtcommand(dev, op, n); 830 n -= sc->sc_resid; 831 fc -= n; 832 switch (mtop->mt_op) { 833 834 case MTWEOF: 835 sc->sc_blkno += (daddr_t)n; 836 sc->sc_nxrec = sc->sc_blkno - 1; 837 break; 838 839 case MTOFFL: 840 case MTREW: 841 case MTFSF: 842 sc->sc_blkno = (daddr_t)0; 843 sc->sc_nxrec = (daddr_t)INF; 844 break; 845 846 case MTBSF: 847 if (sc->sc_resid) { 848 sc->sc_blkno = (daddr_t)0; 849 sc->sc_nxrec = (daddr_t)INF; 850 } else { 851 sc->sc_blkno = (daddr_t)(-1); 852 sc->sc_nxrec = (daddr_t)(-1); 853 } 854 break; 855 856 case MTFSR: 857 sc->sc_blkno += (daddr_t)n; 858 break; 859 860 case MTBSR: 861 sc->sc_blkno -= (daddr_t)n; 862 break; 863 } 864 if (sc->sc_resid) 865 break; 866 } while (fc); 867 if (fc) { 868 sc->sc_resid = callcount + fc; 869 if (mtop->mt_op == MTFSR || 870 mtop->mt_op == MTBSR) 871 return (EIO); 872 break; 873 } 874 if (bp->b_flags & B_ERROR) 875 break; 876 } 877 return (geterror(bp)); 878 879 /* tape status */ 880 case MTIOCGET: 881 mtget = (struct mtget *)data; 882 mtget->mt_erreg = sc->sc_erreg; 883 mtget->mt_resid = sc->sc_resid; 884 mtcommand(dev, MT_SENSE, 1); /* update drive status */ 885 mtget->mt_dsreg = sc->sc_dsreg; 886 mtget->mt_type = MT_ISMT; 887 break; 888 889 /* ignore EOT condition */ 890 case MTIOCIEOT: 891 sc->sc_flags |= H_IEOT; 892 break; 893 894 /* enable EOT condition */ 895 case MTIOCEEOT: 896 sc->sc_flags &= ~H_IEOT; 897 break; 898 899 default: 900 return (ENXIO); 901 } 902 return (0); 903 } 904 905 #define DBSIZE 20 906 907 mtdump() 908 { 909 register struct mba_device *mi; 910 register struct mba_regs *mp; 911 int blk, num; 912 int start; 913 914 start = 0; 915 num = maxfree; 916 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 917 if (mtinfo[0] == 0) 918 return (ENXIO); 919 mi = phys(mtinfo[0], struct mba_device *); 920 mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 921 mp->mba_cr = MBCR_IE; 922 #if lint 923 blk = 0; num = blk; start = num; blk = start; 924 return (0); 925 #endif 926 #ifdef notyet 927 mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive]; 928 mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI; 929 mtaddr->mtcs1 = MT_DCLR|MT_GO; 930 while (num > 0) { 931 blk = num > DBSIZE ? DBSIZE : num; 932 mtdwrite(start, blk, mtaddr, mp); 933 start += blk; 934 num -= blk; 935 } 936 mteof(mtaddr); 937 mteof(mtaddr); 938 mtwait(mtaddr); 939 if (mtaddr->mtds&MTDS_ERR) 940 return (EIO); 941 mtaddr->mtcs1 = MT_REW|MT_GO; 942 return (0); 943 } 944 945 mtdwrite(dbuf, num, mtaddr, mp) 946 register dbuf, num; 947 register struct mtdevice *mtaddr; 948 struct mba_regs *mp; 949 { 950 register struct pte *io; 951 register int i; 952 953 mtwait(mtaddr); 954 io = mp->mba_map; 955 for (i = 0; i < num; i++) 956 *(int *)io++ = dbuf++ | PG_V; 957 mtaddr->mtfc = -(num*NBPG); 958 mp->mba_sr = -1; 959 mp->mba_bcr = -(num*NBPG); 960 mp->mba_var = 0; 961 mtaddr->mtcs1 = MT_WCOM|MT_GO; 962 } 963 964 mtwait(mtaddr) 965 struct mtdevice *mtaddr; 966 { 967 register s; 968 969 do 970 s = mtaddr->mtds; 971 while ((s & MTDS_DRY) == 0); 972 } 973 974 mteof(mtaddr) 975 struct mtdevice *mtaddr; 976 { 977 978 mtwait(mtaddr); 979 mtaddr->mtcs1 = MT_WEOF|MT_GO; 980 #endif notyet 981 } 982 983 #ifdef MTLERRM 984 /* 985 * Failure messages for each failure code, per interrupt code. 986 * Each table ends with a code of -1 as a default. 987 */ 988 struct fmesg { 989 int f_code; 990 char *f_mesg; 991 }; 992 993 static char unclass[] = "unclassified failure code"; 994 995 /* MTER_BOT */ 996 static struct fmesg botmsg[] = { 997 01, "tape was at BOT", 998 02, "BOT seen after tape started", 999 03, "ARA ID detected", 1000 -1, unclass 1001 }; 1002 1003 /* MTER_NOTRDY */ 1004 static struct fmesg notrdymsg[] = { 1005 01, "TU on-line but not ready", 1006 02, "fatal error has occurred", 1007 03, "access allowed but not ready", 1008 -1, unclass 1009 }; 1010 1011 /* MTER_NOTCAP */ 1012 static struct fmesg notcapmsg[] = { 1013 01, "no record found within 25 feet", 1014 02, "ID burst neither PE nor GCR", 1015 03, "ARA ID not found", 1016 04, "no gap found after ID burst", 1017 -1, unclass 1018 }; 1019 1020 /* MTER_LONGREC */ 1021 static struct fmesg longrecmsg[] = { 1022 00, "extended sense data not found", 1023 01, "extended sense data updated", 1024 -1, unclass 1025 }; 1026 1027 /* MTER_UNREAD, MTER_ERROR, MTER_EOTERR, MTER_BADTAPE */ 1028 static struct fmesg code22msg[] = { 1029 01, "GCR write error", 1030 02, "GCR read error", 1031 03, "PE read error", 1032 04, "PE write error", 1033 05, "at least 1 bit set in ECCSTA", 1034 06, "PE write error", 1035 07, "GCR write error", 1036 010, "RSTAT contains bad code", 1037 011, "PE write error", 1038 012, "MASSBUS parity error", 1039 013, "invalid data transferred", 1040 -1, unclass 1041 }; 1042 1043 /* MTER_TMFLTA */ 1044 static struct fmesg tmfltamsg[] = { 1045 01, "illegal command code", 1046 02, "DT command issued when NDT command active", 1047 03, "WMC error", 1048 04, "RUN not received from MASSBUS controller", 1049 05, "mismatch in command read - function routine", 1050 06, "ECC ROM parity error", 1051 07, "XMC ROM parity error", 1052 010, "mismatch in command read - ID burst command", 1053 011, "mismatch in command read - verify ARA burst command", 1054 012, "mismatch in command read - verify ARA ID command", 1055 013, "mismatch in command read - verify gap command", 1056 014, "mismatch in command read - read id burst command", 1057 015, "mismatch in command read - verify ARA ID command", 1058 016, "mismatch in command read - verify gap command", 1059 017, "mismatch in command read - find gap command", 1060 020, "WMC LEFT failed to set", 1061 021, "XL PE set in INTSTA register", 1062 022, "XMC DONE did not set", 1063 023, "WMC ROM PE or RD PE set in WMCERR register", 1064 -1, unclass 1065 }; 1066 1067 /* MTER_TUFLTA */ 1068 static struct fmesg tufltamsg[] = { 1069 01, "TU status parity error", 1070 02, "TU command parity error", 1071 03, "rewinding tape went offline", 1072 04, "tape went not ready during DSE", 1073 05, "TU CMD status changed during DSE", 1074 06, "TU never came up to speed", 1075 07, "TU velocity changed", 1076 010, "TU CMD did not load correctly to start tape motion", 1077 011, "TU CMD did not load correctly to set drive density", 1078 012, "TU CMD did not load correctly to start tape motion to write BOT ID", 1079 013, "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID", 1080 014, "failed to write density ID burst", 1081 015, "failed to write ARA burst", 1082 016, "failed to write ARA ID", 1083 017, "ARA error bit set in MTA status B register", 1084 021, "could not find a gap after ID code was written correctly", 1085 022, "TU CMD did not load correctly to start tape motion to read ID burst", 1086 023, "timeout looking for BOT after detecting ARA ID burst", 1087 024, "failed to write tape mark", 1088 025, "tape never came up to speed while trying to reposition for retry of writing tape mark", 1089 026, "TU CMD did not load correctly to start tape motion in erase gap routine", 1090 027, "could not detect a gap in in erase gap routine", 1091 030, "could not detect a gap after writing record", 1092 031, "read path terminated before entire record was written", 1093 032, "could not find a gap after writing record and read path terminated early", 1094 033, "TU CMD did not load correctly to backup for retry of write tape mark", 1095 034, "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark", 1096 035, "TU CMD did not load correctly to backup to retry a load of BOT ID", 1097 036, "timeout looking for BOT after failing to write BOT ID", 1098 037, "TU velocity changed while writing PE gap before starting to write record", 1099 040, "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst", 1100 041, "TU CMD did not load correctly to set GCR tape density after writing Density ID", 1101 042, "TU CMD did not load correctly to set PE tape density at start of read from BOT", 1102 043, "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst", 1103 }; 1104 1105 /* MTER_TMFLTB */ 1106 static char inlinetest[] = "inline test failed"; 1107 static struct fmesg tmfltbmsg[] = { 1108 00, "RST0 interrupt occurred with TM RDY set", 1109 01, "power failed to interrupt", 1110 02, "unknown interrupt on channel 5.5", 1111 03, "unknown interrupt on channel 6.5", 1112 04, "unknown interrupt on channel 7", 1113 05, "unknown interrupt on channel 7.5", 1114 06, "CAS contention retry count expired", 1115 07, "CAS contention error not retryable", 1116 010, "queue error, could not find queue entry", 1117 011, "queue entry already full", 1118 012, "8085 ROM parity error", 1119 013, inlinetest, 1120 013, inlinetest, 1121 014, inlinetest, 1122 015, inlinetest, 1123 016, inlinetest, 1124 017, inlinetest, 1125 020, inlinetest, 1126 021, inlinetest, 1127 022, inlinetest, 1128 023, inlinetest, 1129 024, inlinetest, 1130 025, inlinetest, 1131 026, inlinetest, 1132 027, inlinetest, 1133 030, inlinetest, 1134 031, inlinetest, 1135 032, inlinetest, 1136 033, inlinetest, 1137 034, inlinetest, 1138 035, inlinetest, 1139 036, inlinetest, 1140 037, inlinetest, 1141 040, inlinetest, 1142 041, inlinetest, 1143 042, inlinetest, 1144 043, inlinetest, 1145 044, inlinetest, 1146 045, inlinetest, 1147 046, inlinetest, 1148 047, inlinetest, 1149 050, inlinetest, 1150 051, inlinetest, 1151 052, inlinetest, 1152 053, inlinetest, 1153 054, inlinetest, 1154 055, inlinetest, 1155 056, inlinetest, 1156 057, inlinetest, 1157 -1, unclass 1158 }; 1159 1160 /* MTER_MBFLT */ 1161 static struct fmesg mbfltmsg[] = { 1162 01, "control bus parity error", 1163 02, "illegal register referenced", 1164 -1, unclass 1165 }; 1166 1167 /* 1168 * MTER_LEOT, MTER_RWDING, NTER_NOTAVL, MTER_NONEX, MTER_KEYFAIL, 1169 * and default: no failure message. 1170 */ 1171 static struct fmesg nullmsg[] = { 1172 -1, "" 1173 }; 1174 1175 /* 1176 * Interrupt code table. 1177 */ 1178 static struct errmsg { 1179 int e_code; 1180 char *e_mesg; 1181 struct fmesg *e_fmesg; 1182 } errmsg[] = { 1183 MTER_BOT, "unexpected BOT", botmsg, 1184 MTER_LEOT, "unexpected LEOT", nullmsg, 1185 MTER_RWDING, "tape rewinding", nullmsg, 1186 MTER_NOTRDY, "drive not ready", notrdymsg, 1187 MTER_NOTAVL, "drive not available", nullmsg, 1188 MTER_NONEX, "unit does not exist", nullmsg, 1189 MTER_NOTCAP, "not capable", notcapmsg, 1190 MTER_LONGREC, "long record", longrecmsg, 1191 MTER_UNREAD, "unreadable record", code22msg, 1192 MTER_ERROR, "error", code22msg, 1193 MTER_EOTERR, "EOT error", code22msg, 1194 MTER_BADTAPE, "tape position lost", code22msg, 1195 MTER_TMFLTA, "TM fault A", tmfltamsg, 1196 MTER_TUFLTA, "TU fault A", tufltamsg, 1197 MTER_TMFLTB, "TM fault B", tmfltbmsg, 1198 MTER_MBFLT, "MB fault", mbfltmsg, 1199 MTER_KEYFAIL, "keypad entry error", nullmsg, 1200 -1, "unclassified error", nullmsg 1201 }; 1202 1203 /* 1204 * Decode an interrupt-time failure. 1205 */ 1206 mtintfail(erreg) 1207 int erreg; 1208 { 1209 register struct errmsg *e; 1210 register struct fmesg *f; 1211 register int ecode, fcode; 1212 1213 ecode = erreg & MTER_INTCODE; 1214 fcode = (erreg & MTER_FAILCODE) >> MTER_FSHIFT; 1215 for (e = errmsg; e->e_code >= 0; e++) 1216 if (e->e_code == ecode) 1217 break; 1218 for (f = e->e_fmesg; f->f_code >= 0; f++) 1219 if (f->f_code == fcode) 1220 break; 1221 printf(" interrupt code = 0%o <%s>\n", ecode, e->e_mesg); 1222 printf(" failure code = 0%o <%s>\n", fcode, f->f_mesg); 1223 } 1224 #endif /* MTLERRM */ 1225 #endif /* NMT > 0 */ 1226