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