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:  *	@(#)uu.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "uu.h"
  10: #if NUU > 0
  11: /*
  12:  * TU58 DECtape II/DL11 device driver
  13:  *
  14:  * The TU58 is treated as a block device (only).  Error detection and
  15:  * recovery is not very extensive, but sufficient to handle the most
  16:  * common errors. It is assumed that the TU58 will follow the RSP
  17:  * protocol exactly, very few protocol errors are checked for.
  18:  *
  19:  * To reduce interrupt latency, `options UUDMA' should be specified
  20:  * in the config file to make sure the `pseudo-DMA' code in locore.s
  21:  * will be compiled into the system. Otherwise overrun errors will
  22:  * occur frequently (these errors are not reported).
  23:  *
  24:  * TODO:
  25:  *
  26:  * - Add ioctl code to wind/rewind cassette
  27:  *
  28:  */
  29: 
  30: #include "../machine/pte.h"
  31: 
  32: #include "param.h"
  33: #include "systm.h"
  34: #include "buf.h"
  35: #include "conf.h"
  36: #include "time.h"
  37: #include "kernel.h"
  38: #include "errno.h"
  39: #include "file.h"
  40: 
  41: #include "../vax/cpu.h"
  42: #include "../vax/nexus.h"
  43: #include "../vax/rsp.h"
  44: 
  45: #include "ubavar.h"
  46: #include "ubareg.h"
  47: #include "uureg.h"
  48: 
  49: #define NTUBLK  512     /* number of blocks on a TU58 cassette */
  50: #define WRV     01              /* bit in minor dev => write w. read verify */
  51: #define NDPC    02      /* drives per controller */
  52: #define NUX NDPC * NUU  /* number of drives */
  53: #define NUUQ    02      /* # of block which can be queued up */
  54: #define UMASK   01      /* unit number mask */
  55: #define UUIPL   0x14        /* ipl level to use */
  56: 
  57: struct packet uucmd[NUU];   /* a command sent to the TU58 */
  58: struct packet uudata[NUU];  /* a command or data returned from TU58 */
  59: struct buf uitab[NUU];      /* buffer queue headers */
  60: 
  61: /*
  62:  * Driver soft carrier structure
  63:  */
  64: struct uu_softc {
  65:     u_char  *tu_rbptr;  /* pointer to buffer for read */
  66:     int tu_rcnt;    /* how much to read */
  67:     u_char  *tu_wbptr;  /* pointer to buffer for write */
  68:     int tu_wcnt;    /* how much to write */
  69:     int tu_state;   /* current state of tansfer operation */
  70:     int tu_flag;    /* read in progress flag */
  71:     char    *tu_addr;   /* real buffer data address */
  72:     int tu_count;   /* real requested count */
  73:     int tu_serrs;   /* count of soft errors */
  74:     int tu_cerrs;   /* count of checksum errors */
  75:     int tu_herrs;   /* count of hard errors */
  76:     char    tu_dopen[2];    /* drive is open */
  77: } uu_softc[NUU];
  78: 
  79: #if defined(VAX750) || defined(VAX730)
  80: extern char *tustates[];
  81: #else
  82: char *tustates[TUS_NSTATES] = {
  83:     "INIT1", "INIT2", "IDLE", "SENDH", "SENDD", "SENDC", "SENDR",
  84:     "SENDW", "GETH", "GETD", "GETC", "GET", "WAIT", "RCVERR", "CHKERR"
  85: };
  86: #endif
  87: 
  88: #define UNIT(dev)   (minor(dev)>>1)
  89: 
  90: u_char  uunull[2] = { 0, 0 };       /* nulls to send for initialization */
  91: u_char  uuinit[2] = { TUF_INITF, TUF_INITF };   /* inits to send */
  92: 
  93: struct  uba_device  *uudinfo[NUU];
  94: 
  95: int uuprobe(), uuattach(), uurintr(), uuxintr(), uuwatch();
  96: u_short uustd[] = { 0176500, 0 };
  97: struct uba_driver uudriver =
  98:     { uuprobe, 0, uuattach, 0, uustd, "uu", uudinfo };
  99: 
 100: int uuwstart;
 101: int uuwake();
 102: static char uu_pcnt[NUX];       /* pee/vee counters, one per drive */
 103: 
 104: /*ARGSUSED*/
 105: uuprobe(reg)
 106:     caddr_t reg;
 107: {
 108:     register int br, cvec;          /* value result */
 109:     struct uudevice *uuaddr = (struct uudevice *)reg;
 110: 
 111: #ifdef lint
 112:     br = 0; cvec = br; br = cvec;
 113:     uurintr(0); uuxintr(0);
 114: #endif
 115:     uuaddr->tcs = UUCS_INTR;
 116:     DELAY(1000);
 117:     uuaddr->tcs = 0;
 118:     cvec -= 4;      /* since we are using the xmitter intrpt */
 119:     return(sizeof (*uuaddr));
 120: }
 121: 
 122: uuattach(ui)
 123:     register struct uba_device *ui;
 124: {
 125: }
 126: 
 127: /*ARGSUSED1*/
 128: uuopen(dev, flag)
 129:     dev_t dev;
 130:     int flag;
 131: {
 132:     register struct uba_device *ui;
 133:     register struct uu_softc *uuc;
 134:     register struct uudevice *uuaddr;
 135:     int ctlr, unit = UNIT(dev), s;
 136: 
 137:     ctlr = unit / NDPC;
 138:     if (unit >= NUX || (ui = uudinfo[ctlr]) == 0 || ui->ui_alive == 0)
 139:         return (ENXIO);
 140:     uuc = &uu_softc[ctlr];
 141:     if (uuc->tu_dopen[unit&UMASK])
 142:         return (EBUSY);
 143:     if (uuwstart++ == 0)
 144:         timeout(uuwatch, (caddr_t)0, hz);
 145: 
 146:     uuc->tu_dopen[unit&UMASK]++;
 147:     uuaddr = (struct uudevice *)ui->ui_addr;
 148:     s = splx(UUIPL);
 149:     /*
 150: 	 * If the other device on this controller
 151: 	 * is already active, no need to initialize
 152: 	 */
 153:     if (uuc->tu_dopen[0] && uuc->tu_dopen[1])
 154:         goto ok;
 155: 
 156:     /*
 157: 	 * If the unit already initialized,
 158: 	 * just enable interrupts and return.
 159: 	 */
 160:     if (uuc->tu_state == TUS_IDLE) {
 161:         uuaddr->rcs = UUCS_INTR;
 162:         goto ok;
 163:     }
 164: 
 165:     /*
 166: 	 * Must initialize, reset the cassette
 167: 	 * and wait for things to settle down.
 168: 	 */
 169:     uureset(ctlr);
 170:     sleep((caddr_t)uuc, PZERO+1);
 171:     uitab[ctlr].b_active = NULL;
 172:     if (uuc->tu_state != TUS_IDLE) {
 173:         uuc->tu_state = TUS_INIT1;
 174:         uuc->tu_dopen[unit&UMASK] = 0;
 175:         uuc->tu_rcnt = uuc->tu_wcnt = 0;
 176:         uuaddr->rcs = 0;
 177:         uuaddr->tcs = 0;
 178:         splx(s);
 179:         return (EIO);
 180:     }
 181: ok:
 182:     splx(s);
 183:     return (0);
 184: }
 185: 
 186: /*
 187:  * Wait for all outstanding IO on this drive
 188:  * complete, before closing. If both drives on
 189:  * this controller are idle, mark the controller
 190:  * `inactive'.
 191:  */
 192: 
 193: uuclose(dev, flag)
 194:     dev_t dev;
 195:     int flag;
 196: {
 197:     int s, unit = UNIT(dev);
 198:     register struct uu_softc *uuc = &uu_softc[unit/NDPC];
 199:     struct buf *bp, *last = NULL;
 200:     struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr;
 201: 
 202:     s = splx(UUIPL);
 203:     while (uu_pcnt[unit])
 204:         sleep(&uu_pcnt[unit], PRIBIO);
 205:     /*
 206: 	 * No more writes are pending, scan the
 207: 	 * buffer queue for oustanding reads from
 208: 	 * this unit.
 209: 	 */
 210:     for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) {
 211:         if (bp->b_dev == dev)
 212:             last = bp;
 213:     }
 214:     if (last) {
 215:         last->b_flags |= B_CALL;
 216:         last->b_iodone = uuwake;
 217:         sleep((caddr_t)last, PRIBIO);
 218:     }
 219:     uuc->tu_dopen[unit&UMASK] = 0;
 220:     if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) {
 221:         uuc->tu_flag = 0;
 222:         uuaddr->rcs = 0;
 223:     }
 224:     splx(s);
 225: }
 226: 
 227: uuwake(bp)
 228:     struct buf *bp;
 229: {
 230:     wakeup(bp);
 231: }
 232: 
 233: uureset(ctlr)
 234:     int ctlr;
 235: {
 236:     register struct uu_softc *uuc = &uu_softc[ctlr];
 237:     register struct packet *cmd = &uucmd[ctlr];
 238:     struct uba_device *ui = uudinfo[ctlr];
 239:     register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
 240: 
 241:     uitab[ctlr].b_active++;
 242:     uuc->tu_state = TUS_INIT1;
 243:     uuc->tu_wbptr = uunull;
 244:     uuc->tu_wcnt = sizeof (uunull);
 245:     uuc->tu_rcnt = 0;
 246:     cmd->pk_flag = TUF_CMD;
 247:     cmd->pk_mcount = sizeof (*cmd) - 4;
 248:     cmd->pk_mod = 0;
 249:     cmd->pk_seq = 0;
 250:     cmd->pk_sw = 0;
 251:     uuaddr->rcs = 0;
 252:     uuaddr->tcs = UUCS_INTR | UUCS_BREAK;
 253:     uuxintr(ctlr);              /* start output */
 254: }
 255: 
 256: /*
 257:  * Strategy routine for block I/O
 258:  */
 259: uustrategy(bp)
 260:     register struct buf *bp;
 261: {
 262:     register struct buf *uutab;
 263:     struct uba_device *ui;
 264:     int s, unit = UNIT(bp->b_dev);
 265: 
 266:     if ((unit > NUX) || (bp->b_blkno >= NTUBLK))
 267:         goto bad;
 268:     ui = uudinfo[unit/NDPC];
 269:     if (ui == 0 || ui->ui_alive == 0)
 270:         goto bad;
 271:     uutab = &uitab[unit/NDPC];  /* one request queue per controller */
 272:     s = splx(UUIPL);
 273:     if ((bp->b_flags&B_READ) == 0)
 274:         tu_pee(&uu_pcnt[unit]);
 275:     bp->b_actf = NULL;
 276:     if (uutab->b_actf == NULL)
 277:         uutab->b_actf = bp;
 278:     else
 279:         uutab->b_actl->b_actf = bp;
 280:     uutab->b_actl = bp;
 281:     if (uutab->b_active == 0)
 282:         uustart(ui);
 283:     splx(s);
 284:     return;
 285: 
 286: bad:
 287:     bp->b_flags |= B_ERROR;
 288:     bp->b_error = ENXIO;
 289:     iodone(bp);
 290:     return;
 291: }
 292: 
 293: /*
 294:  * Start the transfer
 295:  */
 296: uustart(ui)
 297:     register struct uba_device *ui;
 298: {
 299:     register struct buf *bp;
 300:     register struct uu_softc *uuc;
 301:     struct packet *cmd;
 302:     int ctlr = ui->ui_unit, s;
 303: 
 304:     if ((bp = uitab[ctlr].b_actf) == NULL)
 305:         return;
 306:     s = splx(UUIPL);
 307:     uuc = &uu_softc[ctlr];
 308:     if (uuc->tu_state != TUS_IDLE) {
 309:         uureset(ctlr);
 310:         splx(s);
 311:         return;
 312:     }
 313:     cmd = &uucmd[ctlr];
 314:     uitab[ctlr].b_active++;
 315:     uitab[ctlr].b_errcnt = 0;
 316:     uuc->tu_addr = bp->b_un.b_addr;
 317:     uuc->tu_count = cmd->pk_count = bp->b_bcount;
 318:     cmd->pk_block = bp->b_blkno;
 319:     if (bp->b_flags&B_READ) {
 320:         cmd->pk_op = TUOP_READ;
 321:         cmd->pk_mod = 0;
 322:         uuc->tu_state = TUS_SENDR;
 323:     } else {
 324:         cmd->pk_op = TUOP_WRITE;
 325:         cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0;
 326:         uuc->tu_state = TUS_SENDW;
 327:     }
 328:     cmd->pk_unit = UNIT(bp->b_dev)&UMASK;
 329:     cmd->pk_sw = 0;
 330:     cmd->pk_chksum =
 331:         tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount);
 332:     uuc->tu_wbptr = (u_char *)cmd;
 333:     uuc->tu_wcnt = sizeof (*cmd);
 334:     uuxintr(ctlr);
 335:     splx(s);
 336: }
 337: 
 338: /*
 339:  * TU58 receiver interrupt, handles whatever condition the
 340:  * pseudo DMA routine in locore is unable to handle,
 341:  * or, if UUDMA is undefined, handle all receiver interrupt
 342:  * processing.
 343:  */
 344: uurintr(ctlr)
 345:     int ctlr;
 346: {
 347:     struct uba_device *ui = uudinfo[ctlr];
 348:     register struct uu_softc *uuc = &uu_softc[ctlr];
 349:     register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr;
 350:     register struct buf *uutab = &uitab[ctlr];
 351:     struct packet *data, *cmd;
 352:     struct buf *bp;
 353:     int c, unit;
 354: 
 355:     c = uuaddr->rdb;
 356:     data = &uudata[ctlr];
 357:     cmd = &uucmd[ctlr];
 358: #if !defined(UUDMA)
 359:     if (c & UURDB_ERROR)
 360:         uuc->tu_state = TUS_RCVERR;
 361:     else {
 362:         if (uuc->tu_rcnt) {
 363:             *uuc->tu_rbptr++ = c;
 364:             if (--uuc->tu_rcnt)
 365:                 return;
 366:         }
 367:     }
 368: #endif
 369: 
 370:     /*
 371: 	 * Switch on the tu_state of the transfer.
 372: 	 */
 373:     switch(uuc->tu_state) {
 374: 
 375:     /*
 376: 	 * A data error occured in uudma
 377: 	 * (either overrun or break)
 378: 	 */
 379:     case TUS_RCVERR:
 380:         if ((c & UURDB_ORUN) == 0)
 381:             printf("uu%d: break received, transfer restarted\n",
 382:                 data->pk_unit);
 383: #ifdef UUDEBUG
 384:         else
 385:             printf("uu%d: data overrun, recovered\n",
 386:                 data->pk_unit);
 387: #endif
 388:         uuc->tu_serrs++;
 389:         uu_restart(ctlr, ui);
 390:         break;
 391: 
 392:     /*
 393: 	 * If we get an unexpected "continue",
 394: 	 * start all over again...
 395: 	 */
 396:     case TUS_INIT2:
 397:         uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1;
 398:         uuc->tu_flag = 0;
 399:         wakeup((caddr_t)uuc);
 400:         uustart(ui);
 401:         break;
 402: 
 403:     /*
 404: 	 * Only transition from this state
 405: 	 * is on a "continue", so if we don't
 406: 	 * get it, reset the world.
 407: 	 */
 408:     case TUS_WAIT:          /* waiting for continue */
 409:         switch(c) {
 410:         case TUF_CONT:  /* got the expected continue */
 411:             uuc->tu_flag = 0;
 412:             data->pk_flag = TUF_DATA;
 413:             data->pk_mcount = MIN(128, uuc->tu_count);
 414:             data->pk_chksum =
 415:                 tuchk(*((short *)data), (caddr_t)uuc->tu_addr,
 416:                 (int)data->pk_mcount);
 417:             uuc->tu_state = TUS_SENDH;
 418:             uuc->tu_wbptr = (u_char *)data;
 419:             uuc->tu_wcnt = 2;
 420:             uuxintr(ctlr);
 421:             break;
 422: 
 423:         case TUF_CMD:   /* sending us an END packet...error */
 424:             uuc->tu_state = TUS_GET;
 425:             uuc->tu_rbptr = (u_char *)data;
 426:             uuc->tu_rcnt = sizeof (*data) - 1;
 427:             uuc->tu_flag = 1;
 428:             uuaddr->tcs = 0;
 429:             *uuc->tu_rbptr++ = c & UUDB_DMASK;
 430:             break;
 431: 
 432:         case TUF_INITF:
 433:             uureset(ctlr);
 434:             break;
 435: 
 436:         default:        /* something random...bad news */
 437:             uuc->tu_state = TUS_INIT1;
 438:             break;
 439:         }
 440:         break;
 441: 
 442:     case TUS_SENDW:
 443:         if (c != TUF_CONT && c != TUF_INITF)
 444:             goto bad;
 445:         uu_restart(ctlr, ui);
 446:         break;
 447: 
 448:     /*
 449: 	 * Got header, now get data; amount to
 450: 	 * fetch is included in packet.
 451: 	 * (data packets are handled entirely
 452: 	 * in uudma)
 453: 	 */
 454:     case TUS_GETH:
 455: #ifndef UUDMA
 456:         if (data->pk_flag == TUF_DATA)
 457:             uuc->tu_rbptr = (u_char *)uuc->tu_addr;
 458: #endif
 459:         uuc->tu_rcnt = data->pk_mcount;
 460:         uuc->tu_state = TUS_GETD;
 461:         break;
 462: 
 463:     /*
 464: 	 * Got the data, now fetch the checksum.
 465: 	 */
 466:     case TUS_GETD:
 467:         uuc->tu_rbptr = (u_char *)&data->pk_chksum;
 468:         uuc->tu_rcnt = sizeof (data->pk_chksum);
 469:         uuc->tu_state = TUS_GETC;
 470:         break;
 471: 
 472:     case TUS_GETC:
 473:         /* got entire packet */
 474:         if (data->pk_chksum !=
 475:             tuchk(*((short *)data), (u_short *)
 476:              (data->pk_flag == TUF_DATA ?
 477:              (u_short *) uuc->tu_addr : (u_short *)&data->pk_op),
 478:              (int)data->pk_mcount))
 479:     case TUS_CHKERR:
 480:             uuc->tu_cerrs++;
 481:     case TUS_GET:
 482:         if (data->pk_flag == TUF_DATA) {
 483:             /* data packet, advance to next */
 484:             uuc->tu_addr += data->pk_mcount;
 485:             uuc->tu_count -= data->pk_mcount;
 486:             uuc->tu_state = TUS_GETH;
 487:             uuc->tu_rbptr = (u_char *)data; /* next packet */
 488:             uuc->tu_rcnt = 2;
 489:         } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) {
 490:             /* end packet, idle and reenable transmitter */
 491:             uuc->tu_state = TUS_IDLE;
 492:             uuc->tu_flag = 0;
 493:             uuaddr->tcs = UUCS_INTR;
 494:             if ((bp = uutab->b_actf) == NULL) {
 495:                 printf("uu%d: no bp, active %d\n",
 496:                     data->pk_unit, uitab[ctlr].b_active);
 497:                 uustart(ui);
 498:                 return;
 499:             }
 500:             unit = UNIT(bp->b_dev);
 501:             if (data->pk_mod > 1) {        /* hard error */
 502:                 printf("uu%d: hard error bn%d,", unit,
 503:                     bp->b_blkno);
 504:                 printf(" pk_mod 0%o\n", data->pk_mod&0xff);
 505:                 bp->b_flags |= B_ERROR;
 506:                 uuc->tu_herrs++;
 507:             } else if (data->pk_mod)    /* soft error */
 508:                 uuc->tu_serrs++;
 509:             uutab->b_active = NULL;
 510:             uutab->b_actf = bp->b_actf;
 511:             bp->b_resid = uuc->tu_count;
 512:             if ((bp->b_flags&B_READ) == 0)
 513:                 tu_vee(&uu_pcnt[unit]);
 514:             iodone(bp);
 515:             uustart(ui);
 516:         } else {
 517:             /*
 518: 			 * Neither data nor end: data was lost
 519: 			 * somehow, flush and restart the transfer.
 520: 			 */
 521:             uuaddr->rcs = 0;
 522:             uu_restart(ctlr, ui);
 523:             uuc->tu_serrs++;
 524:         }
 525:         break;
 526: 
 527:     case TUS_IDLE:
 528:     case TUS_INIT1:
 529:         break;
 530: 
 531:     default:
 532: bad:
 533:         if (c == TUF_INITF) {
 534:             printf("uu%d protocol error, state=", data->pk_unit);
 535:             printstate(uuc->tu_state);
 536:             printf(", op=%x, cnt=%d, block=%d\n",
 537:                 cmd->pk_op, cmd->pk_count, cmd->pk_block);
 538:             uutab->b_active = NULL;
 539:             if (bp = uutab->b_actf) {
 540:                 bp->b_flags |= B_ERROR;
 541:                 uutab->b_actf = bp->b_actf;
 542:                 if ((bp->b_flags&B_READ) == 0)
 543:                     tu_vee(&uu_pcnt[unit]);
 544:                 iodone(bp);
 545:             }
 546:             uuc->tu_state = TUS_INIT1;
 547:         } else {
 548:             printf("uu%d receive state error, state=",
 549:                 data->pk_unit);
 550:             printstate(uuc->tu_state);
 551:             printf(", byte=%x\n", c & 0xff);
 552: #ifdef notdef
 553:             uuc->tu_state = TUS_INIT1;
 554: #endif
 555:             wakeup((caddr_t)uuc);
 556:         }
 557:     }
 558: }
 559: 
 560: 
 561: /*
 562:  * TU58 transmitter interrupt
 563:  */
 564: uuxintr(ctlr)
 565:     int ctlr;
 566: {
 567:     register struct uu_softc *uuc = &uu_softc[ctlr];
 568:     register struct uudevice *uuaddr;
 569:     register struct packet *data;
 570:     struct uba_device *ui = uudinfo[ctlr];
 571:     int c;
 572: 
 573:     data = &uudata[ctlr];
 574:     uuaddr = (struct uudevice *) ui->ui_addr;
 575: top:
 576:     if (uuc->tu_wcnt > 0) {
 577:         /* still stuff to send, send one byte */
 578:         while ((uuaddr->tcs & UUCS_READY) == 0)
 579:             ;
 580:         uuaddr->tdb = *uuc->tu_wbptr++;
 581:         uuc->tu_wcnt--;
 582:         return;
 583:     }
 584: 
 585:     /*
 586: 	 * Last message byte was sent out.
 587: 	 * Switch on tu_state of transfer.
 588: 	 */
 589:     switch(uuc->tu_state) {
 590: 
 591:     /*
 592: 	 * Two nulls have been sent, remove break, and send inits
 593: 	 */
 594:     case TUS_INIT1:
 595:         uuc->tu_flag = 0;
 596:         uuaddr->tcs = UUCS_INTR;
 597:         uuc->tu_state = TUS_INIT2;
 598:         uuc->tu_wbptr = uuinit;
 599:         uuc->tu_wcnt = sizeof (uuinit);
 600:         goto top;
 601: 
 602:     /*
 603: 	 * Inits have been sent, wait for a continue msg.
 604: 	 */
 605:     case TUS_INIT2:
 606:         c = uuaddr->rdb;    /* prevent overrun error */
 607:         uuaddr->rcs = UUCS_INTR;
 608:         uuc->tu_flag = 1;
 609:         break;
 610: 
 611:     /*
 612: 	 * Read cmd packet sent, get ready for data
 613: 	 */
 614:     case TUS_SENDR:
 615:         uuc->tu_state = TUS_GETH;
 616:         uuc->tu_rbptr = (u_char *)data;
 617:         uuc->tu_rcnt = 2;
 618:         uuc->tu_flag = 1;
 619:         uuaddr->tcs = 0;
 620:         uuaddr->rcs = UUCS_INTR;
 621:         break;
 622: 
 623:     /*
 624: 	 * Write cmd packet sent, wait for continue
 625: 	 */
 626:     case TUS_SENDW:
 627:         uuc->tu_state = TUS_WAIT;
 628:         uuc->tu_flag = 1;
 629:         if ((uuaddr->rcs&UUCS_INTR) == 0) {
 630:             printf("NO IE\n");
 631:             uuaddr->rcs = UUCS_INTR;
 632:         }
 633:         break;
 634: 
 635:     /*
 636: 	 * Header sent, send data.
 637: 	 */
 638:     case TUS_SENDH:
 639:         uuc->tu_state = TUS_SENDD;
 640:         uuc->tu_wbptr = (u_char *)uuc->tu_addr;
 641:         uuc->tu_wcnt = data->pk_mcount;
 642:         goto top;
 643: 
 644:     /*
 645: 	 * Data sent, follow with checksum.
 646: 	 */
 647:     case TUS_SENDD:
 648:         uuc->tu_state = TUS_SENDC;
 649:         uuc->tu_wbptr = (u_char *)&data->pk_chksum;
 650:         uuc->tu_wcnt = 2;
 651:         goto top;
 652: 
 653:     /*
 654: 	 * Checksum sent, wait for continue.
 655: 	 */
 656:     case TUS_SENDC:
 657:         /*
 658: 		 * Update buffer address and count.
 659: 		 */
 660:         uuc->tu_addr += data->pk_mcount;
 661:         uuc->tu_count -= data->pk_mcount;
 662:         if (uuc->tu_count > 0) {
 663:             uuc->tu_state = TUS_WAIT;
 664:             uuc->tu_flag = 1;
 665:             break;
 666:         }
 667: 
 668:         /*
 669: 		 * End of transmission, get ready for end packet.
 670: 		 */
 671:         uuc->tu_state = TUS_GET;
 672:         uuc->tu_rbptr = (u_char *)data;
 673:         uuc->tu_rcnt = sizeof (*data);
 674:         uuc->tu_flag = 1;
 675:         uuaddr->tcs = 0;
 676:         break;
 677: 
 678:     /*
 679: 	 * Random interrupt
 680: 	 */
 681:     case TUS_IDLE:      /* stray interrupt? */
 682: 
 683:     default:
 684:         break;
 685:     }
 686: }
 687: 
 688: uuwatch()
 689: {
 690:     register struct uu_softc *uuc;
 691:     register struct uudevice *uuaddr;
 692:     struct uba_device *ui;
 693:     struct buf *bp, *uutab;
 694:     int s, ctlr, active = 0;
 695: 
 696:     for (ctlr=0; ctlr<NUU; ctlr++) {
 697:         int i;
 698: 
 699:         uuc = &uu_softc[ctlr];
 700: 
 701:         if (uuc->tu_dopen[0] || uuc->tu_dopen[1])
 702:             active++;
 703:         if (uuc->tu_flag == 0)
 704:             /*
 705: 			 * If no read is in progress
 706: 			 * just skip
 707: 			 */
 708:             continue;
 709: 
 710:         ui = uudinfo[ctlr];
 711:         uuaddr = (struct uudevice *)ui->ui_addr;
 712:         uutab = &uitab[ctlr];
 713:         if (uuc->tu_flag++ < 40)
 714:             continue;
 715:         printf("uu%d: read stalled\n", uudata[ctlr].pk_unit);
 716: #ifdef UUDEBUG
 717:         printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt,
 718:                uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr,
 719:                uuc->tu_count);
 720: #endif
 721:         s = splx(UUIPL);
 722:         uuc->tu_flag = 0;
 723:         i = uuaddr->rdb;        /* dummy */
 724:         uuaddr->rcs = UUCS_INTR;    /* in case we were flushing */
 725:         uuaddr->tcs = UUCS_INTR;
 726:         uuc->tu_state = TUS_IDLE;
 727:         if (!uutab->b_active) {
 728:             wakeup((caddr_t)uuc);
 729:             goto retry;
 730:         }
 731:         if (++uutab->b_errcnt <= 1) {
 732:             uustart(ui);
 733:             goto retry;
 734:         }
 735:         if (bp = uutab->b_actf) {
 736:             bp->b_flags |= B_ERROR;
 737:             if ((bp->b_flags&B_READ) == 0)
 738:                 tu_vee(&uu_pcnt[UNIT(bp->b_dev)]);
 739:             iodone(bp);
 740:         }
 741: retry:
 742:         (void) splx(s);
 743:     }
 744:     if (active)
 745:         timeout(uuwatch, (caddr_t)0, hz);
 746:     else
 747:         uuwstart = 0;
 748:     return;
 749: }
 750: 
 751: #if !defined(VAX750) && !defined(VAX730)
 752: /*
 753:  * Compute checksum TU58 fashion
 754:  */
 755: #ifdef lint
 756: tuchk(word, cp, n)
 757:     register word;
 758:     register unsigned short *cp;
 759:     int n;
 760: {
 761:     register int c = n >> 1;
 762:     register long temp;
 763: 
 764:     do {
 765:         temp = *cp++;   /* temp, only because vax cc won't *r++ */
 766:         word += temp;
 767:     } while (--c > 0);
 768:     if (n & 1)
 769:         word += *(unsigned char *)cp;
 770:     while (word & 0xffff0000)
 771:         word = (word & 0xffff) + ((word >> 16) & 0xffff);
 772:     return (word);
 773: }
 774: #else
 775: tuchk(word0, wp, n)
 776:     register int word0;         /* r11 */
 777:     register char *wp;          /* r10 */
 778:     register int n;             /* r9 */
 779: {
 780:     asm("loop:");
 781:     asm("	addw2	(r10)+,r11");       /* add a word to sum */
 782:     asm("	adwc	$0,r11");        /* add in carry, end-around */
 783:     asm("	acbl	$2,$-2,r9,loop");    /* done yet? */
 784:     asm("	blbc	r9,ok");     /* odd byte count? */
 785:     asm("	movzbw	(r10),r10");       /* yes, get last byte */
 786:     asm("	addw2	r10,r11");      /* add it in */
 787:     asm("	adwc	$0,r11");        /* and the carry */
 788:     asm("ok:");
 789:     asm("	movl	r11,r0");        /* return sum */
 790: }
 791: #endif
 792: 
 793: /*
 794:  * Make sure this incredibly slow device
 795:  * doesn't eat up all the buffers in the
 796:  * system by putting the requesting process
 797:  * (remember: this device is 'single-user')
 798:  * to sleep if the write-behind queue grows
 799:  * larger than NUUQ.
 800:  */
 801: tu_pee(cp)
 802:     char *cp;
 803: {
 804:     register int s;
 805: 
 806:     s = splx(UUIPL);
 807:     if (++(*cp) > NUUQ)
 808:         sleep(cp, PRIBIO);
 809:     splx(s);
 810: }
 811: 
 812: tu_vee(cp)
 813:     char *cp;
 814: {
 815:     register int s;
 816: 
 817:     s = splx(UUIPL);
 818:     if (--(*cp) <= NUUQ)
 819:         wakeup(cp);
 820:     splx(s);
 821: }
 822: #endif
 823: 
 824: uuioctl(dev, cmd, data, flag)
 825:     dev_t dev;
 826:     caddr_t data;
 827: {
 828:     /*
 829: 	 * add code to wind/rewind cassette here
 830: 	 */
 831:     return (ENXIO);
 832: }
 833: 
 834: uu_restart(ctlr, ui)
 835:     int ctlr;
 836:     struct uba_device *ui;
 837: {
 838:     uureset(ctlr);
 839:     timeout(uustart, (caddr_t)ui, hz * 3);
 840: }
 841: 
 842: #endif

Defined functions

tu_pee defined in line 801; used 1 times
tu_vee defined in line 812; used 3 times
tuchk defined in line 775; used 3 times
uu_restart defined in line 834; used 3 times
uuattach defined in line 122; used 2 times
uuclose defined in line 193; never used
uuioctl defined in line 824; never used
uuopen defined in line 128; never used
uuprobe defined in line 105; used 2 times
uureset defined in line 233; used 4 times
uurintr defined in line 344; used 2 times
uustart defined in line 296; used 6 times
uustrategy defined in line 259; never used
uuwake defined in line 227; used 2 times
uuwatch defined in line 688; used 3 times
uuxintr defined in line 564; used 5 times

Defined variables

tustates declared in line 80; defined in line 82; never used
uitab defined in line 59; used 10 times
uu_pcnt defined in line 102; used 6 times
uu_softc defined in line 77; used 8 times
uucmd defined in line 57; used 3 times
uudata defined in line 58; used 4 times
uudinfo defined in line 93; used 9 times
uudriver defined in line 97; never used
uuinit defined in line 91; used 2 times
uunull defined in line 90; used 2 times
uustd defined in line 96; used 1 times
  • in line 98
uuwstart defined in line 100; used 2 times

Defined struct's

uu_softc defined in line 64; used 14 times

Defined macros

NDPC defined in line 51; used 7 times
NTUBLK defined in line 49; used 1 times
NUUQ defined in line 53; used 2 times
NUX defined in line 52; used 3 times
UMASK defined in line 54; used 5 times
UNIT defined in line 88; used 6 times
UUIPL defined in line 55; used 7 times
WRV defined in line 50; used 1 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1920
Valid CSS Valid XHTML 1.0 Strict