Commit | Line | Data |
---|---|---|
71357272 | 1 | /* va.c 3.6 %G% */ |
20cc8b5b | 2 | |
20cc8b5b BJ |
3 | #include "../h/param.h" |
4 | #include "../h/dir.h" | |
5 | #include "../h/user.h" | |
6 | #include "../h/buf.h" | |
7 | #include "../h/systm.h" | |
8 | #include "../h/map.h" | |
9 | #include "../h/pte.h" | |
10 | #include "../h/uba.h" | |
11 | #include "../h/vcmd.h" | |
12 | ||
13 | /* | |
71357272 | 14 | * Benson-Varian matrix printer/plotter |
20cc8b5b BJ |
15 | * dma interface driver |
16 | */ | |
71357272 | 17 | int vabdp = 1; |
20cc8b5b | 18 | |
71357272 | 19 | unsigned minvaph(); |
20cc8b5b BJ |
20 | |
21 | #define VAPRI (PZERO-1) | |
22 | ||
71357272 BJ |
23 | #define ushort unsigned short |
24 | struct varegs { | |
25 | ushort vaba; | |
26 | short vawc; | |
20cc8b5b | 27 | union { |
71357272 | 28 | short Vacsw; |
20cc8b5b | 29 | struct { |
71357272 BJ |
30 | char Vacsl; |
31 | char Vacsh; | |
32 | } vacsr; | |
33 | } vacs; | |
20cc8b5b BJ |
34 | short vadata; |
35 | }; | |
36 | ||
71357272 BJ |
37 | #define vacsw vacs.Vacsw |
38 | #define vacsh vacs.vacsr.Vacsh | |
39 | #define vacsl vacs.vacsr.Vacsl | |
40 | ||
20cc8b5b BJ |
41 | #define VAADDR ((struct varegs *)(UBA0_DEV + 0164000)) |
42 | ||
71357272 BJ |
43 | /* vacsw bits */ |
44 | #define ERROR 0100000 /* Some error has occurred */ | |
45 | #define NPRTIMO 01000 /* DMA timeout error */ | |
46 | #define NOTREADY 0400 /* Something besides NPRTIMO */ | |
47 | #define DONE 0200 | |
48 | #define IENABLE 0100 /* Interrupt enable */ | |
49 | #define SUPPLIESLOW 04 | |
50 | #define BOTOFFORM 02 | |
51 | #define BYTEREVERSE 01 /* Reverse byte order in words */ | |
52 | ||
53 | /* vacsh command bytes */ | |
20cc8b5b BJ |
54 | #define VAPLOT 0340 |
55 | #define VAPRINT 0100 | |
56 | #define VAPRINTPLOT 0160 | |
57 | #define VAAUTOSTEP 0244 | |
71357272 BJ |
58 | #define VANOAUTOSTEP 0045 /* unused */ |
59 | #define VAFORMFEED 0263 /* unused */ | |
60 | #define VASLEW 0265 /* unused */ | |
61 | #define VASTEP 0064 /* unused */ | |
20cc8b5b BJ |
62 | |
63 | struct { | |
71357272 | 64 | char va_open; |
20cc8b5b BJ |
65 | char va_busy; |
66 | int va_state; /* State: bits are commands in vcmd.h. */ | |
71357272 | 67 | int va_wc; |
20cc8b5b | 68 | int va_bufp; |
71357272 BJ |
69 | struct buf *va_bp; |
70 | } va11; | |
20cc8b5b BJ |
71 | int va_ubinfo; |
72 | ||
73 | struct buf rvabuf; /* Used by physio for a buffer. */ | |
74 | ||
75 | vaopen() | |
76 | { | |
77 | ||
71357272 | 78 | if (va11.va_open) { |
20cc8b5b BJ |
79 | u.u_error = ENXIO; |
80 | return; | |
81 | } | |
71357272 BJ |
82 | va11.va_open = 1; |
83 | VAADDR->vawc = 0; | |
84 | va11.va_wc = 0; | |
85 | va11.va_state = 0; | |
86 | VAADDR->vacsl = IENABLE; | |
20cc8b5b | 87 | vatimo(); |
71357272 | 88 | vacmd(VPRINT); |
20cc8b5b BJ |
89 | if (u.u_error) |
90 | vaclose(); | |
91 | } | |
92 | ||
93 | vastrategy(bp) | |
94 | register struct buf *bp; | |
95 | { | |
96 | register int e; | |
97 | ||
81263dba | 98 | (void) spl4(); |
71357272 BJ |
99 | while (va11.va_busy) |
100 | sleep((caddr_t)&va11, VAPRI); | |
101 | va11.va_busy = 1; | |
102 | va11.va_bp = bp; | |
103 | va_ubinfo = ubasetup(bp, vabdp); | |
104 | va11.va_bufp = va_ubinfo & 0x3ffff; | |
20cc8b5b BJ |
105 | if (e = vaerror(DONE)) |
106 | goto brkout; | |
71357272 | 107 | va11.va_wc = -(bp->b_bcount/2); |
20cc8b5b | 108 | vastart(); |
71357272 BJ |
109 | e = vaerror(DONE); /* Wait for DMA to complete */ |
110 | va11.va_wc = 0; | |
111 | va11.va_bufp = 0; | |
112 | ||
113 | /* | |
114 | * After printing a line of characters, VPRINTPLOT mode essentially | |
115 | * reverts to VPLOT mode, plotting things until a new mode is set. | |
116 | * This change is indicated by sending a VAAUTOSTEP command to | |
117 | * the va. We also change va_state to reflect this effective | |
118 | * mode change. | |
20cc8b5b | 119 | */ |
71357272 BJ |
120 | if (va11.va_state & VPRINTPLOT) { |
121 | va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT; | |
122 | VAADDR->vacsh = VAAUTOSTEP; | |
20cc8b5b BJ |
123 | e |= vaerror(DONE); |
124 | } | |
81263dba | 125 | (void) spl0(); |
20cc8b5b BJ |
126 | brkout: |
127 | ubafree(va_ubinfo), va_ubinfo = 0; | |
71357272 BJ |
128 | va11.va_bp = 0; |
129 | va11.va_busy = 0; | |
20cc8b5b BJ |
130 | iodone(bp); |
131 | if (e) | |
132 | u.u_error = EIO; | |
71357272 | 133 | wakeup((caddr_t)&va11); |
20cc8b5b BJ |
134 | } |
135 | ||
136 | int vablock = 16384; | |
137 | ||
138 | unsigned | |
139 | minvaph(bp) | |
140 | struct buf *bp; | |
141 | { | |
142 | if (bp->b_bcount > vablock) | |
143 | bp->b_bcount = vablock; | |
144 | } | |
145 | ||
146 | /*ARGSUSED*/ | |
147 | vawrite(dev) | |
148 | { | |
149 | physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph); | |
150 | } | |
151 | ||
152 | /* | |
153 | * Vaerror waits until bit or ERROR gets set, then returns non-zero if | |
154 | * if it was ERROR that was set. | |
155 | */ | |
156 | vaerror(bit) | |
157 | { | |
158 | register int e; | |
159 | ||
71357272 BJ |
160 | while ((e = VAADDR->vacsw & (bit|ERROR)) == 0) |
161 | sleep((caddr_t)&va11, VAPRI); | |
20cc8b5b BJ |
162 | return (e & ERROR); |
163 | } | |
164 | ||
20cc8b5b BJ |
165 | vastart() |
166 | { | |
71357272 BJ |
167 | if (va11.va_wc) { |
168 | VAADDR->vaba = va11.va_bufp; | |
169 | VAADDR->vawc = va11.va_wc; | |
20cc8b5b BJ |
170 | return; |
171 | } | |
172 | } | |
173 | ||
174 | /*ARGSUSED*/ | |
175 | vaioctl(dev, cmd, addr, flag) | |
176 | register caddr_t addr; | |
177 | { | |
178 | register int vcmd; | |
179 | ||
180 | switch (cmd) { | |
181 | ||
182 | case VGETSTATE: | |
71357272 | 183 | (void) suword(addr, va11.va_state); |
20cc8b5b BJ |
184 | return; |
185 | ||
186 | case VSETSTATE: | |
187 | vcmd = fuword(addr); | |
188 | if (vcmd == -1) { | |
189 | u.u_error = EFAULT; | |
190 | return; | |
191 | } | |
192 | vacmd(vcmd); | |
193 | return; | |
194 | ||
195 | default: | |
196 | u.u_error = ENOTTY; /* Not a legal ioctl cmd. */ | |
197 | return; | |
198 | } | |
199 | } | |
200 | ||
71357272 BJ |
201 | /* |
202 | * Send a command code to the va, and wait for it to complete. | |
203 | * If an error occurs, u.u_error is set to EIO. | |
204 | * In any case, update va11.va_state. | |
20cc8b5b | 205 | */ |
20cc8b5b BJ |
206 | vacmd(vcmd) |
207 | { | |
81263dba | 208 | (void) spl4(); |
71357272 | 209 | (void) vaerror(DONE); /* Wait for va to be ready */ |
20cc8b5b BJ |
210 | switch (vcmd) { |
211 | ||
212 | case VPLOT: | |
213 | /* Must turn on plot AND autostep modes. */ | |
71357272 | 214 | VAADDR->vacsh = VAPLOT; |
20cc8b5b BJ |
215 | if (vaerror(DONE)) |
216 | u.u_error = EIO; | |
71357272 | 217 | VAADDR->vacsh = VAAUTOSTEP; |
20cc8b5b BJ |
218 | break; |
219 | ||
220 | case VPRINT: | |
71357272 | 221 | VAADDR->vacsh = VAPRINT; |
20cc8b5b BJ |
222 | break; |
223 | ||
224 | case VPRINTPLOT: | |
71357272 | 225 | VAADDR->vacsh = VAPRINTPLOT; |
20cc8b5b BJ |
226 | break; |
227 | } | |
71357272 BJ |
228 | va11.va_state = |
229 | (va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd; | |
20cc8b5b BJ |
230 | |
231 | if (vaerror(DONE)) /* Wait for command to complete. */ | |
232 | u.u_error = EIO; | |
81263dba | 233 | (void) spl0(); |
20cc8b5b BJ |
234 | } |
235 | ||
236 | vatimo() | |
237 | { | |
71357272 | 238 | if (va11.va_open) |
20cc8b5b BJ |
239 | timeout(vatimo, (caddr_t)0, HZ/10); |
240 | vaintr(0); | |
241 | } | |
242 | ||
243 | /*ARGSUSED*/ | |
244 | vaintr(dev) | |
245 | { | |
71357272 | 246 | wakeup((caddr_t)&va11); |
20cc8b5b BJ |
247 | } |
248 | ||
249 | vaclose() | |
250 | { | |
251 | ||
71357272 BJ |
252 | va11.va_open = 0; |
253 | va11.va_busy = 0; | |
254 | va11.va_state = 0; | |
255 | va11.va_wc = 0; | |
256 | va11.va_bufp = 0; | |
257 | VAADDR->vacsl = 0; | |
258 | } | |
259 | ||
260 | #define DELAY(N) { register int d; d = N; while (--d > 0); } | |
261 | ||
262 | vareset() | |
263 | { | |
264 | ||
265 | if (va11.va_open == 0) | |
266 | return; | |
267 | printf(" va"); | |
268 | VAADDR->vacsl = IENABLE; | |
269 | if (va11.va_state & VPLOT) { | |
270 | VAADDR->vacsh = VAPLOT; | |
271 | DELAY(10000); | |
272 | VAADDR->vacsh = VAAUTOSTEP; | |
273 | } else if (va11.va_state & VPRINTPLOT) | |
274 | VAADDR->vacsh = VPRINTPLOT; | |
275 | else | |
276 | VAADDR->vacsh = VAPRINTPLOT; | |
277 | DELAY(10000); | |
278 | if (va11.va_busy == 0) | |
279 | return; | |
280 | if (va_ubinfo) { | |
281 | printf("<%d>", (va_ubinfo>>28)&0xf); | |
282 | ubafree(va_ubinfo), va_ubinfo = 0; | |
283 | } | |
284 | /* This code belongs in vastart() */ | |
285 | va_ubinfo = ubasetup(va11.va_bp, vabdp); | |
286 | va11.va_bufp = va_ubinfo & 0x3ffff; | |
287 | va11.va_wc = (-va11.va_bp->b_bcount/2); | |
288 | /* End badly placed code */ | |
289 | vastart(); | |
20cc8b5b | 290 | } |