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