ts.c revision 1.6
1/* $NetBSD: ts.c,v 1.6 2002/09/25 22:21:39 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 1991 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)tmscp.c 7.16 (Berkeley) 5/9/91 36 */ 37 38/* 39 * sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86"; 40 */ 41 42/************************************************************************ 43 * * 44 * Licensed from Digital Equipment Corporation * 45 * Copyright (c) * 46 * Digital Equipment Corporation * 47 * Maynard, Massachusetts * 48 * 1985, 1986 * 49 * All rights reserved. * 50 * * 51 * The Information in this software is subject to change * 52 * without notice and should not be construed as a commitment * 53 * by Digital Equipment Corporation. Digital makes no * 54 * representations about the suitability of this software for * 55 * any purpose. It is supplied "As Is" without expressed or * 56 * implied warranty. * 57 * * 58 * If the Regents of the University of California or its * 59 * licensees modify the software in a manner creating * 60 * derivative copyright rights, appropriate copyright * 61 * legends may be placed on the derivative work in addition * 62 * to that set forth above. * 63 * * 64 ************************************************************************/ 65 66/* 67 * TSV05/TS05 device driver, written by Bertram Barth. 68 * 69 * should be TS11 compatible (untested) 70 */ 71 72#include <sys/cdefs.h> 73__KERNEL_RCSID(0, "$NetBSD: ts.c,v 1.6 2002/09/25 22:21:39 thorpej Exp $"); 74 75#undef TSDEBUG 76 77/* 78 * TODO: 79 * 80 * Keep track of tape position so that lseek et al works. 81 * Use tprintf to inform the user, not the system console. 82 */ 83 84 85#include <sys/param.h> 86#include <sys/systm.h> 87#include <sys/kernel.h> 88#include <sys/buf.h> 89#include <sys/conf.h> 90#include <sys/errno.h> 91#include <sys/file.h> 92#include <sys/syslog.h> 93#include <sys/ioctl.h> 94#include <sys/mtio.h> 95#include <sys/uio.h> 96#include <sys/proc.h> 97 98#include <machine/bus.h> 99 100#include <dev/qbus/ubareg.h> 101#include <dev/qbus/ubavar.h> 102 103#include <dev/qbus/tsreg.h> 104 105#include "ioconf.h" 106 107struct ts { 108 struct cmd cmd; /* command packet */ 109 struct chr chr; /* characteristics packet */ 110 struct status status; /* status packet */ 111}; 112 113/* 114 * Software status, per controller. 115 * also status per tape-unit, since only one unit per controller 116 * (thus we have no struct ts_info) 117 */ 118struct ts_softc { 119 struct device sc_dev; /* Autoconf ... */ 120 struct uba_unit sc_unit; /* Struct common for UBA to talk */ 121 struct evcnt sc_intrcnt; /* Interrupt counting */ 122 struct ubinfo sc_ui; /* mapping info for struct ts */ 123 struct uba_unit sc_uu; /* Struct for UBA to communicate */ 124 bus_space_tag_t sc_iot; 125 bus_addr_t sc_ioh; 126 bus_dma_tag_t sc_dmat; 127 bus_dmamap_t sc_dmam; 128 volatile struct ts *sc_vts; /* Memory address of ts struct */ 129 struct ts *sc_bts; /* Unibus address of ts struct */ 130 int sc_type; /* TS11 or TS05? */ 131 short sc_waddr; /* Value to write to TSDB */ 132 struct bufq_state sc_bufq; /* pending I/O requests */ 133 134 short sc_mapped; /* Unibus map allocated ? */ 135 short sc_state; /* see below: ST_xxx */ 136 short sc_rtc; /* retry count for lcmd */ 137 short sc_openf; /* lock against multiple opens */ 138 short sc_liowf; /* last operation was write */ 139 struct buf ts_cbuf; /* internal cmd buffer (for ioctls) */ 140}; 141 142#define XNAME sc->sc_dev.dv_xname 143 144#define TS_WCSR(csr, val) \ 145 bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val) 146#define TS_RCSR(csr) \ 147 bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr) 148 149#define LOWORD(x) ((int)(x) & 0xffff) 150#define HIWORD(x) (((int)(x) >> 16) & 0x3f) 151 152#define TYPE_TS11 0 153#define TYPE_TS05 1 154#define TYPE_TU80 2 155 156#define TS_INVALID 0 157#define TS_INIT 1 158#define TS_RUNNING 2 159#define TS_FASTREPOS 3 160 161static void tsintr(void *); 162static void tsinit(struct ts_softc *); 163static void tscommand(struct ts_softc *, dev_t, int, int); 164static int tsstart(struct ts_softc *, int); 165static void tswchar(struct ts_softc *); 166static int tsreset(struct ts_softc *); 167static int tsmatch(struct device *, struct cfdata *, void *); 168static void tsattach(struct device *, struct device *, void *); 169static int tsready(struct uba_unit *); 170 171struct cfattach ts_ca = { 172 sizeof(struct ts_softc), tsmatch, tsattach 173}; 174 175dev_type_open(tsopen); 176dev_type_close(tsclose); 177dev_type_read(tsread); 178dev_type_write(tswrite); 179dev_type_ioctl(tsioctl); 180dev_type_strategy(tsstrategy); 181dev_type_dump(tsdump); 182 183const struct bdevsw ts_bdevsw = { 184 tsopen, tsclose, tsstrategy, tsioctl, tsdump, nosize, D_TAPE 185}; 186 187const struct cdevsw ts_cdevsw = { 188 tsopen, tsclose, tsread, tswrite, tsioctl, 189 nostop, notty, nopoll, nommap, D_TAPE 190}; 191 192/* Bits in minor device */ 193#define TS_UNIT(dev) (minor(dev)&03) 194#define TS_HIDENSITY 010 195 196#define TS_PRI LOG_INFO 197 198 199/* 200 * Probe for device. If found, try to raise an interrupt. 201 */ 202int 203tsmatch(struct device *parent, struct cfdata *match, void *aux) 204{ 205 struct ts_softc ssc; 206 struct ts_softc *sc = &ssc; 207 struct uba_attach_args *ua = aux; 208 int i; 209 210 sc->sc_iot = ua->ua_iot; 211 sc->sc_ioh = ua->ua_ioh; 212 sc->sc_mapped = 0; 213 sc->sc_dev.dv_parent = parent; 214 strcpy(XNAME, "ts"); 215 216 /* Try to reset the device */ 217 for (i = 0; i < 3; i++) 218 if (tsreset(sc) == 1) 219 break; 220 221 if (i == 3) 222 return 0; 223 224 tsinit(sc); 225 tswchar(sc); /* write charact. to enable interrupts */ 226 /* completion of this will raise the intr. */ 227 228 DELAY(1000000); /* Wait for interrupt */ 229 ubmemfree((void *)parent, &sc->sc_ui); 230 return 1; 231} 232 233/* 234 */ 235void 236tsattach(struct device *parent, struct device *self, void *aux) 237{ 238 struct uba_softc *uh = (void *)parent; 239 struct ts_softc *sc = (void *)self; 240 struct uba_attach_args *ua = aux; 241 int error; 242 char *t; 243 244 sc->sc_iot = ua->ua_iot; 245 sc->sc_ioh = ua->ua_ioh; 246 sc->sc_dmat = ua->ua_dmat; 247 248 sc->sc_uu.uu_softc = sc; 249 sc->sc_uu.uu_ready = tsready; 250 251 tsinit(sc); /* reset and map */ 252 253 if ((error = bus_dmamap_create(sc->sc_dmat, (64*1024), 16, (64*1024), 254 0, BUS_DMA_NOWAIT, &sc->sc_dmam))) 255 return printf(": failed create DMA map %d\n", error); 256 257 bufq_alloc(&sc->sc_bufq, BUFQ_FCFS); 258 259 /* 260 * write the characteristics (again) 261 */ 262 sc->sc_state = TS_INIT; /* tsintr() checks this ... */ 263 tswchar(sc); 264 if (tsleep(sc, PRIBIO, "tsattach", 100)) 265 return printf(": failed SET CHARACTERISTICS\n"); 266 267 sc->sc_state = TS_RUNNING; 268 if (uh->uh_type == UBA_UBA) { 269 if (sc->sc_vts->status.xst2 & TS_SF_TU80) { 270 sc->sc_type = TYPE_TU80; 271 t = "TU80"; 272 } else { 273 sc->sc_type = TYPE_TS11; 274 t = "TS11"; 275 } 276 } else { 277 sc->sc_type = TYPE_TS05; 278 t = "TS05"; 279 } 280 281 printf("\n%s: %s\n", XNAME, t); 282 printf("%s: rev %d, extended features %s, transport %s\n", 283 XNAME, (sc->sc_vts->status.xst2 & TS_SF_MCRL) >> 2, 284 (sc->sc_vts->status.xst2 & TS_SF_EFES ? "enabled" : "disabled"), 285 (TS_RCSR(TSSR) & TS_OFL ? "offline" : "online")); 286 287 uba_intr_establish(ua->ua_icookie, ua->ua_cvec, tsintr, 288 sc, &sc->sc_intrcnt); 289 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, 290 sc->sc_dev.dv_xname, "intr"); 291} 292 293/* 294 * Initialize a TS device. Set up UBA mapping registers, 295 * initialize data structures, what else ??? 296 */ 297void 298tsinit(struct ts_softc *sc) 299{ 300 if (sc->sc_mapped == 0) { 301 302 /* 303 * Map the communications area and command and message 304 * buffer into Unibus address space. 305 */ 306 sc->sc_ui.ui_size = sizeof(struct ts); 307 if ((ubmemalloc((void *)sc->sc_dev.dv_parent, 308 &sc->sc_ui, UBA_CANTWAIT))) 309 return; 310 sc->sc_vts = (void *)sc->sc_ui.ui_vaddr; 311 sc->sc_bts = (void *)sc->sc_ui.ui_baddr; 312 sc->sc_waddr = sc->sc_ui.ui_baddr | 313 ((sc->sc_ui.ui_baddr >> 16) & 3); 314 sc->sc_mapped = 1; 315 } 316 tsreset(sc); 317} 318 319/* 320 * Execute a (ioctl) command on the tape drive a specified number of times. 321 * This routine sets up a buffer and calls the strategy routine which 322 * issues the command to the controller. 323 */ 324void 325tscommand(struct ts_softc *sc, dev_t dev, int cmd, int count) 326{ 327 struct buf *bp; 328 int s; 329 330#ifdef TSDEBUG 331 printf("tscommand (%x, %d)\n", cmd, count); 332#endif 333 334 bp = &sc->ts_cbuf; 335 336 s = splbio(); 337 while (bp->b_flags & B_BUSY) { 338 /* 339 * This special check is because B_BUSY never 340 * gets cleared in the non-waiting rewind case. ??? 341 */ 342 if (bp->b_bcount == 0 && (bp->b_flags & B_DONE)) 343 break; 344 bp->b_flags |= B_WANTED; 345 (void) tsleep(bp, PRIBIO, "tscmd", 0); 346 /* check MOT-flag !!! */ 347 } 348 bp->b_flags = B_BUSY | B_READ; 349 splx(s); 350 351 /* 352 * Load the buffer. The b_count field gets used to hold the command 353 * count. the b_resid field gets used to hold the command mneumonic. 354 * These 2 fields are "known" to be "safe" to use for this purpose. 355 * (Most other drivers also use these fields in this way.) 356 */ 357 bp->b_dev = dev; 358 bp->b_bcount = count; 359 bp->b_resid = cmd; 360 bp->b_blkno = 0; 361 tsstrategy(bp); 362 /* 363 * In case of rewind from close, don't wait. 364 * This is the only case where count can be 0. 365 */ 366 if (count == 0) 367 return; 368 biowait(bp); 369 if (bp->b_flags & B_WANTED) 370 wakeup((caddr_t)bp); 371 bp->b_flags &= B_ERROR; 372} 373 374/* 375 * Start an I/O operation on TS05 controller 376 */ 377int 378tsstart(struct ts_softc *sc, int isloaded) 379{ 380 struct buf *bp; 381 int cmd; 382 383 if (TAILQ_EMPTY(&sc->sc_bufq.bq_head)) 384 return 0; 385 386 bp = BUFQ_PEEK(&sc->sc_bufq); 387#ifdef TSDEBUG 388 printf("buf: %p bcount %ld blkno %d\n", bp, bp->b_bcount, bp->b_blkno); 389#endif 390 /* 391 * Check if command is an ioctl or not (ie. read or write). 392 * If it's an ioctl then just set the flags for later use; 393 * For other commands attempt to setup a buffer pointer. 394 */ 395 if (bp == &sc->ts_cbuf) { 396 switch ((int)bp->b_resid) { 397 case MTWEOF: 398 cmd = TS_CMD_WTM; 399 break; 400 case MTFSF: 401 cmd = TS_CMD_STMF; 402 sc->sc_vts->cmd.cw1 = bp->b_bcount; 403 break; 404 case MTBSF: 405 cmd = TS_CMD_STMR; 406 sc->sc_vts->cmd.cw1 = bp->b_bcount; 407 break; 408 case MTFSR: 409 cmd = TS_CMD_SRF; 410 sc->sc_vts->cmd.cw1 = bp->b_bcount; 411 break; 412 case MTBSR: 413 cmd = TS_CMD_SRR; 414 sc->sc_vts->cmd.cw1 = bp->b_bcount; 415 break; 416 case MTREW: 417 cmd = TS_CMD_RWND; 418 break; 419 case MTOFFL: 420 cmd = TS_CMD_RWUL; 421 break; 422 case MTNOP: 423 cmd = TS_CMD_STAT; 424 break; 425 default: 426 printf ("%s: bad ioctl %d\n", sc->sc_dev.dv_xname, 427 (int)bp->b_resid); 428 /* Need a no-op. get status */ 429 cmd = TS_CMD_STAT; 430 } /* end switch (bp->b_resid) */ 431 } else { 432 if (isloaded == 0) { 433 /* 434 * now we try to map the buffer into uba map space (???) 435 */ 436 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, 437 bp->b_data, 438 bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT)) { 439 uba_enqueue(&sc->sc_uu); 440 return 0; 441 } 442 sc->sc_rtc = 0; 443 } 444 sc->sc_vts->cmd.cw1 = LOWORD(sc->sc_dmam->dm_segs[0].ds_addr); 445 sc->sc_vts->cmd.cw2 = HIWORD(sc->sc_dmam->dm_segs[0].ds_addr); 446 sc->sc_vts->cmd.cw3 = bp->b_bcount; 447 bp->b_error = 0; /* Used for error count */ 448#ifdef TSDEBUG 449 printf("tsstart-1: err %d\n", bp->b_error); 450#endif 451 if (bp->b_flags & B_READ) 452 cmd = TS_CMD_RNF; 453 else 454 cmd = TS_CMD_WD; 455 } 456 457 /* 458 * Now that the command-buffer is setup, give it to the controller 459 */ 460 sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | cmd; 461#ifdef TSDEBUG 462 printf("tsstart: sending cmdr %x\n", sc->sc_vts->cmd.cmdr); 463#endif 464 TS_WCSR(TSDB, sc->sc_waddr); 465} 466 467/* 468 * Called when there are free uba resources. 469 */ 470int 471tsready(struct uba_unit *uu) 472{ 473 struct ts_softc *sc = uu->uu_softc; 474 struct buf *bp = BUFQ_PEEK(&sc->sc_bufq); 475 476 if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, bp->b_data, 477 bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT)) 478 return 0; 479 480 tsstart(sc, 1); 481 return 1; 482} 483 484/* 485 * initialize the controller by sending WRITE CHARACTERISTICS command. 486 * contents of command- and message-buffer are assembled during this 487 * function. 488 */ 489void 490tswchar(struct ts_softc *sc) 491{ 492 /* 493 * assemble and send "WRITE CHARACTERISTICS" command 494 */ 495 496 sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR; 497 sc->sc_vts->cmd.cw1 = LOWORD(&sc->sc_bts->chr); 498 sc->sc_vts->cmd.cw2 = HIWORD(&sc->sc_bts->chr); 499 sc->sc_vts->cmd.cw3 = 010; /* size of charact.-data */ 500 501 sc->sc_vts->chr.sadrl = LOWORD(&sc->sc_bts->status); 502 sc->sc_vts->chr.sadrh = HIWORD(&sc->sc_bts->status); 503 sc->sc_vts->chr.onesix = (sc->sc_type == TYPE_TS05 ? 020 : 016); 504 sc->sc_vts->chr.chrw = TS_WC_ESS; 505 sc->sc_vts->chr.xchrw = TS_WCX_HSP|TS_WCX_RBUF|TS_WCX_WBUF; 506 507 TS_WCSR(TSDB, sc->sc_waddr); 508} 509 510/* 511 * Reset the TS11. Return 1 if failed, 0 if succeeded. 512 */ 513int 514tsreset(struct ts_softc *sc) 515{ 516 int timeout; 517 518 /* 519 * reset ctlr by writing into TSSR, then write characteristics 520 */ 521 timeout = 0; /* timeout in 10 seconds */ 522 TS_WCSR(TSSR, 0); /* start initialization */ 523 while ((TS_RCSR(TSSR) & TS_SSR) == 0) { 524 DELAY(10000); 525 if (timeout++ > 1000) 526 return 0; 527 } 528 return 1; 529} 530 531static void 532prtstat(struct ts_softc *sc, int sr) 533{ 534 char buf[100]; 535 536 bitmask_snprintf(sr, TS_TSSR_BITS, buf, sizeof(buf)); 537 printf("%s: TSSR=%s\n", XNAME, buf); 538 bitmask_snprintf(sc->sc_vts->status.xst0,TS_XST0_BITS,buf,sizeof(buf)); 539 printf("%s: XST0=%s\n", XNAME, buf); 540} 541 542/* 543 * TSV05/TS05 interrupt routine 544 */ 545static void 546tsintr(void *arg) 547{ 548 struct ts_softc *sc = arg; 549 struct buf *bp; 550 551 unsigned short sr = TS_RCSR(TSSR); /* save TSSR */ 552 unsigned short mh = sc->sc_vts->status.hdr; /* and msg-header */ 553 /* clear the message header ??? */ 554 555 short ccode = sc->sc_vts->cmd.cmdr & TS_CF_CCODE; 556 557#ifdef TSDEBUG 558 { 559 char buf[100]; 560 bitmask_snprintf(sr, TS_TSSR_BITS, buf, sizeof(buf)); 561 printf("tsintr: sr %x mh %x\n", sr, mh); 562 printf("srbits: %s\n", buf); 563 } 564#endif 565 /* 566 * There are two different things which can (and should) be checked: 567 * the actual (internal) state and the device's result (tssr/msg.hdr) 568 * 569 * For each state there's only one "normal" interrupt. Anything else 570 * has to be checked more intensively. Thus in a first run according 571 * to the internal state the expected interrupt is checked/handled. 572 * 573 * In a second run the remaining (not yet handled) interrupts are 574 * checked according to the drive's result. 575 */ 576 switch (sc->sc_state) { 577 578 case TS_INVALID: 579 /* 580 * Ignore unsolicited interrupts. 581 */ 582 log(LOG_WARNING, "%s: stray intr [%x,%x]\n", 583 sc->sc_dev.dv_xname, sr, mh); 584 return; 585 586 case TS_INIT: 587 /* 588 * Init phase ready. 589 */ 590 wakeup(sc); 591 return; 592 593 case TS_RUNNING: 594 case TS_FASTREPOS: 595 /* 596 * Here we expect interrupts indicating the end of 597 * commands or indicating problems. 598 */ 599 /* 600 * Anything else is handled outside this switch ... 601 */ 602 break; 603 604 default: 605 printf ("%s: unexpected interrupt during state %d [%x,%x]\n", 606 sc->sc_dev.dv_xname, sc->sc_state, sr, mh); 607 return; 608 } 609 610 /* 611 * now we check the termination class. 612 */ 613 switch (sr & TS_TC) { 614 615 case TS_TC_NORM: 616 /* 617 * Normal termination -- The operation is completed 618 * witout incident. 619 */ 620 if (sc->sc_state == TS_FASTREPOS) { 621#ifdef TSDEBUG 622 printf("Fast repos interrupt\n"); 623#endif 624 /* Fast repos succeeded, start normal data xfer */ 625 sc->sc_state = TS_RUNNING; 626 tsstart(sc, 1); 627 return; 628 } 629 sc->sc_liowf = (ccode == TS_CC_WRITE); 630 break; 631 632 case TS_TC_ATTN: 633 /* 634 * Attention condition -- this code indicates that the 635 * drive has undergone a status change, such as going 636 * off-line or coming on-line. 637 * (Without EAI enabled, no Attention interrupts occur. 638 * drive status changes are signaled by the VCK flag.) 639 */ 640 return; 641 642 case TS_TC_TSA: 643 /* 644 * Tape Status Alert -- A status condition is encountered 645 * that may have significance to the program. Bits of 646 * interest in the extended status registers include 647 * TMK, EOT and RLL. 648 */ 649#ifdef TSDEBUG 650 { 651 char buf[100]; 652 bitmask_snprintf(sc->sc_vts->status.xst0, 653 TS_XST0_BITS, buf, sizeof(buf)); 654 printf("TSA: sr %x bits %s\n", 655 sc->sc_vts->status.xst0, buf); 656 } 657#endif 658 if (sc->sc_vts->status.xst0 & TS_SF_TMK) { 659 /* Read to end-of-file. No error. */ 660 break; 661 } 662 if (sc->sc_vts->status.xst0 & TS_SF_EOT) { 663 /* End of tape. Bad. */ 664#ifdef TSDEBUG 665 printf("TS_TC_TSA: EOT\n"); 666#endif 667 bp->b_flags |= B_ERROR; 668 bp->b_error = EIO; 669 break; 670 } 671 if (sc->sc_vts->status.xst0 & TS_SF_RLS) 672 break; 673 if (sc->sc_vts->status.xst0 & TS_SF_TMK) { 674#ifdef TSDEBUG 675 printf(("Tape Mark detected")); 676#endif 677 } 678 if (sc->sc_vts->status.xst0 & TS_SF_EOT) { 679#ifdef TSDEBUG 680 printf(("End of Tape")); 681#endif 682 } 683#ifndef TSDEBUG 684 { 685 char buf[100]; 686 bitmask_snprintf(sc->sc_vts->status.xst0, 687 TS_XST0_BITS, buf, sizeof(buf)); 688 printf("TSA: sr %x bits %s\n", 689 sc->sc_vts->status.xst0, buf); 690 } 691#endif 692 break; 693 694 case TS_TC_FR: 695 /* 696 * Function Reject -- The specified function was not 697 * initiated. Bits of interest include OFL, VCK, BOT, 698 * WLE, ILC and ILA. 699 */ 700 if (sr & TS_OFL) 701 printf("tape is off-line.\n"); 702#ifdef TSDEBUG 703 { 704 char buf[100]; 705 bitmask_snprintf(sc->sc_vts->status.xst0, 706 TS_XST0_BITS, buf, sizeof(buf)); 707 printf("FR: sr %x bits %s\n", 708 sc->sc_vts->status.xst0, buf); 709 } 710#endif 711 if (sc->sc_vts->status.xst0 & TS_SF_VCK) 712 printf("Volume check\n"); 713 if (sc->sc_vts->status.xst0 & TS_SF_BOT) 714 printf("Start of tape.\n"); 715 if (sc->sc_vts->status.xst0 & TS_SF_WLE) 716 printf("Write Lock Error\n"); 717 if (sc->sc_vts->status.xst0 & TS_SF_EOT) 718 printf("End of tape.\n"); 719 break; 720 721 case TS_TC_TPD: 722 /* 723 * Recoverable Error -- Tape position is a record beyond 724 * what its position was when the function was initiated. 725 * Suggested recovery procedure is to log the error and 726 * issue the appropriate retry command. 727 * 728 * Do a fast repositioning one record back. 729 */ 730 sc->sc_state = TS_FASTREPOS; 731#ifdef TSDEBUG 732 printf("TS_TC_TPD: errcnt %d\n", sc->sc_rtc); 733#endif 734 if (sc->sc_rtc++ == 8) { 735 printf("%s: failed 8 retries\n", XNAME); 736 prtstat(sc, sr); 737 bp->b_flags |= B_ERROR; 738 bp->b_error = EIO; 739 break; 740 } 741 sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_SRR; 742 sc->sc_vts->cmd.cw1 = 1; 743 TS_WCSR(TSDB, sc->sc_waddr); 744 return; 745 746 break; 747 748 case TS_TC_TNM: 749 /* 750 * Recoverable Error -- Tape position has not changed. 751 * Suggested recovery procedure is to log the error and 752 * reissue the original command. 753 */ 754 if (sc->sc_rtc++ == 8) { 755 printf("%s: failed 8 retries\n", XNAME); 756 prtstat(sc, sr); 757 bp->b_flags |= B_ERROR; 758 bp->b_error = EIO; 759 break; 760 } 761 tsstart(sc, 1); 762 return; 763 764 case TS_TC_TPL: 765 /* 766 * Unrecoverable Error -- Tape position has been lost. 767 * No valid recovery procedures exist unless the tape 768 * has labels or sequence numbers. 769 */ 770 printf("Tape position lost\n"); 771 bp->b_flags |= B_ERROR; 772 bp->b_error = EIO; 773 break; 774 775 case TS_TC_FCE: 776 /* 777 * Fatal subsytem Error -- The subsytem is incapable 778 * of properly performing commands, or at least its 779 * integrity is seriously questionable. Refer to the 780 * fatal class code field in the TSSR register for 781 * additional information on the type of fatal error. 782 */ 783 printf ("Fatal Controller Error\n"); 784 prtstat(sc, sr); 785 break; 786 787 default: 788 printf ("%s: error 0x%x, resetting controller\n", 789 sc->sc_dev.dv_xname, sr & TS_TC); 790 tsreset(sc); 791 } 792 if ((bp = BUFQ_GET(&sc->sc_bufq)) != NULL) { 793#ifdef TSDEBUG 794 printf("tsintr2: que %p\n", TAILQ_FIRST(&sc->sc_bufq.bq_head)); 795#endif 796 if (bp != &sc->ts_cbuf) { /* no ioctl */ 797 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmam); 798 uba_done((void *)sc->sc_dev.dv_parent); 799 } 800 bp->b_resid = sc->sc_vts->status.rbpcr; 801 if ((bp->b_flags & B_ERROR) == 0) 802 bp->b_error = 0; 803 biodone (bp); 804 } 805 tsstart(sc, 0); 806} 807 808 809/* 810 * Open a ts device and set the unit online. If the controller is not 811 * in the run state, call init to initialize the ts controller first. 812 */ 813int 814tsopen(dev_t dev, int flag, int type, struct proc *p) 815{ 816 struct ts_softc *sc; 817 int unit = TS_UNIT(dev); 818 819 if (unit >= ts_cd.cd_ndevs) 820 return ENXIO; 821 822 sc = ts_cd.cd_devs[unit]; 823 if (sc == 0) 824 return ENXIO; 825 826 if (sc->sc_state < TS_RUNNING) 827 return ENXIO; 828 829 if (sc->sc_openf) 830 return EBUSY; 831 sc->sc_openf = 1; 832 833 /* 834 * check if transport is really online. 835 * (without attention-interrupts enabled, we really don't know 836 * the actual state of the transport. Thus we call get-status 837 * (ie. MTNOP) once and check the actual status.) 838 */ 839 if (TS_RCSR(TSSR) & TS_OFL) { 840 uprintf("%s: transport is offline.\n", XNAME); 841 sc->sc_openf = 0; 842 return EIO; /* transport is offline */ 843 } 844 tscommand(sc, dev, MTNOP, 1); 845 if ((flag & FWRITE) && (sc->sc_vts->status.xst0 & TS_SF_WLK)) { 846 uprintf("%s: no write ring.\n", XNAME); 847 sc->sc_openf = 0; 848 return EROFS; 849 } 850 if (sc->sc_vts->status.xst0 & TS_SF_VCK) { 851 sc->sc_vts->cmd.cmdr = TS_CF_CVC|TS_CF_ACK; 852 TS_WCSR(TSDB, sc->sc_waddr); 853 } 854 tscommand(sc, dev, MTNOP, 1); 855#ifdef TSDEBUG 856 { 857 char buf[100]; 858 bitmask_snprintf(sc->sc_vts->status.xst0, 859 TS_XST0_BITS, buf, sizeof(buf)); 860 printf("tsopen: xst0 %s\n", buf); 861 } 862#endif 863 sc->sc_liowf = 0; 864 return 0; 865} 866 867 868/* 869 * Close tape device. 870 * 871 * If tape was open for writing or last operation was 872 * a write, then write two EOF's and backspace over the last one. 873 * Unless this is a non-rewinding special file, rewind the tape. 874 * 875 * Make the tape available to others, by clearing openf flag. 876 */ 877int 878tsclose(dev_t dev, int flag, int type, struct proc *p) 879{ 880 struct ts_softc *sc = ts_cd.cd_devs[TS_UNIT(dev)]; 881 882 if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) { 883 /* 884 * We are writing two tape marks (EOT), but place the tape 885 * before the second one, so that another write operation 886 * will overwrite the second one and leave and EOF-mark. 887 */ 888 tscommand(sc, dev, MTWEOF, 1); /* Write Tape Mark */ 889 tscommand(sc, dev, MTWEOF, 1); /* Write Tape Mark */ 890 tscommand(sc, dev, MTBSF, 1); /* Skip Tape Marks Reverse */ 891 } 892 893 if ((dev & T_NOREWIND) == 0) 894 tscommand(sc, dev, MTREW, 0); 895 896 sc->sc_openf = 0; 897 sc->sc_liowf = 0; 898 return 0; 899} 900 901 902/* 903 * Manage buffers and perform block mode read and write operations. 904 */ 905void 906tsstrategy(struct buf *bp) 907{ 908 register int unit = TS_UNIT(bp->b_dev); 909 struct ts_softc *sc = (void *)ts_cd.cd_devs[unit]; 910 int s, empty; 911 912#ifdef TSDEBUG 913 printf("buf: %p bcount %ld blkno %d\n", bp, bp->b_bcount, bp->b_blkno); 914#endif 915 s = splbio (); 916 empty = (BUFQ_PEEK(&sc->sc_bufq) == NULL); 917 BUFQ_PUT(&sc->sc_bufq, bp); 918 if (empty) 919 tsstart(sc, 0); 920 splx(s); 921} 922 923 924/* 925 * Catch ioctl commands, and call the "command" routine to do them. 926 */ 927int 928tsioctl(dev, cmd, data, flag, p) 929 dev_t dev; 930 u_long cmd; 931 caddr_t data; 932 int flag; 933 struct proc *p; 934{ 935 struct buf *bp; 936 struct ts_softc *sc; 937 struct mtop *mtop; /* mag tape cmd op to perform */ 938 struct mtget *mtget; /* mag tape struct to get info in */ 939 int callcount; /* number of times to call routine */ 940 int scount; /* number of files/records to space */ 941 int spaceop = 0; /* flag for skip/space operation */ 942 int error = 0; 943 944#ifdef TSDEBUG 945 printf("tsioctl (%x, %lx, %p, %d)\n", dev, cmd, data, flag); 946#endif 947 948 sc = ts_cd.cd_devs[TS_UNIT(dev)]; 949 bp = &sc->ts_cbuf; 950 951 switch (cmd) { 952 case MTIOCTOP: /* do a mag tape op */ 953 mtop = (struct mtop *)data; 954 switch (mtop->mt_op) { 955 case MTWEOF: /* write an end-of-file record */ 956 callcount = mtop->mt_count; 957 scount = 1; 958 break; 959 case MTFSR: /* forward space record */ 960 case MTBSR: /* backward space record */ 961 spaceop = 1; 962 case MTFSF: /* forward space file */ 963 case MTBSF: /* backward space file */ 964 callcount = 1; 965 scount = mtop->mt_count; 966 break; 967 case MTREW: /* rewind */ 968 case MTOFFL: /* rewind and put the drive offline */ 969 case MTNOP: /* no operation, sets status only */ 970 callcount = 1; 971 scount = 1; /* wait for this rewind */ 972 break; 973 case MTRETEN: /* retension */ 974 case MTERASE: /* erase entire tape */ 975 case MTEOM: /* forward to end of media */ 976 case MTNBSF: /* backward space to begin of file */ 977 case MTCACHE: /* enable controller cache */ 978 case MTNOCACHE: /* disable controller cache */ 979 case MTSETBSIZ: /* set block size; 0 for variable */ 980 case MTSETDNSTY: /* set density code for current mode */ 981 printf("ioctl %d not implemented.\n", mtop->mt_op); 982 return (ENXIO); 983 default: 984#ifdef TSDEBUG 985 printf("invalid ioctl %d\n", mtop->mt_op); 986#endif 987 return (ENXIO); 988 } /* switch (mtop->mt_op) */ 989 990 if (callcount <= 0 || scount <= 0) { 991#ifdef TSDEBUG 992 printf("invalid values %d/%d\n", callcount, scount); 993#endif 994 return (EINVAL); 995 } 996 do { 997 tscommand(sc, dev, mtop->mt_op, scount); 998 if (spaceop && bp->b_resid) { 999#ifdef TSDEBUG 1000 printf(("spaceop didn't complete\n")); 1001#endif 1002 return (EIO); 1003 } 1004 if (bp->b_flags & B_ERROR) { 1005#ifdef TSDEBUG 1006 printf("error in ioctl %d\n", mtop->mt_op); 1007#endif 1008 break; 1009 } 1010 } while (--callcount > 0); 1011 if (bp->b_flags & B_ERROR) 1012 if ((error = bp->b_error) == 0) 1013 return (EIO); 1014 return (error); 1015 1016 case MTIOCGET: /* get tape status */ 1017 mtget = (struct mtget *)data; 1018 mtget->mt_type = MT_ISTS; 1019 mtget->mt_dsreg = TS_RCSR(TSSR); 1020 mtget->mt_erreg = sc->sc_vts->status.xst0; 1021 mtget->mt_resid = 0; /* ??? */ 1022 mtget->mt_density = 0; /* ??? */ 1023 break; 1024 1025 case MTIOCIEOT: /* ignore EOT error */ 1026#ifdef TSDEBUG 1027 printf(("MTIOCIEOT not implemented.\n")); 1028#endif 1029 return (ENXIO); 1030 1031 case MTIOCEEOT: /* enable EOT error */ 1032#ifdef TSDEBUG 1033 printf(("MTIOCEEOT not implemented.\n")); 1034#endif 1035 return (ENXIO); 1036 1037 default: 1038#ifdef TSDEBUG 1039 printf("invalid ioctl cmd 0x%lx\n", cmd); 1040#endif 1041 return (ENXIO); 1042 } 1043 1044 return (0); 1045} 1046 1047 1048/* 1049 * 1050 */ 1051int 1052tsread(dev_t dev, struct uio *uio, int flag) 1053{ 1054 return (physio (tsstrategy, NULL, dev, B_READ, minphys, uio)); 1055} 1056 1057/* 1058 * 1059 */ 1060int 1061tswrite(dev_t dev, struct uio *uio, int flag) 1062{ 1063 return (physio (tsstrategy, NULL, dev, B_WRITE, minphys, uio)); 1064} 1065 1066/* 1067 * 1068 */ 1069int 1070tsdump(dev, blkno, va, size) 1071 dev_t dev; 1072 daddr_t blkno; 1073 caddr_t va; 1074 size_t size; 1075{ 1076 return EIO; 1077} 1078