|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.