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