Annotation of 42BSD/sys/vaxuba/lpa.c, revision 1.1

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

unix.superglobalmegacorp.com

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