|
|
1.1 root 1: /*
2: * to do:
3: * check overflow of user read (bp->b_count)
4: * does the address loaded into the registers
5: * have to be on a 2k boundary?
6: */
7: #include "sys/param.h"
8: #include "sys/conf.h"
9: #include "sys/user.h"
10: #include "sys/buf.h"
11: #include "sys/ubaddr.h"
12: #include "sys/pte.h"
13:
14: #include "sys/rco.h"
15: #include "sys/rcocmd.h"
16:
17: /*
18: * hardware
19: */
20: struct device {
21: u_short csr; /* control/status register */
22: u_short vr; /* virtual register (write only)*/
23: u_short ar; /* address register */
24: u_short xar; /* extended address register */
25: };
26:
27: #define GO 01
28: #define ERROR 016 /* 02 = FAULT, 04 = TIMEOUT, 010 = OVERFLO */
29: #define RESL 060
30: #define HALF 0100
31: #define READY 0200
32: #define UBACT 07400
33: #define UBALOW 010000
34: #define TEOP 020000
35: #define IENABLE 040000
36:
37: #define NUBMREG 4
38: #define IOCHUNK (NBPG*NUBMREG)
39:
40: /*
41: * config glue
42: */
43: int rcoopen(), rcoclose(), rcoread(), rcoioctl();
44:
45: extern struct rco rco[];
46: extern struct ubaddr rcoaddr[];
47: extern int rcocnt;
48: struct cdevsw rcocdev = cdinit(rcoopen, rcoclose, rcoread, nodev, rcoioctl);
49:
50: #define OPEN 0x01
51: #define BUSY 0x02
52:
53: rcoopen(d, f)
54: {
55: register int dev;
56: register struct rco *rp;
57:
58: if((dev = minor(d)) >= rcocnt) {
59: u.u_error = ENODEV;
60: return;
61: }
62: if((rp = &rco[dev])->flags&OPEN) {
63: u.u_error = EBUSY;
64: return;
65: }
66: if((rp->addr = (struct device *)ubaddr(&rcoaddr[dev])) == 0
67: || ubbadaddr(rcoaddr[dev].ubno, (caddr_t)rp->addr, sizeof(u_short))) {
68: printf("rco%d absent\n", dev);
69: u.u_error = ENODEV;
70: return;
71: }
72: rp->flags = OPEN;
73: rp->addr->csr = 0;
74: rp->dither = 0;
75: rp->resol = 2;
76: }
77:
78: rcoclose(d)
79: {
80: rco[minor(d)].flags &= ~OPEN;
81: }
82:
83: rcominp(bp)
84: struct buf *bp;
85: {
86: }
87:
88: rcostrategy(bp)
89: register struct buf *bp;
90: {
91: register struct rco *rp = &rco[minor(bp->b_dev)];
92: register uaddr_t uaddr;
93: register int s, ubno;
94: u_short csr;
95:
96: csr = IENABLE | ((rp->dither << 6) & HALF) | ((rp->resol << 4) & RESL);
97: ubno = rcoaddr[minor(bp->b_dev)].ubno;
98: rp->ubm = ubmalloc(ubno, IOCHUNK+(IOCHUNK-1), UBDP|USLP);
99: rp->chunkubm = (rp->ubm + (NUBMREG-1)) & ~(NUBMREG-1);
100: rp->pte = btopte(bp);
101: uaddr = ubmsetmap(ubno, rp->pte, NUBMREG, rp->chunkubm);
102: rp->pte += NUBMREG;
103: s = spl5();
104: rp->flags |= BUSY;
105: rp->addr->ar = uaddr & 0x7FE; /* bits 10-1 */
106: rp->addr->xar = (uaddr >> 8) & 0x3FF8; /* bits 21-11 */
107: while((rp->addr->csr&READY) == 0)
108: ;
109: rp->addr->csr = csr;
110: for(rp->mreg = NUBMREG; rp->mreg; rp->mreg--)
111: rp->addr->vr = 1;
112: DELAY(50000);
113: rp->addr->csr = csr | GO;
114: if(tsleep((caddr_t)bp, PRIBIO+1, 20) != TS_OK) {
115: bp->b_flags |= B_ERROR;
116: iodone(bp);
117: }
118: rp->addr->csr = 0;
119: rp->flags &= ~BUSY;
120: splx(s);
121: bp->b_resid = 0;
122: ubmfree(ubno, rp->ubm);
123: }
124:
125: rcoread(d)
126: {
127: if((((int)u.u_base) & (IOALIGN-1))) {
128: u.u_error = EFAULT;
129: return;
130: }
131: physio(rcostrategy, &rco[minor(d)].buf, d, B_READ, rcominp);
132: }
133:
134: rcoioctl(dev, cmd, addr, flag)
135: caddr_t addr;
136: {
137: register struct rco *rp = &rco[minor(dev)];
138: int i;
139:
140: if(copyin(addr, (caddr_t)&i, sizeof(i))) {
141: u.u_error = EFAULT;
142: return;
143: }
144: switch(cmd) {
145:
146: case RCORES:
147: rp->resol = i;
148: break;
149:
150: case RCODITHER:
151: rp->dither = i;
152: break;
153:
154: default:
155: u.u_error = ENXIO;
156: }
157: }
158:
159: rco0int(d)
160: {
161: register struct rco *rp = &rco[d];
162: register struct buf *bp;
163: ubm_t ubm;
164: u_short csr;
165:
166: if((rp->flags & (BUSY|OPEN)) != (BUSY|OPEN)) {
167: printf("rco%d: not busy interrupt\n", d);
168: rp->addr->csr = 0;
169: return;
170: }
171: if((csr = rp->addr->csr) & GO) {
172: ubm = rp->chunkubm + rp->mreg++;
173: (void) ubmsetmap(rcoaddr[d].ubno, rp->pte++, 1, ubm);
174: if(rp->mreg > (NUBMREG-1))
175: rp->mreg = 0;
176: rp->addr->vr = 1;
177: return;
178: }
179: bp = &rp->buf;
180: if((csr & ERROR) || (csr & TEOP) == 0) {
181: printf("rco%d: csr=0%o\n", d, csr);
182: bp->b_flags |= B_ERROR;
183: }
184: rp->addr->csr = 0;
185: iodone(bp);
186: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.