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