1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)tu.c 7.5 (Berkeley) 12/16/90 7 */ 8 9 #if defined(VAX750) || defined(VAX730) 10 /* 11 * TU58 DECtape II device driver 12 * 13 * TU58 console cassette driver (for VAX-11/750 or VAX-11/730). 14 * The TU58 is treated as a block device (only). Error detection and 15 * recovery is not extensive, but sufficient for most situations. It is 16 * assumed that the TU58 will follow the RSP (or MRSP) protocol exactly, 17 * very few protocol errors are checked for. It is also assumed that 18 * the 730 uses Modified RSP (MRSP), while the 750 may use either RSP 19 * or MRSP depending on whether defined(MRSP) is true or not. 20 * In the case of a 750 without MRSP, the only way for the CPU to 21 * keep up with the tu58 is to lock out virtually everything else. 22 * 23 * NOTE: Reading large amounts of data from the tu58 is likely 24 * to crash your system if you are running multiuser. 25 * ******FOR SINGLE USER USE ONLY***** 26 */ 27 #include "sys/param.h" 28 #include "sys/systm.h" 29 #include "sys/buf.h" 30 #include "sys/conf.h" 31 #include "sys/user.h" 32 #include "sys/kernel.h" 33 34 #include "../include/cpu.h" 35 #include "../include/mtpr.h" 36 #include "rsp.h" 37 38 #define printd if(tudebug) printf 39 #ifdef printd 40 int tudebug; /* printd */ 41 #endif printd 42 43 #define NTU ((cpu == VAX_750) ? 1 : 2) 44 #define DNUM 01 /* mask for drive number (should match NTU) */ 45 #define NTUBLK 512 /* number of blocks on a TU58 cassette */ 46 #define WRV 02 /* bit in minor dev => write w. read verify */ 47 #define NTUQ 2 /* # of blocks which can be queued up */ 48 #define spltu() ((cpu == VAX_750) ? spl7() : spl4()) 49 50 #ifndef MRSP 51 #define MRSP (cpu != VAX_750) 52 #endif 53 54 /* 55 * State information 56 */ 57 struct tu { 58 u_char *tu_rbptr; /* pointer to buffer for read */ 59 int tu_rcnt; /* how much to read */ 60 u_char *tu_wbptr; /* pointer to buffer for write */ 61 int tu_wcnt; /* how much to write */ 62 int tu_state; /* current state of tansfer operation */ 63 int tu_flag; /* read in progress flag */ 64 char *tu_addr; /* real buffer data address */ 65 int tu_count; /* real requested count */ 66 int tu_serrs; /* count of soft errors */ 67 int tu_cerrs; /* count of checksum errors */ 68 int tu_herrs; /* count of hard errors */ 69 char tu_dopen[2]; /* drive is open */ 70 } tu; 71 72 73 /* 74 * Device register bits 75 */ 76 #define READY 0200 /* transmitter ready */ 77 #define DONE 0200 /* receiver done */ 78 #define IE 0100 /* interrupt enable */ 79 #define BREAK 1 /* send break */ 80 81 struct packet tucmd; /* a command sent to the TU58 */ 82 struct packet tudata; /* a command or data returned from TU58 */ 83 84 char *tustates[TUS_NSTATES] = { 85 "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR", 86 "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR" 87 }; 88 89 u_char tunull[2] = { 0, 0 }; /* nulls to send for initialization */ 90 u_char tuinit[2] = { TUF_INITF, TUF_INITF }; /* inits to send */ 91 static char tu_pcnt[2]; /* pee/vee counters */ 92 int tutimer = 0; 93 int tuwake(); 94 struct buf tutab; /* I/O queue header */ 95 96 /* 97 * Open the TU58 98 */ 99 /*ARGSUSED*/ 100 tuopen(dev, flag) 101 { 102 extern int tuwatch(); 103 register s; 104 int error; 105 106 #ifdef lint 107 turintr(); tuwintr(); 108 #endif 109 if ((minor(dev)&DNUM) >= NTU) 110 return (ENXIO); 111 if (tu.tu_dopen[minor(dev)&DNUM]) 112 return (EBUSY); 113 if (tutimer++ == 0) 114 timeout(tuwatch, (caddr_t)0, hz); 115 116 s = spltu(); 117 tu.tu_dopen[minor(dev)&DNUM]++; 118 /* 119 * If the cassette's already initialized, 120 * just enable interrupts and return. 121 */ 122 if (tu.tu_state == TUS_IDLE) { 123 mtpr(CSRS, IE); 124 goto ok; 125 } 126 127 /* 128 * Must initialize, reset the cassette 129 * and wait for things to settle down. 130 */ 131 tureset(); 132 if (error = tsleep((caddr_t)&tu, (PZERO + 1) | PCATCH, 133 devopn, 0)) { 134 splx(s); 135 return (error); 136 } 137 tutab.b_active = NULL; 138 if (tu.tu_state != TUS_IDLE) { 139 tu.tu_state = TUS_INIT1; 140 tu.tu_dopen[minor(dev)&DNUM] = 0; 141 tu.tu_rcnt = tu.tu_wcnt = 0; 142 mtpr(CSTS, 0); 143 mtpr(CSRS, 0); 144 splx(s); 145 return (EIO); 146 } 147 ok: 148 splx(s); 149 return (0); 150 } 151 152 /* 153 * Close the TU58, but make sure all 154 * outstanding i/o is complete first.. 155 */ 156 /* ARGSUSED */ 157 tuclose(dev, flag) 158 dev_t dev; 159 int flag; 160 { 161 int s, unit = minor(dev); 162 struct buf *bp, *last = NULL; 163 164 s = spltu(); 165 while (tu_pcnt[unit]) 166 sleep(&tu_pcnt[unit], PRIBIO); 167 /* 168 * No more writes are pending, scan the 169 * buffer queue for oustanding reads from 170 * this unit. 171 */ 172 for (bp = tutab.b_actf; bp; bp = bp->b_actf) { 173 if (bp->b_dev == dev) 174 last = bp; 175 } 176 if (last) { 177 last->b_flags |= B_CALL; 178 last->b_iodone = tuwake; 179 sleep((caddr_t)last, PRIBIO); 180 } 181 tu.tu_dopen[unit&DNUM] = 0; 182 if (!tu.tu_dopen[0] && !tu.tu_dopen[1]) { 183 tutimer = 0; 184 mtpr(CSRS, 0); 185 tu.tu_flag = 0; 186 } 187 splx(s); 188 } 189 190 tuwake(bp) 191 struct buf *bp; 192 { 193 wakeup((caddr_t)bp); 194 } 195 196 /* 197 * Reset the TU58 198 */ 199 tureset() 200 { 201 202 mtpr(CSRS, 0); 203 tu.tu_state = TUS_INIT1; 204 tu.tu_wbptr = tunull; 205 tu.tu_wcnt = sizeof (tunull); 206 tucmd.pk_flag = TUF_CMD; 207 tucmd.pk_mcount = sizeof (tucmd) - 4; 208 tucmd.pk_mod = 0; 209 tucmd.pk_seq = 0; 210 tucmd.pk_sw = MRSP ? TUSW_MRSP : 0; 211 tutab.b_active++; 212 mtpr(CSTS, IE | BREAK); 213 tuxintr(); /* start output */ 214 } 215 216 /* 217 * Strategy routine for block I/O 218 */ 219 tustrategy(bp) 220 register struct buf *bp; 221 { 222 register int s; 223 224 if (bp->b_blkno >= NTUBLK) { 225 bp->b_flags |= B_ERROR; 226 iodone(bp); 227 return; 228 } 229 if ((bp->b_flags&B_READ) == 0) 230 tu_pee(&tu_pcnt[minor(bp->b_dev)&DNUM]); 231 bp->av_forw = NULL; 232 s = spltu(); 233 if (tutab.b_actf == NULL) 234 tutab.b_actf = bp; 235 else 236 tutab.b_actl->av_forw = bp; 237 tutab.b_actl = bp; 238 if (tutab.b_active == NULL) 239 tustart(); 240 splx(s); 241 } 242 243 /* 244 * Start the transfer 245 */ 246 tustart() 247 { 248 register struct buf *bp; 249 int s; 250 251 if ((bp = tutab.b_actf) == NULL) 252 return; 253 s = spltu(); 254 if (tu.tu_state != TUS_IDLE) { 255 tureset(); 256 splx(s); 257 return; 258 } 259 tutab.b_active++; 260 tutab.b_errcnt = 0; 261 tucmd.pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE; 262 tucmd.pk_mod = ((bp->b_flags&B_READ) == 0 && (minor(bp->b_dev)&WRV)) ? 263 TUMD_WRV : 0; 264 tucmd.pk_unit = (minor(bp->b_dev)&DNUM); 265 tucmd.pk_sw = MRSP ? TUSW_MRSP : 0; 266 tucmd.pk_count = tu.tu_count = bp->b_bcount; 267 tucmd.pk_block = bp->b_blkno; 268 tucmd.pk_chksum = 269 tuchk(*((short *)&tucmd), (u_short *)&tucmd.pk_op, 270 (int)tucmd.pk_mcount); 271 tu.tu_state = bp->b_flags&B_READ ? TUS_SENDR : TUS_SENDW; 272 tu.tu_addr = bp->b_un.b_addr; 273 tu.tu_wbptr = (u_char *)&tucmd; 274 tu.tu_wcnt = sizeof (tucmd); 275 tuxintr(); 276 splx(s); 277 } 278 279 /* 280 * TU58 receiver interrupt 281 */ 282 turintr() 283 { 284 register struct buf *bp; 285 register int c; 286 287 c = mfpr(CSRD)&0xff; 288 if (MRSP) { 289 while ((mfpr(CSTS)&READY) == 0) 290 ; 291 mtpr(CSTD, TUF_CONT); /* ACK */ 292 if (tu.tu_rcnt) { 293 *tu.tu_rbptr++ = c; 294 if (--tu.tu_rcnt) 295 return; 296 } 297 } 298 299 /* 300 * Switch on the state of the transfer. 301 */ 302 switch(tu.tu_state) { 303 304 /* 305 * Probably an overrun error, 306 * cannot happen if MRSP is used 307 */ 308 case TUS_RCVERR: 309 mtpr(CSRS, 0); /* flush */ 310 printf("overrun error, transfer restarted\n"); /* DEBUG */ 311 tu.tu_serrs++; 312 tu_restart(); 313 break; 314 315 /* 316 * If we get an unexpected "continue", 317 * start all over again... 318 */ 319 case TUS_INIT2: 320 tu.tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; 321 tu.tu_flag = 0; 322 wakeup((caddr_t)&tu); 323 tustart(); 324 break; 325 326 /* 327 * Only transition from this state 328 * is on a "continue", so if we don't 329 * get it, reset the world. 330 */ 331 case TUS_WAIT: /* waiting for continue */ 332 switch(c) { 333 case TUF_CONT: /* got the expected continue */ 334 tu.tu_flag = 0; 335 tudata.pk_flag = TUF_DATA; 336 tudata.pk_mcount = MIN(128, tu.tu_count); 337 tudata.pk_chksum = 338 tuchk(*((short *)&tudata), (u_short *)tu.tu_addr, 339 (int)tudata.pk_mcount); 340 tu.tu_state = TUS_SENDH; 341 tu.tu_wbptr = (u_char *)&tudata; 342 tu.tu_wcnt = 2; 343 tuxintr(); 344 break; 345 346 case TUF_CMD: /* sending us an END packet...error */ 347 tu.tu_state = TUS_GET; 348 tu.tu_rbptr = (u_char *) &tudata; 349 tu.tu_rcnt = sizeof (tudata) - 1; 350 tu.tu_flag = 1; 351 mtpr (CSTS, 0); 352 *tu.tu_rbptr = c; 353 break; 354 355 case TUF_INITF: 356 tureset(); 357 break; 358 359 default: /* something random...bad news */ 360 tu.tu_state = TUS_INIT1; 361 break; 362 } 363 break; 364 365 case TUS_SENDW: 366 if (c != TUF_CONT && c != TUF_INITF) 367 goto bad; 368 tureset(); 369 break; 370 371 /* 372 * Got header, now get data; amount to 373 * fetch is included in packet. 374 */ 375 case TUS_GETH: 376 if (MRSP && (tudata.pk_flag == TUF_DATA)) 377 tu.tu_rbptr = (u_char *)tu.tu_addr; 378 tu.tu_rcnt = tudata.pk_mcount; 379 tu.tu_state = TUS_GETD; 380 break; 381 382 /* 383 * Got the data, now fetch the checksum. 384 */ 385 case TUS_GETD: 386 tu.tu_rbptr = (u_char *)&tudata.pk_chksum; 387 tu.tu_rcnt = sizeof (tudata.pk_chksum); 388 tu.tu_state = TUS_GETC; 389 break; 390 391 case TUS_CHKERR: /* from tudma only */ 392 tu.tu_cerrs++; 393 goto tus_get; 394 395 case TUS_GET: 396 if (MRSP) 397 /* 398 * The checksum has already been calculated and 399 * verified in the pseudo DMA routine 400 */ 401 goto tus_get; 402 403 case TUS_GETC: 404 /* got entire packet */ 405 if (tudata.pk_chksum != 406 tuchk(*((short *)&tudata), (u_short *) 407 (tudata.pk_flag == TUF_DATA ? 408 (u_short *) tu.tu_addr : (u_short *)&tudata.pk_op), 409 (int)tudata.pk_mcount)) 410 tu.tu_cerrs++; 411 tus_get: 412 if (tudata.pk_flag == TUF_DATA) { 413 /* data packet, advance to next */ 414 tu.tu_addr += tudata.pk_mcount; 415 tu.tu_count -= tudata.pk_mcount; 416 tu.tu_state = TUS_GETH; 417 tu.tu_rbptr = (u_char *)&tudata; /* next packet */ 418 tu.tu_rcnt = 2; 419 } else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) { 420 /* end packet, idle and reenable transmitter */ 421 tu.tu_state = TUS_IDLE; 422 tu.tu_flag = 0; 423 mtpr(CSTS, IE); 424 printd("ON "); 425 if ((bp = tutab.b_actf) == NULL) { 426 printf("tu%d: no bp, active %d\n", 427 tudata.pk_unit, tutab.b_active); 428 tustart(); 429 return; 430 } 431 if (tudata.pk_mod > 1) { /* hard error */ 432 bp->b_flags |= B_ERROR; 433 tu.tu_herrs++; 434 printf("tu%d: hard error bn%d,", 435 minor(bp->b_dev)&DNUM, bp->b_blkno); 436 printf(" pk_mod %o\n", tudata.pk_mod&0377); 437 } else if (tudata.pk_mod != 0) /* soft error */ 438 tu.tu_serrs++; 439 tutab.b_active = NULL; 440 tutab.b_actf = bp->av_forw; 441 bp->b_resid = tu.tu_count; 442 if ((bp->b_flags&B_READ) == 0) 443 tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); 444 iodone(bp); 445 tustart(); 446 } else { 447 /* 448 * Neither data nor end: data was lost 449 * somehow, restart the transfer 450 */ 451 mtpr(CSRS, 0); /* flush the rest */ 452 tu_restart(); 453 tu.tu_serrs++; 454 } 455 break; 456 457 case TUS_IDLE: 458 case TUS_INIT1: 459 break; 460 461 default: 462 bad: 463 if (c == TUF_INITF) { 464 printf("tu%d protocol error, state=", 465 (int)tudata.pk_unit); 466 printstate(tu.tu_state); 467 printf(", op=%x, cnt=%d, block=%d\n", 468 tucmd.pk_op, tucmd.pk_count, tucmd.pk_block); 469 tutab.b_active = NULL; 470 if (bp = tutab.b_actf) { 471 bp->b_flags |= B_ERROR; 472 tutab.b_actf = bp->av_forw; 473 if ((bp->b_flags&B_READ) == 0) 474 tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); 475 iodone(bp); 476 } 477 tu.tu_state = TUS_INIT1; 478 } else { 479 printf("tu%d: receive state error, state=", 480 (int)tudata.pk_unit); 481 printstate(tu.tu_state); 482 printf(", byte=%x\n", c & 0xff); 483 if (tutab.b_actf) 484 tu_restart(); 485 else 486 wakeup((caddr_t)&tu); 487 } 488 } 489 } 490 491 /* 492 * TU58 transmitter interrupt 493 */ 494 tuxintr() 495 { 496 497 top: 498 if (tu.tu_wcnt) { 499 /* still stuff to send, send one byte */ 500 while ((mfpr(CSTS) & READY) == 0) 501 ; 502 mtpr(CSTD, *tu.tu_wbptr++); 503 tu.tu_wcnt--; 504 return; 505 } 506 507 /* 508 * Last message byte was sent out. 509 * Switch on state of transfer. 510 */ 511 if (tudebug) { 512 printf("tuxintr: state="); 513 printstate(tu.tu_state); 514 } 515 switch(tu.tu_state) { 516 517 /* 518 * Two nulls have been sent, remove break, and send inits 519 */ 520 case TUS_INIT1: 521 mtpr(CSTS, IE); 522 printd("ON2 "); 523 tu.tu_state = TUS_INIT2; 524 tu.tu_wbptr = tuinit; 525 tu.tu_wcnt = sizeof (tuinit); 526 goto top; 527 528 /* 529 * Inits have been sent, wait for a continue msg. 530 */ 531 case TUS_INIT2: 532 (void) mfpr(CSRD); 533 mtpr(CSRS, IE); 534 tu.tu_flag = 1; 535 break; 536 537 /* 538 * Read cmd packet sent, get ready for data 539 */ 540 case TUS_SENDR: 541 tu.tu_state = TUS_GETH; 542 tu.tu_rbptr = (u_char *)&tudata; 543 tu.tu_rcnt = 2; 544 tu.tu_flag = 1; 545 mtpr(CSTS, 0); /* disable transmitter interrupts */ 546 printd("OFF "); 547 break; 548 549 /* 550 * Write cmd packet sent, wait for continue 551 */ 552 case TUS_SENDW: 553 tu.tu_state = TUS_WAIT; 554 tu.tu_flag = 1; 555 if ((mfpr(CSRS)&IE) == 0) { 556 printf("NO IE\n"); 557 mtpr(CSRS, IE); 558 } 559 break; 560 561 /* 562 * Header sent, send data. 563 */ 564 case TUS_SENDH: 565 tu.tu_state = TUS_SENDD; 566 tu.tu_wbptr = (u_char *)tu.tu_addr; 567 tu.tu_wcnt = tudata.pk_mcount; 568 goto top; 569 570 /* 571 * Data sent, follow with checksum. 572 */ 573 case TUS_SENDD: 574 tu.tu_state = TUS_SENDC; 575 tu.tu_wbptr = (u_char *)&tudata.pk_chksum; 576 tu.tu_wcnt = sizeof tudata.pk_chksum; 577 goto top; 578 579 /* 580 * Checksum sent, wait for continue. 581 */ 582 case TUS_SENDC: 583 /* 584 * Updata buffer address and count. 585 */ 586 tu.tu_addr += tudata.pk_mcount; 587 tu.tu_count -= tudata.pk_mcount; 588 if (tu.tu_count) { 589 tu.tu_state = TUS_WAIT; 590 tu.tu_flag = 1; 591 break; 592 } 593 594 /* 595 * End of transmission, get ready for end packet. 596 */ 597 tu.tu_state = TUS_GET; 598 tu.tu_rbptr = (u_char *)&tudata; 599 tu.tu_rcnt = sizeof (tudata); 600 tu.tu_flag = 1; 601 mtpr(CSTS, 0); 602 printd("OFF2 "); 603 break; 604 605 /* 606 * Random interrupt, probably from MRSP ACK 607 */ 608 case TUS_IDLE: 609 610 default: 611 break; 612 613 } 614 if (tudebug) { 615 printd(" new tu_state="); 616 printstate(tu.tu_state); 617 } 618 } 619 620 /* 621 * Compute checksum TU58 fashion 622 */ 623 #ifdef lint 624 tuchk(word, cp, n) 625 register word; 626 register unsigned short *cp; 627 int n; 628 { 629 register int c = n >> 1; 630 register long temp; 631 632 do { 633 temp = *cp++; /* temp, only because vax cc won't *r++ */ 634 word += temp; 635 } while (--c > 0); 636 if (n & 1) 637 word += *(unsigned char *)cp; 638 while (word & 0xffff0000) 639 word = (word & 0xffff) + ((word >> 16) & 0xffff); 640 return (word); 641 } 642 #else 643 tuchk(word0, wp, n) 644 register int word0; /* r11 */ 645 register u_short *wp; /* r10 */ 646 register int n; /* r9 */ 647 { 648 asm("loop:"); 649 asm(" addw2 (r10)+,r11"); /* add a word to sum */ 650 asm(" adwc $0,r11"); /* add in carry, end-around */ 651 asm(" acbl $2,$-2,r9,loop"); /* done yet? */ 652 asm(" blbc r9,ok"); /* odd byte count? */ 653 asm(" movzbw (r10),r10"); /* yes, get last byte */ 654 asm(" addw2 r10,r11"); /* add it in */ 655 asm(" adwc $0,r11"); /* and the carry */ 656 asm("ok:"); 657 asm(" movl r11,r0"); /* return sum */ 658 } 659 #endif 660 661 tuwatch() 662 { 663 register int s; 664 register struct buf *bp; 665 666 if (tutimer == 0) 667 return; 668 669 if (tu.tu_flag == 0) { /* if no read in progress - skip */ 670 timeout(tuwatch, (caddr_t)0, hz); 671 return; 672 } 673 if (tu.tu_flag++ <= 40) { 674 timeout(tuwatch, (caddr_t)0, hz); 675 return; 676 } 677 printf("tu%d: read stalled\n", tudata.pk_unit); 678 #ifdef TUDEBUG 679 printf("%X %X %X %X %X %X %X %X\n", tu.tu_rbptr, tu.tu_rcnt, 680 tu.tu_wbptr, tu.tu_wcnt, tu.tu_state, tu.tu_flag, 681 tu.tu_addr, tu.tu_count); 682 #endif 683 s = spltu(); 684 tu.tu_flag = 0; 685 (void) mfpr(CSRD); 686 mtpr(CSRS, IE); /* in case we were flushing */ 687 mtpr(CSTS, IE); 688 tu.tu_state = TUS_IDLE; 689 if (!tutab.b_active) { 690 wakeup((caddr_t)&tu); 691 goto retry; 692 } 693 if (++tutab.b_errcnt <= 1) { 694 tustart(); 695 goto retry; 696 } 697 if (bp = tutab.b_actf) { 698 bp->b_flags |= B_ERROR; 699 if ((bp->b_flags&B_READ) == 0) 700 tu_vee(&tu_pcnt[minor(bp->b_dev)&DNUM]); 701 iodone(bp); 702 } 703 retry: 704 splx(s); 705 timeout(tuwatch, (caddr_t)0, hz); 706 } 707 708 tu_pee(cp) 709 char *cp; 710 { 711 register int s; 712 713 s = spltu(); 714 if (++(*cp) > NTUQ) 715 sleep(cp, PRIBIO); 716 splx(s); 717 } 718 719 tu_vee(cp) 720 char *cp; 721 { 722 register int s; 723 724 s = spltu(); 725 if (--(*cp) <= NTUQ) 726 wakeup(cp); 727 splx(s); 728 } 729 730 tu_restart() 731 { 732 tureset(); 733 timeout(tustart, (caddr_t)0, hz * 3); 734 } 735 736 #endif 737