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