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