|
|
1.1 root 1: #include "cv.h"
2: #if NCV > 0
3: /*
4: * Raster Technologies Color Video Interface -- Rob Pike
5: * Model One 20 with Option Card, on DR-11/W
6: */
7:
8: #include "../h/param.h"
9: #include "../h/dir.h"
10: #include "../h/user.h"
11: #include "../h/buf.h"
12: #include "../h/systm.h"
13: #include "../h/pte.h"
14: #include "../h/map.h"
15: #include "../h/ioctl.h"
16: #include "../h/ubareg.h"
17: #include "../h/ubavar.h"
18:
19: struct cvdevice {
20: short wcr; /* Unibus word count reg */
21: u_short bar; /* Unibus address register */
22: u_short csr; /* Unibus status/command reg */
23: u_short idr; /* Input Data Register */
24: };
25: #define eir csr /* Error and Information Register */
26: #define odr idr /* Output Data Register */
27:
28: /*
29: * Unibus status/command register bits
30: */
31:
32: #define GO 0000001
33: #define IENABLE 0000100
34: #define READY 0000200
35: #define MAINT 0010000
36: #define ERROR 0100000
37:
38: /*
39: * Function codes
40: */
41: #define WR_IMAGE (1<<1)
42: #define WR_CMD (4<<1)
43: #define WR_RLE (5<<1)
44: #define RD_CMD (7<<1)
45: #define RD_IMAGE (3<<1)
46: #define FUNCMASK (7<<1)
47: #define TOGGLE (8<<1) /* toggle between X and WR_CMD, WR_CMD first */
48:
49: /*
50: * IOCTL
51: */
52: #define CVSETDMA (('c'<<8)|1)
53:
54: #define BUSY 01
55: #define DMAPRI (PZERO-1)
56: #define WAITPRI (PZERO+1)
57:
58: int cvprobe(), cvattach(), cvintr();
59: struct uba_device *cvdinfo[NCV];
60: u_short cvstd[] = { 0772410, 0000000, 0 };
61: struct uba_driver cvdriver = {
62: cvprobe, 0, cvattach, 0, cvstd, "cv", cvdinfo, 0, 0
63: };
64:
65: struct cvsoftc {
66: char open;
67: short uid;
68: short state;
69: int ubinfo;
70: int count;
71: struct buf *bp;
72: int bufp;
73: int icnt;
74: short dmamode;
75: short func;
76: } cvsoftc[NCV];
77:
78: int cvstrategy();
79: u_int cvminphys();
80: struct buf rcvbuf[NCV];
81:
82: #define UNIT(dev) (minor(dev))
83:
84: cvprobe(reg)
85: caddr_t reg;
86: {
87: register int br, cvec; /* value-result */
88: register struct cvdevice *cvaddr = (struct cvdevice *) reg;
89:
90: #ifdef lint
91: br = 0; cvec = br; br = cvec;
92: cvintr(0);
93: #endif
94: cvaddr->csr = IENABLE;
95: cvaddr->odr = 0x0707; /* clear screen, force interrupt */
96: DELAY(10000);
97: cvaddr->csr = 0;
98: /* KLUDGE */
99: br=0x15;
100: cvec=0124;
101: return (sizeof (struct cvdevice));
102: }
103:
104: /*ARGSUSED*/
105: cvattach(ui)
106: struct uba_device *ui;
107: {
108:
109: }
110:
111: cvopen(dev)
112: dev_t dev;
113: {
114: register struct cvsoftc *cvp;
115: register struct uba_device *ui;
116:
117: if (UNIT(dev) >= NCV || (cvp = &cvsoftc[minor(dev)])->open ||
118: (ui = cvdinfo[UNIT(dev)]) == 0 || ui->ui_alive == 0)
119: u.u_error = EBUSY;
120: else {
121: cvp->open = 1;
122: cvp->icnt = 0;
123: cvp->state = 0;
124: cvp->uid = u.u_uid;
125: cvp->dmamode = -1;
126: }
127: }
128:
129: cvclose(dev)
130: dev_t dev;
131: {
132:
133: cvsoftc[minor(dev)].open = 0;
134: cvsoftc[minor(dev)].state = 0;
135: }
136:
137: cvread(dev, uio)
138: dev_t dev;
139: struct uio *uio;
140: {
141: register int unit = UNIT(dev);
142:
143: if (unit >= NCV)
144: return (ENXIO);
145: return (physio(cvstrategy, &rcvbuf[unit], dev, B_READ, cvminphys, uio));
146: }
147:
148: cvwrite(dev, uio)
149: dev_t dev;
150: struct uio *uio;
151: {
152: register int unit = UNIT(dev);
153:
154: if (unit >= NCV)
155: return (ENXIO);
156: return (physio(cvstrategy, &rcvbuf[unit], dev, B_WRITE, cvminphys, uio));
157: }
158:
159: u_int
160: cvminphys(bp)
161: register struct buf *bp;
162: {
163:
164: if (bp->b_bcount > 65536) /* may be able to do twice as much */
165: bp->b_bcount = 65536;
166: }
167:
168: cvstrategy(bp)
169: register struct buf *bp;
170: {
171: register struct cvsoftc *cvp = &cvsoftc[UNIT(bp->b_dev)];
172: register struct uba_device *ui;
173:
174: if (UNIT(bp->b_dev) >= NCV || (ui = cvdinfo[UNIT(bp->b_dev)]) == 0
175: || ui->ui_alive == 0)
176: goto bad;
177: (void) spl5();
178: while (cvp->state & BUSY)
179: sleep((caddr_t)cvp, DMAPRI+1);
180: cvp->state |= BUSY;
181: cvp->bp = bp;
182: if(bp->b_bcount<=0 || (bp->b_bcount&1) ||
183: ((int)bp->b_un.b_addr&1) || cvp->dmamode<0){
184: u.u_error = EINVAL;
185: goto bad;
186: }
187: cvp->ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
188: cvp->bufp = cvp->ubinfo & 0x3ffff;
189: cvp->count = -(bp->b_bcount>>1); /* it's a word count */
190: cvstart(ui);
191: if(tsleep((caddr_t)cvp, DMAPRI+1, 15) != TS_OK){
192: register struct cvdevice *cvaddr = (struct cvdevice *) ui->ui_addr;
193: bp->b_flags |= B_ERROR;
194: /* stop the dma */
195: cvslam(cvaddr);
196: cvaddr->wcr=0xFFFF; /* gently; -1 first... */
197: cvaddr->wcr=0x0000; /* then zero */
198: /* reset device */
199: cvslam(cvaddr);
200: /* fake an interrupt to clear software status */
201: cvintr(UNIT(bp->b_dev));
202: }
203: cvp->count = 0;
204: cvp->bufp = 0;
205: (void) spl0();
206: ubarelse(ui->ui_ubanum, &cvp->ubinfo);
207: cvp->bp = 0;
208: iodone(bp);
209: wakeup((caddr_t)cvp);
210: return;
211: bad:
212: cvp->state &= ~BUSY;
213: bp->b_flags |= B_ERROR;
214: iodone(bp);
215: return;
216: }
217:
218: cvslam(cvaddr)
219: register struct cvdevice *cvaddr;
220: {
221: register i;
222: cvaddr->csr=MAINT;
223: for(i=0; i<10; i++)
224: ;
225: cvaddr->csr=0;
226: for(i=0; i<10; i++)
227: ;
228: }
229: cvstart(ui)
230: register struct uba_device *ui;
231: {
232: register int csr;
233: register struct cvdevice *cvaddr = (struct cvdevice *) ui->ui_addr;
234: register struct cvsoftc *cvp = &cvsoftc[UNIT(ui->ui_unit)];
235:
236: if((cvp->dmamode&TOGGLE) && cvp->func!=WR_CMD)
237: cvp->func = WR_CMD;
238: else
239: cvp->func = cvp->dmamode&~TOGGLE;
240: csr = IENABLE|((cvp->bufp>>12)&060) | cvp->func;
241: cvaddr->wcr = cvp->count;
242: cvaddr->bar = cvp->bufp;
243: cvaddr->csr = csr; /* No GO bit; let function codes settle */
244: cvaddr->csr = csr|GO;
245: }
246:
247: /*ARGSUSED*/
248: cvioctl(dev, cmd, data)
249: dev_t dev;
250: int cmd;
251: register caddr_t data;
252: {
253: register struct uba_device *ui = cvdinfo[UNIT(dev)];
254: register struct cvsoftc *cvp = &cvsoftc[UNIT(dev)];
255: int fmt;
256:
257: switch (cmd) {
258: case CVSETDMA: /* set DMA mode */
259: if (copyin(data, (caddr_t)&fmt, sizeof(fmt))) {
260: u.u_error = EFAULT;
261: goto out;
262: }
263: switch (fmt&~TOGGLE) {
264: case WR_IMAGE:
265: case WR_CMD:
266: case WR_RLE:
267: case RD_CMD:
268: case RD_IMAGE:
269: cvp->dmamode = cvp->func = fmt;
270: cvp->func &= ~TOGGLE;
271: break;
272: default:
273: u.u_error = EINVAL;
274: }
275: goto out;
276:
277: default:
278: return (ENOTTY);
279: }
280: out:
281: return u.u_error;
282: }
283:
284: /*ARGSUSED*/
285: cvintr(dev)
286: dev_t dev;
287: {
288: register struct cvdevice *cvaddr =
289: (struct cvdevice *) cvdinfo[UNIT(dev)]->ui_addr;
290: register struct cvsoftc *cvp = &cvsoftc[UNIT(dev)];
291: register csr;
292:
293: cvp->icnt++;
294: if (cvp->state&BUSY) {
295: csr = cvaddr->csr;
296: if(csr & ERROR){
297: cvaddr->eir |= ERROR;
298: printf("cv: CSR %x EIR %x\n", csr, cvaddr->eir);
299: }
300: cvaddr->csr = csr&~FUNCMASK;
301: cvp->state &= ~BUSY;
302: wakeup((caddr_t)cvp);
303: }
304: }
305:
306: cvreset(uban)
307: int uban;
308: {
309: register int i;
310: register struct uba_device *ui;
311: register struct cvsoftc *cvp = cvsoftc;
312: #ifdef untried
313: for (i = 0; i < NCV; i++, cvp++) {
314: if ((ui = cvdinfo[i]) == 0 || ui->ui_alive == 0 ||
315: ui->ui_ubanum != uban || cvp->open == 0)
316: continue;
317: printf(" cv%d", i);
318: if ((cvp->state&CVBUSY) == 0)
319: continue;
320: cvp->ubinfo =
321: ubasetup(ui->ui_ubanum, cvp->bp, UBA_NEEDBDP);
322: cvp->count = -(cvp->bp->b_bcount/2);
323: cvstart(ui);
324: }
325: #endif
326: }
327: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.