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