Annotation of 43BSDReno/sys/vaxuba/lpa.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.