|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.