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