1 /* $NetBSD: wt.c,v 1.36 1996/10/13 01:38:08 christos Exp $ */ 2 3 /* 4 * Streamer tape driver. 5 * Supports Archive and Wangtek compatible QIC-02/QIC-36 boards. 6 * 7 * Copyright (C) 1993 by: 8 * Sergey Ryzhkov <sir@kiae.su> 9 * Serge Vakulenko <vak@zebub.msk.su> 10 * 11 * This software is distributed with NO WARRANTIES, not even the implied 12 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 * 14 * Authors grant any other persons or organisations permission to use 15 * or modify this software as long as this message is kept with the software, 16 * all derivative works or modified versions. 17 * 18 * This driver is derived from the old 386bsd Wangtek streamer tape driver, 19 * made by Robert Baron at CMU, based on Intel sources. 20 */ 21 22 /* 23 * Copyright (c) 1989 Carnegie-Mellon University. 24 * All rights reserved. 25 * 26 * Authors: Robert Baron 27 * 28 * Permission to use, copy, modify and distribute this software and 29 * its documentation is hereby granted, provided that both the copyright 30 * notice and this permission notice appear in all copies of the 31 * software, derivative works or modified versions, and any portions 32 * thereof, and that both notices appear in supporting documentation. 33 * 34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 35 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 36 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 37 * 38 * Carnegie Mellon requests users of this software to return to 39 * 40 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 41 * School of Computer Science 42 * Carnegie Mellon University 43 * Pittsburgh PA 15213-3890 44 * 45 * any improvements or extensions that they make and grant Carnegie the 46 * rights to redistribute these changes. 47 */ 48 49 /* 50 * Copyright 1988, 1989 by Intel Corporation 51 */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/buf.h> 57 #include <sys/fcntl.h> 58 #include <sys/malloc.h> 59 #include <sys/ioctl.h> 60 #include <sys/mtio.h> 61 #include <sys/device.h> 62 #include <sys/proc.h> 63 #include <sys/conf.h> 64 65 #include <vm/vm_param.h> 66 67 #include <machine/intr.h> 68 #include <machine/pio.h> 69 70 #include <dev/isa/isavar.h> 71 #include <dev/isa/isadmavar.h> 72 #include <dev/isa/wtreg.h> 73 74 /* 75 * Uncomment this to enable internal device tracing. 76 */ 77 #define WTDBPRINT(x) /* printf x */ 78 79 #define WTPRI (PZERO+10) /* sleep priority */ 80 81 /* 82 * Wangtek controller ports 83 */ 84 #define WT_CTLPORT(base) ((base)+0) /* control, write only */ 85 #define WT_STATPORT(base) ((base)+0) /* status, read only */ 86 #define WT_CMDPORT(base) ((base)+1) /* command, write only */ 87 #define WT_DATAPORT(base) ((base)+1) /* data, read only */ 88 #define WT_NPORT 2 /* 2 i/o ports */ 89 90 /* status port bits */ 91 #define WT_BUSY 0x01 /* not ready bit define */ 92 #define WT_NOEXCEP 0x02 /* no exception bit define */ 93 #define WT_RESETMASK 0x07 /* to check after reset */ 94 #define WT_RESETVAL 0x05 /* state after reset */ 95 96 /* control port bits */ 97 #define WT_ONLINE 0x01 /* device selected */ 98 #define WT_RESET 0x02 /* reset command */ 99 #define WT_REQUEST 0x04 /* request command */ 100 #define WT_IEN 0x08 /* enable dma */ 101 102 /* 103 * Archive controller ports 104 */ 105 #define AV_DATAPORT(base) ((base)+0) /* data, read only */ 106 #define AV_CMDPORT(base) ((base)+0) /* command, write only */ 107 #define AV_STATPORT(base) ((base)+1) /* status, read only */ 108 #define AV_CTLPORT(base) ((base)+1) /* control, write only */ 109 #define AV_SDMAPORT(base) ((base)+2) /* start dma */ 110 #define AV_RDMAPORT(base) ((base)+3) /* reset dma */ 111 #define AV_NPORT 4 /* 4 i/o ports */ 112 113 /* status port bits */ 114 #define AV_BUSY 0x40 /* not ready bit define */ 115 #define AV_NOEXCEP 0x20 /* no exception bit define */ 116 #define AV_RESETMASK 0xf8 /* to check after reset */ 117 #define AV_RESETVAL 0x50 /* state after reset */ 118 119 /* control port bits */ 120 #define AV_RESET 0x80 /* reset command */ 121 #define AV_REQUEST 0x40 /* request command */ 122 #define AV_IEN 0x20 /* enable interrupts */ 123 124 enum wttype { 125 UNKNOWN = 0, /* unknown type, driver disabled */ 126 ARCHIVE, /* Archive Viper SC499, SC402 etc */ 127 WANGTEK, /* Wangtek */ 128 }; 129 130 struct wt_softc { 131 struct device sc_dev; 132 void *sc_ih; 133 134 enum wttype type; /* type of controller */ 135 int sc_iobase; /* base i/o port */ 136 int chan; /* dma channel number, 1..3 */ 137 int flags; /* state of tape drive */ 138 unsigned dens; /* tape density */ 139 int bsize; /* tape block size */ 140 void *buf; /* internal i/o buffer */ 141 142 void *dmavaddr; /* virtual address of dma i/o buffer */ 143 size_t dmatotal; /* size of i/o buffer */ 144 int dmaflags; /* i/o direction */ 145 size_t dmacount; /* resulting length of dma i/o */ 146 147 u_short error; /* code for error encountered */ 148 u_short ercnt; /* number of error blocks */ 149 u_short urcnt; /* number of underruns */ 150 151 int DATAPORT, CMDPORT, STATPORT, CTLPORT, SDMAPORT, RDMAPORT; 152 u_char BUSY, NOEXCEP, RESETMASK, RESETVAL, ONLINE, RESET, REQUEST, IEN; 153 }; 154 155 /* XXX: These don't belong here really */ 156 cdev_decl(wt); 157 bdev_decl(wt); 158 159 int wtwait __P((struct wt_softc *sc, int catch, char *msg)); 160 int wtcmd __P((struct wt_softc *sc, int cmd)); 161 int wtstart __P((struct wt_softc *sc, int flag, void *vaddr, size_t len)); 162 void wtdma __P((struct wt_softc *sc)); 163 void wttimer __P((void *arg)); 164 void wtclock __P((struct wt_softc *sc)); 165 int wtreset __P((struct wt_softc *sc)); 166 int wtsense __P((struct wt_softc *sc, int verbose, int ignore)); 167 int wtstatus __P((struct wt_softc *sc)); 168 void wtrewind __P((struct wt_softc *sc)); 169 int wtreadfm __P((struct wt_softc *sc)); 170 int wtwritefm __P((struct wt_softc *sc)); 171 u_char wtsoft __P((struct wt_softc *sc, int mask, int bits)); 172 173 int wtprobe __P((struct device *, void *, void *)); 174 void wtattach __P((struct device *, struct device *, void *)); 175 int wtintr __P((void *sc)); 176 177 struct cfattach wt_ca = { 178 sizeof(struct wt_softc), wtprobe, wtattach 179 }; 180 181 struct cfdriver wt_cd = { 182 NULL, "wt", DV_TAPE 183 }; 184 185 /* 186 * Probe for the presence of the device. 187 */ 188 int 189 wtprobe(parent, match, aux) 190 struct device *parent; 191 void *match, *aux; 192 { 193 struct wt_softc *sc = match; 194 struct isa_attach_args *ia = aux; 195 int iobase; 196 197 sc->chan = ia->ia_drq; 198 sc->sc_iobase = iobase = ia->ia_iobase; 199 if (sc->chan < 1 || sc->chan > 3) { 200 printf("%s: Bad drq=%d, should be 1..3\n", sc->sc_dev.dv_xname, 201 sc->chan); 202 return 0; 203 } 204 205 /* Try Wangtek. */ 206 sc->type = WANGTEK; 207 sc->CTLPORT = WT_CTLPORT(iobase); 208 sc->STATPORT = WT_STATPORT(iobase); 209 sc->CMDPORT = WT_CMDPORT(iobase); 210 sc->DATAPORT = WT_DATAPORT(iobase); 211 sc->SDMAPORT = sc->RDMAPORT = 0; 212 sc->BUSY = WT_BUSY; sc->NOEXCEP = WT_NOEXCEP; 213 sc->RESETMASK = WT_RESETMASK; sc->RESETVAL = WT_RESETVAL; 214 sc->ONLINE = WT_ONLINE; sc->RESET = WT_RESET; 215 sc->REQUEST = WT_REQUEST; sc->IEN = WT_IEN; 216 if (wtreset(sc)) { 217 ia->ia_iosize = WT_NPORT; 218 return 1; 219 } 220 221 /* Try Archive. */ 222 sc->type = ARCHIVE; 223 sc->CTLPORT = AV_CTLPORT(iobase); 224 sc->STATPORT = AV_STATPORT(iobase); 225 sc->CMDPORT = AV_CMDPORT(iobase); 226 sc->DATAPORT = AV_DATAPORT(iobase); 227 sc->SDMAPORT = AV_SDMAPORT(iobase); 228 sc->RDMAPORT = AV_RDMAPORT(iobase); 229 sc->BUSY = AV_BUSY; sc->NOEXCEP = AV_NOEXCEP; 230 sc->RESETMASK = AV_RESETMASK; sc->RESETVAL = AV_RESETVAL; 231 sc->ONLINE = 0; sc->RESET = AV_RESET; 232 sc->REQUEST = AV_REQUEST; sc->IEN = AV_IEN; 233 if (wtreset(sc)) { 234 ia->ia_iosize = AV_NPORT; 235 return 1; 236 } 237 238 /* Tape controller not found. */ 239 sc->type = UNKNOWN; 240 return 0; 241 } 242 243 /* 244 * Device is found, configure it. 245 */ 246 void 247 wtattach(parent, self, aux) 248 struct device *parent, *self; 249 void *aux; 250 { 251 struct wt_softc *sc = (void *)self; 252 struct isa_attach_args *ia = aux; 253 254 if (sc->type == ARCHIVE) { 255 printf(": type <Archive>\n"); 256 /* Reset DMA. */ 257 outb(sc->RDMAPORT, 0); 258 } else 259 printf(": type <Wangtek>\n"); 260 sc->flags = TPSTART; /* tape is rewound */ 261 sc->dens = -1; /* unknown density */ 262 263 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 264 IPL_BIO, wtintr, sc); 265 } 266 267 int 268 wtdump(dev, blkno, va, size) 269 dev_t dev; 270 daddr_t blkno; 271 caddr_t va; 272 size_t size; 273 { 274 275 /* Not implemented. */ 276 return ENXIO; 277 } 278 279 int 280 wtsize(dev) 281 dev_t dev; 282 { 283 284 /* Not implemented. */ 285 return -1; 286 } 287 288 /* 289 * Open routine, called on every device open. 290 */ 291 int 292 wtopen(dev, flag, mode, p) 293 dev_t dev; 294 int flag; 295 int mode; 296 struct proc *p; 297 { 298 int unit = minor(dev) & T_UNIT; 299 struct wt_softc *sc; 300 int error; 301 302 if (unit >= wt_cd.cd_ndevs) 303 return ENXIO; 304 sc = wt_cd.cd_devs[unit]; 305 if (!sc) 306 return ENXIO; 307 308 /* Check that device is not in use */ 309 if (sc->flags & TPINUSE) 310 return EBUSY; 311 312 /* If the tape is in rewound state, check the status and set density. */ 313 if (sc->flags & TPSTART) { 314 /* If rewind is going on, wait */ 315 if ((error = wtwait(sc, PCATCH, "wtrew")) != 0) 316 return error; 317 318 /* Check the controller status */ 319 if (!wtsense(sc, 0, (flag & FWRITE) ? 0 : TP_WRP)) { 320 /* Bad status, reset the controller. */ 321 if (!wtreset(sc)) 322 return EIO; 323 if (!wtsense(sc, 1, (flag & FWRITE) ? 0 : TP_WRP)) 324 return EIO; 325 } 326 327 /* Set up tape density. */ 328 if (sc->dens != (minor(dev) & WT_DENSEL)) { 329 int d = 0; 330 331 switch (minor(dev) & WT_DENSEL) { 332 case WT_DENSDFLT: 333 default: 334 break; /* default density */ 335 case WT_QIC11: 336 d = QIC_FMT11; break; /* minor 010 */ 337 case WT_QIC24: 338 d = QIC_FMT24; break; /* minor 020 */ 339 case WT_QIC120: 340 d = QIC_FMT120; break; /* minor 030 */ 341 case WT_QIC150: 342 d = QIC_FMT150; break; /* minor 040 */ 343 case WT_QIC300: 344 d = QIC_FMT300; break; /* minor 050 */ 345 case WT_QIC600: 346 d = QIC_FMT600; break; /* minor 060 */ 347 } 348 if (d) { 349 /* Change tape density. */ 350 if (!wtcmd(sc, d)) 351 return EIO; 352 if (!wtsense(sc, 1, TP_WRP | TP_ILL)) 353 return EIO; 354 355 /* Check the status of the controller. */ 356 if (sc->error & TP_ILL) { 357 printf("%s: invalid tape density\n", 358 sc->sc_dev.dv_xname); 359 return ENODEV; 360 } 361 } 362 sc->dens = minor(dev) & WT_DENSEL; 363 } 364 sc->flags &= ~TPSTART; 365 } else if (sc->dens != (minor(dev) & WT_DENSEL)) 366 return ENXIO; 367 368 sc->bsize = (minor(dev) & WT_BSIZE) ? 1024 : 512; 369 sc->buf = malloc(sc->bsize, M_TEMP, M_WAITOK); 370 371 sc->flags = TPINUSE; 372 if (flag & FREAD) 373 sc->flags |= TPREAD; 374 if (flag & FWRITE) 375 sc->flags |= TPWRITE; 376 return 0; 377 } 378 379 /* 380 * Close routine, called on last device close. 381 */ 382 int 383 wtclose(dev, flags, mode, p) 384 dev_t dev; 385 int flags; 386 int mode; 387 struct proc *p; 388 { 389 int unit = minor(dev) & T_UNIT; 390 struct wt_softc *sc = wt_cd.cd_devs[unit]; 391 392 /* If rewind is pending, do nothing */ 393 if (sc->flags & TPREW) 394 goto done; 395 396 /* If seek forward is pending and no rewind on close, do nothing */ 397 if (sc->flags & TPRMARK) { 398 if (minor(dev) & T_NOREWIND) 399 goto done; 400 401 /* If read file mark is going on, wait */ 402 wtwait(sc, 0, "wtrfm"); 403 } 404 405 if (sc->flags & TPWANY) { 406 /* Tape was written. Write file mark. */ 407 wtwritefm(sc); 408 } 409 410 if ((minor(dev) & T_NOREWIND) == 0) { 411 /* Rewind to beginning of tape. */ 412 /* Don't wait until rewind, though. */ 413 wtrewind(sc); 414 goto done; 415 } 416 if ((sc->flags & TPRANY) && (sc->flags & (TPVOL | TPWANY)) == 0) { 417 /* Space forward to after next file mark if no writing done. */ 418 /* Don't wait for completion. */ 419 wtreadfm(sc); 420 } 421 422 done: 423 sc->flags &= TPREW | TPRMARK | TPSTART | TPTIMER; 424 free(sc->buf, M_TEMP); 425 return 0; 426 } 427 428 /* 429 * Ioctl routine. Compatible with BSD ioctls. 430 * Direct QIC-02 commands ERASE and RETENSION added. 431 * There are three possible ioctls: 432 * ioctl(int fd, MTIOCGET, struct mtget *buf) -- get status 433 * ioctl(int fd, MTIOCTOP, struct mtop *buf) -- do BSD-like op 434 * ioctl(int fd, WTQICMD, int qicop) -- do QIC op 435 */ 436 int 437 wtioctl(dev, cmd, addr, flag, p) 438 dev_t dev; 439 u_long cmd; 440 caddr_t addr; 441 int flag; 442 struct proc *p; 443 { 444 int unit = minor(dev) & T_UNIT; 445 struct wt_softc *sc = wt_cd.cd_devs[unit]; 446 int error, count, op; 447 448 switch (cmd) { 449 default: 450 return EINVAL; 451 case WTQICMD: /* direct QIC command */ 452 op = *(int *)addr; 453 switch (op) { 454 default: 455 return EINVAL; 456 case QIC_ERASE: /* erase the whole tape */ 457 if ((sc->flags & TPWRITE) == 0 || (sc->flags & TPWP)) 458 return EACCES; 459 if ((error = wtwait(sc, PCATCH, "wterase")) != 0) 460 return error; 461 break; 462 case QIC_RETENS: /* retension the tape */ 463 if ((error = wtwait(sc, PCATCH, "wtretens")) != 0) 464 return error; 465 break; 466 } 467 /* Both ERASE and RETENS operations work like REWIND. */ 468 /* Simulate the rewind operation here. */ 469 sc->flags &= ~(TPRO | TPWO | TPVOL); 470 if (!wtcmd(sc, op)) 471 return EIO; 472 sc->flags |= TPSTART | TPREW; 473 if (op == QIC_ERASE) 474 sc->flags |= TPWANY; 475 wtclock(sc); 476 return 0; 477 case MTIOCIEOT: /* ignore EOT errors */ 478 case MTIOCEEOT: /* enable EOT errors */ 479 return 0; 480 case MTIOCGET: 481 ((struct mtget*)addr)->mt_type = 482 sc->type == ARCHIVE ? MT_ISVIPER1 : 0x11; 483 ((struct mtget*)addr)->mt_dsreg = sc->flags; /* status */ 484 ((struct mtget*)addr)->mt_erreg = sc->error; /* errors */ 485 ((struct mtget*)addr)->mt_resid = 0; 486 ((struct mtget*)addr)->mt_fileno = 0; /* file */ 487 ((struct mtget*)addr)->mt_blkno = 0; /* block */ 488 return 0; 489 case MTIOCTOP: 490 break; 491 } 492 493 switch ((short)((struct mtop*)addr)->mt_op) { 494 default: 495 #if 0 496 case MTFSR: /* forward space record */ 497 case MTBSR: /* backward space record */ 498 case MTBSF: /* backward space file */ 499 #endif 500 return EINVAL; 501 case MTNOP: /* no operation, sets status only */ 502 case MTCACHE: /* enable controller cache */ 503 case MTNOCACHE: /* disable controller cache */ 504 return 0; 505 case MTREW: /* rewind */ 506 case MTOFFL: /* rewind and put the drive offline */ 507 if (sc->flags & TPREW) /* rewind is running */ 508 return 0; 509 if ((error = wtwait(sc, PCATCH, "wtorew")) != 0) 510 return error; 511 wtrewind(sc); 512 return 0; 513 case MTFSF: /* forward space file */ 514 for (count = ((struct mtop*)addr)->mt_count; count > 0; 515 --count) { 516 if ((error = wtwait(sc, PCATCH, "wtorfm")) != 0) 517 return error; 518 if ((error = wtreadfm(sc)) != 0) 519 return error; 520 } 521 return 0; 522 case MTWEOF: /* write an end-of-file record */ 523 if ((sc->flags & TPWRITE) == 0 || (sc->flags & TPWP)) 524 return EACCES; 525 if ((error = wtwait(sc, PCATCH, "wtowfm")) != 0) 526 return error; 527 if ((error = wtwritefm(sc)) != 0) 528 return error; 529 return 0; 530 } 531 532 #ifdef DIAGNOSTIC 533 panic("wtioctl: impossible"); 534 #endif 535 } 536 537 /* 538 * Strategy routine. 539 */ 540 void 541 wtstrategy(bp) 542 struct buf *bp; 543 { 544 int unit = minor(bp->b_dev) & T_UNIT; 545 struct wt_softc *sc = wt_cd.cd_devs[unit]; 546 int s; 547 548 bp->b_resid = bp->b_bcount; 549 550 /* at file marks and end of tape, we just return '0 bytes available' */ 551 if (sc->flags & TPVOL) 552 goto xit; 553 554 if (bp->b_flags & B_READ) { 555 /* Check read access and no previous write to this tape. */ 556 if ((sc->flags & TPREAD) == 0 || (sc->flags & TPWANY)) 557 goto errxit; 558 559 /* For now, we assume that all data will be copied out */ 560 /* If read command outstanding, just skip down */ 561 if ((sc->flags & TPRO) == 0) { 562 if (!wtsense(sc, 1, TP_WRP)) { 563 /* Clear status. */ 564 goto errxit; 565 } 566 if (!wtcmd(sc, QIC_RDDATA)) { 567 /* Set read mode. */ 568 wtsense(sc, 1, TP_WRP); 569 goto errxit; 570 } 571 sc->flags |= TPRO | TPRANY; 572 } 573 } else { 574 /* Check write access and write protection. */ 575 /* No previous read from this tape allowed. */ 576 if ((sc->flags & TPWRITE) == 0 || (sc->flags & (TPWP | TPRANY))) 577 goto errxit; 578 579 /* If write command outstanding, just skip down */ 580 if ((sc->flags & TPWO) == 0) { 581 if (!wtsense(sc, 1, 0)) { 582 /* Clear status. */ 583 goto errxit; 584 } 585 if (!wtcmd(sc, QIC_WRTDATA)) { 586 /* Set write mode. */ 587 wtsense(sc, 1, 0); 588 goto errxit; 589 } 590 sc->flags |= TPWO | TPWANY; 591 } 592 } 593 594 if (bp->b_bcount == 0) 595 goto xit; 596 597 sc->flags &= ~TPEXCEP; 598 s = splbio(); 599 if (wtstart(sc, bp->b_flags, bp->b_data, bp->b_bcount)) { 600 wtwait(sc, 0, (bp->b_flags & B_READ) ? "wtread" : "wtwrite"); 601 bp->b_resid -= sc->dmacount; 602 } 603 splx(s); 604 605 if (sc->flags & TPEXCEP) { 606 errxit: 607 bp->b_flags |= B_ERROR; 608 bp->b_error = EIO; 609 } 610 xit: 611 biodone(bp); 612 return; 613 } 614 615 int 616 wtread(dev, uio, flags) 617 dev_t dev; 618 struct uio *uio; 619 int flags; 620 { 621 622 return (physio(wtstrategy, NULL, dev, B_READ, minphys, uio)); 623 } 624 625 int 626 wtwrite(dev, uio, flags) 627 dev_t dev; 628 struct uio *uio; 629 int flags; 630 { 631 632 return (physio(wtstrategy, NULL, dev, B_WRITE, minphys, uio)); 633 } 634 635 /* 636 * Interrupt routine. 637 */ 638 int 639 wtintr(arg) 640 void *arg; 641 { 642 struct wt_softc *sc = arg; 643 u_char x; 644 645 x = inb(sc->STATPORT); /* get status */ 646 WTDBPRINT(("wtintr() status=0x%x -- ", x)); 647 if ((x & (sc->BUSY | sc->NOEXCEP)) == (sc->BUSY | sc->NOEXCEP)) { 648 WTDBPRINT(("busy\n")); 649 return 0; /* device is busy */ 650 } 651 652 /* 653 * Check if rewind finished. 654 */ 655 if (sc->flags & TPREW) { 656 WTDBPRINT(((x & (sc->BUSY | sc->NOEXCEP)) == (sc->BUSY | sc->NOEXCEP) ? 657 "rewind busy?\n" : "rewind finished\n")); 658 sc->flags &= ~TPREW; /* rewind finished */ 659 wtsense(sc, 1, TP_WRP); 660 wakeup((caddr_t)sc); 661 return 1; 662 } 663 664 /* 665 * Check if writing/reading of file mark finished. 666 */ 667 if (sc->flags & (TPRMARK | TPWMARK)) { 668 WTDBPRINT(((x & (sc->BUSY | sc->NOEXCEP)) == (sc->BUSY | sc->NOEXCEP) ? 669 "marker r/w busy?\n" : "marker r/w finished\n")); 670 if ((x & sc->NOEXCEP) == 0) /* operation failed */ 671 wtsense(sc, 1, (sc->flags & TPRMARK) ? TP_WRP : 0); 672 sc->flags &= ~(TPRMARK | TPWMARK); /* operation finished */ 673 wakeup((caddr_t)sc); 674 return 1; 675 } 676 677 /* 678 * Do we started any i/o? If no, just return. 679 */ 680 if ((sc->flags & TPACTIVE) == 0) { 681 WTDBPRINT(("unexpected interrupt\n")); 682 return 0; 683 } 684 sc->flags &= ~TPACTIVE; 685 sc->dmacount += sc->bsize; /* increment counter */ 686 687 /* 688 * Clean up dma. 689 */ 690 if ((sc->dmaflags & DMAMODE_READ) && 691 (sc->dmatotal - sc->dmacount) < sc->bsize) { 692 /* If reading short block, copy the internal buffer 693 * to the user memory. */ 694 isa_dmadone(sc->dmaflags, sc->buf, sc->bsize, sc->chan); 695 bcopy(sc->buf, sc->dmavaddr, sc->dmatotal - sc->dmacount); 696 } else 697 isa_dmadone(sc->dmaflags, sc->dmavaddr, sc->bsize, sc->chan); 698 699 /* 700 * On exception, check for end of file and end of volume. 701 */ 702 if ((x & sc->NOEXCEP) == 0) { 703 WTDBPRINT(("i/o exception\n")); 704 wtsense(sc, 1, (sc->dmaflags & DMAMODE_READ) ? TP_WRP : 0); 705 if (sc->error & (TP_EOM | TP_FIL)) 706 sc->flags |= TPVOL; /* end of file */ 707 else 708 sc->flags |= TPEXCEP; /* i/o error */ 709 wakeup((caddr_t)sc); 710 return 1; 711 } 712 713 if (sc->dmacount < sc->dmatotal) { 714 /* Continue I/O. */ 715 sc->dmavaddr += sc->bsize; 716 wtdma(sc); 717 WTDBPRINT(("continue i/o, %d\n", sc->dmacount)); 718 return 1; 719 } 720 if (sc->dmacount > sc->dmatotal) /* short last block */ 721 sc->dmacount = sc->dmatotal; 722 /* Wake up user level. */ 723 wakeup((caddr_t)sc); 724 WTDBPRINT(("i/o finished, %d\n", sc->dmacount)); 725 return 1; 726 } 727 728 /* start the rewind operation */ 729 void 730 wtrewind(sc) 731 struct wt_softc *sc; 732 { 733 int rwmode = sc->flags & (TPRO | TPWO); 734 735 sc->flags &= ~(TPRO | TPWO | TPVOL); 736 /* 737 * Wangtek strictly follows QIC-02 standard: 738 * clearing ONLINE in read/write modes causes rewind. 739 * REWIND command is not allowed in read/write mode 740 * and gives `illegal command' error. 741 */ 742 if (sc->type == WANGTEK && rwmode) { 743 outb(sc->CTLPORT, 0); 744 } else if (!wtcmd(sc, QIC_REWIND)) 745 return; 746 sc->flags |= TPSTART | TPREW; 747 wtclock(sc); 748 } 749 750 /* 751 * Start the `read marker' operation. 752 */ 753 int 754 wtreadfm(sc) 755 struct wt_softc *sc; 756 { 757 758 sc->flags &= ~(TPRO | TPWO | TPVOL); 759 if (!wtcmd(sc, QIC_READFM)) { 760 wtsense(sc, 1, TP_WRP); 761 return EIO; 762 } 763 sc->flags |= TPRMARK | TPRANY; 764 wtclock(sc); 765 /* Don't wait for completion here. */ 766 return 0; 767 } 768 769 /* 770 * Write marker to the tape. 771 */ 772 int 773 wtwritefm(sc) 774 struct wt_softc *sc; 775 { 776 777 tsleep((caddr_t)wtwritefm, WTPRI, "wtwfm", hz); 778 sc->flags &= ~(TPRO | TPWO); 779 if (!wtcmd(sc, QIC_WRITEFM)) { 780 wtsense(sc, 1, 0); 781 return EIO; 782 } 783 sc->flags |= TPWMARK | TPWANY; 784 wtclock(sc); 785 return wtwait(sc, 0, "wtwfm"); 786 } 787 788 /* 789 * While controller status & mask == bits continue waiting. 790 */ 791 u_char 792 wtsoft(sc, mask, bits) 793 struct wt_softc *sc; 794 int mask, bits; 795 { 796 u_char x; 797 int i; 798 799 /* Poll status port, waiting for specified bits. */ 800 for (i = 0; i < 1000; ++i) { /* up to 1 msec */ 801 x = inb(sc->STATPORT); 802 if ((x & mask) != bits) 803 return x; 804 delay(1); 805 } 806 for (i = 0; i < 100; ++i) { /* up to 10 msec */ 807 x = inb(sc->STATPORT); 808 if ((x & mask) != bits) 809 return x; 810 delay(100); 811 } 812 for (;;) { /* forever */ 813 x = inb(sc->STATPORT); 814 if ((x & mask) != bits) 815 return x; 816 tsleep((caddr_t)wtsoft, WTPRI, "wtsoft", 1); 817 } 818 } 819 820 /* 821 * Execute QIC command. 822 */ 823 int 824 wtcmd(sc, cmd) 825 struct wt_softc *sc; 826 int cmd; 827 { 828 u_char x; 829 int s; 830 831 WTDBPRINT(("wtcmd() cmd=0x%x\n", cmd)); 832 s = splbio(); 833 x = wtsoft(sc, sc->BUSY | sc->NOEXCEP, sc->BUSY | sc->NOEXCEP); /* ready? */ 834 if ((x & sc->NOEXCEP) == 0) { /* error */ 835 splx(s); 836 return 0; 837 } 838 839 outb(sc->CMDPORT, cmd); /* output the command */ 840 841 outb(sc->CTLPORT, sc->REQUEST | sc->ONLINE); /* set request */ 842 wtsoft(sc, sc->BUSY, sc->BUSY); /* wait for ready */ 843 outb(sc->CTLPORT, sc->IEN | sc->ONLINE); /* reset request */ 844 wtsoft(sc, sc->BUSY, 0); /* wait for not ready */ 845 splx(s); 846 return 1; 847 } 848 849 /* wait for the end of i/o, seeking marker or rewind operation */ 850 int 851 wtwait(sc, catch, msg) 852 struct wt_softc *sc; 853 int catch; 854 char *msg; 855 { 856 int error; 857 858 WTDBPRINT(("wtwait() `%s'\n", msg)); 859 while (sc->flags & (TPACTIVE | TPREW | TPRMARK | TPWMARK)) 860 if ((error = tsleep((caddr_t)sc, WTPRI | catch, msg, 0)) != 0) 861 return error; 862 return 0; 863 } 864 865 /* initialize dma for the i/o operation */ 866 void 867 wtdma(sc) 868 struct wt_softc *sc; 869 { 870 871 sc->flags |= TPACTIVE; 872 wtclock(sc); 873 874 if (sc->type == ARCHIVE) { 875 /* Set DMA. */ 876 outb(sc->SDMAPORT, 0); 877 } 878 879 if ((sc->dmaflags & DMAMODE_READ) && 880 (sc->dmatotal - sc->dmacount) < sc->bsize) { 881 /* Reading short block; do it through the internal buffer. */ 882 isa_dmastart(sc->dmaflags, sc->buf, sc->bsize, sc->chan); 883 } else 884 isa_dmastart(sc->dmaflags, sc->dmavaddr, sc->bsize, sc->chan); 885 } 886 887 /* start i/o operation */ 888 int 889 wtstart(sc, flag, vaddr, len) 890 struct wt_softc *sc; 891 int flag; 892 void *vaddr; 893 size_t len; 894 { 895 u_char x; 896 897 WTDBPRINT(("wtstart()\n")); 898 x = wtsoft(sc, sc->BUSY | sc->NOEXCEP, sc->BUSY | sc->NOEXCEP); /* ready? */ 899 if ((x & sc->NOEXCEP) == 0) { 900 sc->flags |= TPEXCEP; /* error */ 901 return 0; 902 } 903 sc->flags &= ~TPEXCEP; /* clear exception flag */ 904 sc->dmavaddr = vaddr; 905 sc->dmatotal = len; 906 sc->dmacount = 0; 907 sc->dmaflags = flag & B_READ ? DMAMODE_READ : DMAMODE_WRITE; 908 wtdma(sc); 909 return 1; 910 } 911 912 /* 913 * Start timer. 914 */ 915 void 916 wtclock(sc) 917 struct wt_softc *sc; 918 { 919 920 if (sc->flags & TPTIMER) 921 return; 922 sc->flags |= TPTIMER; 923 /* 924 * Some controllers seem to lose dma interrupts too often. To make the 925 * tape stream we need 1 tick timeout. 926 */ 927 timeout(wttimer, sc, (sc->flags & TPACTIVE) ? 1 : hz); 928 } 929 930 /* 931 * Simulate an interrupt periodically while i/o is going. 932 * This is necessary in case interrupts get eaten due to 933 * multiple devices on a single IRQ line. 934 */ 935 void 936 wttimer(arg) 937 void *arg; 938 { 939 struct wt_softc *sc = (struct wt_softc *)arg; 940 int s; 941 942 sc->flags &= ~TPTIMER; 943 if ((sc->flags & (TPACTIVE | TPREW | TPRMARK | TPWMARK)) == 0) 944 return; 945 946 /* If i/o going, simulate interrupt. */ 947 s = splbio(); 948 if ((inb(sc->STATPORT) & (sc->BUSY | sc->NOEXCEP)) != (sc->BUSY | sc->NOEXCEP)) { 949 WTDBPRINT(("wttimer() -- ")); 950 wtintr(sc); 951 } 952 splx(s); 953 954 /* Restart timer if i/o pending. */ 955 if (sc->flags & (TPACTIVE | TPREW | TPRMARK | TPWMARK)) 956 wtclock(sc); 957 } 958 959 /* 960 * Perform QIC-02 and QIC-36 compatible reset sequence. 961 */ 962 int 963 wtreset(sc) 964 struct wt_softc *sc; 965 { 966 u_char x; 967 int i; 968 969 outb(sc->CTLPORT, sc->RESET | sc->ONLINE); /* send reset */ 970 delay(30); 971 outb(sc->CTLPORT, sc->ONLINE); /* turn off reset */ 972 delay(30); 973 974 /* Read the controller status. */ 975 x = inb(sc->STATPORT); 976 if (x == 0xff) /* no port at this address? */ 977 return 0; 978 979 /* Wait 3 sec for reset to complete. Needed for QIC-36 boards? */ 980 for (i = 0; i < 3000; ++i) { 981 if ((x & sc->BUSY) == 0 || (x & sc->NOEXCEP) == 0) 982 break; 983 delay(1000); 984 x = inb(sc->STATPORT); 985 } 986 return (x & sc->RESETMASK) == sc->RESETVAL; 987 } 988 989 /* 990 * Get controller status information. Return 0 if user i/o request should 991 * receive an i/o error code. 992 */ 993 int 994 wtsense(sc, verbose, ignore) 995 struct wt_softc *sc; 996 int verbose, ignore; 997 { 998 char *msg = 0; 999 int error; 1000 1001 WTDBPRINT(("wtsense() ignore=0x%x\n", ignore)); 1002 sc->flags &= ~(TPRO | TPWO); 1003 if (!wtstatus(sc)) 1004 return 0; 1005 if ((sc->error & TP_ST0) == 0) 1006 sc->error &= ~TP_ST0MASK; 1007 if ((sc->error & TP_ST1) == 0) 1008 sc->error &= ~TP_ST1MASK; 1009 sc->error &= ~ignore; /* ignore certain errors */ 1010 error = sc->error & (TP_FIL | TP_BNL | TP_UDA | TP_EOM | TP_WRP | 1011 TP_USL | TP_CNI | TP_MBD | TP_NDT | TP_ILL); 1012 if (!error) 1013 return 1; 1014 if (!verbose) 1015 return 0; 1016 1017 /* lifted from tdriver.c from Wangtek */ 1018 if (error & TP_USL) 1019 msg = "Drive not online"; 1020 else if (error & TP_CNI) 1021 msg = "No cartridge"; 1022 else if ((error & TP_WRP) && (sc->flags & TPWP) == 0) { 1023 msg = "Tape is write protected"; 1024 sc->flags |= TPWP; 1025 } else if (error & TP_FIL) 1026 msg = 0 /*"Filemark detected"*/; 1027 else if (error & TP_EOM) 1028 msg = 0 /*"End of tape"*/; 1029 else if (error & TP_BNL) 1030 msg = "Block not located"; 1031 else if (error & TP_UDA) 1032 msg = "Unrecoverable data error"; 1033 else if (error & TP_NDT) 1034 msg = "No data detected"; 1035 else if (error & TP_ILL) 1036 msg = "Illegal command"; 1037 if (msg) 1038 printf("%s: %s\n", sc->sc_dev.dv_xname, msg); 1039 return 0; 1040 } 1041 1042 /* 1043 * Get controller status information. 1044 */ 1045 int 1046 wtstatus(sc) 1047 struct wt_softc *sc; 1048 { 1049 char *p; 1050 int s; 1051 1052 s = splbio(); 1053 wtsoft(sc, sc->BUSY | sc->NOEXCEP, sc->BUSY | sc->NOEXCEP); /* ready? */ 1054 outb(sc->CMDPORT, QIC_RDSTAT); /* send `read status' command */ 1055 1056 outb(sc->CTLPORT, sc->REQUEST | sc->ONLINE); /* set request */ 1057 wtsoft(sc, sc->BUSY, sc->BUSY); /* wait for ready */ 1058 outb(sc->CTLPORT, sc->ONLINE); /* reset request */ 1059 wtsoft(sc, sc->BUSY, 0); /* wait for not ready */ 1060 1061 p = (char *)&sc->error; 1062 while (p < (char *)&sc->error + 6) { 1063 u_char x = wtsoft(sc, sc->BUSY | sc->NOEXCEP, sc->BUSY | sc->NOEXCEP); 1064 if ((x & sc->NOEXCEP) == 0) { /* error */ 1065 splx(s); 1066 return 0; 1067 } 1068 1069 *p++ = inb(sc->DATAPORT); /* read status byte */ 1070 1071 outb(sc->CTLPORT, sc->REQUEST | sc->ONLINE); /* set request */ 1072 wtsoft(sc, sc->BUSY, 0); /* wait for not ready */ 1073 outb(sc->CTLPORT, sc->ONLINE); /* unset request */ 1074 } 1075 splx(s); 1076 return 1; 1077 } 1078