|
|
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.4 (Berkeley) 4/3/90 ! 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, error; ! 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: if (error = tsleep((caddr_t)uuc, (PZERO+1) | PCATCH, devopn, 0)) { ! 171: splx(s); ! 172: return (error); ! 173: } ! 174: uitab[ctlr].b_active = NULL; ! 175: if (uuc->tu_state != TUS_IDLE) { ! 176: uuc->tu_state = TUS_INIT1; ! 177: uuc->tu_dopen[unit&UMASK] = 0; ! 178: uuc->tu_rcnt = uuc->tu_wcnt = 0; ! 179: uuaddr->rcs = 0; ! 180: uuaddr->tcs = 0; ! 181: splx(s); ! 182: return (EIO); ! 183: } ! 184: ok: ! 185: splx(s); ! 186: return (0); ! 187: } ! 188: ! 189: /* ! 190: * Wait for all outstanding IO on this drive ! 191: * complete, before closing. If both drives on ! 192: * this controller are idle, mark the controller ! 193: * `inactive'. ! 194: */ ! 195: ! 196: uuclose(dev, flag) ! 197: dev_t dev; ! 198: int flag; ! 199: { ! 200: int s, unit = UNIT(dev); ! 201: register struct uu_softc *uuc = &uu_softc[unit/NDPC]; ! 202: struct buf *bp, *last = NULL; ! 203: struct uudevice *uuaddr = (struct uudevice *)uudinfo[unit/NDPC]->ui_addr; ! 204: ! 205: s = splx(UUIPL); ! 206: while (uu_pcnt[unit]) ! 207: sleep(&uu_pcnt[unit], PRIBIO); ! 208: /* ! 209: * No more writes are pending, scan the ! 210: * buffer queue for oustanding reads from ! 211: * this unit. ! 212: */ ! 213: for (bp = uitab[unit/NDPC].b_actf; bp; bp = bp->b_actf) { ! 214: if (bp->b_dev == dev) ! 215: last = bp; ! 216: } ! 217: if (last) { ! 218: last->b_flags |= B_CALL; ! 219: last->b_iodone = uuwake; ! 220: sleep((caddr_t)last, PRIBIO); ! 221: } ! 222: uuc->tu_dopen[unit&UMASK] = 0; ! 223: if (!uuc->tu_dopen[0] && !uuc->tu_dopen[1]) { ! 224: uuc->tu_flag = 0; ! 225: uuaddr->rcs = 0; ! 226: } ! 227: splx(s); ! 228: return (0); ! 229: } ! 230: ! 231: uuwake(bp) ! 232: struct buf *bp; ! 233: { ! 234: wakeup(bp); ! 235: } ! 236: ! 237: uureset(ctlr) ! 238: int ctlr; ! 239: { ! 240: register struct uu_softc *uuc = &uu_softc[ctlr]; ! 241: register struct packet *cmd = &uucmd[ctlr]; ! 242: struct uba_device *ui = uudinfo[ctlr]; ! 243: register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; ! 244: ! 245: uitab[ctlr].b_active++; ! 246: uuc->tu_state = TUS_INIT1; ! 247: uuc->tu_wbptr = uunull; ! 248: uuc->tu_wcnt = sizeof (uunull); ! 249: uuc->tu_rcnt = 0; ! 250: cmd->pk_flag = TUF_CMD; ! 251: cmd->pk_mcount = sizeof (*cmd) - 4; ! 252: cmd->pk_mod = 0; ! 253: cmd->pk_seq = 0; ! 254: cmd->pk_sw = 0; ! 255: uuaddr->rcs = 0; ! 256: uuaddr->tcs = UUCS_INTR | UUCS_BREAK; ! 257: uuxintr(ctlr); /* start output */ ! 258: } ! 259: ! 260: /* ! 261: * Strategy routine for block I/O ! 262: */ ! 263: uustrategy(bp) ! 264: register struct buf *bp; ! 265: { ! 266: register struct buf *uutab; ! 267: struct uba_device *ui; ! 268: int s, unit = UNIT(bp->b_dev); ! 269: ! 270: if ((unit > NUX) || (bp->b_blkno >= NTUBLK)) ! 271: goto bad; ! 272: ui = uudinfo[unit/NDPC]; ! 273: if (ui == 0 || ui->ui_alive == 0) ! 274: goto bad; ! 275: uutab = &uitab[unit/NDPC]; /* one request queue per controller */ ! 276: s = splx(UUIPL); ! 277: if ((bp->b_flags&B_READ) == 0) ! 278: tu_pee(&uu_pcnt[unit]); ! 279: bp->b_actf = NULL; ! 280: if (uutab->b_actf == NULL) ! 281: uutab->b_actf = bp; ! 282: else ! 283: uutab->b_actl->b_actf = bp; ! 284: uutab->b_actl = bp; ! 285: if (uutab->b_active == 0) ! 286: uustart(ui); ! 287: splx(s); ! 288: return; ! 289: ! 290: bad: ! 291: bp->b_flags |= B_ERROR; ! 292: bp->b_error = ENXIO; ! 293: iodone(bp); ! 294: return; ! 295: } ! 296: ! 297: /* ! 298: * Start the transfer ! 299: */ ! 300: uustart(ui) ! 301: register struct uba_device *ui; ! 302: { ! 303: register struct buf *bp; ! 304: register struct uu_softc *uuc; ! 305: struct packet *cmd; ! 306: int ctlr = ui->ui_unit, s; ! 307: ! 308: if ((bp = uitab[ctlr].b_actf) == NULL) ! 309: return; ! 310: s = splx(UUIPL); ! 311: uuc = &uu_softc[ctlr]; ! 312: if (uuc->tu_state != TUS_IDLE) { ! 313: uureset(ctlr); ! 314: splx(s); ! 315: return; ! 316: } ! 317: cmd = &uucmd[ctlr]; ! 318: uitab[ctlr].b_active++; ! 319: uitab[ctlr].b_errcnt = 0; ! 320: uuc->tu_addr = bp->b_un.b_addr; ! 321: uuc->tu_count = cmd->pk_count = bp->b_bcount; ! 322: cmd->pk_block = bp->b_blkno; ! 323: if (bp->b_flags&B_READ) { ! 324: cmd->pk_op = TUOP_READ; ! 325: cmd->pk_mod = 0; ! 326: uuc->tu_state = TUS_SENDR; ! 327: } else { ! 328: cmd->pk_op = TUOP_WRITE; ! 329: cmd->pk_mod = minor(bp->b_dev)&WRV ? TUMD_WRV : 0; ! 330: uuc->tu_state = TUS_SENDW; ! 331: } ! 332: cmd->pk_unit = UNIT(bp->b_dev)&UMASK; ! 333: cmd->pk_sw = 0; ! 334: cmd->pk_chksum = ! 335: tuchk(*((short *)cmd), (u_short *)&cmd->pk_op, (int)cmd->pk_mcount); ! 336: uuc->tu_wbptr = (u_char *)cmd; ! 337: uuc->tu_wcnt = sizeof (*cmd); ! 338: uuxintr(ctlr); ! 339: splx(s); ! 340: } ! 341: ! 342: /* ! 343: * TU58 receiver interrupt, handles whatever condition the ! 344: * pseudo DMA routine in locore is unable to handle, ! 345: * or, if UUDMA is undefined, handle all receiver interrupt ! 346: * processing. ! 347: */ ! 348: uurintr(ctlr) ! 349: int ctlr; ! 350: { ! 351: struct uba_device *ui = uudinfo[ctlr]; ! 352: register struct uu_softc *uuc = &uu_softc[ctlr]; ! 353: register struct uudevice *uuaddr = (struct uudevice *)ui->ui_addr; ! 354: register struct buf *uutab = &uitab[ctlr]; ! 355: struct packet *data, *cmd; ! 356: struct buf *bp; ! 357: int c, unit; ! 358: ! 359: c = uuaddr->rdb; ! 360: data = &uudata[ctlr]; ! 361: cmd = &uucmd[ctlr]; ! 362: #if !defined(UUDMA) ! 363: if (c & UURDB_ERROR) ! 364: uuc->tu_state = TUS_RCVERR; ! 365: else { ! 366: if (uuc->tu_rcnt) { ! 367: *uuc->tu_rbptr++ = c; ! 368: if (--uuc->tu_rcnt) ! 369: return; ! 370: } ! 371: } ! 372: #endif ! 373: ! 374: /* ! 375: * Switch on the tu_state of the transfer. ! 376: */ ! 377: switch(uuc->tu_state) { ! 378: ! 379: /* ! 380: * A data error occured in uudma ! 381: * (either overrun or break) ! 382: */ ! 383: case TUS_RCVERR: ! 384: if ((c & UURDB_ORUN) == 0) ! 385: printf("uu%d: break received, transfer restarted\n", ! 386: data->pk_unit); ! 387: #ifdef UUDEBUG ! 388: else ! 389: printf("uu%d: data overrun, recovered\n", ! 390: data->pk_unit); ! 391: #endif ! 392: uuc->tu_serrs++; ! 393: uu_restart(ctlr, ui); ! 394: break; ! 395: ! 396: /* ! 397: * If we get an unexpected "continue", ! 398: * start all over again... ! 399: */ ! 400: case TUS_INIT2: ! 401: uuc->tu_state = c == TUF_CONT ? TUS_IDLE : TUS_INIT1; ! 402: uuc->tu_flag = 0; ! 403: wakeup((caddr_t)uuc); ! 404: uustart(ui); ! 405: break; ! 406: ! 407: /* ! 408: * Only transition from this state ! 409: * is on a "continue", so if we don't ! 410: * get it, reset the world. ! 411: */ ! 412: case TUS_WAIT: /* waiting for continue */ ! 413: switch(c) { ! 414: case TUF_CONT: /* got the expected continue */ ! 415: uuc->tu_flag = 0; ! 416: data->pk_flag = TUF_DATA; ! 417: data->pk_mcount = MIN(128, uuc->tu_count); ! 418: data->pk_chksum = ! 419: tuchk(*((short *)data), (caddr_t)uuc->tu_addr, ! 420: (int)data->pk_mcount); ! 421: uuc->tu_state = TUS_SENDH; ! 422: uuc->tu_wbptr = (u_char *)data; ! 423: uuc->tu_wcnt = 2; ! 424: uuxintr(ctlr); ! 425: break; ! 426: ! 427: case TUF_CMD: /* sending us an END packet...error */ ! 428: uuc->tu_state = TUS_GET; ! 429: uuc->tu_rbptr = (u_char *)data; ! 430: uuc->tu_rcnt = sizeof (*data) - 1; ! 431: uuc->tu_flag = 1; ! 432: uuaddr->tcs = 0; ! 433: *uuc->tu_rbptr++ = c & UUDB_DMASK; ! 434: break; ! 435: ! 436: case TUF_INITF: ! 437: uureset(ctlr); ! 438: break; ! 439: ! 440: default: /* something random...bad news */ ! 441: uuc->tu_state = TUS_INIT1; ! 442: break; ! 443: } ! 444: break; ! 445: ! 446: case TUS_SENDW: ! 447: if (c != TUF_CONT && c != TUF_INITF) ! 448: goto bad; ! 449: uu_restart(ctlr, ui); ! 450: break; ! 451: ! 452: /* ! 453: * Got header, now get data; amount to ! 454: * fetch is included in packet. ! 455: * (data packets are handled entirely ! 456: * in uudma) ! 457: */ ! 458: case TUS_GETH: ! 459: #ifndef UUDMA ! 460: if (data->pk_flag == TUF_DATA) ! 461: uuc->tu_rbptr = (u_char *)uuc->tu_addr; ! 462: #endif ! 463: uuc->tu_rcnt = data->pk_mcount; ! 464: uuc->tu_state = TUS_GETD; ! 465: break; ! 466: ! 467: /* ! 468: * Got the data, now fetch the checksum. ! 469: */ ! 470: case TUS_GETD: ! 471: uuc->tu_rbptr = (u_char *)&data->pk_chksum; ! 472: uuc->tu_rcnt = sizeof (data->pk_chksum); ! 473: uuc->tu_state = TUS_GETC; ! 474: break; ! 475: ! 476: case TUS_GETC: ! 477: /* got entire packet */ ! 478: if (data->pk_chksum != ! 479: tuchk(*((short *)data), (u_short *) ! 480: (data->pk_flag == TUF_DATA ? ! 481: (u_short *) uuc->tu_addr : (u_short *)&data->pk_op), ! 482: (int)data->pk_mcount)) ! 483: case TUS_CHKERR: ! 484: uuc->tu_cerrs++; ! 485: case TUS_GET: ! 486: if (data->pk_flag == TUF_DATA) { ! 487: /* data packet, advance to next */ ! 488: uuc->tu_addr += data->pk_mcount; ! 489: uuc->tu_count -= data->pk_mcount; ! 490: uuc->tu_state = TUS_GETH; ! 491: uuc->tu_rbptr = (u_char *)data; /* next packet */ ! 492: uuc->tu_rcnt = 2; ! 493: } else if (data->pk_flag==TUF_CMD && data->pk_op==TUOP_END) { ! 494: /* end packet, idle and reenable transmitter */ ! 495: uuc->tu_state = TUS_IDLE; ! 496: uuc->tu_flag = 0; ! 497: uuaddr->tcs = UUCS_INTR; ! 498: if ((bp = uutab->b_actf) == NULL) { ! 499: printf("uu%d: no bp, active %d\n", ! 500: data->pk_unit, uitab[ctlr].b_active); ! 501: uustart(ui); ! 502: return; ! 503: } ! 504: unit = UNIT(bp->b_dev); ! 505: if (data->pk_mod > 1) { /* hard error */ ! 506: printf("uu%d: hard error bn%d,", unit, ! 507: bp->b_blkno); ! 508: printf(" pk_mod 0%o\n", data->pk_mod&0xff); ! 509: bp->b_flags |= B_ERROR; ! 510: uuc->tu_herrs++; ! 511: } else if (data->pk_mod) /* soft error */ ! 512: uuc->tu_serrs++; ! 513: uutab->b_active = NULL; ! 514: uutab->b_actf = bp->b_actf; ! 515: bp->b_resid = uuc->tu_count; ! 516: if ((bp->b_flags&B_READ) == 0) ! 517: tu_vee(&uu_pcnt[unit]); ! 518: iodone(bp); ! 519: uustart(ui); ! 520: } else { ! 521: /* ! 522: * Neither data nor end: data was lost ! 523: * somehow, flush and restart the transfer. ! 524: */ ! 525: uuaddr->rcs = 0; ! 526: uu_restart(ctlr, ui); ! 527: uuc->tu_serrs++; ! 528: } ! 529: break; ! 530: ! 531: case TUS_IDLE: ! 532: case TUS_INIT1: ! 533: break; ! 534: ! 535: default: ! 536: bad: ! 537: if (c == TUF_INITF) { ! 538: printf("uu%d protocol error, state=", data->pk_unit); ! 539: printstate(uuc->tu_state); ! 540: printf(", op=%x, cnt=%d, block=%d\n", ! 541: cmd->pk_op, cmd->pk_count, cmd->pk_block); ! 542: uutab->b_active = NULL; ! 543: if (bp = uutab->b_actf) { ! 544: bp->b_flags |= B_ERROR; ! 545: uutab->b_actf = bp->b_actf; ! 546: if ((bp->b_flags&B_READ) == 0) ! 547: tu_vee(&uu_pcnt[unit]); ! 548: iodone(bp); ! 549: } ! 550: uuc->tu_state = TUS_INIT1; ! 551: } else { ! 552: printf("uu%d receive state error, state=", ! 553: data->pk_unit); ! 554: printstate(uuc->tu_state); ! 555: printf(", byte=%x\n", c & 0xff); ! 556: #ifdef notdef ! 557: uuc->tu_state = TUS_INIT1; ! 558: #endif ! 559: wakeup((caddr_t)uuc); ! 560: } ! 561: } ! 562: } ! 563: ! 564: ! 565: /* ! 566: * TU58 transmitter interrupt ! 567: */ ! 568: uuxintr(ctlr) ! 569: int ctlr; ! 570: { ! 571: register struct uu_softc *uuc = &uu_softc[ctlr]; ! 572: register struct uudevice *uuaddr; ! 573: register struct packet *data; ! 574: struct uba_device *ui = uudinfo[ctlr]; ! 575: int c; ! 576: ! 577: data = &uudata[ctlr]; ! 578: uuaddr = (struct uudevice *) ui->ui_addr; ! 579: top: ! 580: if (uuc->tu_wcnt > 0) { ! 581: /* still stuff to send, send one byte */ ! 582: while ((uuaddr->tcs & UUCS_READY) == 0) ! 583: ; ! 584: uuaddr->tdb = *uuc->tu_wbptr++; ! 585: uuc->tu_wcnt--; ! 586: return; ! 587: } ! 588: ! 589: /* ! 590: * Last message byte was sent out. ! 591: * Switch on tu_state of transfer. ! 592: */ ! 593: switch(uuc->tu_state) { ! 594: ! 595: /* ! 596: * Two nulls have been sent, remove break, and send inits ! 597: */ ! 598: case TUS_INIT1: ! 599: uuc->tu_flag = 0; ! 600: uuaddr->tcs = UUCS_INTR; ! 601: uuc->tu_state = TUS_INIT2; ! 602: uuc->tu_wbptr = uuinit; ! 603: uuc->tu_wcnt = sizeof (uuinit); ! 604: goto top; ! 605: ! 606: /* ! 607: * Inits have been sent, wait for a continue msg. ! 608: */ ! 609: case TUS_INIT2: ! 610: c = uuaddr->rdb; /* prevent overrun error */ ! 611: uuaddr->rcs = UUCS_INTR; ! 612: uuc->tu_flag = 1; ! 613: break; ! 614: ! 615: /* ! 616: * Read cmd packet sent, get ready for data ! 617: */ ! 618: case TUS_SENDR: ! 619: uuc->tu_state = TUS_GETH; ! 620: uuc->tu_rbptr = (u_char *)data; ! 621: uuc->tu_rcnt = 2; ! 622: uuc->tu_flag = 1; ! 623: uuaddr->tcs = 0; ! 624: uuaddr->rcs = UUCS_INTR; ! 625: break; ! 626: ! 627: /* ! 628: * Write cmd packet sent, wait for continue ! 629: */ ! 630: case TUS_SENDW: ! 631: uuc->tu_state = TUS_WAIT; ! 632: uuc->tu_flag = 1; ! 633: if ((uuaddr->rcs&UUCS_INTR) == 0) { ! 634: printf("NO IE\n"); ! 635: uuaddr->rcs = UUCS_INTR; ! 636: } ! 637: break; ! 638: ! 639: /* ! 640: * Header sent, send data. ! 641: */ ! 642: case TUS_SENDH: ! 643: uuc->tu_state = TUS_SENDD; ! 644: uuc->tu_wbptr = (u_char *)uuc->tu_addr; ! 645: uuc->tu_wcnt = data->pk_mcount; ! 646: goto top; ! 647: ! 648: /* ! 649: * Data sent, follow with checksum. ! 650: */ ! 651: case TUS_SENDD: ! 652: uuc->tu_state = TUS_SENDC; ! 653: uuc->tu_wbptr = (u_char *)&data->pk_chksum; ! 654: uuc->tu_wcnt = 2; ! 655: goto top; ! 656: ! 657: /* ! 658: * Checksum sent, wait for continue. ! 659: */ ! 660: case TUS_SENDC: ! 661: /* ! 662: * Update buffer address and count. ! 663: */ ! 664: uuc->tu_addr += data->pk_mcount; ! 665: uuc->tu_count -= data->pk_mcount; ! 666: if (uuc->tu_count > 0) { ! 667: uuc->tu_state = TUS_WAIT; ! 668: uuc->tu_flag = 1; ! 669: break; ! 670: } ! 671: ! 672: /* ! 673: * End of transmission, get ready for end packet. ! 674: */ ! 675: uuc->tu_state = TUS_GET; ! 676: uuc->tu_rbptr = (u_char *)data; ! 677: uuc->tu_rcnt = sizeof (*data); ! 678: uuc->tu_flag = 1; ! 679: uuaddr->tcs = 0; ! 680: break; ! 681: ! 682: /* ! 683: * Random interrupt ! 684: */ ! 685: case TUS_IDLE: /* stray interrupt? */ ! 686: ! 687: default: ! 688: break; ! 689: } ! 690: } ! 691: ! 692: uuwatch() ! 693: { ! 694: register struct uu_softc *uuc; ! 695: register struct uudevice *uuaddr; ! 696: struct uba_device *ui; ! 697: struct buf *bp, *uutab; ! 698: int s, ctlr, active = 0; ! 699: ! 700: for (ctlr=0; ctlr<NUU; ctlr++) { ! 701: int i; ! 702: ! 703: uuc = &uu_softc[ctlr]; ! 704: ! 705: if (uuc->tu_dopen[0] || uuc->tu_dopen[1]) ! 706: active++; ! 707: if (uuc->tu_flag == 0) ! 708: /* ! 709: * If no read is in progress ! 710: * just skip ! 711: */ ! 712: continue; ! 713: ! 714: ui = uudinfo[ctlr]; ! 715: uuaddr = (struct uudevice *)ui->ui_addr; ! 716: uutab = &uitab[ctlr]; ! 717: if (uuc->tu_flag++ < 40) ! 718: continue; ! 719: printf("uu%d: read stalled\n", uudata[ctlr].pk_unit); ! 720: #ifdef UUDEBUG ! 721: printf("%X %X %X %X %X %X %X\n", uuc->tu_rbptr, uuc->tu_rcnt, ! 722: uuc->tu_wbptr, uuc->tu_wcnt, uuc->tu_state, uuc->tu_addr, ! 723: uuc->tu_count); ! 724: #endif ! 725: s = splx(UUIPL); ! 726: uuc->tu_flag = 0; ! 727: i = uuaddr->rdb; /* dummy */ ! 728: uuaddr->rcs = UUCS_INTR; /* in case we were flushing */ ! 729: uuaddr->tcs = UUCS_INTR; ! 730: uuc->tu_state = TUS_IDLE; ! 731: if (!uutab->b_active) { ! 732: wakeup((caddr_t)uuc); ! 733: goto retry; ! 734: } ! 735: if (++uutab->b_errcnt <= 1) { ! 736: uustart(ui); ! 737: goto retry; ! 738: } ! 739: if (bp = uutab->b_actf) { ! 740: bp->b_flags |= B_ERROR; ! 741: if ((bp->b_flags&B_READ) == 0) ! 742: tu_vee(&uu_pcnt[UNIT(bp->b_dev)]); ! 743: iodone(bp); ! 744: } ! 745: retry: ! 746: (void) splx(s); ! 747: } ! 748: if (active) ! 749: timeout(uuwatch, (caddr_t)0, hz); ! 750: else ! 751: uuwstart = 0; ! 752: return; ! 753: } ! 754: ! 755: #if !defined(VAX750) && !defined(VAX730) ! 756: /* ! 757: * Compute checksum TU58 fashion ! 758: */ ! 759: #ifdef lint ! 760: tuchk(word, cp, n) ! 761: register word; ! 762: register unsigned short *cp; ! 763: int n; ! 764: { ! 765: register int c = n >> 1; ! 766: register long temp; ! 767: ! 768: do { ! 769: temp = *cp++; /* temp, only because vax cc won't *r++ */ ! 770: word += temp; ! 771: } while (--c > 0); ! 772: if (n & 1) ! 773: word += *(unsigned char *)cp; ! 774: while (word & 0xffff0000) ! 775: word = (word & 0xffff) + ((word >> 16) & 0xffff); ! 776: return (word); ! 777: } ! 778: #else ! 779: tuchk(word0, wp, n) ! 780: register int word0; /* r11 */ ! 781: register char *wp; /* r10 */ ! 782: register int n; /* r9 */ ! 783: { ! 784: asm("loop:"); ! 785: asm(" addw2 (r10)+,r11"); /* add a word to sum */ ! 786: asm(" adwc $0,r11"); /* add in carry, end-around */ ! 787: asm(" acbl $2,$-2,r9,loop"); /* done yet? */ ! 788: asm(" blbc r9,ok"); /* odd byte count? */ ! 789: asm(" movzbw (r10),r10"); /* yes, get last byte */ ! 790: asm(" addw2 r10,r11"); /* add it in */ ! 791: asm(" adwc $0,r11"); /* and the carry */ ! 792: asm("ok:"); ! 793: asm(" movl r11,r0"); /* return sum */ ! 794: } ! 795: #endif ! 796: ! 797: /* ! 798: * Make sure this incredibly slow device ! 799: * doesn't eat up all the buffers in the ! 800: * system by putting the requesting process ! 801: * (remember: this device is 'single-user') ! 802: * to sleep if the write-behind queue grows ! 803: * larger than NUUQ. ! 804: */ ! 805: tu_pee(cp) ! 806: char *cp; ! 807: { ! 808: register int s; ! 809: ! 810: s = splx(UUIPL); ! 811: if (++(*cp) > NUUQ) ! 812: sleep(cp, PRIBIO); ! 813: splx(s); ! 814: } ! 815: ! 816: tu_vee(cp) ! 817: char *cp; ! 818: { ! 819: register int s; ! 820: ! 821: s = splx(UUIPL); ! 822: if (--(*cp) <= NUUQ) ! 823: wakeup(cp); ! 824: splx(s); ! 825: } ! 826: #endif ! 827: ! 828: uuioctl(dev, cmd, data, flag) ! 829: dev_t dev; ! 830: caddr_t data; ! 831: { ! 832: /* ! 833: * add code to wind/rewind cassette here ! 834: */ ! 835: return (ENXIO); ! 836: } ! 837: ! 838: uu_restart(ctlr, ui) ! 839: int ctlr; ! 840: struct uba_device *ui; ! 841: { ! 842: uureset(ctlr); ! 843: timeout(uustart, (caddr_t)ui, hz * 3); ! 844: } ! 845: ! 846: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.