Annotation of researchv8dc/sys/dev/ds.c, revision 1.1

1.1     ! root        1: /* 5-29-84  dsrelease checks for zombie state or even death */
        !             2: /* dsclose() shuts down device */
        !             3: /* DSWAIT added */
        !             4: /* 5-25-84  process pointer saved in dsopen for dsintr() */
        !             5: /*     vsunlock must then be duplicated using correct process structure */
        !             6: /* the interrelation of dsstart-sleeping, dsintr, and dscleanup
        !             7:        needs to be cleaned up 
        !             8:        Probably dscleanup should not call wakeup */
        !             9: 
        !            10: 
        !            11: #include "ds.h"
        !            12: # if NDS > 0
        !            13: 
        !            14: /*
        !            15:  * DSC System 200 driver
        !            16:  * via DSC dma11.
        !            17:  * vax 4.1bsd version
        !            18:  */
        !            19: 
        !            20: #include "../h/param.h"
        !            21: #include "../h/systm.h"
        !            22: #include "../h/mount.h"
        !            23: #include "../h/dir.h"
        !            24: #include "../h/user.h"
        !            25: #include "../h/pte.h"
        !            26: #include "../h/map.h"
        !            27: #include "../h/buf.h"
        !            28: #include "../h/ubareg.h"
        !            29: #include "../h/ubavar.h"
        !            30: #include "../h/conf.h"
        !            31: #include "../h/proc.h"
        !            32: #include "../h/file.h"
        !            33: #include "../h/vmmac.h"
        !            34: 
        !            35: #include "../h/dsreg.h"
        !            36: #include "../h/dsc.h"
        !            37: 
        !            38: /*
        !            39:  * THESE ARE SITE-SPECIFIC
        !            40:  *
        !            41:  * starting base for the
        !            42:  * d/a and a/d converters,
        !            43:  * for setting up sequence ram.
        !            44:  */
        !            45: 
        !            46: /*
        !            47:  * reset device
        !            48:  */
        !            49: # define RESETDEV      bit(4)
        !            50: # define dsseq(sc, reg, conv, dir) \
        !            51:        (sc->c_ascseq[reg] = conv | ((dir & 01) << 6))
        !            52: 
        !            53: /*
        !            54:  * ds flags
        !            55:  */
        !            56: # define DS_CLOSED     0
        !            57: # define DS_OPEN       bit(0)
        !            58: # define DS_IDLE       bit(1)
        !            59: # define DS_NDSK       bit(2)
        !            60: # define DS_MON                bit(3)
        !            61: # define DS_BRD                bit(4) 
        !            62: # define DS_READ       bit(5)
        !            63: # define DS_WRITE      bit(6)
        !            64: 
        !            65: 
        !            66: # define DSPRI         (PZERO+1)
        !            67: /*
        !            68:  * Redundant book-keeping
        !            69:  * to help avoid page-wise overlap of buffers
        !            70:  *     remember that this device is both asynchronous and
        !            71:  *     uses user-supplied buffers
        !            72:  */
        !            73: struct dspageinfo {
        !            74:        int firstunit,
        !            75:                lastunit;       /* in units of CLSIZE*NBPG, i.e. 1024 */
        !            76: };
        !            77: /*
        !            78:  * relevant information
        !            79:  * about the dma and asc
        !            80:  */
        !            81: struct ds_softc {
        !            82:        short           c_dmacsr;       /* copy of dma csr */
        !            83:        short           c_asccsr;       /* copy of asc csr */
        !            84:        short           c_ascflags;     /* initial asc flags */
        !            85:        short           c_ascsrt;       /* sampling rate */
        !            86:        short           c_ascseq[8];
        !            87:        int             c_flags;        /* internal flags */
        !            88:        int             c_errs;         /* errors, returned via ioctl */
        !            89:        int             c_bufno;        /* dsubinfo/buffer */
        !            90:        int             c_outbufno;
        !            91:        int             c_uid;          /* user id */
        !            92:        short           c_pid;          /* process id */
        !            93:        struct proc     *c_procp;       /* process structure pointer */
        !            94:        int             c_ubinfo[NDSB]; /* uba info */
        !            95:        struct dspageinfo       c_pageinfo[NDSB];
        !            96:        struct buf      c_dsb[NDSB];    /* buffer list */
        !            97:        struct buf      *c_ibp, *c_obp; /* buffer list pointers */
        !            98:        int             c_nbytes;       /* total # of bytes xferred since reset */
        !            99:        int             c_to_idle;      /* total # times idle flag set */
        !           100:        int             c_to_active;    /* total # times idle flag cleared */
        !           101: } ds_softc[NDS];
        !           102: 
        !           103: int dsprobe(), dsattach(), dsintr();
        !           104: 
        !           105: struct uba_device *dsdinfo[NDS];
        !           106: struct uba_ctlr dsctlr[NDS], *dscinfo[NDS];    /* dsattach() sets dscinfo to point to this */
        !           107: 
        !           108: u_short dsstd[] = {
        !           109:        0165400, 0
        !           110: };
        !           111: 
        !           112: struct uba_driver dsdriver = {
        !           113:        dsprobe, 0, dsattach, 0, dsstd, "ds", dsdinfo, "ds", dscinfo
        !           114: };
        !           115: int    dsdebug;
        !           116: 
        !           117: /*
        !           118:  * all this just to generate
        !           119:  * an interrupt; rather
        !           120:  * involved isn't it?
        !           121:  */
        !           122: dsprobe(reg)
        !           123: caddr_t reg;
        !           124: {
        !           125:        register int br, cvec;          /* value-result */
        !           126:        register struct dsdevice *dsaddr;
        !           127:        int dummy;
        !           128: 
        !           129: # ifdef lint   
        !           130:        br = 0; cvec = br; br = cvec;
        !           131: # endif lint
        !           132: 
        !           133:        dsaddr = (struct dsdevice *) reg;
        !           134: 
        !           135:        dsaddr->dmacsr = 0;
        !           136:        dsaddr->dmacls = 0;
        !           137:        dsaddr->ascseq[0] = DABASE+0 | ((DA & 01) << 6);
        !           138:        dsaddr->ascseq[0] |= LAST_SEQ;  /* last sequence register */
        !           139:        dsaddr->ascsrt = 0100;
        !           140:        dsaddr->dmacsr = DMA_IE;
        !           141:        dsaddr->asccsr = ASC_RUN | ASC_IE;
        !           142: 
        !           143:        DELAY(40000);
        !           144:        /*
        !           145:         * now shut everything down.
        !           146:         * too bad we have to duplicate
        !           147:         * the code from dsinit but to
        !           148:         * call dsinit we need to give
        !           149:         * it a unit.
        !           150:         */
        !           151: 
        !           152:        dsaddr->dmacls = 0;
        !           153:        dummy = dsaddr->dmasar;                 /* clears sar flag */
        !           154:        dsaddr->dmaclr = 0;
        !           155: 
        !           156:        dummy = dsaddr->ascrst;
        !           157:        dsaddr->ascrst = 0; 
        !           158: 
        !           159:        return(1);
        !           160: }
        !           161: 
        !           162: dsattach(ui)
        !           163: struct uba_device *ui;
        !           164: {
        !           165:        register struct uba_ctlr *um;
        !           166:        register int unit;
        !           167:        register int i;
        !           168: 
        !           169:        unit = ui->ui_unit;
        !           170: 
        !           171:        um = &dsctlr[unit];
        !           172:        dscinfo[unit] = um;
        !           173:        ui->ui_ctlr = unit;
        !           174:        ui->ui_mi = um;
        !           175:        um->um_driver = ui->ui_driver;
        !           176:        um->um_ctlr = unit;
        !           177:        um->um_ubanum = ui->ui_ubanum;
        !           178:        um->um_alive = 1;
        !           179:        um->um_intr = ui->ui_intr;
        !           180:        um->um_addr = ui->ui_addr;
        !           181:        um->um_hd = ui->ui_hd;
        !           182:        ds_softc[unit].c_flags = DS_IDLE;
        !           183:        for(i=0;i<NDSB;i++)
        !           184:                ds_softc[unit].c_dsb[i].b_flags &= ~B_BUSY;
        !           185: }
        !           186: 
        !           187: /* ARGSUSED */
        !           188: dsopen(dev, flag)
        !           189: dev_t dev;
        !           190: {
        !           191:        register struct dsdevice *dsaddr;
        !           192:        register struct uba_device *ui;
        !           193:        register struct ds_softc *sc;
        !           194:        register int unit, i;
        !           195:        register struct buf *bp;
        !           196:        int dummy;
        !           197: 
        !           198:        if ((unit = (minor(dev) & ~RESETDEV)) >= NDS)
        !           199:                goto bad;
        !           200: 
        !           201:        if ((ui = dsdinfo[unit]) == NULL)
        !           202:                goto bad;
        !           203: 
        !           204:        if (ui->ui_alive == 0)
        !           205:                goto bad;
        !           206: 
        !           207:        sc = &ds_softc[ui->ui_unit];
        !           208:        dsaddr = (struct dsdevice *)ui->ui_addr;
        !           209: 
        !           210:        if(dsdebug)printf("dsopen: unit %d, flag %x\n",unit,flag);
        !           211:        if (dsaddr->dmacsr & DMA_OFL) {
        !           212:                u.u_error = ENXIO;
        !           213:                return;
        !           214:        }
        !           215: 
        !           216:        /*
        !           217:         * if this is the reset device
        !           218:         * then just do a reset and return.
        !           219:         */
        !           220:        if (minor(dev) & RESETDEV) {
        !           221:                /*
        !           222:                 * if the converters are in use then
        !           223:                 * only the current user or root can
        !           224:                 * do a reset.
        !           225:                 */
        !           226:                if (sc->c_flags & DS_OPEN) {
        !           227:                        if ((sc->c_uid != u.u_ruid) && (u.u_uid != 0)) {
        !           228:                                u.u_error = ENXIO;
        !           229:                                return;
        !           230:                        }
        !           231:                }
        !           232:                ds_softc[unit].c_flags = DS_CLOSED | DS_IDLE;
        !           233:                dscleanup(unit);
        !           234:                printf("ds%d: reset\n",unit);
        !           235:                return;
        !           236:        }
        !           237: 
        !           238:        /*
        !           239:         * only one person can use it at a time
        !           240:         * and it can't be opened for both reading and writing
        !           241:         */
        !           242:        if (sc->c_flags & DS_OPEN || (flag & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
        !           243: bad:           u.u_error = ENXIO;
        !           244:                return;
        !           245:        }
        !           246: 
        !           247:        /*
        !           248:         * initialize
        !           249:         */
        !           250: 
        !           251: 
        !           252:        /* set defaults and initial conditions in ds_softc */
        !           253:        sc->c_flags = DS_IDLE;
        !           254:        sc->c_errs = 0;
        !           255: 
        !           256:        sc->c_nbytes = sc->c_to_idle = sc->c_to_active = 0;
        !           257: 
        !           258:        sc->c_ascflags = (flag & FWRITE ? ASC_PLAY : ASC_RECORD) | ASC_HZ04;
        !           259:        sc->c_ascseq[0] = (
        !           260:                (flag & FWRITE) ?
        !           261:                        (DABASE+0 | (DA << 6)) :  (ADBASE+0 | (AD << 6))
        !           262:                                                ) | LAST_SEQ;
        !           263:        sc->c_ascsrt = 399;
        !           264: 
        !           265: 
        !           266:        sc->c_uid = u.u_ruid;
        !           267:        sc->c_pid = u.u_procp->p_pid;
        !           268:        sc->c_procp = u.u_procp;
        !           269:        if(dsdebug)printf("pid %d %d, flag %x stat %x\n",
        !           270:                sc->c_pid,sc->c_procp->p_pid,sc->c_procp->p_stat);
        !           271:        sc->c_flags |= DS_OPEN | (flag & FREAD ? DS_READ : DS_WRITE);
        !           272:        u.u_procp->p_flag |= SPHYSIO;
        !           273:        dsaddr->dmacsr = 0;
        !           274:        dummy = dsaddr->dmasar;
        !           275: }
        !           276: 
        !           277: /* ARGSUSED */
        !           278: dsclose(dev, flag) {
        !           279:        register int unit;
        !           280:        register struct dsdevice *dsaddr;
        !           281:        register struct uba_device *ui;
        !           282:        register struct ds_softc *sc;
        !           283: 
        !           284:        unit = minor(dev) & ~RESETDEV;
        !           285:        sc = &ds_softc[unit];
        !           286:        ui = dsdinfo[unit];
        !           287:        dsaddr = (struct dsdevice *)ui->ui_addr;
        !           288:        if(dsdebug)printf("X");
        !           289:        if (sc->c_outbufno != sc->c_bufno && 
        !           290:                sc->c_errs == 0 && !(sc->c_flags & DS_IDLE))
        !           291:                tsleep((caddr_t)&ds_softc[unit], DSPRI,0);
        !           292:        dsaddr->asccsr = 0;
        !           293:        ds_softc[unit].c_flags = DS_CLOSED | DS_IDLE;
        !           294:        dscleanup(unit);
        !           295:        u.u_procp->p_flag &= ~ SPHYSIO;
        !           296:        if(dsdebug){
        !           297:                printf("to_active %d, to_idle %d, c_nbytes %d\n",
        !           298:                sc->c_to_active,
        !           299:                sc->c_to_idle,
        !           300:                sc->c_nbytes);
        !           301:                printf("c_ascseq[0] %x\n",sc->c_ascseq[0]);
        !           302:                dsdb(dsaddr);
        !           303:        }
        !           304: }
        !           305: 
        !           306: /*
        !           307:  *
        !           308:  * Using u.u_count, u.u_base, each buffer header is set up.
        !           309:  * The converters only need the base address of the buffer and the word
        !           310:  * count.
        !           311:  *
        !           312:  */
        !           313: dsstart(dev, rw)
        !           314: register dev_t dev;
        !           315: {
        !           316:        register struct dsdevice *dsaddr;
        !           317:        register struct uba_device *ui;
        !           318:        register struct ds_softc *sc;
        !           319:        register struct buf *bp;
        !           320:        register int    unit, c, bufno, ps;
        !           321:        int dummy,i, count;
        !           322:        caddr_t base;
        !           323:        int bits;
        !           324: 
        !           325:        if(dsdebug)printf("S");
        !           326: 
        !           327:        unit = minor(dev) & ~RESETDEV;
        !           328:        sc = &ds_softc[unit];
        !           329:        ui = dsdinfo[unit];
        !           330:        dsaddr = (struct dsdevice *)ui->ui_addr;
        !           331: 
        !           332:        /*
        !           333:         * check user access rights to buffer
        !           334:         */
        !           335:        if (useracc(u.u_base, u.u_count, rw==B_READ?B_WRITE:B_READ) == NULL) {
        !           336:                u.u_error = EFAULT;
        !           337:                return;
        !           338:        }
        !           339: 
        !           340:        if (sc->c_errs) {
        !           341:                u.u_error = EIO;
        !           342:                return;
        !           343:        }
        !           344: 
        !           345: 
        !           346:        /*
        !           347:         * Get a buffer for each 64K block
        !           348:         * point each device buffer somewhere into
        !           349:         * the user's buffer
        !           350:         */
        !           351:        /* NOTE that in order to get reasonable performance,
        !           352:         * buffer lengths (initial u.u_count) must be either
        !           353:         * less than 64K or sufficiently greater than a multiple
        !           354:         * of 64K.
        !           355:         */
        !           356:        base = u.u_base;
        !           357:        count = u.u_count;
        !           358:        while(count > 0) {
        !           359: 
        !           360:                if(dsdebug)printf("LT ");
        !           361: 
        !           362:                /*
        !           363:                 * no hardware buffers left, sleep till interrupt
        !           364:                 * wakes us up
        !           365:                 */
        !           366: 
        !           367:                
        !           368:                ps = spl6();
        !           369:                if ((sc->c_dmacsr = dsaddr->dmacsr) & DMA_SFL) {
        !           370:                        register        ts;
        !           371:                        if(dsdebug)printf("s");
        !           372:                        ts = tsleep((caddr_t) &ds_softc[unit], DSPRI, 0);
        !           373:                        if(dsdebug)printf("w");
        !           374:                        switch(ts) {
        !           375:                                case TS_SIG:
        !           376:                                        u.u_error = EINTR;
        !           377:                                        /* stop dsc, if active */
        !           378:                                        dsaddr->asccsr = dummy = 0;
        !           379:                                        dscleanup(unit);
        !           380:                                        return;
        !           381:                                case TS_OK:
        !           382:                                        if ((sc->c_dmacsr = dsaddr->dmacsr) & DMA_SFL) {
        !           383:                                                u.u_error = EIO;
        !           384:                                                printf("ds%d  still full after tsleep\n",unit);
        !           385:                                                dscleanup(unit);
        !           386:                                                return; 
        !           387:                                        }
        !           388:                        /* I don't think this allows for a clean dsclose()
        !           389:                                in all cases */
        !           390:                                        if((sc->c_flags & DS_CLOSED) ||
        !           391:                                          !(sc->c_flags & DS_OPEN)){
        !           392:                                                if(dsdebug)
        !           393:                                          printf("ds: wakeup unopen\n");
        !           394:                                                u.u_error = EIO;
        !           395:                                                dscleanup(unit);
        !           396:                                                return;
        !           397:                                        }
        !           398:                                        break;
        !           399:                                default:
        !           400:                                        printf("ds: %x from tsleep\n",ts);
        !           401:                                        dscleanup(unit);
        !           402:                                        u.u_error = EIO;
        !           403:                                        return;
        !           404:                        }
        !           405:                }
        !           406: 
        !           407:                splx(ps);
        !           408: 
        !           409: 
        !           410:                ps = spl6();
        !           411: 
        !           412:        /*
        !           413:         *      If device is IDLE (initial read/write, or datalate condition
        !           414:         *        has been detected in dsintr()), (re)initialize dsc
        !           415:         */
        !           416: 
        !           417:        if (sc->c_flags & DS_IDLE) {
        !           418: 
        !           419:                if(dsdebug)
        !           420:                        printf("I1 ");
        !           421:                dsaddr->asccsr = sc->c_asccsr = sc->c_ascflags;
        !           422:                dummy = dsaddr->ascrst;
        !           423:                dsaddr->asccsr = (sc->c_asccsr |= ASC_IE);
        !           424:                dsaddr->ascsrt = sc->c_ascsrt;
        !           425:                {register       j, i = 0;
        !           426:                        do {
        !           427:                                dsaddr->ascseq[i] = sc->c_ascseq[i];
        !           428:                                j = i++;
        !           429:                        } while(!(sc->c_ascseq[j] & LAST_SEQ) && i<8);
        !           430:                }
        !           431:                dsaddr->dmacsr = sc->c_dmacsr = 0;
        !           432:                dsaddr->dmacls = 0;
        !           433:                dummy = dsaddr->dmasar;                 /* clears sfl flag */
        !           434:                dsaddr->dmawc = -1;
        !           435:                dsaddr->dmacsr = sc->c_dmacsr = (DMA_IE | DMA_CHN
        !           436:                                | (rw == B_READ ? DMA_W2M : 0) );
        !           437: 
        !           438:                sc->c_bufno = sc->c_outbufno = 0;
        !           439:                sc->c_ibp = sc->c_obp = &sc->c_dsb[0];  /* correct?  */
        !           440: 
        !           441:        }
        !           442: 
        !           443: 
        !           444:                /* get next device buffer and set it up */
        !           445:                bp = sc->c_ibp++;
        !           446:                if (sc->c_ibp > &sc->c_dsb[NDSB-1])
        !           447:                        sc->c_ibp = &sc->c_dsb[0];
        !           448: 
        !           449:                /* hopefully  redundant check against going to fast */
        !           450:                if(bp->b_flags & B_BUSY){
        !           451:                        printf("dsstart: about to set up BUSY buffer!\n");
        !           452:                        u.u_error = EIO;
        !           453:                        return;
        !           454:                }
        !           455: 
        !           456: 
        !           457:                c = MIN(count, 1024*64);
        !           458:                bp->b_un.b_addr = base;
        !           459:                bp->b_error = 0;
        !           460:                bp->b_proc = u.u_procp;
        !           461:                bp->b_dev = dev;
        !           462:                bp->b_blkno = sc->c_bufno;
        !           463:                bp->b_bcount = c;
        !           464:                bufno = sc->c_bufno % NDSB;
        !           465: 
        !           466:                /* the page computations should be relative to param.h defs */
        !           467: 
        !           468:                sc->c_pageinfo[bufno].firstunit = (int)base >> 10;
        !           469:                sc->c_pageinfo[bufno].lastunit=(((int)base+c+1023)>>10)-1;
        !           470: 
        !           471:                for(i=0;i<NDSB;i++)
        !           472:                        if((sc->c_dsb[i].b_flags & B_BUSY)
        !           473:                                &&
        !           474:                        (!(sc->c_pageinfo[bufno].firstunit >
        !           475:                                sc->c_pageinfo[i].lastunit)
        !           476:                                &&
        !           477:                         !(sc->c_pageinfo[bufno].lastunit <
        !           478:                                sc->c_pageinfo[i].firstunit))) {
        !           479:                                printf("ds: buf %d overlaps %d\n",i,bufno);
        !           480:                                u.u_error=EIO;
        !           481:                                return;
        !           482:                        }
        !           483: 
        !           484:                /* lock the buffer and send it off */
        !           485: 
        !           486:                bp->b_flags = B_BUSY | B_PHYS  | rw;
        !           487:                if(dsdebug)printf("lk%d %x %d ",bufno,base,c);
        !           488:                dslock(base, (int) c);  /* fasten seat belts */
        !           489: 
        !           490:                sc->c_ubinfo[bufno] = ubasetup(ui->ui_ubanum, bp, UBA_WANTBDP);
        !           491: 
        !           492:                dsaddr->dmablr = ~ (c >> 1);
        !           493:                dsaddr->dmasax = (sc->c_ubinfo[bufno] >> 16) & 03;
        !           494:                dsaddr->dmasar = sc->c_ubinfo[bufno];
        !           495:                        
        !           496:                sc->c_bufno++;
        !           497: 
        !           498:                /*
        !           499:                 * start the dsc, if necessary
        !           500:                 */
        !           501:                if(sc->c_flags & DS_IDLE){
        !           502:                        if(dsdebug)printf("I2 ");
        !           503:                        sc->c_flags &= ~DS_IDLE;
        !           504:                        ++sc->c_to_active;
        !           505:                        dsaddr->asccsr = (sc->c_asccsr |= ASC_RUN);
        !           506:                }
        !           507: 
        !           508:                splx(ps);
        !           509: 
        !           510:                base += c;
        !           511:                count -= c;
        !           512:                if(dsdebug)printf("LB%x",u.u_error);
        !           513:        }
        !           514:                
        !           515:        u.u_count = count;
        !           516: }
        !           517: dsdb(dsaddr)
        !           518: register struct dsdevice *dsaddr;
        !           519: {
        !           520:        printf("dmacsr %b\n", dsaddr->dmacsr, DMA_BITS);
        !           521:        printf("asccsr %b\n", dsaddr->asccsr, ASC_BITS);
        !           522:        printf("dmawc %o\t", dsaddr->dmawc);
        !           523:        printf("dmablr %o\n", dsaddr->dmablr);
        !           524:        printf("dmaac %o\t", dsaddr->dmaac);
        !           525:        printf("dmasar %o\n", dsaddr->dmasar);
        !           526:        printf("dmaacx %o\t", dsaddr->dmaacx);
        !           527:        printf("dmasax %o\n", dsaddr->dmasax);
        !           528:        printf("ascsrt(decimal) %d\n", dsaddr->ascsrt);
        !           529:        printf("ascseq[0] %o\n", dsaddr->ascseq[0]);
        !           530: }
        !           531: /*
        !           532:  * this is where the real work is done. we copy any device registers that
        !           533:  * we will be looking at to decrease the amount of traffic on the ds 200
        !           534:  * bus.
        !           535:  *
        !           536:  */
        !           537: dsintr(dev)
        !           538: dev_t dev;
        !           539: {
        !           540:        register struct dsdevice *dsaddr;
        !           541:        register struct uba_device *ui;
        !           542:        register struct ds_softc *sc;
        !           543:        register struct buf *bp;
        !           544:        register int bufno;
        !           545:        register int i;
        !           546:        int unit, dummy;
        !           547: 
        !           548:        unit = minor(dev) & ~RESETDEV;
        !           549:        sc = &ds_softc[unit];
        !           550:        ui = dsdinfo[unit];
        !           551: 
        !           552:        dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr;
        !           553:        
        !           554:        sc->c_dmacsr = dsaddr->dmacsr;
        !           555: 
        !           556:        dsaddr->dmacls = 0;
        !           557:        if(dsdebug)printf("i");
        !           558:        if (sc->c_flags & DS_IDLE) {
        !           559:                printf("ds%d: interrupt while idle\n", unit);
        !           560:                return;
        !           561:        }
        !           562: 
        !           563:        if (sc->c_dmacsr & DMA_ERR) {
        !           564:                if(dsdebug)printf("e");
        !           565:                sc->c_asccsr = (sc->c_dmacsr & DMA_XIN ? dsaddr->asccsr : 0);
        !           566:                dsaddr->asccsr = dummy = 0;
        !           567: 
        !           568:                dsaddr->dmacsr = (sc->c_dmacsr &= ~DMA_CHN);
        !           569:                if ((sc->c_dmacsr & (DMA_XER|DMA_UBA|DMA_AMPE|DMA_XBA))
        !           570:                                || (sc->c_asccsr & (ASC_BA|ASC_DCN|ASC_DNP))) {
        !           571:                        ++sc->c_errs;
        !           572:                        printf("ds%d error: asccsr=%b dmacsr=%b\n",
        !           573:                                unit, sc->c_asccsr, ASC_BITS,
        !           574:                                sc->c_dmacsr, DMA_BITS);
        !           575:                } else
        !           576:                        sc->c_nbytes += sc->c_obp->b_bcount;
        !           577:        /* the above may be wrong, since DLT interrupt seems to occur
        !           578:         *      separately from (and later than) DMA completion
        !           579:         *      interrupt       */
        !           580:                dscleanup(unit);
        !           581:                return;
        !           582:        }
        !           583:                
        !           584:        /*
        !           585:         * get current buffer and release it
        !           586:         */
        !           587: 
        !           588:        bp = sc->c_obp++;
        !           589:        if (sc->c_obp > &sc->c_dsb[NDSB-1])
        !           590:                sc->c_obp = &sc->c_dsb[0];
        !           591: 
        !           592:        sc->c_outbufno++;
        !           593:        if(dsdebug)printf("b ");
        !           594:        dsrelease(sc, ui, bp);
        !           595: 
        !           596:        /*
        !           597:         * update byte count.
        !           598:         */
        !           599: 
        !           600:        sc->c_nbytes += bp->b_bcount;
        !           601: 
        !           602:        wakeup((caddr_t) &ds_softc[unit]);
        !           603: }
        !           604: 
        !           605: /*
        !           606:  * release resources, if any, associated with a buffer
        !           607:  */
        !           608: dsrelease(sc, ui, bp)
        !           609: register struct ds_softc *sc;
        !           610: struct uba_device *ui;
        !           611: register struct buf *bp;
        !           612: {
        !           613:        register int    ps;
        !           614:        register struct pte *pte;
        !           615:        register int npf;
        !           616:        int     bufno;
        !           617: 
        !           618:        bufno = bp->b_blkno % NDSB;
        !           619:        if(dsdebug)printf("R%d ",bufno);
        !           620:        /*
        !           621:         * release uba resources
        !           622:         * and memory resources if process seems healthy
        !           623:         */
        !           624:        ps = spl6();
        !           625: 
        !           626:        if (bp->b_flags & B_BUSY) {
        !           627:                if(dsdebug)printf("%x %d ",bp->b_un.b_addr,bp->b_bcount);
        !           628:                ubarelse(ui->ui_ubanum, &sc->c_ubinfo[bufno]);
        !           629: 
        !           630:                /* we can't call vsunlock() because u.u_procp may be
        !           631:                        different */
        !           632:        if( !(sc->c_pid == sc->c_procp->p_pid) ||
        !           633:            (sc->c_procp->p_flag & SWEXIT) ||
        !           634:                (sc->c_procp->p_stat == SZOMB)){
        !           635:                           /* process is dying or dead */
        !           636:                        /* exit() will release memory (does it unlock???) */
        !           637:                        /* but will not release uba resources */
        !           638:                printf(" REL pid %d %d flag %x stat %x ",sc->c_pid,
        !           639:                                sc->c_procp->p_pid,sc->c_procp->p_flag,
        !           640:                                        sc->c_procp->p_stat);
        !           641:                sc->c_flags |= DS_CLOSED;
        !           642:        }
        !           643:        else {
        !           644:                pte = vtopte(sc->c_procp,btop(bp->b_un.b_addr));
        !           645:                npf = btoc(bp->b_bcount + ((int)(bp->b_un.b_addr)&CLOFSET));
        !           646:                if(dsdebug)printf("U%x %d ",pte->pg_pfnum,npf);
        !           647:                while(npf > 0) {
        !           648:                        munlock(pte->pg_pfnum);
        !           649:                        if(sc->c_ascflags & ASC_RECORD)
        !           650:                                pte->pg_m = 1;  /* memory written */
        !           651:                        pte += CLSIZE;
        !           652:                        npf -= CLSIZE;
        !           653:                }
        !           654:        }
        !           655: 
        !           656:                bp->b_flags = 0;  /* better than resetting B_BUSY */
        !           657:        }
        !           658: 
        !           659:        splx(ps);
        !           660: }
        !           661: 
        !           662: /*
        !           663:  * release all buffers and do general cleanup
        !           664:  */
        !           665: dscleanup(unit)
        !           666: int unit;
        !           667: {
        !           668:        register struct dsdevice *dsaddr;
        !           669:        register struct uba_device *ui;
        !           670:        register struct ds_softc *sc;
        !           671:        register struct buf *bp;
        !           672:        int     dummy;
        !           673: 
        !           674:        unit = (unit & ~RESETDEV);
        !           675:        sc = &ds_softc[unit];
        !           676:        ui = dsdinfo[unit];
        !           677:        dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr;
        !           678:        
        !           679:        if(dsdebug)printf("C ");
        !           680:        if (!(sc->c_flags & DS_IDLE))
        !           681:                ++sc->c_to_idle;
        !           682:        sc->c_flags |= DS_IDLE;
        !           683: 
        !           684:        dsaddr->asccsr = dummy = 0;
        !           685:        dummy = dsaddr->ascrst;
        !           686:        dsaddr->dmacsr = dummy = 0;
        !           687:        dummy = dsaddr->dmasar;
        !           688: 
        !           689:        for (bp = &(sc->c_dsb[0]); bp < &(sc->c_dsb[NDSB]); ++bp)
        !           690:                dsrelease(sc, ui, bp);
        !           691: 
        !           692: 
        !           693:        /* if called from dsintr while dsstart is sleeping */
        !           694: 
        !           695:        wakeup((caddr_t) &ds_softc[unit]);
        !           696: }
        !           697: 
        !           698: /*
        !           699:  * a/d conversion
        !           700:  */
        !           701: dsread(dev)
        !           702: dev_t dev;
        !           703: {
        !           704:        dsstart(dev, B_READ);           /* writes on disk */
        !           705: }
        !           706: 
        !           707: /*
        !           708:  * d/a conversion
        !           709:  */
        !           710: dswrite(dev)
        !           711: dev_t dev;
        !           712: {
        !           713:        dsstart(dev, B_WRITE);          /* reads from disk */
        !           714: }
        !           715: 
        !           716: /* ARGSUSED */
        !           717: dsioctl(dev, cmd, addr, flag)
        !           718: dev_t dev;
        !           719: caddr_t addr;
        !           720: {
        !           721:        register struct dsdevice *dsaddr;
        !           722:        register struct ds_softc *sc;
        !           723:        register struct ds_seq *dq;
        !           724:        register struct ds_err *de;
        !           725:        register struct ds_trans *dt;
        !           726:        struct uba_device *ui;
        !           727:        struct ds_seq ds_seq;
        !           728:        struct ds_err ds_err;
        !           729:        struct ds_trans ds_trans;
        !           730:        int unit;
        !           731:        int flts;
        !           732:        int i;
        !           733:        int iarg[2];
        !           734: 
        !           735:        if (minor(dev) & RESETDEV) {
        !           736:                u.u_error = EINVAL;
        !           737:                return;
        !           738:        }
        !           739:        unit = minor(dev) & ~RESETDEV;
        !           740: 
        !           741:        sc = &ds_softc[unit];
        !           742:        ui = dsdinfo[unit];
        !           743:        dsaddr = (struct dsdevice *) ui->ui_addr;
        !           744: 
        !           745:        switch (cmd) {
        !           746:                /* set sample rate */
        !           747:                case DSRATE:
        !           748:                        
        !           749:                        if (copyin(addr, (caddr_t) iarg, (unsigned) sizeof(int))) {
        !           750:                                u.u_error = EFAULT;
        !           751:                                return;
        !           752:                        }
        !           753:                        sc->c_ascsrt = 4000000/iarg[0] - 1;
        !           754:                        break;
        !           755: 
        !           756:                case DS08KHZ:
        !           757:                        sc->c_ascflags &= ~ ASC_HZMSK;
        !           758:                        sc->c_ascflags |= ASC_HZ08;     /* set 8kHz filter */
        !           759:                        break;
        !           760: 
        !           761:                case DS04KHZ:
        !           762:                        sc->c_ascflags &= ~ ASC_HZMSK;
        !           763:                        sc->c_ascflags |= ASC_HZ04;     /* set 4kHz filter */
        !           764:                        break;
        !           765: 
        !           766: 
        !           767: 
        !           768:                case DSBYPAS:
        !           769:                        sc->c_ascflags &= ~ ASC_HZMSK;
        !           770:                        sc->c_ascflags |= ASC_BYPASS;   /* set bypass */
        !           771:                        break;
        !           772: 
        !           773:                /* fetch errors */
        !           774:                case DSERRS:
        !           775:                        de = &ds_err;
        !           776:                        de->dma_csr = sc->c_dmacsr;
        !           777:                        de->asc_csr = sc->c_asccsr;
        !           778:                        de->errors = sc->c_errs;
        !           779:                        if (copyout((caddr_t) de, addr, (unsigned) sizeof(struct ds_err))) {
        !           780:                                u.u_error = EFAULT;
        !           781:                                return;
        !           782:                        }
        !           783:                        break;
        !           784: 
        !           785:                /* fetch transition counts */
        !           786:                case DSTRANS:
        !           787:                        dt = &ds_trans;
        !           788:                        dt->to_idle = sc->c_to_idle;
        !           789:                        dt->to_active = sc->c_to_active;
        !           790:                        if (copyout((caddr_t) dt, addr, sizeof(struct ds_trans))) {
        !           791:                                u.u_error = EFAULT;
        !           792:                                return;
        !           793:                        }
        !           794:                        break;
        !           795: 
        !           796:                /* how many samples actually converted */
        !           797:                case DSDONE:
        !           798:                        if (copyout((caddr_t) sc->c_nbytes, addr, (unsigned) sizeof(int))) {
        !           799:                                u.u_error = EFAULT;
        !           800:                                return;
        !           801:                        }
        !           802:                        break;
        !           803: 
        !           804:                case DSSTEREO:
        !           805:                        while(!sc->c_flags & DS_IDLE);
        !           806:                        if (sc->c_flags & DS_READ) {
        !           807:                                dsseq(sc, 0, ADBASE, AD);
        !           808:                                dsseq(sc, 1, ADBASE+1 | LAST_SEQ, AD);
        !           809:                        } else {
        !           810:                                dsseq(sc, 0, DABASE, DA);
        !           811:                                dsseq(sc, 1, DABASE+1 | LAST_SEQ, DA);
        !           812:                        }
        !           813:                        break;
        !           814: 
        !           815:                case DSMONO:
        !           816:                        while(!sc->c_flags & DS_IDLE);
        !           817:                        if (sc->c_flags & DS_READ)
        !           818:                                dsseq(sc, 0, ADBASE | LAST_SEQ, AD);
        !           819:                        else
        !           820:                                dsseq(sc, 0, DABASE | LAST_SEQ, DA);
        !           821:                        break;
        !           822: 
        !           823:                case DSRESET:
        !           824:                                /* not adequate */
        !           825:                        sc->c_flags = DS_CLOSED | DS_IDLE;
        !           826:                        dscleanup(unit);
        !           827:                        break;
        !           828: 
        !           829:                case DSDEBUG:
        !           830:                        dsdebug = 1 - dsdebug;
        !           831:                        break;
        !           832:                case DSWAIT:
        !           833:                        while(sc->c_outbufno != sc->c_bufno
        !           834:                                && !(sc->c_flags & DS_IDLE))
        !           835:                                tsleep((caddr_t)&ds_softc[unit],DSPRI,0);
        !           836:                        break;
        !           837: 
        !           838:                default:
        !           839:                        u.u_error = ENOTTY;
        !           840:                        break;
        !           841:        }
        !           842: }
        !           843: 
        !           844: 
        !           845: /*
        !           846:  * zero uba vector.
        !           847:  * shut off converters.
        !           848:  * set error bit.
        !           849:  */
        !           850: dsreset(uban) {
        !           851:        register struct uba_device *ui;
        !           852:        register struct ds_softc *sc;
        !           853:        register int ds;
        !           854: 
        !           855:        for (ds = 0; ds < NDS; ds++) {
        !           856:                if ((ui = dsdinfo[ds]) == NULL)
        !           857:                        continue;
        !           858:                if (ui->ui_alive == 0)
        !           859:                        continue;
        !           860:                if (ui->ui_ubanum != uban)
        !           861:                        continue;
        !           862: 
        !           863:                printf(" ds%d", ds);
        !           864: 
        !           865:                sc = &ds_softc[ds];
        !           866: 
        !           867:                /*
        !           868:                 * release unibus resources
        !           869:                 */
        !           870:                sc->c_flags = DS_CLOSED | DS_IDLE;
        !           871:                dscleanup(ds);
        !           872:        }
        !           873: }
        !           874: /*
        !           875:  equivalent to vslock() from vmmem.c
        !           876:   inserted differently here for debugging convenience only.
        !           877:  */
        !           878: dslock(base, count)
        !           879:        caddr_t base;
        !           880: {
        !           881:        register unsigned v;
        !           882:        register int npf;
        !           883:        register struct pte *pte;
        !           884: 
        !           885:        u.u_procp->p_flag |= SDLYU;
        !           886:        v = btop(base);
        !           887:        pte = vtopte(u.u_procp, v);
        !           888:        npf = btoc(count + ((int)base & CLOFSET));
        !           889:        if(dsdebug)printf("Lk %x %d ",pte->pg_pfnum,npf);
        !           890:        while (npf > 0) {
        !           891:                if (pte->pg_v) 
        !           892:                        mlock(pte->pg_pfnum);
        !           893:                else
        !           894:                        if (fubyte((caddr_t)ctob(v)) < 0)
        !           895:                                panic("vslock");
        !           896:                pte += CLSIZE;
        !           897:                v += CLSIZE;
        !           898:                npf -= CLSIZE;
        !           899:        }
        !           900:        u.u_procp->p_flag &= ~SDLYU;
        !           901: }
        !           902: # endif

unix.superglobalmegacorp.com

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