|
|
1.1 ! root 1: /* lpa.c 6.1 83/07/29 */ ! 2: ! 3: #include "lpa.h" ! 4: #if NLPA > 0 ! 5: ! 6: #include "../h/param.h" ! 7: #include "../h/dir.h" ! 8: #include "../h/user.h" ! 9: #include "../h/buf.h" ! 10: #include "../h/proc.h" ! 11: #include "../h/ioctl.h" ! 12: #include "../h/uio.h" ! 13: ! 14: #include "../vaxuba/ubavar.h" ! 15: ! 16: /* ! 17: * LPA driver for -- Asa Romberger ! 18: * ! 19: * open ! 20: * write microcode ! 21: * write dedicated mode dispatch table ! 22: * ioctl TIOCSETP to set parameters ! 23: * struct iocb { ! 24: * short *baddr; buffer address ! 25: * short rate; - 1,000,000 / frequency in Hz ! 26: * short wc; 15-13 = number of buffers - 1 ! 27: * 12-0 = buffer size in words ! 28: * } iocb; ! 29: * read - 1 character indicating buffer index ! 30: * fill or empty buffer ! 31: * minor device number = DDCCCCCC where: ! 32: * DD = 00 for analog input ! 33: * = 01 for analog output ! 34: * CCCCCC = channel number ! 35: */ ! 36: * define NOMCODE to eliminate the microcode download check ! 37: */ ! 38: /* #define TRACELPA */ ! 39: /* #define NOMCODE */ ! 40: ! 41: #ifdef TRACELPA ! 42: # define TRACER(x) printf(x) ! 43: # define TRACERN(x, d) printf(x, d) ! 44: #else ! 45: # define TRACER(x) ! 46: # define TRACERN(x, d) ! 47: #endif ! 48: ! 49: /* PRIORITY AT WHICH PROGRAM SHOULD RUN */ ! 50: /* THIS SHOULD EVENTUALLY TELL UNIX THIS IS A REAL-TIME DEVICE */ ! 51: ! 52: #define NICE 0 ! 53: ! 54: #define inc(v) (sc->v = ((sc->v + 1) % sc->sc_nbuf)) ! 55: ! 56: #define LPAPRI (PZERO + 0) ! 57: #define LPAUNIT(dev) 0 ! 58: #define LPADEVICE(dev) (((dev) >> 6) & 03) ! 59: #define LPACHANNEL(dev) ((dev) & 077) ! 60: ! 61: int lpaprobe(), lpaattach(), lpaiintr(), lpaointr(); ! 62: u_short lpastd[] = {0170460, 0}; ! 63: struct uba_device *lpadinfo[NLPA]; ! 64: struct uba_driver lpadriver = ! 65: {lpaprobe, 0, lpaattach, 0, lpastd, "lpa", lpadinfo, 0, 0, 0 }; ! 66: ! 67: struct lpa_softc { ! 68: int sc_flag; /* flags, as defined below */ ! 69: int sc_device; /* device: 0 = analog in, 1 = analog out */ ! 70: int sc_channel; /* device channel number */ ! 71: struct buf sc_ubuffer; /* user buffer header */ ! 72: int sc_ubabuf; /* uba allocation pointer for buffer */ ! 73: int sc_ubufn; /* present buffer that user is accessing */ ! 74: int sc_lbufn; /* present buffer that lpa is accessing */ ! 75: int sc_lbufnx; /* next buffer for lpa (value in ustat) */ ! 76: int sc_nbuf; /* number of buffers */ ! 77: int sc_count; /* buffer size in words */ ! 78: short sc_ustat; /* user status word */ ! 79: struct buf sc_ustatbuf; /* dummy user status word buffer for ubasetup */ ! 80: int sc_ubaustat; /* uba allocation pointer for ustat */ ! 81: struct buf *sc_buffer; /* scratch buffer header */ ! 82: int sc_start; /* 0 if lpa operation has been started */ ! 83: } lpa_softc[NLPA]; ! 84: ! 85: /* flags for sc_flag */ ! 86: #define OPEN 01 /* device is open */ ! 87: #define MCODE 02 /* microcode has been loaded */ ! 88: #define DMDT 04 /* dedicated mode dispatch table loaded */ ! 89: #define STTY 010 /* stty call and device initialized */ ! 90: #define SLEEP 020 /* sleeping */ ! 91: ! 92: /* bits for ustat */ ! 93: #define DONE 0100000 /* done */ ! 94: #define STOP 0040000 /* stop data transfer */ ! 95: #define NBI 0003400 /* next buffer index */ ! 96: #define LBI 0000003 /* last buffer index */ ! 97: ! 98: struct lpadevice { ! 99: short lcim; /* control in and maintenance */ ! 100: short lcos; /* control and status out */ ! 101: short lrda; /* request description array address word */ ! 102: short lms; /* maintenance status */ ! 103: }; ! 104: ! 105: /* control in and maintenance register bits */ ! 106: #define READYI 0000200 /* ready in */ ! 107: #define IIE 0000100 /* in interrupt enable */ ! 108: #define RDAEXT 0000014 /* rda address extension */ ! 109: #define RDAEXTOFFSET 2 /* offset of RDAEXT from right side */ ! 110: #define GO 0000001 /* go */ ! 111: #define RUN 0100000 /* run */ ! 112: #define RESET 0040000 /* reset */ ! 113: #define CWRITE 0020000 /* cram write */ ! 114: #define EA 0004000 /* enable arbitration */ ! 115: #define ROMO 0002000 /* rom O */ ! 116: #define ROMI 0001000 /* rom I */ ! 117: #define SMICRO 0000400 /* step microprocessor */ ! 118: ! 119: /* control and status out register bits */ ! 120: #define READYO 0200 /* ready out */ ! 121: #define OIE 0100 /* out interrupt enable */ ! 122: #define UINDEX 0007 /* user index */ ! 123: #define ERROR 0100000 /* error */ ! 124: #define ESTAT 0060000 /* error status */ ! 125: #define ESCODE 0017400 /* error sub code */ ! 126: #define ECODE 0077400 /* error status + error sub code */ ! 127: #define OVERRUN 0243 /* overrun error */ ! 128: ! 129: /* LPA COMMAND DESCRIPTION AREA */ ! 130: ! 131: /* INIT COMMAND */ ! 132: #define INIT 0 /* mode */ ! 133: #define MCVERS 4 /* microcode version */ ! 134: #define ACLOCKA 0170404 /* LPA bus addresses */ ! 135: #define ACLOCKB 0170432 ! 136: #define AAD1 0170400 ! 137: #define AAD2 1 /* 0170440 - DOES NOT EXIST */ ! 138: #define ADA 0170420 ! 139: #define ADIO1 1 /* 0167770 - DOES NOT EXIST */ ! 140: #define ADIO2 1 /* 0167760 - DOES NOT EXIST */ ! 141: #define ADIO3 1 /* 0167750 - DOES NOT EXIST */ ! 142: #define ADIO4 1 /* 0167740 - DOES NOT EXIST */ ! 143: #define ADIO5 1 /* 0167730 - DOES NOT EXIST */ ! 144: ! 145: /* CLOCK START COMMAND */ ! 146: #define CLOCK 1 /* mode */ ! 147: #define CLOCKA 0<<4 /* clock A */ ! 148: /* clock status word */ ! 149: #define ENACTR 1 /* enable counter */ ! 150: #define R1M 1<<1 /* 1 MHz rate */ ! 151: #define R100K 2<<1 /* 100 KHz rate */ ! 152: #define R10K 3<<1 /* 10 KHz rate */ ! 153: #define R1K 4<<1 /* 1 KHz rate */ ! 154: #define R100 5<<1 /* 100 Hz rate */ ! 155: #define REXT 6<<1 /* external rate (from st1 input) */ ! 156: #define R60 7<<1 /* line frequency rate */ ! 157: #define MFIE 0100 /* mode flag interrupt enable */ ! 158: #define MSI 0<<8 /* single interval mode */ ! 159: #define MRI 1<<8 /* repeat interval mode */ ! 160: #define MEET 2<<8 /* external event time mode */ ! 161: #define MEETZ 3<<8 /* external event time mode from zero base */ ! 162: #define ST1EC 020000 /* st1 enable counter */ ! 163: #define ST1IE 040000 /* st1 interrupt enable */ ! 164: ! 165: /* DATA TRANSFER START COMMAND */ ! 166: #define DTS 2 /* mode */ ! 167: #define SCHAN 1<<8 /* single channel */ ! 168: ! 169: lpaprobe(reg) ! 170: caddr_t reg; ! 171: { ! 172: register int br, cvec; /* value result */ ! 173: register struct lpadevice *lpaaddr = (struct lpadevice *)reg; ! 174: ! 175: #ifdef lint ! 176: br = 0; cvec = br; br = cvec; ! 177: #endif ! 178: /* this should force an interrupt, stall, clear the lpa */ ! 179: br = 0x15; ! 180: cvec = 0330; ! 181: TRACER("PROBE\n"); ! 182: return (sizeof (struct lpadevice)); ! 183: } ! 184: ! 185: lpaattach(ui) ! 186: register struct upa_device *ui; ! 187: { ! 188: ! 189: } ! 190: ! 191: lpaopen(dev, flag) ! 192: dev_t dev; ! 193: int flag; ! 194: { ! 195: register int unit = LPAUNIT(dev); ! 196: register struct lpa_softc *sc = &lpa_softc[unit]; ! 197: register struct uba_device *ui = lpadinfo[unit]; ! 198: register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; ! 199: ! 200: TRACER("OPEN\n"); ! 201: if (unit >= NLPA || sc->sc_flag & OPEN || ui == 0 || ! 202: ui->ui_alive == 0) ! 203: return (ENXIO); ! 204: (void) spl7(); ! 205: lpaaddr->lcim = RESET; ! 206: lpaaddr->lcim = 0; ! 207: (void) spl0(); ! 208: lpaaddr->lcos = 0; /* clear the registers as a precaution */ ! 209: lpaaddr->lrda = 0; ! 210: lpaaddr->lms = 0; ! 211: sc->sc_flag = OPEN; ! 212: sc->sc_device = LPADEVICE(dev); ! 213: sc->sc_channel = LPACHANNEL(dev); ! 214: sc->sc_buffer = geteblk(); ! 215: sc->sc_buffer->b_error = 0; ! 216: sc->sc_buffer->b_proc = u.u_procp; ! 217: sc->sc_ubufn = -1; ! 218: /* THIS SHOULD EVENTUALLY SPECIFY "REAL-TIME" */ ! 219: u.u_procp->p_nice = NICE; ! 220: return (0); ! 221: } ! 222: ! 223: lpaclose(dev, flag) ! 224: dev_t dev; ! 225: int flag; ! 226: { ! 227: register int unit = LPAUNIT(dev); ! 228: register struct lpa_softc *sc = &lpa_softc[unit]; ! 229: register struct uba_device *ui = lpadinfo[unit]; ! 230: register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; ! 231: ! 232: if (sc->sc_device && sc->sc_ubufn >= 0 && (sc->sc_flag & ERROR) == 0) { ! 233: if (sc->sc_start) ! 234: lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum); ! 235: sc->sc_flag |= STOP; ! 236: (void) spl5(); ! 237: while (sc->sc_flag & STOP) { ! 238: TRACER("SLEEP\n"); ! 239: sc->sc_flag |= SLEEP; ! 240: sleep((caddr_t)sc, LPAPRI); ! 241: } ! 242: } ! 243: (void) spl7(); ! 244: lpaaddr->lcim = RESET; ! 245: lpaaddr->lcim = 0; ! 246: (void) spl0(); ! 247: if (sc->sc_ubabuf) { ! 248: ubarelse(ui->ui_ubanum, &sc->sc_ubabuf); ! 249: sc->sc_ubabuf = 0; ! 250: (void) spl6(); ! 251: vsunlock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount, ! 252: (sc->sc_device)? B_READ : B_WRITE); ! 253: u.u_procp->p_flag &= ~SPHYSIO; ! 254: (void) spl0(); ! 255: } ! 256: if (sc->sc_ubaustat) { ! 257: ubarelse(ui->ui_ubanum, &sc->sc_ubaustat); ! 258: sc->sc_ubaustat = 0; ! 259: } ! 260: if (sc->sc_buffer) { ! 261: brelse(sc->sc_buffer); ! 262: sc->sc_buffer = 0; ! 263: } ! 264: sc->sc_flag = 0; ! 265: TRACER("CLOSE\n"); ! 266: } ! 267: ! 268: lpawrite(dev, uio) ! 269: dev_t dev; ! 270: struct uio *uio; ! 271: { ! 272: register int unit = LPAUNIT(dev); ! 273: register struct lpa_softc *sc = &lpa_softc[unit]; ! 274: register struct uba_device *ui = lpadinfo[unit]; ! 275: register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; ! 276: register int f; ! 277: ! 278: TRACER("WRITE\n"); ! 279: f = sc->sc_flag; ! 280: if ((f & OPEN) == 0) ! 281: return (ENXIO); ! 282: if ((f & MCODE) == 0) /* first write is the microcode */ ! 283: return (lpamcode(lpaaddr, sc, uio)); ! 284: if ((f & DMDT) == 0) /* second write is the dispatch table */ ! 285: return (lpadmdt(lpaaddr, sc, ui->ui_ubanum, uio)); ! 286: return (ENXIO); ! 287: } ! 288: ! 289: lpamcode(lpaaddr, sc, uio) ! 290: register struct lpadevice *lpaaddr; ! 291: register struct lpa_softc *sc; ! 292: struct uio *uio; ! 293: { ! 294: short v, r; ! 295: register int mcaddr; ! 296: int error; ! 297: ! 298: mcaddr = 0; ! 299: while (uio->uio_resid) { ! 300: error = uiomove(&v, 2, UIO_WRITE, uio); ! 301: if (error) ! 302: break; ! 303: lpaaddr->lcim = 0; /* load microcode word */ ! 304: lpaaddr->lrda = mcaddr; ! 305: lpaaddr->lms = v; ! 306: lpaaddr->lcim = ROMO; ! 307: lpaaddr->lcim |= CWRITE; ! 308: lpaaddr->lcim = 0; /* verify microcode word */ ! 309: lpaaddr->lrda = mcaddr; ! 310: lpaaddr->lcim = ROMO; ! 311: if ((r = lpaaddr->lms) != v) { ! 312: /* download failure */ ! 313: printf("LPA MICROCODE FAIL: exp:%o got:%o\n", v, r); ! 314: return (ENXIO); ! 315: } ! 316: mcaddr++; ! 317: } ! 318: lpaaddr->lcim = RUN | EA; /* turn it on */ ! 319: sc->sc_flag |= MCODE; ! 320: lpaaddr->lcim |= IIE; ! 321: lpaaddr->lcos |= OIE; ! 322: return (error); ! 323: TRACER("MCODE\n"); ! 324: } ! 325: ! 326: lpadmdt(lpaaddr, sc, ubanum, uio) ! 327: register struct lpadevice *lpaaddr; ! 328: register struct lpa_softc *sc; ! 329: register short ubanum; ! 330: struct uio *uio; ! 331: { ! 332: register short *p; ! 333: register int n; ! 334: int error; ! 335: ! 336: p = (short *) sc->sc_buffer->b_un.b_addr; /* INIT */ ! 337: *p++ = (MCVERS << 8) | INIT; /* mode */ ! 338: *p++ = ACLOCKA; /* LPA bus device addresses */ ! 339: *p++ = ACLOCKB; ! 340: *p++ = AAD1; ! 341: *p++ = AAD2; ! 342: *p++ = ADA; ! 343: *p++ = ADIO1; ! 344: *p++ = ADIO2; ! 345: *p++ = ADIO3; ! 346: *p++ = ADIO4; ! 347: *p++ = ADIO5; ! 348: n = min(uio->uio_resid, 256); /* dedicated mode dispatch table */ ! 349: error = uiomove((char *)p, n, UIO_WRITE, uio); ! 350: if (error) ! 351: return (error); ! 352: n >>= 1; ! 353: p += n; ! 354: while (n++ < 128) ! 355: *p++ = 0; ! 356: lpacmd(sc->sc_buffer, lpaaddr, sc, ubanum); ! 357: sc->sc_flag |= DMDT; ! 358: return (0); ! 359: TRACER("DMDT\n"); ! 360: } ! 361: ! 362: lpaioctl(dev, cmd, data, flag) ! 363: dev_t dev; ! 364: caddr_t data; ! 365: { ! 366: register int unit = LPAUNIT(dev); ! 367: register struct lpa_softc *sc = &lpa_softc[unit]; ! 368: register struct uba_device *ui = lpadinfo[unit]; ! 369: register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; ! 370: register short *p; ! 371: register int i; ! 372: register int v; ! 373: struct iocb { ! 374: short *baddr; ! 375: short rate; ! 376: short wc; ! 377: } *iocb; ! 378: ! 379: TRACER("IOCTL IN\n"); ! 380: if (cmd != TIOCSETP || (sc->sc_flag & DMDT) == 0) ! 381: return (ENXIO); ! 382: iocb = (struct iocb *)data; ! 383: p = (short *) sc->sc_buffer->b_un.b_addr; /* CLOCK START */ ! 384: *p++ = CLOCK | CLOCKA; /* mode */ ! 385: *p++ = ENACTR | R1M | MFIE | MRI; /* clock status */ ! 386: *p = iocb->rate; /* clock preset */ ! 387: lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum); ! 388: TRACER("CLOCK STARTED\n"); ! 389: p = (short *) sc->sc_buffer->b_un.b_addr; /* DATA TRANSFER START*/ ! 390: *p++ = (sc->sc_device << 7) | DTS | SCHAN; /* mode */ ! 391: sc->sc_count = iocb->wc & 017777; /* word count per buffer */ ! 392: *p++ = sc->sc_count; ! 393: /* user status word */ ! 394: sc->sc_ustatbuf.b_un.b_addr = (caddr_t) &sc->sc_ustat; ! 395: sc->sc_ustatbuf.b_flags = 0; ! 396: sc->sc_ustatbuf.b_bcount = 2; ! 397: sc->sc_ustatbuf.b_proc = u.u_procp; ! 398: sc->sc_ubaustat = ubasetup(ui->ui_ubanum, &sc->sc_ustatbuf, 0); ! 399: v = sc->sc_ubaustat; ! 400: *p++ = v; ! 401: *p = (v >> 16) & 03; /* into low portion of word */ ! 402: sc->sc_nbuf = (iocb->wc >> 13) & 07; /* number of buffers */ ! 403: *p++ |= sc->sc_nbuf++ << 8; /* into high portion of word */ ! 404: /* buffer addresses */ ! 405: if (useracc(sc->sc_ubuffer.b_un.b_addr = (caddr_t) iocb->baddr, ! 406: sc->sc_ubuffer.b_bcount = sc->sc_count * sc->sc_nbuf * 2, ! 407: (i = (sc->sc_device)? B_READ : B_WRITE) ) == NULL) { ! 408: TRACER("USER BUFFER FAULT\n"); ! 409: return (EFAULT); ! 410: } ! 411: sc->sc_ubuffer.b_flags = B_PHYS | B_BUSY | i; ! 412: sc->sc_ubuffer.b_proc = u.u_procp; ! 413: u.u_procp->p_flag |= SPHYSIO; ! 414: vslock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount); ! 415: sc->sc_ubabuf = ubasetup(ui->ui_ubanum, &sc->sc_ubuffer, 0); ! 416: v = sc->sc_ubabuf; ! 417: for (i = 0; i < sc->sc_nbuf; i++) { ! 418: *p++ = v; ! 419: *p++ = (v >> 16) & 03; ! 420: v += sc->sc_count * 2; ! 421: } ! 422: for ( ; i <= 7; i++) { ! 423: *p++ = 0; ! 424: *p++ = 0; ! 425: } ! 426: *p++ = 0; *p++ = 0; /* random channel list address */ ! 427: *p++ = 0; /* delay */ ! 428: *p++ = sc->sc_channel; /* start channel, channel inc */ ! 429: *p++ = 1; /* number of samples in a sequence */ ! 430: *p++ = 0; /* dwell */ ! 431: *p++ = 0; /* start word no., event mark word */ ! 432: *p++ = 0; /* start word mask */ ! 433: *p = 0; /* event mark mask */ ! 434: sc->sc_ustat = 0; ! 435: sc->sc_start = (sc->sc_device)? sc->sc_nbuf+1 : 1; ! 436: sc->sc_lbufn = 0; ! 437: sc->sc_lbufnx = 0; ! 438: sc->sc_flag |= STTY; ! 439: TRACER("IOCTL OUT\n"); ! 440: return (0); ! 441: } ! 442: ! 443: lparead(dev, uio) ! 444: dev_t dev; ! 445: struct uio *uio; ! 446: { ! 447: register int unit = LPAUNIT(dev); ! 448: register struct lpa_softc *sc = &lpa_softc[unit]; ! 449: register struct uba_device *ui = lpadinfo[unit]; ! 450: register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; ! 451: ! 452: TRACER("READ\n"); ! 453: if ((sc->sc_flag & STTY) == 0) ! 454: return (ENXIO); ! 455: if (sc->sc_flag & ERROR) ! 456: return (ENXIO); ! 457: if (sc->sc_start) ! 458: if (--sc->sc_start == 0) { ! 459: lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum); ! 460: TRACER("START\n"); ! 461: } ! 462: inc(sc_ubufn); ! 463: if (sc->sc_start == 0) { ! 464: (void) spl5(); ! 465: while (sc->sc_ubufn == sc->sc_lbufn) { ! 466: if (sc->sc_flag & ERROR) ! 467: return (ENXIO); ! 468: TRACER("SLEEP\n"); ! 469: sc->sc_flag |= SLEEP; ! 470: sleep(sc, LPAPRI); ! 471: } ! 472: (void) spl0(); ! 473: } ! 474: TRACERN("READ %d\n", sc->sc_ubufn); ! 475: return (uiomove(&sc->sc_ubufn, 1, UIO_READ, uio)); ! 476: } ! 477: ! 478: lpacmd(bp, lpaaddr, sc, ubanum) ! 479: register struct buf *bp; ! 480: register struct lpadevice *lpaaddr; ! 481: register struct lpa_softc *sc; ! 482: register short ubanum; ! 483: { ! 484: int ubareg; ! 485: ! 486: TRACER("CMD\n"); ! 487: ubareg = ubasetup(ubanum, bp, UBA_NEEDBDP); ! 488: lpawait(lpaaddr, sc); ! 489: lpaaddr->lrda = ubareg; ! 490: lpaaddr->lcim &= ~RDAEXT; ! 491: lpaaddr->lcim |= ((ubareg >> (16-RDAEXTOFFSET)) & RDAEXT) | GO; ! 492: lpawait(lpaaddr, sc); ! 493: ubarelse(ubanum, &ubareg); ! 494: } ! 495: ! 496: lpawait(lpaaddr, sc) ! 497: register struct lpadevice *lpaaddr; ! 498: register struct lpa_softc *sc; ! 499: { ! 500: ! 501: (void) spl5(); ! 502: while ((lpaaddr->lcim & READYI) == 0) { ! 503: TRACER("SLEEP\n"); ! 504: sc->sc_flag |= SLEEP; ! 505: sleep((caddr_t)sc, LPAPRI); ! 506: } ! 507: (void) spl0(); ! 508: } ! 509: ! 510: lpaiintr(unit) ! 511: int unit; ! 512: { ! 513: register struct lpa_softc *sc = &lpa_softc[unit]; ! 514: ! 515: TRACER("{I"); ! 516: if (sc->sc_flag & SLEEP) { ! 517: TRACER("<WAKEUP>"); ! 518: wakeup((caddr_t)sc); ! 519: sc->sc_flag &= ~SLEEP; ! 520: } ! 521: TRACER("}"); ! 522: } ! 523: ! 524: lpaointr(unit) ! 525: int unit; ! 526: { ! 527: register int c, m; ! 528: register struct lpa_softc *sc = &lpa_softc[unit]; ! 529: register struct uba_device *ui = lpadinfo[unit]; ! 530: register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; ! 531: int spx; ! 532: ! 533: TRACER("{O"); ! 534: if (sc->sc_flag & SLEEP) { ! 535: TRACER("<WAKEUP>"); ! 536: wakeup(sc); ! 537: sc->sc_flag &= ~SLEEP; ! 538: } ! 539: c = lpaaddr->lcos; ! 540: m = lpaaddr->lms; ! 541: lpaaddr->lcos &= ~READYO; ! 542: if (c & ERROR) { ! 543: TRACER("<ERROR>"); ! 544: c = (c >> 8) & 0377; ! 545: if ((sc->sc_flag & STOP) == 0 || (c != OVERRUN)) { ! 546: printf("LPA ERROR %o %o\n", c, m&0177777); ! 547: sc->sc_flag |= ERROR; ! 548: } ! 549: sc->sc_flag &= ~STOP; ! 550: TRACER("}\n"); ! 551: return; ! 552: } ! 553: TRACERN("<LPA %d>", sc->sc_lbufnx); ! 554: sc->sc_lbufn = sc->sc_lbufnx; ! 555: if (sc->sc_ubufn == sc->sc_lbufnx && c & ECODE) { ! 556: TRACER("<STOP?>"); ! 557: if (sc->sc_flag & STOP) ! 558: return; ! 559: printf("LPA OVERRUN\n"); ! 560: sc->sc_flag |= ERROR; ! 561: } ! 562: inc(sc_lbufnx); ! 563: TRACERN("<USTAT %o>", sc->sc_ustat); ! 564: spx = spl7(); ! 565: sc->sc_ustat &= ~NBI; ! 566: sc->sc_ustat |= sc->sc_lbufnx << 8; ! 567: sc->sc_ustat &= ~DONE; ! 568: (void) splx(spx); ! 569: TRACERN("<LPAN %d>}", sc->sc_lbufnx); ! 570: } ! 571: ! 572: lpareset(uban) ! 573: int uban; ! 574: { ! 575: register struct uba_device *ui; ! 576: register struct lpadevice *lpaaddr; ! 577: register struct lpa_softc *sc; ! 578: register int unit; ! 579: ! 580: TRACER("LPA RESET\n"); ! 581: for (unit = 0; unit < NLPA; unit++) { ! 582: if ((ui = lpadinfo[unit]) == 0 || ! 583: ui->ui_ubanum != uban || ui->ui_alive == 0) ! 584: continue; ! 585: printf(" lpa%d", unit); ! 586: lpaaddr = (struct lpadevice *)ui->ui_addr; ! 587: sc = &lpa_softc[unit]; ! 588: sc->sc_flag |= ERROR; ! 589: (void) spl7(); ! 590: lpaaddr->lcim = RESET; ! 591: lpaaddr->lcim = 0; ! 592: (void) spl0(); ! 593: if (sc->sc_flag & SLEEP) { ! 594: wakeup((caddr_t)sc); ! 595: sc->sc_flag &= ~SLEEP; ! 596: } ! 597: } ! 598: } ! 599: #endif NLPA
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.