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) 6/5/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