Annotation of 43BSD/sys/vaxuba/lpa.c, revision 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.1 (Berkeley) 6/5/86
        !             7:  */
        !             8: 
        !             9: #include "lpa.h"
        !            10: #if NLPA > 0
        !            11: 
        !            12: #include "param.h"
        !            13: #include "dir.h"
        !            14: #include "user.h"
        !            15: #include "buf.h"
        !            16: #include "proc.h"
        !            17: #include "ioctl.h"
        !            18: #include "uio.h"
        !            19: 
        !            20: #include "ubavar.h"
        !            21: 
        !            22: /*
        !            23:  * LPA driver for -- Asa Romberger
        !            24:  *
        !            25:  *     open
        !            26:  *     write microcode
        !            27:  *     write dedicated mode dispatch table
        !            28:  *     ioctl TIOCSETP to set parameters
        !            29:  *             struct iocb {
        !            30:  *                     short *baddr;   buffer address
        !            31:  *                     short rate;     - 1,000,000 / frequency in Hz
        !            32:  *                     short wc;       15-13 = number of buffers - 1
        !            33:  *                                     12-0 = buffer size in words
        !            34:  *             } iocb;
        !            35:  *     read - 1 character indicating buffer index
        !            36:  *             fill or empty buffer
        !            37:  * minor device number = DDCCCCCC where:
        !            38:  *     DD      = 00 for analog input
        !            39:  *             = 01 for analog output
        !            40:  *     CCCCCC  = channel number
        !            41:  */
        !            42:  *     define NOMCODE to eliminate the microcode download check
        !            43:  */
        !            44: /* #define TRACELPA */
        !            45: /* #define NOMCODE */
        !            46: 
        !            47: #ifdef TRACELPA
        !            48: #      define TRACER(x)        printf(x)
        !            49: #      define TRACERN(x, d)    printf(x, d)
        !            50: #else
        !            51: #      define TRACER(x)
        !            52: #      define TRACERN(x, d)
        !            53: #endif
        !            54: 
        !            55:        /* PRIORITY AT WHICH PROGRAM SHOULD RUN */
        !            56:        /* THIS SHOULD EVENTUALLY  TELL UNIX THIS IS A REAL-TIME DEVICE */
        !            57: 
        !            58: #define NICE   0
        !            59: 
        !            60: #define inc(v)         (sc->v = ((sc->v + 1) % sc->sc_nbuf))
        !            61: 
        !            62: #define LPAPRI         (PZERO + 0)
        !            63: #define LPAUNIT(dev)   0
        !            64: #define LPADEVICE(dev) (((dev) >> 6) & 03)
        !            65: #define LPACHANNEL(dev)        ((dev) & 077)
        !            66: 
        !            67: int    lpaprobe(), lpaattach(), lpaiintr(), lpaointr();
        !            68: u_short        lpastd[] = {0170460, 0};
        !            69: struct uba_device *lpadinfo[NLPA];
        !            70: struct uba_driver lpadriver =
        !            71:   {lpaprobe, 0, lpaattach, 0, lpastd, "lpa", lpadinfo, 0, 0, 0 };
        !            72: 
        !            73: struct lpa_softc {
        !            74:        int     sc_flag;        /* flags, as defined below */
        !            75:        int     sc_device;      /* device: 0 = analog in, 1 = analog out */
        !            76:        int     sc_channel;     /* device channel number */
        !            77:        struct buf sc_ubuffer;  /* user buffer header */
        !            78:        int     sc_ubabuf;      /* uba allocation pointer for buffer */
        !            79:        int     sc_ubufn;       /* present buffer that user is accessing */
        !            80:        int     sc_lbufn;       /* present buffer that lpa is accessing */
        !            81:        int     sc_lbufnx;      /* next buffer for lpa (value in ustat) */
        !            82:        int     sc_nbuf;        /* number of buffers */
        !            83:        int     sc_count;       /* buffer size in words */
        !            84:        short   sc_ustat;       /* user status word */
        !            85:        struct buf sc_ustatbuf; /* dummy user status word buffer for ubasetup */
        !            86:        int     sc_ubaustat;    /* uba allocation pointer for ustat */
        !            87:        struct buf *sc_buffer;  /* scratch buffer header */
        !            88:        int     sc_start;       /* 0 if lpa operation has been started */
        !            89: } lpa_softc[NLPA];
        !            90: 
        !            91: /* flags for sc_flag */
        !            92: #define OPEN   01              /* device is open */
        !            93: #define MCODE  02              /* microcode has been loaded */
        !            94: #define DMDT   04              /* dedicated mode dispatch table loaded */
        !            95: #define STTY   010             /* stty call and device initialized */
        !            96: #define SLEEP  020             /* sleeping */
        !            97: 
        !            98: /* bits for ustat */
        !            99: #define DONE   0100000         /* done */
        !           100: #define STOP   0040000         /* stop data transfer */
        !           101: #define NBI    0003400         /* next buffer index */
        !           102: #define LBI    0000003         /* last buffer index */
        !           103: 
        !           104: struct lpadevice {
        !           105:        short   lcim;           /* control in and maintenance */
        !           106:        short   lcos;           /* control and status out */
        !           107:        short   lrda;           /* request description array address word */
        !           108:        short   lms;            /* maintenance status */
        !           109: };
        !           110: 
        !           111: /* control in and maintenance register bits */
        !           112: #define        READYI  0000200         /* ready in */
        !           113: #define IIE    0000100         /* in interrupt enable */
        !           114: #define RDAEXT 0000014         /* rda address extension */
        !           115: #define RDAEXTOFFSET   2       /* offset of RDAEXT from right side */
        !           116: #define GO     0000001         /* go */
        !           117: #define RUN    0100000         /* run */
        !           118: #define RESET  0040000         /* reset */
        !           119: #define CWRITE 0020000         /* cram write */
        !           120: #define EA     0004000         /* enable arbitration */
        !           121: #define ROMO   0002000         /* rom O */
        !           122: #define ROMI   0001000         /* rom I */
        !           123: #define SMICRO 0000400         /* step microprocessor */
        !           124: 
        !           125: /* control and status out register bits */
        !           126: #define READYO 0200            /* ready out */
        !           127: #define OIE    0100            /* out interrupt enable */
        !           128: #define UINDEX 0007            /* user index */
        !           129: #define ERROR  0100000         /* error */
        !           130: #define ESTAT  0060000         /* error status */
        !           131: #define ESCODE 0017400         /* error sub code */
        !           132: #define ECODE  0077400         /* error status + error sub code */
        !           133: #define OVERRUN        0243            /* overrun error */
        !           134: 
        !           135: /* LPA COMMAND DESCRIPTION AREA */
        !           136: 
        !           137: /* INIT COMMAND */
        !           138: #define INIT   0               /* mode */
        !           139: #define MCVERS 4               /* microcode version */
        !           140: #define ACLOCKA        0170404         /* LPA bus addresses */
        !           141: #define ACLOCKB        0170432
        !           142: #define AAD1   0170400
        !           143: #define AAD2   1               /* 0170440 - DOES NOT EXIST */
        !           144: #define ADA    0170420
        !           145: #define ADIO1  1               /* 0167770 - DOES NOT EXIST */
        !           146: #define ADIO2  1               /* 0167760 - DOES NOT EXIST */
        !           147: #define ADIO3  1               /* 0167750 - DOES NOT EXIST */
        !           148: #define ADIO4  1               /* 0167740 - DOES NOT EXIST */
        !           149: #define ADIO5  1               /* 0167730 - DOES NOT EXIST */
        !           150: 
        !           151: /* CLOCK START COMMAND */
        !           152: #define CLOCK  1               /* mode */
        !           153: #define CLOCKA 0<<4            /* clock A */
        !           154:        /* clock status word */
        !           155: #define ENACTR 1               /* enable counter */
        !           156: #define R1M    1<<1            /* 1 MHz rate */
        !           157: #define R100K  2<<1            /* 100 KHz rate */
        !           158: #define R10K   3<<1            /* 10 KHz rate */
        !           159: #define R1K    4<<1            /* 1 KHz rate */
        !           160: #define R100   5<<1            /* 100 Hz rate */
        !           161: #define REXT   6<<1            /* external rate (from st1 input) */
        !           162: #define R60    7<<1            /* line frequency rate */
        !           163: #define MFIE   0100            /* mode flag interrupt enable */
        !           164: #define MSI    0<<8            /* single interval mode */
        !           165: #define MRI    1<<8            /* repeat interval mode */
        !           166: #define MEET   2<<8            /* external event time mode */
        !           167: #define MEETZ  3<<8            /* external event time mode from zero base */
        !           168: #define ST1EC  020000          /* st1 enable counter */
        !           169: #define ST1IE  040000          /* st1 interrupt enable */
        !           170: 
        !           171: /* DATA TRANSFER START COMMAND */
        !           172: #define DTS    2               /* mode */
        !           173: #define SCHAN  1<<8            /* single channel */
        !           174: 
        !           175: lpaprobe(reg)
        !           176:        caddr_t reg;
        !           177: {
        !           178:        register int br, cvec;  /* value result */
        !           179:        register struct lpadevice *lpaaddr = (struct lpadevice *)reg;
        !           180: 
        !           181: #ifdef lint
        !           182:        br = 0; cvec = br; br = cvec;
        !           183: #endif
        !           184:        /* this should force an interrupt, stall, clear the lpa */
        !           185:        br = 0x15;
        !           186:        cvec = 0330;
        !           187: TRACER("PROBE\n");
        !           188:        return (sizeof (struct lpadevice));
        !           189: }
        !           190: 
        !           191: lpaattach(ui)
        !           192:        register struct upa_device *ui;
        !           193: {
        !           194: 
        !           195: }
        !           196: 
        !           197: lpaopen(dev, flag)
        !           198:        dev_t dev;
        !           199:        int flag;
        !           200: {
        !           201:        register int unit = LPAUNIT(dev);
        !           202:        register struct lpa_softc *sc = &lpa_softc[unit];
        !           203:        register struct uba_device *ui = lpadinfo[unit];
        !           204:        register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
        !           205: 
        !           206: TRACER("OPEN\n");
        !           207:        if (unit >= NLPA || sc->sc_flag & OPEN || ui == 0 ||
        !           208:            ui->ui_alive == 0)
        !           209:                return (ENXIO);
        !           210:        (void) splhigh();
        !           211:        lpaaddr->lcim = RESET;
        !           212:        lpaaddr->lcim = 0;
        !           213:        (void) spl0();
        !           214:        lpaaddr->lcos = 0;      /* clear the registers as a precaution */
        !           215:        lpaaddr->lrda = 0;
        !           216:        lpaaddr->lms = 0;
        !           217:        sc->sc_flag = OPEN;
        !           218:        sc->sc_device = LPADEVICE(dev);
        !           219:        sc->sc_channel = LPACHANNEL(dev);
        !           220:        sc->sc_buffer = geteblk();
        !           221:        sc->sc_buffer->b_error = 0;
        !           222:        sc->sc_buffer->b_proc = u.u_procp;
        !           223:        sc->sc_ubufn = -1;
        !           224:        /* THIS SHOULD EVENTUALLY SPECIFY "REAL-TIME" */
        !           225:        u.u_procp->p_nice = NICE;
        !           226:        return (0);
        !           227: }
        !           228: 
        !           229: lpaclose(dev, flag)
        !           230:        dev_t dev;
        !           231:        int flag;
        !           232: {
        !           233:        register int unit = LPAUNIT(dev);
        !           234:        register struct lpa_softc *sc = &lpa_softc[unit];
        !           235:        register struct uba_device *ui = lpadinfo[unit];
        !           236:        register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr;
        !           237: 
        !           238:        if (sc->sc_device && sc->sc_ubufn >= 0 && (sc->sc_flag & ERROR) == 0) {
        !           239:                if (sc->sc_start)
        !           240:                        lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum);
        !           241:                sc->sc_flag |= STOP;
        !           242:                (void) spl5();
        !           243:                while (sc->sc_flag & STOP) {
        !           244: TRACER("SLEEP\n");
        !           245:                        sc->sc_flag |= SLEEP;
        !           246:                        sleep((caddr_t)sc, LPAPRI);
        !           247:                }
        !           248:        }
        !           249:        (void) splhigh();
        !           250:        lpaaddr->lcim = RESET;
        !           251:        lpaaddr->lcim = 0;
        !           252:        (void) spl0();
        !           253:        if (sc->sc_ubabuf) {
        !           254:                ubarelse(ui->ui_ubanum, &sc->sc_ubabuf);
        !           255:                sc->sc_ubabuf = 0;
        !           256:                (void) splclock();
        !           257:                vsunlock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount,
        !           258:                        (sc->sc_device)? B_READ : B_WRITE);
        !           259:                u.u_procp->p_flag &= ~SPHYSIO;
        !           260:                (void) spl0();
        !           261:        }
        !           262:        if (sc->sc_ubaustat) {
        !           263:                ubarelse(ui->ui_ubanum, &sc->sc_ubaustat);
        !           264:                sc->sc_ubaustat = 0;
        !           265:        }
        !           266:        if (sc->sc_buffer) {
        !           267:                brelse(sc->sc_buffer);
        !           268:                sc->sc_buffer = 0;
        !           269:        }
        !           270:        sc->sc_flag = 0;
        !           271: TRACER("CLOSE\n");
        !           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_WRITE, 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_WRITE, 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_READ, 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.