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