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

Defined functions

tu_pee defined in line 704; used 1 times
tu_restart defined in line 726; used 3 times
tu_vee defined in line 715; used 3 times
tuchk defined in line 639; used 3 times
tuclose defined in line 153; never used
tuopen defined in line 101; never used
tureset defined in line 195; used 5 times
turintr defined in line 278; used 2 times
tustart defined in line 242; used 6 times
tustrategy defined in line 215; never used
tuwake defined in line 186; used 2 times
tuwatch defined in line 657; used 5 times
tuxintr defined in line 490; used 4 times

Defined variables

tu defined in line 71; used 115 times
tu_pcnt defined in line 92; used 6 times
tucmd defined in line 82; used 21 times
tudata defined in line 83; used 40 times
tudebug defined in line 41; used 3 times
tuinit defined in line 91; used 2 times
tunull defined in line 90; used 2 times
tustates defined in line 85; never used
tutab defined in line 95; used 22 times
tutimer defined in line 93; used 3 times

Defined struct's

tu defined in line 58; never used

Defined macros

BREAK defined in line 80; used 1 times
DNUM defined in line 45; used 11 times
DONE defined in line 78; never used
IE defined in line 79; used 9 times
MRSP defined in line 52; used 6 times
NTU defined in line 44; used 1 times
NTUBLK defined in line 46; used 1 times
NTUQ defined in line 48; used 2 times
READY defined in line 77; used 2 times
WRV defined in line 47; used 1 times
printd defined in line 39; used 6 times
spltu defined in line 49; used 7 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1930
Valid CSS Valid XHTML 1.0 Strict