1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)wt.c 7.1 (Berkeley) 5/9/91 34 * $Id: wt.c,v 1.5 1993/07/28 02:21:40 cgd Exp $ 35 */ 36 37 /* 38 * 39 * Copyright (c) 1989 Carnegie-Mellon University. 40 * All rights reserved. 41 * 42 * Authors: Robert Baron 43 * 44 * Permission to use, copy, modify and distribute this software and 45 * its documentation is hereby granted, provided that both the copyright 46 * notice and this permission notice appear in all copies of the 47 * software, derivative works or modified versions, and any portions 48 * thereof, and that both notices appear in supporting documentation. 49 * 50 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 51 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 52 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 53 * 54 * Carnegie Mellon requests users of this software to return to 55 * 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57 * School of Computer Science 58 * Carnegie Mellon University 59 * Pittsburgh PA 15213-3890 60 * 61 * any improvements or extensions that they make and grant Carnegie the 62 * rights to redistribute these changes. 63 */ 64 65 #include "wt.h" 66 #if NWT > 0 67 /* 68 * (Mach) HISTORY 69 * Revision 2.2.1.3 90/01/08 13:29:38 rvb 70 * Add Intel copyright. 71 * [90/01/08 rvb] 72 * 73 * Revision 2.2.1.2 89/12/21 18:00:09 rvb 74 * Change WTPRI to make the streamer tape read/write 75 * interruptible. [lin] 76 * 77 * Revision 2.2.1.1 89/11/10 09:49:49 rvb 78 * ORC likes their streamer port at 0x288. 79 * [89/11/08 rvb] 80 * 81 * Revision 2.2 89/09/25 12:33:02 rvb 82 * Driver was provided by Intel 9/18/89. 83 * [89/09/23 rvb] 84 * 85 */ 86 87 /* 88 * 89 * Copyright 1988, 1989 by Intel Corporation 90 * 91 * Support Bell Tech QIC-02 and WANGTEK QIC-36 or QIC-02 92 */ 93 94 /*#include <sys/errno.h> 95 #include <sys/signal.h> 96 #include <sys/types.h>*/ 97 #include "sys/param.h" 98 #include "sys/buf.h" 99 #include "sys/file.h" 100 #include "sys/proc.h" 101 #include "sys/user.h" 102 #include "i386/isa/wtreg.h" 103 104 #ifdef ORC 105 unsigned wtport = 0x288; /* base I/O port of controller */ 106 #else ORC 107 unsigned wtport = 0x300; /* base I/O port of controller */ 108 #endif ORC 109 /* standard = 0x300 */ 110 /* alternate = 0x338 */ 111 112 unsigned wtchan = 1; /* DMA channel number */ 113 /* stardard = 1 */ 114 /* hardware permits 1, 2 or 3. */ 115 /* (Avoid DMA 2: used by disks) */ 116 117 int first_wtopen_ever = 1; 118 119 120 #define ERROR 1 /* return from tape routines */ 121 #define SUCCESS 0 /* return from tape routines */ 122 123 int wci = 0; 124 int exflag = 0; 125 int bytes = 0; 126 127 static unsigned char eqdma = 0x8; 128 static unsigned char pagereg = 0x83; 129 static unsigned char dmareg = 2; 130 static unsigned char dma_write = 0x49; 131 static unsigned char dma_read = 0x45; 132 static unsigned char dma_done = 2; 133 static unsigned char mode = 0; 134 static unsigned char mbits; /* map bits into each other */ 135 static long bufptr; 136 static unsigned numbytes; 137 /* 138 _wci dw 0 ; interrupt chain finished normally 139 _exflag dw 0 ; exception variable 140 _bytes dw 0 ; current bytes 141 142 eqdma db 8h ; enable dma command: ch1,ch2=8h, ch3=10h 143 pagereg db 83h ; ch1=83h, ch2=81h, ch3=82h 144 dmareg db 2 ; ch1=2, ch2=4, ch3=6 145 dma_write db 49h ; write dma command: 48h+_wtchan 146 dma_read db 45h ; read dma command: 44h+_wtchan 147 dma_done db 2 ; dma done flag: 1<<_wtchan 148 mode db 0 ; dma operation mode 149 lbufptr dw 0 ; buffer pointer to data buffers, low word 150 hbufptr dw 0 ; buffer pointer to data buffers, high word 151 numbytes dw 0 ; number of bytes to read or write (new) 152 */ 153 154 #define PAGESIZ 4096 155 #define HZ 60 156 157 /* tape controller ports */ 158 #define STATPORT wtport 159 #define CTLPORT STATPORT 160 #define CMDPORT (wtport+1) 161 #define DATAPORT CMDPORT 162 163 /* defines for reading out status from wangtek tape controller */ 164 #define READY 0x01 /* ready bit define */ 165 #define EXCEP 0x02 /* exception bit define */ 166 #define STAT (READY|EXCEP) 167 #define RESETMASK 0x7 168 #define RESETVAL (RESETMASK & ~EXCEP) 169 170 /* tape controller control bits (CTLPORT) */ 171 #define ONLINE 0x01 172 #define RESET 0x02 173 #define REQUEST 0x04 /* request command */ 174 #define CMDOFF 0xC0 175 176 /* QIC-02 commands (CMDPORT) */ 177 #define RDDATA 0x80 /* read data */ 178 #define READFM 0xA0 /* read file mark */ 179 #define WRTDATA 0x40 /* write data */ 180 #define WRITEFM 0x60 /* write file mark */ 181 #define RDSTAT 0xC0 /* read status command */ 182 #define REWIND 0x21 /* rewind command (position+bot) */ 183 184 /* 8237 DMA controller regs */ 185 #define STATUSREG 0x8 186 #define MASKREG 0xA 187 #define MODEREG 0xB 188 #define CLEARFF 0xC 189 190 /* streamer tape block size */ 191 #define BLKSIZE 512 192 193 /* Tape characteristics */ 194 #define NBPS 512 /* 512-byte blocks */ 195 #define ERROR 1 /* return from tape routines */ 196 #define SUCCESS 0 /* return from tape routines */ 197 198 /* Minor devs */ 199 #define TP_REWCLOSE(d) ((minor(d)&04) == 0) /* Rewind tape on close if read/write */ 200 #define TP_DENS(dev) ((minor(dev) >> 3) & 03) /* set density */ 201 #define TPHOG(d) 0 /* use Hogproc during tape I/O */ 202 203 /* defines for wtflags */ 204 #define TPINUSE 0x0001 /* tape is already open */ 205 #define TPREAD 0x0002 /* tape is only open for reading */ 206 #define TPWRITE 0x0004 /* tape is only open for writing */ 207 #define TPSTART 0x0008 /* tape must be rewound and reset */ 208 #define TPDEAD 0x0010 /* tape drive does not work or driver error */ 209 #define TPSESS 0x0020 /* no more reads or writes allowed in session */ 210 /* for example, when tape has to be changed */ 211 #define TPSTOP 0x0040 /* Stop command outstanding */ 212 #define TPREW 0x0080 /* Rewind command outstanding, see wtdsl2() */ 213 #define TPVOL 0x0100 /* Read file mark, or hit end of tape */ 214 #define TPWO 0x0200 /* write command outstanding */ 215 #define TPRO 0x0400 /* read command outstanding */ 216 #define TPWANY 0x0800 /* write command requested */ 217 #define TPRANY 0x1000 /* read command requested */ 218 #define TPWP 0x2000 /* write protect error seen */ 219 220 unsigned int wtflags = TPSTART; /* state of tape drive */ 221 222 struct buf rwtbuf; /* header for raw i/o */ 223 struct proc *myproc; /* process which opened tape driver */ 224 225 char wtimeron; /* wtimer() active flag */ 226 char wtio; /* dma (i/o) active flag */ 227 char isrlock; /* isr() flag */ 228 229 struct proc * Hogproc; /* no Hogproc on Microport */ 230 #define ftoseg(x) ((unsigned) (x >> 16)) 231 232 struct wtstatus { 233 ushort wt_err; /* code for error encountered */ 234 ushort wt_ercnt; /* number of error blocks */ 235 ushort wt_urcnt; /* number of underruns */ 236 } wterror; 237 238 /* defines for wtstatus.wt_err */ 239 #define TP_POR 0x100 /* Power on/reset occurred */ 240 #define TP_RES1 0x200 /* Reserved for end of media */ 241 #define TP_RES2 0x400 /* Reserved for bus parity */ 242 #define TP_BOM 0x800 /* Beginning of media */ 243 #define TP_MBD 0x1000 /* Marginal block detected */ 244 #define TP_NDT 0x2000 /* No data detected */ 245 #define TP_ILL 0x4000 /* Illegal command */ 246 #define TP_ST1 0x8000 /* Status byte 1 bits */ 247 #define TP_FIL 0x01 /* File mark detected */ 248 #define TP_BNL 0x02 /* Bad block not located */ 249 #define TP_UDA 0x04 /* Unrecoverable data error */ 250 #define TP_EOM 0x08 /* End of media */ 251 #define TP_WRP 0x10 /* Write protected cartridge */ 252 #define TP_USL 0x20 /* Unselected drive */ 253 #define TP_CNI 0x40 /* Cartridge not in place */ 254 #define TP_ST0 0x80 /* Status byte 0 bits */ 255 256 /* Grounds for reporting I/O error to user */ 257 #define TP_ERR0 (TP_BNL|TP_UDA|TP_WRP|TP_CNI|TP_FIL|TP_EOM|TP_USL) 258 #define TP_ERR1 (TP_MBD|TP_NDT|TP_ILL) 259 /* TP_ILL should never happen! */ 260 /* 261 #define TP_ERR0 0x7f 262 #define TP_ERR1 0x7700 263 */ 264 265 /* defines for reading out status from wangtek tape controller */ 266 #define READY 0x01 /* ready bit define */ 267 #define EXCEP 0x02 /* exception bit define */ 268 269 /* sleep priority */ 270 #define WTPRI (PZERO+10) 271 272 char pagebuf[NBPS]; /* buffer of size NBPS */ 273 unsigned long pageaddr; /* physical addr of pagebuf */ 274 /* pageaddr is used with DMA controller */ 275 time_t Hogtime; /* lbolt when Hog timer started */ 276 extern time_t lbolt; 277 278 #define debug printf 279 280 /* 281 * Strategy routine. 282 * 283 * Arguments: 284 * Pointer to buffer structure 285 * Function: 286 * Start transfer. 287 * 288 * It would be nice to have this multiple-threaded. 289 * There is a version of dump from Berkeley that works with multiple processes 290 * trading off with disk & tape I/O. 291 */ 292 293 int 294 wtstrategy(bp) 295 register struct buf *bp; 296 { 297 unsigned ucnt1, ucnt2, finished; 298 unsigned long adr1, adr2; 299 int bad; 300 301 adr1 = kvtop(bp->b_un.b_addr); 302 #ifdef DEBUG 303 debug("bpaddr %x\n", adr1); 304 #endif 305 ucnt1 = bp->b_bcount % NBPG; 306 ucnt2 = 0; 307 adr2 = 0; 308 #ifdef DEBUG 309 debug("WTstart: adr1 %lx cnt %x\n", adr1, ucnt1); 310 #endif 311 /* 64K boundary? (XXX) */ 312 if (ftoseg(adr1) != ftoseg(adr1 + (unsigned) ucnt1 - 1)) 313 { 314 adr2 = (adr1 & 0xffff0000L) + 0x10000L; 315 ucnt2 = (adr1 + ucnt1) - adr2; 316 ucnt1 -= ucnt2; 317 } 318 /* page boundary? */ 319 if (trunc_page(adr1) != trunc_page(adr1 + (unsigned) ucnt1 - 1)) 320 { unsigned u; 321 u = NBPG - ((unsigned)bp->b_un.b_addr & (NBPG-1)); 322 adr2 = kvtop(bp->b_un.b_addr + u); 323 ucnt2 = ucnt1 - u; 324 ucnt1 = u; 325 } 326 /* at file marks and end of tape, we just return '0 bytes available' */ 327 if (wtflags & TPVOL) { 328 bp->b_resid = bp->b_bcount; 329 goto xit; 330 } 331 if ((Hogproc == (struct proc *) 0) && TPHOG(bp->b_dev)) 332 { 333 #ifdef DEBUG 334 printf("setting Hogproc\n"); 335 #endif 336 Hogtime = 0; 337 Hogproc = myproc; 338 } 339 if (bp->b_flags & B_READ) { 340 bad = 0; 341 342 /* For now, we assume that all data will be copied out */ 343 /* If read command outstanding, just skip down */ 344 if (!(wtflags & TPRO)) { 345 if (ERROR == wtsense(TP_WRP)) /* clear status */ 346 goto errxit; 347 #ifdef DEBUG 348 debug("WTread: Start read\n"); 349 #endif 350 if (!(wtflags & TPREAD) || (wtflags & TPWANY) || 351 (rstart() == ERROR)) { 352 #ifdef DEBUG 353 debug("Tpstart: read init error\n"); /* */ 354 #endif 355 goto errxit; 356 } 357 wtflags |= TPRO|TPRANY; 358 } 359 360 finished = 0; 361 /* Take a deep breath */ 362 if (ucnt1) { 363 if ((rtape(adr1, ucnt1) == ERROR) && 364 (wtsense(TP_WRP) == ERROR)) 365 goto endio; 366 /* wait for it */ 367 bad = pollrdy(); 368 finished = bytes; 369 if (bad) 370 goto endio; 371 } 372 /* if a second I/O region, start it */ 373 if (ucnt2) { 374 if ((rtape(adr2, ucnt2) == ERROR) && 375 (wtsense(TP_WRP) == ERROR)) 376 ucnt2 = 0; /* don't poll for me */ 377 } 378 379 /* if second i/o pending wait for it */ 380 if (ucnt2) { 381 pollrdy(); 382 /* whether pollrdy is ok or not */ 383 finished += bytes; 384 } 385 } else { 386 if (wtflags & TPWP) /* write protected */ 387 goto errxit; 388 389 /* If write command outstanding, just skip down */ 390 if (!(wtflags & TPWO)) { 391 if (ERROR == wtsense(0)) /* clear status */ 392 { 393 #ifdef DEBUG 394 debug("TPstart: sense 0\n"); 395 #endif 396 goto errxit; 397 } 398 if (!(wtflags & TPWRITE) || (wtflags & TPRANY) || 399 (wstart() == ERROR)) { 400 #ifdef DEBUG 401 debug("Tpstart: write init error\n"); /* */ 402 #endif 403 wtsense(0); 404 405 errxit: bp->b_flags |= B_ERROR; 406 bp->b_resid = bp->b_bcount; 407 goto xit; 408 } 409 wtflags |= TPWO|TPWANY; 410 } 411 412 /* and hold your nose */ 413 if (ucnt1 && ((wtape(adr1, ucnt1) == ERROR) 414 && (wtsense(0) == ERROR))) 415 finished = bytes; 416 417 else if (ucnt2 && 418 (((ucnt1 && pollrdy()) || 419 (wtape(adr2, ucnt2) == ERROR)) && 420 (wtsense(0) == ERROR))) 421 finished = ucnt1 + NBPS + bytes; 422 /* All writes and/or copyins were fine! */ 423 else 424 finished = bp->b_bcount; 425 bad = pollrdy(); 426 } 427 428 endio: 429 if(bad == EIO) bad = 0; 430 wterror.wt_err = 0; 431 if (exflag && wtsense((bp->b_flags & B_READ) ? TP_WRP : 0)) { 432 if ((wterror.wt_err & TP_ST0) 433 && (wterror.wt_err & (TP_FIL|TP_EOM))) { 434 #ifdef DEBUG 435 debug("WTsta: Hit end of tape\n"); /* */ 436 #endif 437 wtflags |= TPVOL; 438 if (wterror.wt_err & TP_FIL) { 439 if (wtflags & TPRO) 440 /* interrupter is bogus */ 441 rstart(); /* restart read command */ 442 else 443 wtflags &= ~TPWO; 444 finished += NBPS; 445 } 446 /* Reading file marks or writing end of tape return 0 bytes */ 447 } else { 448 bp->b_flags |= B_ERROR; 449 wtflags &= ~(TPWO|TPRO); 450 } 451 } 452 453 if(bad) { 454 bp->b_flags |= B_ERROR; 455 bp->b_error = bad; 456 } 457 bp->b_resid = bp->b_bcount - finished; 458 xit: 459 biodone(bp); 460 if (wtimeron) 461 Hogtime = lbolt; 462 else if (Hogproc == myproc) 463 Hogproc = (struct proc *) 0; 464 } 465 466 /* 467 * simulate an interrupt periodically while I/O is going 468 * this is necessary in case interrupts get eaten due to 469 * multiple devices on a single IRQ line 470 */ 471 wtimer() 472 { 473 /* If I/O going and not in isr(), simulate interrupt 474 * If no I/O for at least 1 second, stop being a Hog 475 * If I/O done and not a Hog, turn off wtimer() 476 */ 477 if (wtio && !isrlock) 478 isr(); 479 480 if ((Hogproc == myproc) && Hogtime && (lbolt-Hogtime > HZ)) 481 Hogproc = (struct proc *) 0; 482 483 if (wtio || (Hogproc == myproc)) 484 timeout(wtimer, (caddr_t) 0, HZ); 485 else 486 wtimeron = 0; 487 } 488 489 490 wtrawio(bp) 491 struct buf *bp; 492 { 493 wtstrategy(bp); 494 biowait(bp); 495 return(0); 496 } 497 498 /* 499 * ioctl routine 500 * for user level QIC commands only 501 */ 502 wtioctl(dev, cmd, arg, mode) 503 int dev, cmd; 504 unsigned long arg; 505 int mode; 506 { 507 if (cmd == WTQICMD) 508 { 509 if ((qicmd((int)arg) == ERROR) || (rdyexc(HZ) == ERROR)) 510 { 511 wtsense(0); 512 return(EIO); 513 } 514 return(0); 515 } 516 return(EINVAL); 517 } 518 519 /* 520 * open routine 521 * called on every device open 522 */ 523 wtopen(dev, flag) 524 int dev, flag; 525 { 526 if (first_wtopen_ever) { 527 wtinit(); 528 first_wtopen_ever = 0; 529 } 530 #ifdef DEBUG 531 printf("wtopen ...\n"); 532 #endif 533 if (!pageaddr) { 534 return(ENXIO); 535 } 536 if (wtflags & (TPINUSE)) { 537 return(ENXIO); 538 } 539 if (wtflags & (TPDEAD)) { 540 return(EIO); 541 } 542 /* If a rewind from the last session is going on, wait */ 543 while(wtflags & TPREW) { 544 #ifdef DEBUG 545 debug("Waiting for rew to finish\n"); 546 #endif 547 DELAY(1000000); /* delay one second */ 548 } 549 /* Only do reset and select when tape light is off, and tape is rewound. 550 * This allows multiple volumes. */ 551 if (wtflags & TPSTART) { 552 if (t_reset() != SUCCESS) { 553 return(ENXIO); 554 } 555 #ifdef DEBUG 556 debug("reset done. calling wtsense\n"); 557 #endif 558 if (wtsense(TP_WRP) == ERROR) { 559 return (EIO); 560 } 561 #ifdef DEBUG 562 debug("wtsense done\n"); 563 #endif 564 wtflags &= ~TPSTART; 565 } 566 567 wtflags = TPINUSE; 568 if (flag & FREAD) 569 wtflags |= TPREAD; 570 if (flag & FWRITE) 571 wtflags |= TPWRITE; 572 rwtbuf.b_flags = 0; 573 myproc = curproc; /* for comparison */ 574 #ifdef not 575 switch(TP_DENS(dev)) { 576 case 0: 577 cmds(0x28); 578 break; 579 case 1: 580 cmds(0x29); 581 break; 582 case 2: 583 cmds(0x27); 584 break; 585 case 3: 586 cmds(0x24); 587 } 588 #endif 589 return(0); 590 } 591 592 /* 593 * close routine 594 * called on last device close 595 * If not rewind-on-close, leave read or write command intact. 596 */ 597 wtclose(dev) 598 { 599 int wtdsl2(); 600 601 #ifdef DEBUG 602 debug("WTclose:\n"); 603 #endif 604 if (Hogproc == myproc) 605 Hogproc = (struct proc *) 0; 606 if (!exflag && (wtflags & TPWANY) && !(wtflags & (TPSESS|TPDEAD))) { 607 if (!(wtflags & TPWO)) 608 wstart(); 609 #ifdef DEBUG 610 debug("WT: Writing file mark\n"); 611 #endif 612 wmark(); /* write file mark */ 613 #ifdef DEBUG 614 debug("WT: Wrote file mark, going to wait\n"); 615 #endif 616 if (rdyexc(HZ/10) == ERROR) { 617 wtsense(0); 618 } 619 } 620 if (TP_REWCLOSE(dev) || (wtflags & (TPSESS|TPDEAD))) { 621 /* rewind tape to beginning of tape, deselect tape, and make a note */ 622 /* don't wait until rewind, though */ 623 /* Ending read or write causes rewind to happen, if no error, 624 * and READY and EXCEPTION stay up until it finishes */ 625 if (wtflags & (TPRO|TPWO)) 626 { 627 #ifdef DEBUG 628 debug("End read or write\n"); 629 #endif 630 rdyexc(HZ/10); 631 ioend(); 632 wtflags &= ~(TPRO|TPWO); 633 } 634 else wtwind(); 635 wtflags |= TPSTART | TPREW; 636 timeout(wtdsl2, 0, HZ); 637 } 638 else if (!(wtflags & (TPVOL|TPWANY))) 639 { 640 /* space forward to after next file mark no writing done */ 641 /* This allows skipping data without reading it.*/ 642 #ifdef DEBUG 643 debug("Reading past file mark\n"); 644 #endif 645 if (!(wtflags & TPRO)) 646 rstart(); 647 rmark(); 648 if (rdyexc(HZ/10)) 649 { 650 wtsense(TP_WRP); 651 } 652 } 653 wtflags &= TPREW|TPDEAD|TPSTART|TPRO|TPWO; 654 return(0); 655 } 656 657 /* return ERROR if user I/O request should receive an I/O error code */ 658 659 wtsense(ignor) 660 { 661 wtflags &= ~(TPRO|TPWO); 662 #ifdef DEBUGx 663 debug("WTsense: start "); 664 #endif 665 if (rdstatus(&wterror) == ERROR) 666 { 667 #ifdef DEBUG 668 debug("WTsense: Can't read status\n"); 669 #endif 670 return(ERROR); 671 } 672 #ifdef DEBUG 673 if (wterror.wt_err & (TP_ST0|TP_ST1)) 674 { 675 debug("Tperror: status %x error %d underruns %d\n", 676 wterror.wt_err, wterror.wt_ercnt, wterror.wt_urcnt); 677 } 678 else 679 debug("done. no error\n"); 680 #endif 681 wterror.wt_err &= ~ignor; /* ignore certain errors */ 682 reperr(wterror.wt_err); 683 if (((wterror.wt_err & TP_ST0) && (wterror.wt_err & TP_ERR0)) || 684 ((wterror.wt_err & TP_ST1) && (wterror.wt_err & TP_ERR1))) 685 return ERROR; 686 687 return SUCCESS; 688 } 689 690 /* lifted from tdriver.c from Wangtek */ 691 reperr(srb0) 692 int srb0; 693 { 694 int s0 = srb0 & (TP_ERR0|TP_ERR1); /* find out which exception to report */ 695 696 if (s0) { 697 if (s0 & TP_USL) 698 sterr("Drive not online"); 699 else if (s0 & TP_CNI) 700 sterr("No cartridge"); 701 else if ((s0 & TP_WRP) && !(wtflags & TPWP)) 702 { 703 sterr("Tape is write protected"); 704 wtflags |= TPWP; 705 } 706 /* 707 if (s0 & TP_FIL) 708 sterr("Filemark detected"); 709 */ 710 else if (s0 & TP_BNL) 711 sterr("Block in error not located"); 712 else if (s0 & TP_UDA) 713 sterr("Unrecoverable data error"); 714 /* 715 else if (s0 & TP_EOM) 716 sterr("End of tape"); 717 */ 718 else if (s0 & TP_NDT) 719 sterr("No data detected"); 720 /* 721 if (s0 & TP_POR) 722 sterr("Reset occured"); 723 */ 724 else if (s0 & TP_BOM) 725 sterr("Beginning of tape"); 726 else if (s0 & TP_ILL) 727 sterr("Illegal command"); 728 } 729 } 730 731 sterr(errstr) 732 char *errstr; 733 { 734 printf("Streamer: %s\n", errstr); 735 } 736 737 /* Wait until rewind finishes, and deselect drive */ 738 wtdsl2() { 739 int stat; 740 741 stat = inb(wtport) & (READY|EXCEP); 742 #ifdef DEBUG 743 debug("Timeout: Waiting for rewind to finish: stat %x\n", stat); 744 #endif 745 switch (stat) { 746 /* They're active low, ya'know */ 747 case READY|EXCEP: 748 timeout(wtdsl2, (caddr_t) 0, HZ); 749 return; 750 case EXCEP: 751 wtflags &= ~TPREW; 752 return; 753 case READY: 754 case 0: 755 wtflags &= ~TPREW; 756 sterr("Rewind failed"); 757 wtsense(TP_WRP); 758 return; 759 } 760 } 761 762 wtwind() { 763 #ifdef DEBUG 764 debug("WT: About to rewind\n"); 765 #endif 766 rwind(); /* actually start rewind */ 767 } 768 769 wtintr(unit) { 770 if (wtflags & (TPWO|TPRO)) 771 { 772 isrlock = 1; 773 if (wtio) isr(); 774 isrlock = 0; 775 } 776 } 777 778 wtinit() { 779 if (wtchan < 1 || wtchan > 3) 780 { 781 sterr("Bad DMA channel, cannot init driver"); 782 return; 783 } 784 wtlinit(); /* init assembly language variables */ 785 pageset(); 786 } 787 788 rdyexc(ticks) 789 { 790 int s; 791 #ifdef DEBUG 792 int os = 0xffff; /* force printout first time */ 793 #endif 794 for (;;) { /* loop until ready or exception */ 795 s=(inb(wtport) & 0xff); /* read the status register */ 796 #ifdef DEBUG 797 if (os != s) { 798 debug("Status reg = %x\n", s); /* */ 799 os = s; 800 } 801 #endif 802 if (!(s & EXCEP)) /* check if exception have occured */ 803 break; 804 if (!(s & READY)) /* check if controller is ready */ 805 break; 806 s = splbio(); 807 DELAY((ticks/HZ)*1000000); /* */ 808 splx(s); 809 } 810 #ifdef DEBUG 811 debug("Status reg = %x on return\n", s); /* */ 812 #endif 813 return((s & EXCEP)?SUCCESS:ERROR); /* return exception if it occured */ 814 } 815 816 pollrdy() 817 { 818 int sps; 819 #ifdef DEBUG 820 debug("Pollrdy\n"); 821 #endif 822 sps = splbio(); 823 while (wtio) { 824 int error; 825 826 if (error = tsleep((caddr_t)&wci, WTPRI | PCATCH, 827 "wtpoll", 0)) { 828 splx(sps); 829 return(error); 830 } 831 } 832 splx(sps); 833 #ifdef DEBUG 834 debug("Finish poll, wci %d exflag %d\n", wci, exflag); 835 #endif 836 return (EIO); 837 } 838 839 wtdma() /* start up i/o operation, called from dma() in wtlib1.s */ 840 { 841 wtio = 1; 842 if (!wtimeron) 843 { 844 wtimeron = 1; 845 timeout(wtimer, (caddr_t) 0, HZ/2); 846 } 847 } 848 849 wtwake() /* end i/o operation, called from isr() in wtlib1.s */ 850 { 851 wtio = 0; 852 wakeup(&wci); 853 } 854 855 pageset() 856 { 857 unsigned long pp; 858 859 pp = (unsigned long) pagebuf; 860 pageaddr = kvtop(pp); 861 #ifdef DEBUG 862 debug("pageset: addr %lx\n", pageaddr); 863 #endif 864 } 865 866 867 868 #define near 869 870 static near 871 sendcmd() 872 { 873 /* desired command in global mbits */ 874 875 outb(CTLPORT, mbits | REQUEST); /* set request */ 876 while (inb(STATPORT) & READY); /* wait for ready */ 877 outb(CTLPORT, mbits & ~REQUEST); /* reset request */ 878 while ((inb(STATPORT) & READY) == 0); /* wait for not ready */ 879 } 880 881 static near /* execute command */ 882 cmds(cmd) 883 { 884 register s; 885 886 do s = inb(STATPORT); 887 while ((s & STAT) == STAT); /* wait for ready */ 888 889 if ((s & EXCEP) == 0) /* if exception */ 890 return ERROR; /* error */ 891 892 outb(CMDPORT, cmd); /* output the command */ 893 894 outb(CTLPORT, mbits=ONLINE); /* set & send ONLINE */ 895 sendcmd(); 896 897 return SUCCESS; 898 } 899 900 qicmd(cmd) 901 { 902 return cmds(cmd); 903 } 904 905 rstart() 906 { 907 return cmds(RDDATA); 908 } 909 910 rmark() 911 { 912 return cmds(READFM); 913 } 914 915 wstart() 916 { 917 return cmds(WRTDATA); 918 } 919 920 ioend() 921 { 922 register s; 923 register rval = SUCCESS; 924 925 do s = inb(STATPORT); 926 while ((s & STAT) == STAT); /* wait for ready */ 927 928 if ((s & EXCEP) == 0) /* if exception */ 929 rval = ERROR; /* error */ 930 931 mbits &= ~ONLINE; 932 outb(CTLPORT, mbits); /* reset ONLINE */ 933 outb(MASKREG, wtchan+4); /* turn off dma */ 934 outb(CLEARFF, 0); /* reset direction flag */ 935 936 return rval; 937 } 938 939 wmark() 940 { 941 register s; 942 943 if (cmds(WRITEFM) == ERROR) 944 return ERROR; 945 946 do s = inb(STATPORT); 947 while ((s & STAT) == STAT); /* wait for ready */ 948 949 if ((s & EXCEP) == 0) /* if exception */ 950 return ERROR; /* error */ 951 952 return SUCCESS; 953 } 954 955 rwind() 956 { 957 register s; 958 959 mbits = CMDOFF; 960 961 do s = inb(STATPORT); 962 while ((s & STAT) == STAT); /* wait for ready */ 963 964 outb(CMDPORT, REWIND); 965 sendcmd(); 966 967 return SUCCESS; 968 } 969 970 rdstatus(stp) 971 char *stp; /* pointer to 6 byte buffer */ 972 { 973 register s; 974 int n; 975 976 do s = inb(STATPORT); 977 while ((s & STAT) == STAT); /* wait for ready or exception */ 978 979 outb(CMDPORT, RDSTAT); 980 sendcmd(); /* send read status command */ 981 982 for (n=0; n<6; n++) 983 { 984 #ifdef DEBUGx 985 debug("rdstatus: waiting, byte %d\n", n); 986 #endif 987 do s = inb(STATPORT); 988 while ((s & STAT) == STAT); /* wait for ready */ 989 #ifdef DEBUGx 990 debug("rdstatus: done\n"); 991 #endif 992 if ((s & EXCEP) == 0) /* if exception */ 993 return ERROR; /* error */ 994 995 *stp++ = inb(DATAPORT); /* read status byte */ 996 997 outb(CTLPORT, mbits | REQUEST); /* set request */ 998 #ifdef DEBUGx 999 debug("rdstatus: waiting after request, byte %d\n", n); 1000 #endif 1001 while ((inb(STATPORT)&READY) == 0); /* wait for not ready */ 1002 for (s=100; s>0; s--); /* wait an additional time */ 1003 1004 outb(CTLPORT, mbits & ~REQUEST);/* unset request */ 1005 #ifdef DEBUGx 1006 debug("rdstatus: done\n"); 1007 #endif 1008 } 1009 return SUCCESS; 1010 } 1011 1012 t_reset() 1013 { 1014 register i; 1015 mbits |= RESET; 1016 outb(CTLPORT, mbits); /* send reset */ 1017 DELAY(20); 1018 mbits &= ~RESET; 1019 outb(CTLPORT, mbits); /* turn off reset */ 1020 if ((inb(STATPORT) & RESETMASK) == RESETVAL) 1021 return SUCCESS; 1022 return ERROR; 1023 } 1024 1025 static 1026 dma() 1027 { 1028 int x=splbio(); 1029 wtdma(); 1030 outb(CLEARFF, 0); 1031 outb(MODEREG, mode); /* set dma mode */ 1032 outb(dmareg, bufptr & 0xFF); 1033 outb(dmareg, (bufptr>>8) & 0xFF); 1034 outb(pagereg, (bufptr>>16) & 0xFF); 1035 outb(dmareg+1, (BLKSIZE-1) & 0xFF); 1036 outb(dmareg+1, (BLKSIZE-1) >> 8); 1037 outb(wtport, eqdma+ONLINE); 1038 outb(MASKREG, wtchan); /* enable command to 8237, start dma */ 1039 splx(x); 1040 } 1041 1042 static near 1043 wtstart(buf, cnt) 1044 long buf; 1045 int cnt; 1046 { 1047 register s; 1048 1049 bufptr = buf; /* init statics */ 1050 numbytes = cnt; 1051 wci = 0; /* init flags */ 1052 exflag = 0; 1053 bytes = 0; /* init counter */ 1054 1055 do s = inb(STATPORT) & STAT; 1056 while (s == STAT); /* wait for ready or error */ 1057 1058 if (s & EXCEP) /* no error */ 1059 { 1060 dma(); 1061 return SUCCESS; 1062 } 1063 return ERROR; /* error */ 1064 } 1065 1066 rtape(buf, cnt) 1067 long buf; /* physical address */ 1068 int cnt; /* number of bytes */ 1069 { 1070 mode = dma_read; 1071 return wtstart(buf,cnt); 1072 } 1073 1074 wtape(buf, cnt) 1075 long buf; /* physical address */ 1076 int cnt; /* number of bytes */ 1077 { 1078 mode = dma_write; 1079 return wtstart(buf,cnt); 1080 } 1081 1082 isr() 1083 { 1084 int stat = inb(wtport); 1085 if (!(stat & EXCEP)) /* exception during I/O */ 1086 { 1087 if (bytes + BLKSIZE >= numbytes) wci = 1; 1088 exflag = 1; 1089 goto isrwake; 1090 } 1091 if ((stat & READY) || !(inb(STATUSREG) & dma_done)) 1092 return; 1093 exflag = 0; 1094 outb(wtport, ONLINE); 1095 bytes += BLKSIZE; 1096 if (bytes >= numbytes) /* normal completion of I/O */ 1097 { 1098 wci = 1; 1099 isrwake: 1100 outb(MASKREG, 4+wtchan); /* turn off dma */ 1101 wtwake(); /* wake up user level */ 1102 } 1103 else 1104 { /* continue I/O */ 1105 bufptr += BLKSIZE; 1106 dma(); 1107 } 1108 } 1109 1110 wtlinit() 1111 { 1112 switch (wtchan) { 1113 case 1: 1114 return; 1115 case 2: 1116 pagereg = 0x81; 1117 dma_done = 4; 1118 break; 1119 case 3: 1120 eqdma = 0x10; 1121 pagereg = 0x82; 1122 dma_done = 8; 1123 break; 1124 } 1125 dma_write = wtchan+0x48; 1126 dma_read = wtchan+0x44; 1127 dmareg = wtchan+wtchan; 1128 } 1129 1130 wtsize() 1131 { 1132 } 1133 1134 wtdump() 1135 { 1136 } 1137 1138 #include "i386/isa/isa_device.h" 1139 #include "i386/isa/icu.h" 1140 1141 int wtprobe(), wtattach(); 1142 struct isa_driver wtdriver = { 1143 wtprobe, wtattach, "wt", 1144 }; 1145 1146 wtprobe(dvp) 1147 struct isa_device *dvp; 1148 { 1149 int val,i,s; 1150 1151 #ifdef lint 1152 wtintr(0); 1153 #endif 1154 1155 wtport = dvp->id_iobase; 1156 if(t_reset() != SUCCESS) return(0); 1157 return(1); 1158 } 1159 1160 wtattach() { } 1161 1162 #endif NWT 1163