Annotation of researchv8dc/sys/dev/ds.c, revision 1.1.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.