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